DLL劫持自动化检测 OS

admin 3月前 67

DLL劫持自动化检测

简介

本文将介绍动态链接库(DLL)搜索顺序劫持的概念,以及如何实现在Windows上的持久化攻击。MITRE ATT&CK对DLL搜索顺序劫持的描述详见DLL Search Order Hijacking (T1038)

 

DLL劫持对攻击者很有用,原因有很多,但本文会重点介绍与开机自启程序结合使用时的持久化攻击。例如,由于Slack和Microsoft Teams开机自启(默认情况下),因此,只要用户登录,这些应用程序中的DLL劫持将允许攻击者能够持久访问攻击目标。

 

在介绍DLL、DLL搜索顺序和DLL劫持的概念后,我会阐述DLL劫持自动化检测的过程https://github.com/slyd0g/DLLHijackTest。本文将涉及Slack、Microsoft Teams以及Visual Studio Code相关的DLL劫持检测。

 

最后,我注意到很多DLL劫持会同时作用于多个程序。我调查了底层原因,发现调用某些位于C:\Windows\System32\下的Windows API的程序容易成为DLL劫持的目标。

 

这里我要感谢我的同事,Josiah Massari (@Airzero24)。是他最早发现的这些DLL劫持案例并解释其方法和原理,促成了我将检测做成自动化。

DLL是什么

