進程隱藏核心:遠程線程在宿主 (如 explorer.exe) 空間執行代碼。難點二:代碼重定位 (解決直接絕對地址指令) 與隱式 DLL 鏈接 (解決 IAT 填充)。本文給出純 C/C++ 完整方案:手工解析 PE 重定位表與導入表,在注入前完成重定位與 IAT 填充,讓遠程線程代碼如同正常加載般直接調用 API,無需繁瑣顯式 GetProcAddress。
結構:按 4KB 頁分塊,每塊 IMAGE_BASE_RELOCATION (頁 RVA + 塊長度) + 多個 16 位項 (高 4 位類型,低 12 位頁內偏移)。類型 3 表示 32 位絕對地址需修正。
算法:遍歷塊→遍歷項→類型 3 時計算目標地址 = 載入基址 + 頁 RVA + 頁內偏移 → 加上差值 (實際基址 - ImageBase)。
while(pibr->VirtualAddress) {
WORD* arr = (WORD*)(pRelocTbl + sizeof(IMAGE_BASE_RELOCATION));
for(i=0; iVirtualAddress + (arr[i]&0xFFF));
*p += dwRelocOffset;
}
pRelocTbl += pibr->SizeOfBlock; pibr = (PIMAGE_BASE_RELOCATION)pRelocTbl;
}
遍歷 IMAGE_IMPORT_DESCRIPTOR 陣列:
1. LoadLibrary(Name) 載入 DLL
2. 遍歷 OriginalFirstThunk 指向的 IMAGE_THUNK_DATA:
- 序號導入:GetProcAddress(hDll, 序號)
- 名稱導入:讀取 IMAGE_IMPORT_BY_NAME 取名 → GetProcAddress
3. 將返回地址寫入對應 FirstThunk 項 (Function 欄位)
關鍵洞見:kernel32.dll 幾乎在所有進程同一地址載入,故注入器進程的 LoadLibrary/GetProcAddress 地址在目標進程亦有效,直接傳入線程參數使用。
MapRsrcToImage 映射為內存映像 → 計算重定位差值 → RelocImage → 重定位表空間存線程參數 (fnLoadLibrary, fnGetProcAddress, pImageBase) → GetEntryPoint 解析導出表找 ThreadEntry RVA → VirtualAllocEx/WriteProcessMemory/CreateRemoteThread 注入ThreadEntry(PTHREADPARAM) → SEH 保護 → LoadImportFx 填充 IAT → ThreadMain(HINSTANCE) 核心邏輯 (彈訊息框演示)將遠程線程開發簡化為「寫普通 DLL 導出 ThreadMain」,重定位與 IAT 由 Loader 自動完成。代碼結構清晰,可作進階注入技術模板。作者強調僅供防禦研究,勿用於惡意用途。