简单Demo
IATHook原理
IATHook 是指 hook 某个进程的导入表函数,当程序运行起来后 IAT 会填入该函数实际的内存地址,这个地址通常都在加载的某个 dll 内存中!然后我们修改这个地址值为我们自写函数所在的地址,当系统调用这个 IAT 函数时,就会跳转到我们所写的函数代码
#include#include #include int WINAPI MessageBoxPro(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType){ printf("IATHook Success\n"); system("pause"); return 0; }int main(){ HMODULE hmod; PIMAGE_DOS_HEADER pdos; PIMAGE_NT_HEADERS pnt; PIMAGE_OPTIONAL_HEADER popt; PIMAGE_IMPORT_DESCRIPTOR piid; PIMAGE_THUNK_DATA pfuncname_addr,pfunc_addr; DWORD dwOldProtect,dwNewProtect; DWORD* repAddr = (DWORD *)MessageBoxPro; // 务必得转换一下 hmod = GetModuleHandle(NULL); pdos = (PIMAGE_DOS_HEADER)hmod; pnt = (PIMAGE_NT_HEADERS)((PBYTE)hmod + pdos->e_lfanew); popt = (PIMAGE_OPTIONAL_HEADER)(&(pnt->OptionalHeader)); piid = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)hmod+popt->DataDirectory[1].VirtualAddress); // Base_addr + RVA_addr MessageBox(NULL,"HelloWorld","Title",MB_OK); while(piid->FirstThunk){ pfuncname_addr = (PIMAGE_THUNK_DATA)((BYTE *)hmod + piid->OriginalFirstThunk); pfunc_addr = (PIMAGE_THUNK_DATA)((BYTE *)hmod + piid->FirstThunk); // char* pdll_name = (char *)((BYTE *)hmod + piid->Name); // printf("%s\n",pdll_name); while(pfuncname_addr->u1.Function){ char* func_name = (char *)((BYTE *)hmod + pfuncname_addr->u1.AddressOfData+2); DWORD *lpAddr = (DWORD *)&pfunc_addr->u1.AddressOfData; if(!strcmp(func_name,"MessageBoxA")){ VirtualProtect(lpAddr,4,PAGE_EXECUTE_READWRITE,&dwOldProtect); WriteProcessMemory((HMODULE)-1,lpAddr,&repAddr,4,NULL); // 修改地址的第一种方式 // *lpAddr = repAddr; // 修改地址的第二种方式 } VirtualProtect(lpAddr,4,dwOldProtect,&dwNewProtect); pfuncname_addr++; pfunc_addr++; } piid++; } MessageBox(NULL,"HelloWorld","Title",MB_OK); return 0;}
说明
修改 IAT 地址可以赋值修改
,也还可以用WriteProcessMemory
函数修改!千万别忘了用VirtualProtect
来修改内存页的属性,不然无法成功写入!需要注意函数名的类型转换以及指针的合理使用!最后就是尽量编译成 32 位程序,如要编译成 64 位程序需要自行修改变量类型,当然不改也是可以运行的! 运行结果
进阶Demo
待续...