hook模板x86/x64通用版(3)--CHook.h說明
阿新 • • 發佈:2019-02-09
因為註釋比較齊全,所以不多說別的了。
Hook.h:
#pragma once #ifdef _UNICODE #define _T(x) L ## x #else #define _T(x) x #endif #ifdef _WIN64 #define WriteCall WriteCall_x64 #define WriteJMP WriteJMP_x64 #else #define WriteCall WriteCall_x86 #define WriteJMP WriteJMP_x86 #endif #ifdef _WIN64 //普通hook的shellcode大小 #define TRANSFER_FUNC_SIZE 0xcd //API hook的shellcode大小 #define TRANSFER_FUNC_FOR_CALL_SIZE 0x193 //64位下跳轉指令需要的空間大小 #define JMP_CODE_LEN 0xe //引數結構 struct ST_PARAMS { //ST_REGISTER結構中RSP後面的5個暫存器還有0x20的保護空間,一共9個,用不到也別修改 const DWORD64 no_use[9]; //不包含返回地址,返回地址會先pop掉 DWORD64 pdwParams[]; //非API頭的hook不要使用該結構 }; //儲存hook現場的結構,一般x64的前四個引數是按順序安排在RCX,RDX,R8,R9 struct ST_REGISTER { DWORD64 dw64_R15; DWORD64 dw64_R14; DWORD64 dw64_R13; DWORD64 dw64_R12; DWORD64 dw64_R11; DWORD64 dw64_R10; union { DWORD64 dw64_R9; DWORD64 dw64_Param3; }; union { DWORD64 dw64_R8; DWORD64 dw64_Param2; }; DWORD64 dw64_Rdi; DWORD64 dw64_Rsi; union { DWORD64 dw64_Rsp; ST_PARAMS* pstMoreParams; }; DWORD64 dw64_Rbp; DWORD64 dw64_Rbx; union { DWORD64 dw64_Rdx; DWORD64 dw64_Param1; }; union { DWORD64 dw64_Rcx; DWORD64 dw64_Param0; }; DWORD64 dw64_Rax; }; #else //普通hook的shellcode大小 #define TRANSFER_FUNC_SIZE 0x49 //API hook的shellcode大小 #define TRANSFER_FUNC_FOR_CALL_SIZE 0x7d //32位下跳轉指令需要的空間大小 #define JMP_CODE_LEN 5 //儲存hook現場的結構 struct ST_REGISTER { DWORD dw_edi; DWORD dw_esi; DWORD dw_ebp; union { DWORD dw_esp; DWORD* pParamsOfCall;//API頭的hook使用該結構可以修改引數數值 }; DWORD dw_ebx; DWORD dw_edx; DWORD dw_ecx; DWORD dw_eax; }; #endif class CHook { public: //一個類只hook一個地址,所以在建構函式這裡進行hook防止使用者多次呼叫 CHook(void* pOriginAdr , void* pNewHook); CHook(void* pOriginAdr , void* pNewHook , void* pHookAfterCall); ~CHook(void); //移除hook的函式,未作測試=。= BOOL RemoveHook(); //直接移除hook的函式,在本hook的使用者函式中呼叫的話會出大事,所以名字加了unsafe。 //在其他地方呼叫的話要確保沒有執行到該hook的程式碼,所以最好還是呼叫上面那個函式 BOOL RemoveHook_unsafe(); //獲取hook點現場 ST_REGISTER* GetRegOnHookPoint(); private: //初始化,然而並沒有初始化多少東西 void Init(); //給某地址寫跳轉指令 void WriteJMP_x86(DWORD_PTR dwFrom , DWORD_PTR dwTo); void WriteJMP_x64(DWORD_PTR dwFrom , DWORD_PTR dwTo); //給某地址寫一個call指令 void WriteCall_x86(DWORD_PTR dwFrom , DWORD_PTR dwTo); void WriteCall_x64(DWORD_PTR dwFrom , DWORD_PTR dwTo); //在地址pOriginAdr設定普通hook,使用者定義回撥函式pNewHook BOOL SetHook(void* pOriginAdr , void* pNewHook); //在函式頭pOriginAdr設定hook,使用者定義回撥函式pNewHook在函式執行前執行,用於攔截和修改引數; //pHookAfterCall在函式執行後執行,用於攔截和修改函式返回。pNewHook和pHookAfterCall不可同時為空 BOOL SetHook(void* pOriginAdr , void* pNewHook , void* pHookAfterCall); //遷移、儲存hook點被破壞的程式碼 int TransplantCode( void* pOriginAdr , BYTE* pDestAdr); //儲存hook現場的Tls索引 DWORD m_dwTlsIndexForRegister; //儲存API頭hook儲存函式返回地址的Tls索引 DWORD m_dwTlsIndexForRetAdr; //儲存hook點地址 void* m_pOrigin_Adr; //儲存hook點被破壞的指令長度 int m_nOrigin_CodeLen; //hook點被破壞的指令遷移到的地址 BYTE* m_pOldCode; //每個CHook類初始化時會申請一塊記憶體,把shellcode複製進去並修正一些偏移,作為中轉函式 BYTE* m_szMyTransfer; //單純c3返回的函式,用於API hook時候某個使用者定義的函式為空的時候直接呼叫這個函式 //在修正shellcode的時候能簡化一點操作 static BYTE* m_szRet; //普通hook的shellcode模板 static BYTE m_szTransferFunction[TRANSFER_FUNC_SIZE]; //API hook的shellcode模板 static BYTE m_szTransferFunction_ForCall[TRANSFER_FUNC_FOR_CALL_SIZE]; };