DLL是一个包含可被多个程序同时使用的代码和数据的库。(定义源于Microsoft

 

Windows程序可以调用LoadLibrary*系列函数来使用DLL中的功能。程序可以引用自定义的DLL,也可以引用System32中Windows自带的DLL。开发者可以加载System32中的DLL,使其程序使用Windows的现成功能,而不必重新造轮子。

 

例如,开发者需要发起HTTP请求时,可以使用WinHTTP库(winhttp.dll),而无需用原始套接字开发并实现HTTP功能。

DLL搜索顺序和劫持

由于DLL也是存储在磁盘上的文件,那么程序是如何知道从哪里加载DLL的呢?Microsoft在详细记录了DLL搜索顺序。

 

自Windows XP SP2起,安全DLL搜索模式默认开启(HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode)。当安全模式启用时,搜索顺序如下:

  1. 程序安装目录。
  2. 系统目录。使用GetSystemDirectory获取该目录路径。
  3. 16位系统目录。没有函数可以获取该目录路径,但该目录会被搜索。
  4. Windows目录。使用GetWindowsDirectory获取该目录路径。
  5. 当前目录。
  6. PATH环境变量中的目录。注意,这不包括App Paths注册表键指定的程序路径。App Paths键不会参与DLL搜索路径的计算。

系统可包含动态链接库(DLL)的多个版本。程序可通过指定完整路径或使用比如manifest的其他机制来控制加载特定的DLL。(定义源于Microsoft

 

如果程序没有加载指定的DLL,Windows会默认执行上述的DLL搜索流程。DLL搜索的第一顺位,即程序的安装目录,是攻击者最感兴趣的。

 

如果开发者想要从C:\Windows\System32\加载 DLL,但并没有写清楚让程序这么做,那么程序安装目录下的恶意DLL就会优先于System32下的合法DLL被加载。这里恶意DLL指的是DLL劫持,攻击者用来在受信/签名程序中加载恶意代码。

DLL劫持持久化利用

当目标程序/服务启动并且恶意DLL被植入到了关键位置,DLL劫持即可用于持久化攻击。我的同事@Airzero24,发现了Microsoft OneDrive、 Microsoft Teams、以及Slack中针对userenv.dll的劫持。

 

这类程序被盯上的原因是,他们默认都会随着Windows开机启动。任务管理器中可以看到:

 

开机启动的WIndows程序

 

为了验证DLL劫持,我写了一段运行Cobalt Strike Beacon的DLL shellcode,命名为userenv.dll,并且复制到目标程序的安装目录。运行程序,我看到肉鸡上线了。

 

通过DLL劫持运行Cobalt Strike Beacon

 

查看Process Explorer,可以确认恶意DLL确实被目标程序加载了。

 

Process Explorer中显示恶意DLL被加载

DLL劫持自动化检测

确认先前已知的DLL劫持之后,我想看看是否可以找到其他的DLL劫持。

 

测试代码在此:https://github.com/slyd0g/DLLHijackTest

案例研究:Slack

首先,运行Process Monitor(ProcMon),过滤规则如下:

  • Process Name为slack.exe
  • Result包含NOT FOUND
  • Path以.dll结尾

ProcMon过滤规则

 

接下来,运行Slack,留意Slack搜索但无法找到的DLL。

 

用ProcMon找到的疑似DLL劫持

 

从ProcMon中导出数据,方便用PowerShell处理。

 

用当前加载shellcode的DLL,我无法轻易找出被Slack加载的DLL的名字。我写了一个新的使用了GetModuleHandleExGetModuleFileNameDLL的DLL,输出加载DLL的名字到文本文件

 

接下来就是解析CSV得到DLL路径列表,遍历路径列表,把我的测试DLL复制到特定路径,运行目标进程,退出目标进程,删除测试DLL。如果测试DLL被成功加载,其文件名会写入结果文件。

 

上述步骤完成后,会得到一个有效DLL劫持的列表。

 

在我的DLLHijackTest项目中的PowerShell脚本可以处理所有步骤。脚本的输入参数有:ProcMon生成的CSV文件的路径,恶意DLL的路径,目标程序的路径,以及其他你想要传递给目标程序的参数。

 

Get-PotentialDLLHijack

 

Get-PotentialDLLHijack.ps1

 

几分钟后,打开“恶意”DLL中指定的文本文件,发现以下针对Slack的DLL劫持:

1
2
3
4
5
6
7
PS C:Users\John\Desktop> Get-PotentialDLLHijack -CSVPath .\Logfile.CSV -MaliciousDLLPath .\DLLHijackTest.dll -ProcessPath "C:\Users\John\AppData\Local\slack\slack.exe"
C:\Users\John\AppData\Local\slack\app-4.6.0\WINSTA.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\LINKINFO.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\ntshrui.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\srvcli.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\cscapi.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\KBDUS.DLL

案例研究:Microsoft Teams

重复上述过程:

  1. 用ProcMon找出可能的DLL劫持,导出至CSV。
  2. 找出目标进程的路径。
  3. 找出传入进程的参数。
  4. 传入参数,运行Get-PotentialDLLHijack.ps1。

发现以下针对Microsoft Teams的DLL劫持:

1
2
3
4
5
6
7
8
PS C:Users\John\Desktop> Get-PotentialDLLHijack -CSVPath .\Logfile.CSV -MaliciousDLLPath .\DLLHijackTest.dll -ProcessPath "C:\Users\John\AppData\Local\Microsoft\Teams\Update.exe" -ProcessArguments '--processStart "Teams.exe"'
C:\Users\John\AppData\Local\Microsoft\Teams\current\WINSTA.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\LINKINFO.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\ntshrui.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\srvcli.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\cscapi.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\WindowsCodecs.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\TextInputFramework.dll

注意:我这里修改了下PowerShell脚本,终止的进程是Teams.exe,启动的进程是Update.exe。

案例研究:Visual Studio Code

重复以上关键步骤,发现针对Visual Studio Code的劫持,如下:

1
2
3
4
5
6
PS C:Users\John\Desktop> Get-PotentialDLLHijack -CSVPath .\Logfile.CSV -MaliciousDLLPath .\DLLHijackTest.dll -ProcessPath "C:\Users\John\AppData\Local\Programs\Microsoft VS Code\Code.exe"
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\WINSTA.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\LINKINFO.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\ntshrui.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\srvcli.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\cscapi.dll

共有DLL劫持

我发现Slack、Microsoft Teams和Visual Studio Code都会出现以下DLL劫持:

  • WINSTA.dll
  • LINKINFO.dll
  • ntshrui.dll
  • srvcli.dll
  • cscapi.dll

我觉得很有趣,尝试挖掘造成此现象的底层原因。

方法论:理解共有DLL劫持

我观察了下Slack加载WINSTA.dll、LINKINFO.dll、ntshrui.dll、srvcli.dll和cscapi.dll的栈轨迹。

延迟加载DLL

我注意到当WINSTA.dll、LINKINFO.dll、ntshrui.dll、srvcli.dll和cscapi.dll被加载时栈轨迹存在共性。

 

Code.exe加载WINSTA.dll时的栈轨迹

 

Teams.exe加载LINKINFO.dll时的栈轨迹

 

Slack加载ntshrui.dll时的栈轨迹

 

栈轨迹都调用了_tailMerge_<dllname>_dll和delayLoadHelper2,之后还调用了LdrResolveDelayLoadedAPI。三个程序都出现了这种情况。

 

我认为这种情况与延迟加载DLL有关。当WINSTA.dll被加载时,从栈轨迹可以看到,wtsapi32.dll导致了延迟加载。

 

Ghidra中打开wtsapi32.dll,设置Search -> For Strings -> Filter: WINSTA.dll。双击查找的结果会看到其内存地址。

 

wtsapi32.dll中“WINSTA.dll”字符串

 

右键点击内存地址,可以找到对该地址的引用。

 

WINSTA.dll引用

 

我们看到WINSTA.dll被传递至名为ImgDelayDescr的结构体。查看该结构体的说明文档,可以确定其与延迟加载DLL有关。

1
2
3
4
5
6
7
8
9
10
11
typedef struct ImgDelayDescr {
    DWORD        grAttrs;        // attributes
    RVA          rvaDLLName;     // RVA to dll name
    RVA          rvaHmod;        // RVA of module handle
    RVA          rvaIAT;         // RVA of the IAT
    RVA          rvaINT;         // RVA of the INT
    RVA          rvaBoundIAT;    // RVA of the optional bound IAT
    RVA          rvaUnloadIAT;   // RVA of optional copy of original IAT
    DWORD        dwTimeStamp;    // 0 if not bound,
                                 // O.W. date/time stamp of DLL bound to (Old BIND)
    } ImgDelayDescr, * PImgDelayDescr;

该结构体可被传递至__delayLoadHelper2,后者会通过LoadLibrary/GetProcAddress加载特定DLL,并且会修正延迟加载导入地址表(IAT)中导入函数的地址。

1
2
3
4
FARPROC WINAPI __delayLoadHelper2(
    PCImgDelayDescr pidd,  //Const pointer to a ImgDelayDescr struct
    FARPROC * ppfnIATEntry //A pointer to the slot in delay load IAT
);

查找其他对ImgDelayDescr结构体的引用,发现__delayLoadHelper2调用,后者之后调用了ResolveDelayLoadedAPI。为方便理解,我重命名了函数名、类型和变量。

 

Ghidra中查看__delayLoadHelper2和ResolveDelayLoadedAPI

 

很好!这与我们之前在Slack加载WINSTA.dll时在ProcMon中看到的栈轨迹一致。

 

ProcMon中查看__delayLoadHelper2和ResolveDelayLoadedAPI

 

WINSTA.dll、LINKINFO.dll、ntshrui.dll和srvcli.dll的行为是一致的,每个延迟加载的DLL间主要的不同点是“父级”DLL。在三个程序中:

  • wtsapi32.dll延迟加载了WINSTA.dll
  • shell32.dll延迟加载了shell32.dll
  • LINKINFO.dll延迟加载了ntshrui.dll
  • ntshrui.dll延迟加载了srvcli.dll

看到有意思的点了吗?shell32.dll加载了LINKINFO.dll,LINKINFO.dll加载了ntshrui.dll,ntshrui.dll最后加载了srvcli.dll。 最后我们看到共有的针对cscapi.dll的劫持。

NetShareGetInfo和NetShareEnum中的DLL劫持

观察Slack加载cscapi.dll的栈轨迹,看到调用了LoadLibraryExW,后者似乎来源于srvcli.dll。

 

加载cscapi.dll时的栈轨迹

 

Ghidra中打开srvcli.dll,设置Search -> For Strings -> Filter: cscapi.dll。双击查找的结果并跟踪引用,找到LoadLibrary调用。

 

cscapi.dll中srvcli.dll调用LoadLibrary

 

重命名包含LoadLibrary的函数,跟踪引用可以看到两个函数地址:

NetShareEnum调用cscapi.dll

 

NetShareGetInfo调用cscapi.dll

 

我使用调用NetShareEnum和NetShareGetInfo的PoC程序验证了该过程:

 

NetShareEnum.exe调用cscapi.dll

 

NetShareGetInfo.exe调用cscapi.dll

结果

Slack中,存在以下DLL劫持:

1
2
3
4
5
6
C:\Users\John\AppData\Local\slack\app-4.6.0\WINSTA.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\LINKINFO.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\ntshrui.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\srvcli.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\cscapi.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\KBDUS.DLL

Microsoft Teams中,存在以下DLL劫持:

1
2
3
4
5
6
7
C:\Users\John\AppData\Local\Microsoft\Teams\current\WINSTA.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\LINKINFO.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\ntshrui.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\srvcli.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\cscapi.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\WindowsCodecs.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\TextInputFramework.dll

Visual Studio Code中,存在以下DLL劫持:

1
2
3
4
5
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\WINSTA.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\LINKINFO.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\ntshrui.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\srvcli.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\cscapi.dll

另外,我发现使用NetShareEnum和NetShareGetInfo的程序会引入cscapi.dll劫持,这是由硬编码的LoadLibrary调用导致的,并且我用Ghidra和PoC确认了该结论。

结论

简要回顾下,DLL劫持是攻击者在签名/受信的程序中执行代码的一种方法。我开发了自动检测DLL劫持的工具。利用此工具,我发现了Slack、Microsoft Teams和Visual Studio Code中的DLL劫持。

 

我注意到这三个程序存在共有DLL劫持的情况,并调查了根本原因。我重点介绍了研究的方法,并了解了延迟加载DLL,以及定位到了两个API调用,这两个API会引入DLL劫持到调用它们的程序中:

  • NetShareEnum加载cscapi.dll
  • NetShareGetInfo加载cscapi.dll

感谢花时间阅读本文,希望你能学到一些关于Windows API、Ghidra、ProcMon、DLL和DLL劫持的知识!

参考资料

感谢我的同事Daniel Heinsen(@hotnops), Lee Christensen(@tifkin_), and Matt Hand(@matterpreter)给我提供的帮助。

  1. https://github.com/slyd0g/DLLHijackTest
  2. https://attack.mitre.org/techniques/T1038/
  3. https://support.microsoft.com/en-us/help/815065/what-is-a-dll
  4. https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order
  5. https://msrc-blog.microsoft.com/2018/04/04/triaging-a-dll-planting-vulnerability/
  6. https://stackoverflow.com/questions/3573475/how-does-the-import-library-work-details
  7. https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/build/reference/understanding-the-helper-function.md
  8. https://docs.microsoft.com/en-us/cpp/build/reference/linker-support-for-delay-loaded-dlls
  9. https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/february/inside-windows-win32-portable-executable-file-format-in-detail

原文作者:Justin Bui

 

原文链接:https://posts.specterops.io/automating-dll-hijack-discovery-81c4295904b0



少客联盟- 版权声明 1、本主题所有言论和图片纯属会员个人意见,与少客联盟立场无关。
2、本站所有主题由该帖子作者发表,该帖子作者admin少客联盟享有帖子相关版权。
3、少客联盟管理员和版主有权不事先通知发贴者而删除本文。
4、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者admin少客联盟的同意。
5、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任。
6、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责。
7、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意。
8、官方反馈邮箱:chinasuc@chinasuc.cn


上一篇:kali信息收集工具enumIAX详解
下一篇:kali 信息收集工具exploitdb详解
Whatever is worth doing is worth doing well. juvenile hacker league
最新回复 (0)
    • 少客联盟
      2
        登录 注册 QQ登录(停用)
返回