关于利用 rundll32 执行程序的分析
0x00 前言
最近看到了一篇有趣的文章 《Abusing Exported Functions and Exposed DCOM Interfaces for Pass-Thru Command Execution and Lateral Movement》 ,介绍了利用 rundll32.exe 加载 url.dll,通过导出函数 OpenURL 执行程序的方法。于是我对此做了研究,整理成文,解决以下问题:
- 利用 rundll32 执行程序的细节和原理
- 利用脚本批量扫描 dll,查找能够执行程序的 dll
0x01 简介
本文将要介绍以下内容:
- rundll32 加载 dll 的用法
- OpenURL 的用法
- API ShellExecute 的用法
- 三者结合实现通过 rundll32 直接执行程序
- 寻找其他可用的导出函数
- 利用 powershell 脚本批量获得 dll 的导出函数,筛选特定 dll
0x02 相关细节
1、rundll32 加载 dll 的用法
官方文档:https://support.microsoft.com/sk-sk/help/164787/info-windows-rundll-and-rundll32-interface
用法:
rundll32 <dllname>,<entrypoint> <optional arguments>
参数 <entrypoint>
代表传入 dll 的导出函数名,在 dll 中定义如下:
void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
参数 <optional arguments>
对应 dll 导出函数中的 LPSTR lpszCmdLine
也就是说通过 rundll32 能控制 dll 导出函数的 LPSTR lpszCmdLine
参数
2、OpenURL 的用法
这里直接参考文章中的提示,找到 url.dll,包含导出函数 OpenURL,使用 IDA 查看 url.dll 的导出函数 OpenURL,其中调用了 API ShellExecute,如下图
查看伪代码,如下图
注意 ShellExecute 的第二个参数为 NULL,第三个参数 lpFile 对应传入的参数 lpFile
3、API ShellExecute 的用法
函数原型与参数定义如下:
HINSTANCE ShellExecute(
_In_opt_ HWND hwnd,
_In_opt_ LPCTSTR lpOperation,
_In_ LPCTSTR lpFile,
_In_opt_ LPCTSTR lpParameters,
_In_opt_ LPCTSTR lpDirectory,
_In_ INT nShowCmd
);
第二个参数为 NULL 时,表示执行默认操作 open
第三个参数 lpFile 表示要打开的程序或文件路径
也就是说,url.dll 中导出函数 OpenURL 的参数 lpFile 决定 API ShellExecute 要打开的程序或文件路径
综上,
rundll32.exe url.dll,OpenURL calc.exe
实际上的操作为 ShellExecuteA(hwnd, NULL, "calc.exe", NULL, NULL, nShowCmd);
,即执行计算器
使用 Immunity Debugger 动态调试,跟踪到 ShellExecuteA
,验证判断,传入的参数为 calc.exe
,如下图
0x03 扩展利用
1、查找 url.dll 中其它可供利用的导出函数
IDA 加载 url.dll,选择 Search
- text...
,搜索 ShellExecuteA
导出函数 FileProtocolHandler 同样调用 API ShellExecute,如下图
测试命令如下:
rundll32.exe url.dll,FileProtocolHandler calc.exe
执行计算器
2、查看其它 dll 是否包含导出函数 OpenURL
实现思路:
枚举 %windir%/system32
下所有 dll 的导出函数,筛选出包含导出函数 OpenURL 的 dll
通过 powershell 获得 dll 的导出函数可参考 FuzzySecurity 的代码,地址如下:https://github.com/FuzzySecurity/PowerShell-Suite/blob/master/Get-Exports.ps1
在这个代码的基础上,添加枚举 dll 的功能,分别获得导出函数,进行判断
实现细节:
(1) 枚举 c:\windows\system32
下的所有 dll:
$DllSearchPath = dir c:\windows\system32\*.dll
foreach($DllName in $DllSearchPath)
{
$DllName.Name
}
(2) 对于 c:\windows\system32\auditpolmsg.dll
会报错提示输入字符串的格式不正确,所以对语句 $OffsetPtr = New-Object System.Intptr -ArgumentList $($HModule.ToInt64() + $ExportRVA)
加入 try catch 判断
代码位置:https://github.com/FuzzySecurity/PowerShell-Suite/blob/master/Get-Exports.ps1#L141
(3) 对于 c:\windows\system32\avicap.dll
会报错,尝试读取或写入受保护的内存,对语句 $EXPORT_DIRECTORY_FLAGS = [system.runtime.interopservices.marshal]::PtrToStructure($OffsetPtr, [type]$IMAGE_EXPORT_DIRECTORY)
加入 try catch 判断
(4) 目前代码只支持 32 位 dll 的判断
完整代码可参考:
..//Writeup/master/Find-OpenURL.ps1
执行如下图,获得其他两个 dll,分别为 ieframe.dll 和 shdocvw.dll
使用 IDA 加载 ieframe.dll,查看导出函数 OpenURL,伪代码如下图
由 CInternetShortcut
可以得知执行的文件为.url 文件
编写一个.url 文件,内容如下:
[InternetShortcut]
URL=c:\windows\system32\calc.exe
cmd:
rundll32.exe ieframe.dll,OpenURL C:\4\calc.url
成功执行,弹出计算器
同样,shdocvw.dll 也是相同的测试结果
3、执行的程序类型
调用 API ShellExecute 执行程序,不仅支持 exe,也同样支持脚本
例如执行 js 文件,内容如下:
WScript.Echo("1");
cmd:
rundll32.exe url.dll,OpenURL C:\4\echo.js
执行后弹框,例如 hta 文件,内容如下:
<HTML>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<HEAD>
<script language="VBScript">
Window.ReSizeTo 0, 0
Window.moveTo -2000,-2000
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "calc.exe"
self.close
</script>
<body>
demo
</body>
</HEAD>
</HTML>
cmd:
rundll32.exe url.dll,OpenURLA C:\4\calc.hta
执行后弹出计算器
例如 url 文件,内容如下:
[InternetShortcut]
URL=c:\windows\system32\calc.exe
cmd:
rundll32.exe ieframe.dll,OpenURL C:\4\calc.url
成功执行,弹出计算器
4、更多利用方法
hexacorn 在他的 文章 里分享了另一个可供使用的 dll 和导出函数:
rundll32 zipfldr.dll, RouteTheCall calc.exe
当然,还有更多可供使用的 dll,本文暂不介绍
0x04 小结
本文分析了利用 rundll32.exe 加载 url.dll 并通过导出函数 OpenURL 执行程序的细节,对其扩展,尝试利用脚本批量扫描 %windir%/system32
下的 dll,找到能够执行程序的 dll,分别验证了 bohops 和 Hexacorn 的结论。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 渗透技巧——通过 SAM 数据库获得本地用户 hash
下一篇: Covenant 利用分析
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论