0x00 前言
最近,来自 SensePost 的 Chris Le Roy 开源了一款工具:Rattler,可用来自动识别 DLL 是否存在预加载漏洞 (也可以理解为 DLL 劫持漏洞,文中该名词均采用 DLL 劫持漏洞)。虽然 DLL 劫持漏洞已不再是新技术,可追溯到 2010 年,但是我对自动化很是感兴趣,于是对此做了进一步研究。
本文将理清 DLL 劫持漏洞原理,实例分析,测试自动化工具 Rattler,分享心得,并测试一个存在该漏洞的软件——Explorer Suite 安装包
注:
Explorer Suite 安装包内包含 CFF Explorer,免费,常用来编辑 PE 文件格式,最后更新于 2012 年 11 月 18 日,是比较小众的一款工具。对于分析 PE 文件格式,建议使用作者另一款更专业的工具:Cerbero Profiler
Chris Le Roy 介绍 Rattler 的博客地址:
https://sensepost.com/blog/20…
Chris Le Roy 在 BSides Cape Town 上也介绍了 Rattler,简介如下:
http://www.bsidescapetown.co….
0x01 简介 DLL 劫持漏洞根源
程序在调用 DLL 时未指明 DLL 的完整路径
SafeDllSearchMode
从 WindowsXPSP2 开始,SafeDllSearchMode 默认开启,SafeDllSearchMode 的存在是为了阻止在 XP 时代存在的 DLL 劫持漏洞
注:
强制关闭 SafeDllSearchMode 的方法:创建注册表项 HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerSafeDllSearchMode 值设为 0
程序在调用 DLL 时,如果未指明 DLL 的完整路径,那么系统会按照一套固定的搜索顺序寻找 DLL
如果 SafeDllSearchMode 开启,程序会依次从以下位置查找 DLL 文件:
The directory from which the application loaded
The system directory
The 16-bit system directory
The Windows directory
The current directory
The directories that are listed in the PATH environment variable
如果关闭,则从以下位置查找 DLL 文件:
The directory from which the application loaded
The current directory
The system directory
The 16-bit system directory
The Windows directory
The directories that are listed in the PATH environment variable
详细内容见:
https://msdn.microsoft.com/en…
KnownDLLs
注册表位置:
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerKnownDLLs
KnownDLLs 注册表项下包含一系列常见的系统 dll,如 usp10.dll、lpk.dll、shell32.dll、user32.dll
注:
如果创建注册表项 HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerExcludeFromKnownDlls 并指定具体 dll 名称,可以使 KnownDLLs 列表中同名的 dll 保护失效修改后需要重启才能生效
SafeDllSearchMode+KnownDLLs
二者结合可用来防范对系统 dll 的劫持
注:
系统 dll 是指排除 ExcludeFromKnownDlls 项后,KnownDLLs 注册表项下包含的 dll 列表
如果调用的 dll“不常见”,也就是并未出现在 KnownDLLs 的列表中,那么无论 SafeDllSearchMode 是否开启,dll 搜索的第一顺序均为程序的当前目录,这里就存在一个 DLL 劫持漏洞:
在程序同级目录下预先放置一个同名的 dll,在进程启动的过程中会优先加载,实现劫持
注:
这里提到的 DLL 劫持漏洞微软尚未给出直接的修复方法,个人认为原因有以下几点:1. 这是开发者的失误,换用绝对路径就能避免这个问题 2. 利用的前提是攻击者已经能够在同级目录放置文件,这代表系统已经被攻破 3. 如果直接修复,或许会影响老版本程序,兼容性不好
注:
该文章对理清上述顺序起到很大帮助:http://www.freebuf.com/articl…
0x02 利用实例
接下来编写一个存在 DLL 劫持漏洞的实例,演示如何利用
测试 dll:
使用 dll 模板,具体代码略,加载成功后弹出计算器
测试程序的 c ++ 代码如下:
include “stdafx.h”#include <windows.h> int main(){HMODULE hDllLib = LoadLibrary(_T(“Kernel32.dll”));if (hDllLib){FARPROC fpFun = GetProcAddress(hDllLib, “GetVersion”);DWORD dwVersion = (*fpFun)();DWORD dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));DWORD dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));printf(“version:%d,%d n”, dwWindowsMajorVersion, dwWindowsMinorVersion);FreeLibrary(hDllLib);}HMODULE hDllLib2 = LoadLibrary(_T(“CRYPTSP.dll”));FreeLibrary(hDllLib2);return 0;}
程序通过 LoadLibrary 分别调用 Kernel32.dll 和 CRYPTSP.dll
实际测试:
将测试 dll 重命名为 Kernel32.dll,并放于程序同级目录下,运行如图
由于 Kernel32.dll 出现在 KnownDLLs 的列表中,所以在程序同级目录下的 Kernel32.dll 并不会被加载
然后将测试 dll 重命名为 CRYPTSP.dll,并放于程序同级目录下,运行如图
由于 CRYPTSP.dll 并未在 KnownDLLs 的列表中,所以在程序同级目录下的 CRYPTSP.dll 被加载,成功弹出计算器
0x03 实际利用
本节通过实例介绍如何使用 Process Monitor 查找程序中存在的 DLL 劫持漏洞,测试实例为 Chris Le Roy 在介绍 Rattler 的博客中提到过的 NDP461-KB3102438-Web.exe
博客地址如下:
https://sensepost.com/blog/20…
NDP461-KB3102438-Web.exe 的下载地址:
http://www.microsoft.com/zh-c…
使用 Process Monitor 做如下设置:
Include the following filters:Operation is CreateFileOperation is LoadImagePath contains .cplPath contains .dllPath contains .drvPath contains .exePath contains .ocxPath contains .scrPath contains .sysExclude the following filters:Process Name is procmon.exeProcess Name is Procmon64.exeProcess Name is SystemOperation begins with IRP_MJ_Operation begins with FASTIO_Result is SUCCESSPath ends with pagefile.sys
参考地址:
https://msdn.microsoft.com/li…
注:
设置 Exclude Result is SUCCESS 后会只显示 NAME NOT FOUND 项,也就是只查看未成功加载的 dll 项,即 KnownDLLs 的列表中不包含的 dll 名称,可用于查找存在漏洞的 dll 路径
如图
启动 NDP461-KB3102438-Web.exe 后,查看 Process Monitor,如图
可以看到 NDP461-KB3102438-Web.exe 在启动的过程中会加载 CRYPTSP.dll,同时显示 NAME NOT FOUND,表示无法找到该文件,加载失败
现在将测试 dll 重命名为 CRYPTSP.dll,并放于 NDP461-KB3102438-Web.exe 的同级目录下
打开 Process Monitor,设置 Filter,去掉 Exclude Result is SUCCESS 项,再次启动 NDP461-KB3102438-Web.exe 并记录
如下图,显示 C:testCRYPTSP.dll 已被成功加载,Result 为 Success,DLL 劫持成功
如下图,程序在执行过程中成功弹出计算器
0x04 程序自动化实现
通过 Process Monitor 查看 DLL 劫持漏洞是比较直接的方法,但是对于较大的程序,加载的 DLL 数目很多,手动查找很不现实,费事费力,所以如果能够通过程序实现上述过程,自动查找并利用,就可以大大提高效率,这就是 Rattler 所解决的问题
项目地址:
https://github.com/sensepost/…
思路:
枚举进程调用的 dll 列表,解析出 dll 的名称
将测试 dll 分别重命名为列表中的 dll 名称
再次启动程序,检测是否成功创建进程 calc.exe, 如果成功,代表存在漏洞,否则不存在
实际测试:
使用 Visual Studio 编译 Rattler
将 payload.dll 放于同级目录下
payload.dll 下载地址:
https://github.com/sensepost/…
管理员权限的 cmd 下运行命令:
Rattler.exe NDP461-KB3102438-Web.exe 1
注:
因为 NDP461-KB3102438-Web.exe 需要管理员权限运行,所以 cmd 也需要管理员权限
如下图,自动找到存在预加载漏洞的 dll 列表
注:
在反复启动进程的过程中,calc.exe 没有正常被关闭,所以得出的结果要多于实际结果
补充:
下载的 NDP461-KB3102438-Web.exe 通常位于 Downloads 文件夹下,所以只要在该目录预先放置 CRYPTSP.dll,那么在用户下载运行 NDP461-KB3102438-Web.exe 的过程中,就能够实现加载 CRYPTSP.dll
同时,安装 NDP461-KB3102438-Web.exe 需要管理员权限,那么此时 CRYPTSP.dll 也获得了管理员权限
0x05 验证测试
掌握该方法后,测试其他程序,例如 CFF Explorer 的安装包 Explorer Suite
下载地址:http://www.ntcore.com/exsuite…
同样借助 Process Monitor 查看 CFF Explorer 的安装包 ExplorerSuite.exe 在启动过程中的操作
如图,找到 ExplorerSuite.exe 在启动过程中加载的 dll 列表
经实际测试,将 payload.dll 重命名为 apphelp.dll 或者 dwmapi.dll 均能够触发 payload,弹出计算器
自动化程序测试:
如图,得出存在劫持漏洞的 dll 列表
注:
在反复启动进程的过程中,calc.exe 正常被关闭,所以得出的结果准确
0x06 防御 1、开发者需要注意的问题:
调用第三方 DLL 时,使用 LoadLibrary API 加载 DLL 时使用绝对路径,类似的情况还包括其他 API 如 LoadLibraryEx, CreateProcess, ShellExecute 等,将所有需要使用到的 DLL 放在应用程序所在的目录,不放到系统目录或者其他目录
调用系统 DLL 时,使用绝对路径
程序启动时调用 API SetDllDirectory(L”“) 将当前目录从 DLL 加载顺序中移除
补充:
从 Windows 7 的 KB2533623 补丁开始,微软更新了三个解决 DLL 劫持问题的新 API:SetDefaultDllDirectories,AddDllDirectory,RemoveDllDirectory 这几个 API 配合使用,可以有效的规避 DLL 劫持问题
但是这些 API 只能在打了 KB2533623 补丁的 Windows7 和 Server2008 上使用
详情见:
https://support.microsoft.com…
2、用户需要注意的问题:
留意浏览器下载目录下是否有可疑 dll,防止其劫持下载的安装程序
对于“不可信”的程序,建议使用 Process Monitor 或者 Rattler 检查是否存在 DLL 劫持漏洞
0x07 小结
我在对 DLL 劫持漏洞原理的研究过程中,走了一小段弯路,某些资料提到
如果进程尝试加载的 DLL 并不存在,那么进程仍然会尝试去当前目录加载这个 DLL,这是 SafeDllSearchMode 所无法防范的。
这让我产生了如下疑问:
这里提到的“并不存在的 DLL”究竟是指哪些 dll? 系统不存在的 dll? 但 CRYPTSP.dll 却是系统默认的包含的 dll
“SafeDllSearchMode 所无法防范的”DLL 劫持到底是指什么? 难道 DLL 劫持还有多种? 有几种?
好在最终解决了这些问题,希望本文也能帮助有同样疑惑的人
利用 DLL 劫持漏洞自动化识别工具 Rattler 对常用工具进行测试,能很快找出存在的漏洞位置,高效,方便,值得测试使用
作者:CanMengBlog
来源:CSDN
原文:https://blog.csdn.net/weixin_…
版权声明:本文为博主原创文章,转载请附上博文链接!