简单Demo
IATHook原理
IATHook 是指 hook 某个进程的导入表函数,当程序运行起来后 IAT 会填入该函数实际的内存地址,这个地址通常都在加载的某个 dll 内存中!然后我们修改这个地址值为我们自写函数所在的地址,当系统调用这个 IAT 函数时,就会跳转到我们所写的函数
代码
#include <windows.h>
#include <string.h>
#include <stdio.h>
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
待续...