转载

JavaScript后门深层分析

0x00 背景

之前@三好学生的文章JavaScript BackDoor中提到了利用rundll32.exe执行一段JavaScript代码即可反弹一个Http Shell,这里将之前看到的对其原理进行分析的文章翻译和大家分享。

links: http://thisissecurity.net/2014/08/20/poweliks-command-line-confusion/

最近,hFireF0X在逆向工程论坛kernelmode.info上发表了对Win32/Poweeliks恶意软件详细调查的文章。这个恶意软件的特别之处就是它存在于window注册表中并且使用rundll32.exe来执行JavaScript代码。

我发现很有趣的是我显然不是唯一一个发现可以通过rundll32来执行一些JavaScript代码的人。

JavaScript后门深层分析

当我们第一次发现命令行执行JavaScript,我们很好奇它是如何工作的。

在接下来的文章中,我们会分析JavaScript代码时如何执以及为什么会在调用这样简单的命令行代码时执行:

#!bash rundll32.exe javascript:"/../mshtml,RunHTMLApplication ";alert(‘foo’); 

0x01 Rundll32介绍

关于rundll32.dll的使用在MSDN上有专门的 文档 ;它往往被用来调用一个DLL文件的输出函数,可以通过以下的命令来实现:

#!bash RUNDLL32.EXE <dllname>,<entrypoint> <optional arguments> 

entrypoint就是输出函数;它的函数原型应该是如下所示:

#!cpp void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow); 

参数lpszCmdLine是由rundll32.exe命令语句中的 <optional arguments> 值确定的。

我们会尝试指出rundll32.exe是如何能够调用被mshtml.dll输出的函数RunHTMLApplication,以及“Javascript”前缀是如何被用来执行实际的JavaScript代码的。

0x02 Rundll32.exe分析

a.参数

rundll32.exe做的第一件事就是使用内置的ParseCommand命令来对命令进行解析。这个函数会查找一个逗号(‘,’,0x2c)来定位dll的名称和一个空格(‘ ’,0x20)来定位入口点名称

JavaScript后门深层分析

当使用我们的样本命令时,ParseCommand会返回 javascript:"/../mshtml 作为DLL名称,返回 RunHTMLApplication 作为入口点。

JavaScript后门深层分析

0x03 Dll loader

rundll32.exe会尝试几种方法来从最初的“ JavaScript:"/../mshtml ”加载实际的DLL。

