IAT Hook MessageBoxA出现递归调用问题求助
IAT Hook MessageBoxA 引发无限递归问题
问题现象
编写IAT Hook程序替换MessageBoxA为自定义函数print_evil,预期仅打印一次"Evil print"后调用原始MessageBoxA,但实际程序持续重复打印"Evil print",陷入无限循环。
问题原因
核心问题出在原始函数地址的获取方式:
FunctionLikeMessageBoxA originalMsgBoxA = MessageBoxA;
程序启动时,MessageBoxA其实是从当前进程的IAT(导入地址表)中读取的地址,并非user32.dll中函数的真实地址。当你完成IAT Hook后,IAT里的MessageBoxA地址已被替换为print_evil,此时originalMsgBoxA指向的就是你的Hook函数,调用它自然会触发递归,导致无限循环。
解决方案
直接从user32.dll中获取MessageBoxA的真实原始地址,绕过IAT的影响。具体修改如下:
修改后的代码
#include <Windows.h> #include <stdio.h> typedef int(__stdcall* FunctionLikeMessageBoxA) (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType); FunctionLikeMessageBoxA originalMsgBoxA = NULL; // 先初始化为空 int print_evil(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) { printf("Evil print\n"); Sleep(1000); return originalMsgBoxA(hWnd, lpText, lpCaption, uType); } int main() { // 从user32.dll获取原始MessageBoxA地址 HMODULE user32 = LoadLibraryA("user32.dll"); originalMsgBoxA = (FunctionLikeMessageBoxA)GetProcAddress(user32, "MessageBoxA"); // message box before IAT hooking MessageBoxA(NULL, "Before Hooking", "Before Hooking", 0); LPVOID imageBase = GetModuleHandleA(NULL); PIMAGE_DOS_HEADER dosHeaders = (PIMAGE_DOS_HEADER)imageBase; PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)imageBase + dosHeaders->e_lfanew); PIMAGE_IMPORT_DESCRIPTOR importDescriptor = NULL; IMAGE_DATA_DIRECTORY importsDirectory = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(importsDirectory.VirtualAddress + (DWORD_PTR)imageBase); LPCSTR currentLibraryName = NULL; HMODULE loadedLibrary = NULL; PIMAGE_IMPORT_BY_NAME functionName = NULL; while (importDescriptor->Name != NULL) { currentLibraryName = (LPCSTR)importDescriptor->Name + (DWORD_PTR)imageBase; loadedLibrary = LoadLibraryA(currentLibraryName); if (loadedLibrary) { PIMAGE_THUNK_DATA originalFirstThunk = NULL; PIMAGE_THUNK_DATA firstThunk = NULL; originalFirstThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)imageBase + importDescriptor->OriginalFirstThunk); firstThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)imageBase + importDescriptor->FirstThunk); while (originalFirstThunk->u1.AddressOfData != NULL) { functionName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)imageBase + originalFirstThunk->u1.AddressOfData); if (strcmp(functionName->Name, "MessageBoxA") == 0) { DWORD oldProtect = 0; VirtualProtect((LPVOID)(&firstThunk->u1.Function), sizeof(DWORD_PTR), PAGE_READWRITE, &oldProtect); firstThunk->u1.Function = (DWORD_PTR)print_evil; VirtualProtect((LPVOID)(&firstThunk->u1.Function), sizeof(DWORD_PTR), oldProtect, &NULL); } originalFirstThunk++; firstThunk++; } } importDescriptor++; } // after IAT hooking MessageBoxA(0, "Hello", "Hello msg", 0); return 0; }
关键修改点
- 将
originalMsgBoxA初始化为NULL,不再直接赋值为MessageBoxA - 在
main函数开头,通过LoadLibraryA加载user32.dll,再用GetProcAddress获取MessageBoxA的真实原始地址 - 调整
VirtualProtect的内存大小参数为sizeof(DWORD_PTR),适配32/64位系统(原代码写死8字节仅适配64位)
这样修改后,originalMsgBoxA指向的是user32.dll中MessageBoxA的真实入口,调用它不会触发IAT Hook,自然避免了递归循环。
内容的提问来源于stack exchange,提问作者nortain32
相关产品推荐
相关产品推荐

