inline Hook簡單介紹
阿新 • • 發佈:2018-12-11
What is Inline Hook ?
就是一個函式鉤子而已,把程式原本要呼叫的函式改成另一個函式,就是對原函式的一個掛鉤(hook) 。
How did this work ?
讓我們看看呼叫一個函式控制流的跳轉圖:
fun_b 呼叫 fun_a
如果我們需要修改、截獲對fun_a 函式呼叫的引數該怎麼做呢?
Definitely 對 fun_a 的呼叫進行Hook操作,看看Hook後的控制流跳轉圖:
雖然在fun_hook函式中沒有修改、截獲fun_a 的引數,但是我們演示了Hook一個函式
的實質。就是修改指令call fun_a 的跳轉地址,把它改成我們的Hook函式的地址。
Hook函式想做啥就做啥,可以對原函式呼叫,也可以不對原函式進行呼叫,如果要
保證程式在Hook函式呼叫後能正常繼續執行,最好儲存下呼叫Hook函式時的Context現場。
用pushad 和 popad 指令就可以完成咯。
進行Inline Hook並呼叫原函式需要兩個關鍵地址:
1. 呼叫原函式的指令位置 。以修改指令跳轉到鉤子函式.
2.原函式的地址。鉤子函式處理完後,呼叫原函式,保證程式繼續正常執行。
下面以Hook某程式中的某個函式呼叫為例,實戰下:
目標:用我的 evil.dll 中的匯出函式 Hook_fun 勾住某程式的某個函式呼叫。
DWORD jmpAddr; //hook 函式結束後跳轉的原函式的地址 //獲取目標指令地址 和 原函式的地址 DWORD GetHookAddr(void) { HMODULE hDll = GetModuleHandle(L"xxnetwork.dll"); jmpAddr = (DWORD)hDll + 0x581C; //hook 函式結束後跳轉的原函式的地址 return (DWORD)hDll + 0x42855; //要 Hook 的指令的地址 } //安裝 Inline hook bool MakeInlineHook(void) { //1.獲取 hook 地址 DWORD targetAddr = GetHookAddr(); //2.計算相對跳轉偏移 HMODULE hDll1 = GetModuleHandle(L"evil.dll"); DWORD HookFunAddr = (DWORD)GetProcAddress(hDll1, "HookFun")+6 - targetAddr - 5; //注意,這裡+6是為了跳過 vs2015 為函式生成的保護現場的指令(push ebp,mov ebp,esp) //-5 是因為call 指令的偏移計算是按照下一條指令的首地址計算的 //3.修改記憶體屬性,並寫入hook 程式碼 DWORD oldP,tmp; unsigned char code[5]; if (VirtualProtect((LPVOID)targetAddr, 5, PAGE_EXECUTE_READWRITE, &oldP)) { code[0] = 0xe8; //call 指令opcode memcpy(&code[1], &HookFunAddr,4); //addr memcpy((void*)targetAddr, (void*)code, sizeof(code)); //修改程式碼 VirtualProtect((LPVOID)targetAddr, 5, oldP, &tmp); //還原保護屬性 return true; } return false; } //DLL 匯出鉤子函式 DLLEXPORT void HookFun(void) { _asm { pushad //在這裡可以截獲原函式的引數,修改…… //用你的想象力,隨意發揮…… hookRet : popad //跳轉到原來的函式執行 jmp jmpAddr } } //DLL main 函式,當載入程式的時候按照 Inline Hook BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: MakeInlineHook(); break; } }
OK,以上就是Inline hook 的基本介紹,是不是很簡單呢~~~