第一次测试使用了函数 GetFileAttributes("javascript:"/../mshtml") 。这个函数最终会接近 C:/Windows/system32/mshtml 。如果这个文件没有被发现,那么这个函数就会返回-1。

JavaScript后门深层分析

接下来 SearchPath 会被调用来确定DLL的名称。这个函数会读取注册表键值 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/SafeProcessSearchMode 。微软对于这个键值的定义是:

当这个REG_DWORD类型的注册表键值被设为1,SearchPath会首先搜索系统路径中指定的文件夹,然后会搜索当前工作的文件夹。当这个注册表键值被设为0时,电脑首先会搜索当前工作的文件夹,然后再去搜索系统路径中指定的文件夹。系统对于这个注册表键的默认值是0。

在默认情况下,这个注册表键值是不存在的(在win xp、7、8下),所以 SearchPath 会优先尝试在rundll32.dll的当前目录中加载文件mshtml,其次才会尝试在系统路径中进行定位。

JavaScript后门深层分析

如果所有的尝试都失败了,那么rundll32.exe就会进行下一步。 GetFileAttribute 将再次被调用来给模块查找manifest文件: javascript:"/../mshtml.manifest

若所有的之前的步骤都失败了,rundll32.exe最终会调用 Loadlibrary("javascript:"/../mshtml")

LoadLibrary 只是位于ntdll.dll中的一个对LdrLoadDLL的简单封装。在内部,LdrLoadDll会添加默认的扩展dll并且把结果字串( javascript:”/../mshtml.dll )作为路径来解析。“ .. ”代表再向上一层文件夹:它就解析成了 mshtml.dll

mshtml.dll 已经被确定了,LdrLoadDll就可以加载系统目录中的lib库了。

JavaScript后门深层分析

rundll32.exe接下来会使用之前提取的入口点名称 RunHTMLApplication 调用 GetProcAddress

这个时候我们可以发现, javascript: 前缀看起来毫无用处: LoadLibrary("foobar:/"/../mshtml") 工作的很好。所以,为什么要加这么一个前缀呢?

0x04 协议处理

一旦入口地址已经被解析出来,rundll32.dll会调用函数 mshtml.dll!RunHTMLApplication

即使没有被记录,实际的RunHTMLApplication也能从 c:/windows/system32/mshta.exe 的调用中推断出来(这个应用专门来启动一个.hta文件)。

#!cpp HRESULT RunHTMLApplication( HINSTANCE hinst, HINSTANCE hPrevInst, LPSTR szCmdLine, int nCmdShow ); 

这和期望的rundll32.exe的入口点地址很相似:

#!cpp void CALLBACK EntryPoint( HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow ); 

RunHTMLApplication接受一个窗口的句柄而不是一个模块的句柄作为第一个参数。这个参数会在mshml登记一个窗口类或者为一个类创建窗口时被使用。传递一个同实际的实例并不相一致的值并不会给user32带来很大影响。

第二个参数完全没有被使用,所以这个不匹配并不重要。

最后一个参数, nCmdShow ,被 RunHTMLApplication 函数用来展示代管这个HTML应用的主机窗口。rundll32经常使用值 SW_SHOWDEFAULT 来调用入口点函数来指示任何可能打开的窗口使用窗口默认配置。

在我们的例子中,可能更让人感兴趣的参数是 lpszCmdLine (";alert('foo'))

JavaScript后门深层分析

这显然会导致问题,因为这并不是一个有效的JavaScript语句(注意在语句末尾丢掉的双引号)。但是它仍然有效,因为 RunHTMLApplication 忽略给定的参数,并且更倾向于从windows API GetCommandLine 中重新请求原始的命令(封装在 GetCmdKLine 函数的一个调用中)。

JavaScript后门深层分析

完整的命令包含了可执行文件和参数的名称: GetCmdLine 通过整理可执行规范来提取参数。

JavaScript后门深层分析

在这之后, RunHTMLApplication 会调用 CreateURLMonitor :

JavaScript后门深层分析

这也是需要字符串“javascript”的地方。

CreateURLMonitor 解析命令行来提取char":"(0x3A)之前的字符串:“javascript”。

JavaScript后门深层分析

CreateUrlMoniker 会爬取注册表键值 HKCR/SOFTWARE/Classes/PROTOCOLS/Handler/ 。这些键值和一个协议集以及它们的CLSID有关。

CreateUrlMoniker 会发现一个合适的协议处理器来对Javascript的协议进行处理( HKCR/SOFTWARE/Classes/PROTOCOLS/Handler/javascript ):

JavaScript后门深层分析

CLSID {3050F3B2-98B5-11CF-BB82-00AA00BDCE0B} 符合微软“Microsoft HTML Javascript Pluggable Protocol”规范。

JavaScript后门深层分析

这也是为什么字符串“javascript”必须在参数的开始部分的原因。

相同的机制在人们在IE的导航栏输入javascript:alert('alert')时也会起作用。

JavaScript后门深层分析

位于“:”分隔符之后的字符串会被JavaScript URL moniker解释成JavaScript指令:

#!js "/../mshtml,RunHTMLApplication ";alert(‘foo’); 

这是一个带有字符串 "/../mshtml,RunHTMLApplication " 和函数 (alert) 的无效JavaScript语句(因为双引号会跳过所有之前的步骤!)。

最终RunHTMLApplication会调用 CHTMLApp::Run ,这条JavaScript语句也会被执行:

JavaScript后门深层分析

0x05 安全影响

从安全的角度来看,通过rundll32来执行JavaScript就像执行一个HTML应用。

换句话说,我们可以使用IE的全部权利。当区域安全被关闭,允许跨域脚本访问,我们就可以拥有读写客户端机器文件和注册表的权力。

通过这个技巧,JavaScript可以在IE外部被执行,并且脚本没有任何安全概念的约束,比如保护模式/沙盒。

0x06 结论

按照我们的理解,这个技术语序绕过一些信任内置的rundll32的行为的安全产品。

0x07 本文相关

原文  http://drops.wooyun.org/tips/12074
正文到此结束
Loading...