vc++HOOK API编程必知必会
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | #include // 定义API挂接项结构 typedef struct _HOOK_ITEM { DWORD dwAddr ; // IAT项所在地址 DWORD dwOldValue ; // IAT项的原始函数地址 DWORD dwNewValue ; // IAT项的新函数地址 } HOOK_ITEM, *PHOOK_ITEM ; HOOK_ITEM HookItem = {0} ; // 定义IAT项,用于保存MessageBoxA的IAT项信息 // 定义MessageBoxA函数原型 typedef int (WINAPI* PFNMessageBoxA)( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType ) ; // 定义重定向API的实现函数 BOOL WINAPI RedirectApi ( PCHAR pDllName, PCHAR pFunName, DWORD dwNewProc, PHOOK_ITEM pItem ) ; // 自定义的MessageBoxA函数 // 实现对原始MessageBoxA的输入、输出参数的监控,甚至是取消调用 int WINAPI NEW_MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType ) { // 此处可以观察/修改调用参数,甚至可以取消调用直接返回。 // …… // 取得原函数地址 PFNMessageBoxA pfnMessageBoxA = (PFNMessageBoxA)HookItem.dwOldValue ; // 输出测试信息, // 如果这里直接调用MessageBoxA,就进入无限循环 pfnMessageBoxA ( hWnd, "这是API重定向过程的消息框" , "测试" , 0 ) ; // 调用原函数 int ret = pfnMessageBoxA ( hWnd, lpText, lpCaption, uType ) ; // 此处可以查看/修改调用原函数的返回值 // …… return ret ; } int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // 重定向API if ( !RedirectApi ( "USER32.dll" , "MessageBoxA" , ( DWORD )NEW_MessageBoxA, &HookItem ) ) OutputDebugStringA ( "RedirectApi failed!" ) ; else OutputDebugStringA ( "RedirectApi success!" ) ; MessageBoxA ( 0, "正常消息框" , "测试" , 0 ) ; return 0 ; } // 实现重定向API // 参数pDllName:目标API所在的DLL名称 // 参数pFunName:目标API名称 // 参数dwNewProc:自定义的函数地址 // 参数pItem:用于保存IAT项信息 BOOL WINAPI RedirectApi ( PCHAR pDllName, PCHAR pFunName, DWORD dwNewProc, PHOOK_ITEM pItem ) { // 检查参数是否合法 if ( pDllName == NULL || pFunName == NULL || !dwNewProc || !pItem ) return FALSE ; // 检测目标模块是否存在 char szTempDllName[256] = {0} ; DWORD dwBaseImage = ( DWORD )GetModuleHandle(NULL) ; if ( dwBaseImage == 0 ) return FALSE ; // 取得PE文件头信息指针 PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)dwBaseImage ; PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(dwBaseImage + (pDosHeader->e_lfanew)) ; PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = &(pNtHeader->OptionalHeader) ; PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(( DWORD )pNtHeader + 0x18 + pNtHeader->FileHeader.SizeOfOptionalHeader ) ; // 遍历导入表 PIMAGE_THUNK_DATA pThunk, pIAT ; PIMAGE_IMPORT_DESCRIPTOR pIID = (PIMAGE_IMPORT_DESCRIPTOR)(dwBaseImage+pOptionalHeader->DataDirectory[1].VirtualAddress ) ; while ( pIID->FirstThunk ) { // 检测是否目标模块 if ( strcmp ( ( PCHAR )(dwBaseImage+pIID->Name), pDllName ) ) { pIID++ ; continue ; } pIAT = (PIMAGE_THUNK_DATA)( dwBaseImage + pIID->FirstThunk ) ; if ( pIID->OriginalFirstThunk ) pThunk = (PIMAGE_THUNK_DATA)( dwBaseImage + pIID->OriginalFirstThunk ) ; else pThunk = pIAT ; // 遍历IAT DWORD dwThunkValue = 0 ; while ( ( dwThunkValue = *(( DWORD *)pThunk) ) != 0 ) { if ( ( dwThunkValue & IMAGE_ORDINAL_FLAG32 ) == 0 ) { // 检测是否目标函数 if ( strcmp ( ( PCHAR )(dwBaseImage+dwThunkValue+2), pFunName ) == 0 ) { // 填充函数重定向信息 pItem->dwAddr = ( DWORD )pIAT ; pItem->dwOldValue = *(( DWORD *)pIAT) ; pItem->dwNewValue = dwNewProc; // 修改IAT项 DWORD dwOldProtect = 0 ; VirtualProtect ( pIAT, 4, PAGE_READWRITE, &dwOldProtect ) ; *(( DWORD *)pIAT) = dwNewProc ; VirtualProtect ( pIAT, 4, PAGE_READWRITE, &dwOldProtect ) ; return TRUE ; } } pThunk ++ ; pIAT ++ ; } pIID ++ ; } return FALSE ; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步