0x00 前言php
最近,来自SensePost的Chris Le Roy开源了一款工具:Rattler,可用来自动识别DLL是否存在预加载漏洞(也能够理解为DLL劫持漏洞,文中该名词均采用DLL劫持漏洞)。虽然DLL劫持漏洞已再也不是新技术,可追溯到2010年,可是我对自动化非常感兴趣,因而对此作了进一步研究。html
本文将理清DLL劫持漏洞原理,实例分析,测试自动化工具Rattler,分享心得,并测试一个存在该漏洞的软件——Explorer Suite安装包c++
注:git
Explorer Suite安装包内包含CFF Explorer,免费,经常使用来编辑PE文件格式,最后更新于2012年11月18日,是比较小众的一款工具。对于分析PE文件格式,建议使用做者另外一款更专业的工具:Cerbero Profilergithub
Chris Le Roy介绍Rattler的博客地址:shell
https://sensepost.com/blog/20...windows
Chris Le Roy在BSides Cape Town上也介绍了Rattler,简介以下:api
http://www.bsidescapetown.co....浏览器
0x01 简介DLL劫持漏洞根源app
程序在调用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++代码以下:
程序经过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 防护一、开发者须要注意的问题:
调用第三方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...
二、用户须要注意的问题:
留意浏览器下载目录下是否有可疑dll,防止其劫持下载的安装程序
对于“不可信”的程序,建议使用Process Monitor或者Rattler检查是否存在DLL劫持漏洞
0x07 小结
我在对DLL劫持漏洞原理的研究过程当中,走了一小段弯路,某些资料提到
若是进程尝试加载的DLL并不存在,那么进程仍然会尝试去当前目录加载这个DLL,这是SafeDllSearchMode所没法防范的。
这让我产生了以下疑问:
这里提到的“并不存在的DLL”到底是指哪些dll?系统不存在的dll?但CRYPTSP.dll倒是系统默认的包含的dll
“SafeDllSearchMode所没法防范的”DLL劫持究竟是指什么?难道DLL劫持还有多种?有几种?
好在最终解决了这些问题,但愿本文也能帮助有一样疑惑的人
做者:CanMengBlog
来源:CSDN
原文:https://blog.csdn.net/weixin_... 版权声明:本文为博主原创文章,转载请附上博文连接!