- IAT - Import Address Table ,导入地址列表。这里保存着各个导入的函数加载后的地址,它是动态的,随着Dll的加载的位置不同而不同。
- PE - Portable Execute 可执行的程序结构。在PE结构中有个数据目录(Data Directory) 内部保存导入表的数据。格式大概如下:
dll-数据 1
函数数据1
函数数据2
函数数据3
…
dll-数据 2
…
- 我们根据PE的格式找到函数的已经定位的位置,然后修改这个位置,就能用自己的函数替换这个函数。(再此之前保留好原来的函数)
- 下面以win32 的程序为例,代码如下
#include <windows.h>
#include <stdio.h>
void* test()
{
void* a = MessageBoxA;
return a;
}
VOID* g_lpMsgBox = NULL;
typedef int(WINAPI *LpMsgBox)(HWND wnd, char* msg, char* title, UINT btn);
int WINAPI MyMessageBox(HWND wnd, char* msg, char* title, UINT btn)
{
char buf[256] = {0};
strcpy(buf, msg);
strcat(buf, "+mybox");
((LpMsgBox)g_lpMsgBox)(wnd, buf, title, btn);
return 0;
}
BOOL checkIATHook()
{
PIMAGE_DOS_HEADER dos_header = GetModuleHandle(NULL);
PIMAGE_NT_HEADERS nt_headers = (LPBYTE)dos_header + dos_header->e_lfanew;
DWORD import_rva = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
LPBYTE import_va = (LPBYTE)dos_header + import_rva;
PIMAGE_IMPORT_DESCRIPTOR imp_desc = import_va;
while (1){
if (imp_desc->Name)
{
char* name = (LPBYTE)dos_header + imp_desc->Name;
HMODULE imp_dll = GetModuleHandleA(name);
PIMAGE_THUNK_DATA thunk = (LPBYTE)dos_header + imp_desc->FirstThunk;
PIMAGE_THUNK_DATA thunk1 = (LPBYTE)dos_header + imp_desc->OriginalFirstThunk;
for (;;)
{
if (thunk->u1.ForwarderString == 0)
{
break;
}
if (thunk->u1.ForwarderString & IMAGE_ORDINAL_FLAG)
{
__asm nop;
}
else
{
PIMAGE_IMPORT_BY_NAME fnName = (LPBYTE)dos_header + thunk1->u1.AddressOfData;
DWORD proc_addr = GetProcAddress(imp_dll, fnName->Name);
if (thunk->u1.Function != proc_addr)
{
printf("%s be hooked : 0x%x\n", fnName->Name, thunk->u1.Function);
}
__asm nop;
}
thunk += 1;
thunk1 += 1;
}
imp_desc += 1;
}
else
{
break;
}
}
return TRUE;
}
void hookMessageBoxA()
{
PIMAGE_DOS_HEADER dos_header = GetModuleHandle(NULL);
PIMAGE_NT_HEADERS nt_headers = (LPBYTE)dos_header + dos_header->e_lfanew;
DWORD import_rva = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
LPBYTE import_va = (LPBYTE)dos_header + import_rva;
PIMAGE_IMPORT_DESCRIPTOR imp_desc = import_va;
while (1){
if (imp_desc->Name)
{
char* name = (LPBYTE)dos_header + imp_desc->Name;
if (stricmp(name, "user32.dll") == 0)
{
PIMAGE_THUNK_DATA thunk = (LPBYTE)dos_header + imp_desc->FirstThunk;
PIMAGE_THUNK_DATA thunk1 = (LPBYTE)dos_header + imp_desc->OriginalFirstThunk;
for (;;)
{
if (thunk->u1.ForwarderString == 0)
{
break;
}
if (thunk->u1.ForwarderString&IMAGE_ORDINAL_FLAG)
{
__asm nop;
}
else
{
PIMAGE_IMPORT_BY_NAME fnName = (LPBYTE)dos_header + thunk1->u1.AddressOfData;
if (strcmp(fnName->Name, "MessageBoxA")==0)
{
g_lpMsgBox = thunk->u1.Function;
DWORD prFlag;
BOOL b = VirtualProtect(&imp_desc->FirstThunk, 4, PAGE_EXECUTE_READWRITE, &prFlag);
if (b)
{
*(DWORD*)thunk = MyMessageBox;
}
VirtualProtect(&imp_desc->FirstThunk, 4, prFlag, &prFlag);
}
return;
__asm nop;
}
thunk += 1;
}
}
imp_desc += 1;
}
else
{
break;
}
}
}
int main(int argc, char** argv)
{
test();
hookMessageBoxA();
checkIATHook();
MessageBoxA(NULL, "msg", "haha", MB_OK);
return 0;
}