什么是DLL
DLL(Dynamic Link Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。一个应用程序可使用多个DLL文件,一个DLL文件也可能被不同的应用程序使用,这样的DLL文件被称为共享DLL文件。
DLL 是一个包含可由多个程序同时使用的代码和数据的库。例如,在 Windows 操作系统中,Comdlg32 DLL 执行与对话框有关的常见函数。因此,每个程序都可以使用该 DLL 中包含的功能来实现“打开”对话框。这有助于促进代码重用和内存的有效使用。
DLL加载顺序
一、Windows XP SP2之前 Windows查找DLL的目录以及对应的顺序:
- 进程对应的应用程序所在目录;
- 当前目录(Current Directory);
- 系统目录(通过 GetSystemDirectory 获取);
- 16位系统目录;
- Windows目录(通过 GetWindowsDirectory 获取);
- PATH环境变量中的各个目录;
例如:对于文件系统,如doc文档打开会被应用程序office打开,而office运行的时候会加载系统的一个dll文件,如果我们将用恶意的dll来替换系统的dll文件,就是将DLL和doc文档放在一起,运行的时候就会在当前目录中找到DLL,从而优先系统目录下的DLL而被执行。
二、在Windows xp sp2之后
Windows查找DLL的目录以及对应的顺序(SafeDllSearchMode 默认会被开启):
默认注册表为:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode,其键值为1
- 进程对应的应用程序所在目录(可理解为程序安装目录比如C:ProgramFilesuTorrent);
- 系统目录(即%windir%system32);
- 16位系统目录(即%windir%system);
- Windows目录(即%windir%);
- 当前目录(运行的某个文件所在目录,比如C:DocumentsandSettingsAdministratorDesktoptest);
- PATH环境变量中的各个目录;
三、Windows7以上
系统没有了SafeDllSearchMode 而采用KnownDLLs,那么凡是此项下的DLL文件就会被禁止从EXE自身所在的目录下调用,而只能从系统目录即SYSTEM32目录下调用,其注册表位置:
计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
那么最终Windows2003以上以及win7以上操作系统通过“DLL路径搜索目录顺序”和“KnownDLLs注册表项”的机制来确定应用程序所要调用的DLL的路径,之后,应用程序就将DLL载入了自己的内存空间,执行相应的函数功能。
进程对应的应用程序所在目录(可理解为程序安装目录比如C:ProgramFilesuTorrent);
系统目录(即%windir%system32);
16位系统目录(即%windir%system);
Windows目录(即%windir%);
当前目录(运行的某个文件所在目录,比如C:DocumentsandSettingsAdministratorDesktoptest);
PATH环境变量中的各个目录
DLL正常调用demo
DLLdemo
vs2019新建动态链接库模板项目
项目结构如下
在dllmain.cpp中添加如下代码
1 | // dllmain.cpp : 定义 DLL 应用程序的入口点。 |
该dll的作用是在进程调用该dll时执行计算器
添加头文件test.h
1 |
|
__declspec(dllexport)用于Windows中的动态库中,声明导出函数msg供其它程序调用
添加cpp文件实现msg方法
1 |
|
调用demo
新建一个控制台项目
1 |
|
将consoleapplication 与dll文件放在同一目录,运行exe
可以看到,根据代码逻辑调用了dll文件,弹出了计算器并且成功调用了msg方法
什么是DLL劫持
由上述的DLL加载顺序得知,如果某个程序需要的dll文件在程序根目录不存在,会继续向后寻找dll文件,那么我们手动编写一个dll文件至程序根目录并且将dll名称改为程序需要的那个缺少的dll文件,根据加载顺序会优先加载我们编写的dll文件,实现dll劫持的效果。dll劫持的目的是替换/劫持/新增 恶意dll文件实现代码执行。
由此可以引出几种dll劫持的形式:
- 直接将恶意dll暴力替换掉正常dll,软件正常功能会受影响
- 将恶意dll作为中间人,转发调用正常dll的导出函数,同时加入额外的恶意操作
- 利用加载顺序的机制,让恶意dll先于正常dll加载
- 利用软件本身缺失的dll加载恶意dll
- 更改环境变量或是.exe.manifest/.exe.local文件实现dll重定向
- 如果利用低权限劫持的dll文件,会被高权限程序加载运行,就是一个权限提升漏洞
DLL劫持实例
劫持Notepad++不存在的DLL
一般可以使用processmonitor、process explorer查找可能存在dll劫持的进程
使用process monitor查找与notepad++相关的进程,注:notepad++不要用最新版,最新版修复了劫持漏洞,这里用的是6.6.6版本。
这里打开过后设置几个过滤条件,分别是进程名、路径以及结果
然后这里找一个需要用到loadlibrary
这个api的dll,这里找有这个api的原因是因为如果该dll的调用栈中存在有 **LoadLibrary(Ex)**,说明这个DLL是被进程所动态加载的。在这种利用场景下,伪造的DLL文件不需要存在任何导出函数即可被成功加载,即使加载后进程内部出错,也是在DLL被成功加载之后的事情。
可以看到,Msimg32.dll文件是程序运行需要但是没找到的,所以我们可以写一个Msimg32.dll文件放到程序根目录实现动态恶意dll加载。
将刚才的dll hijack demo生成的dll文件放到notepad++的根目录并改名为Msimg32.dll,当再次打开notepad++.exe时即可完成劫持
劫持Notepad++中存在的DLL
将procmon中NOT FOUND 的条件改为SUCCESS
发现存在loadLibraryEx,尝试劫持该dll
使用工具CFF explorer查看该DLL的输出函数,输出函数是可以被外部访问的,就像刚才写的demo一样
编写dll文件内容如下
1 | // dllmain.cpp : 定义 DLL 应用程序的入口点。 |
生成DLL改名为SciLexer.dll并放到notepad++根目录并尝试运行
发现报错了,感觉是dll中有些内容是必须实现的,但是我们不知道其内容是什么,所以考虑其他方法劫持该dll
下面使用dll转发的方式劫持该dll
dll文件代码如下
1 |
|
将原始dll文件SciLexer.dll改名为SciLexer_re.dll,将该文件改名为SciLexer.dll并放到notepad++.exe的目录下,该dll起了转发的作用,调用顺序为exe->SciLexer.dll->SciLexer_re.dll
需要注意的是,本次测试环境vs2019配置release x86生成的dll才能正常运行,猜测notepad++为32位。
运行notepad.exe即可弹出计算器,但是无法正常运行notepad.exe
直接转发劫持QQ
这里还是使用导入表进行劫持,首先用cff(下载地址:[https://ntcore.com/files/CFF_Explorer.zip]) 打开QQ.exe的导入表,找一个不在HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session) Manager\KnownDLLs
路径里面的dll进行劫持,因为在这个路径里面的dll是优先加载的,加载之后已经进入内核空间,想要劫持难度很大。这里我选择的是libuv.dll
进行劫持
使用aheadlib生成cpp文件并放到vscode的dll项目中,代码如下,记住libuvOrg这个名字,后面要用。
1 | // 头文件 |
采用release x86编译生成dll文件,将生成的dll文件命名位libuv.dll并放到原dll目录下,将原dll文件命名为libuvOrg.dll,双击qq.exe即可弹出计算器
即时调用劫持QQ
todo,一直报错,麻了。
劫持不存在的dll–音速启动
音速启动V5安装程序,打开procmon过滤进程名和NAME NOT FOUND:
发现音速启动在当前安装目录尝试加载DLL,打开一些NOT FOUND 的dll调用栈看一下
尝试劫持,将上文生成的dll hijack demo改名为SHFOLDER.dll并放至与安装文件同目录
再次运行安装文件,即可弹出计算器
自动化DLL劫持检测工具–Rattler
github地址:https://github.com/sensepost/rattler/releases/tag/v1.0
使用时需要注意,要根据程序是64位还是32位选择Rattler版本,否则识别失败。
使用Rattler建议的DLL文件尝试劫持
将生成的CRYPTBASE.DLL放到应用根目录,可以看到成功弹出了计算器
红队武器化
todo,https://www.anquanke.com/post/id/232891
白加黑免杀实现
权限维持实现
DLL劫持防御及实例
参考链接
https://www.anquanke.com/post/id/232891
https://skewwg.github.io/2020/11/26/diao-yu-yu-she-gong-xi-lie-zhi-dll-jie-chi/