1.简介
当程序运行后IAT表才会被系统根据pe文件的导入表等信息填充该IAT字段,
填充后的IAT的函数地址是对应模块加载后真正的函数地址,程序中对dll中
的导出函数的调用也是通过该IAT的记录来调用的.因此可以通过注入dll后,
通过dll中的代码修改IAT表的记录,来实现hook.
原来的调用过程:
call [aaaaa] => IAT[aaaaaa]::bbbbb => xxx.dll::bbbbb
ret后
next code of call [aaaaa] <= next ret of xxx.dll::bbbbb
注入后的调用过程:
call [aaaaa] => IAT[aaaaaa]::ccccc => hook.dll::ccccc => xxx.dll::bbbbb
ret后
next code of call [aaaaa] <= next ret of hook.dll::ccccc => next ret of xxx.dll::bbbbb
2.测试,将calc的显示改为中文文字零到九
效果图:
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "stdafx.h" #include<Windows.h> #include<malloc.h> #include<wchar.h> //要hook的API所属的dll名字 #define dllName "user32.dll" #define funcName "SetWindowTextW" DWORD imageBase; DWORD funcBase; typedef BOOL (WINAPI *TypeSetWindowTextW)( __in HWND hWnd, __in_opt LPCWSTR lpString); DWORD hookSetWindowTextW(HWND hWnd, LPWSTR lpBuffer); BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { funcBase = (DWORD)(GetProcAddress(GetModuleHandleA(dllName), funcName)); imageBase = (DWORD)GetModuleHandle(0);//获取本模块基址(句柄) IMAGE_DOS_HEADER *dosHeader = (IMAGE_DOS_HEADER*)imageBase; PIMAGE_NT_HEADERS32 ntHeader; ntHeader=(PIMAGE_NT_HEADERS32)(imageBase+dosHeader->e_lfanew); IMAGE_IMPORT_DESCRIPTOR *importTable = (IMAGE_IMPORT_DESCRIPTOR *)(ntHeader->OptionalHeader.DataDirectory[1].VirtualAddress + imageBase); IMAGE_THUNK_DATA32* iat; DWORD page; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: MessageBoxA(0,"inject","inject",0); for(;importTable->Name;importTable++) { //MessageBoxA(0,"inject1","inject1",0); if(stricmp((char*)(imageBase + importTable->Name),dllName)==0) { break; } } if (importTable->Name!=0) { iat = (IMAGE_THUNK_DATA32*)(importTable->FirstThunk + imageBase); while (iat->u1.Function!=funcBase) { iat++; } if (iat->u1.Function) { VirtualProtect(&iat->u1.Function, 4, PAGE_EXECUTE_READWRITE, &page); iat->u1.Function = (DWORD)hookSetWindowTextW; VirtualProtect(&iat->u1.Function, 4, page, &page); } } break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } DWORD hookSetWindowTextW(HWND hWnd, LPWSTR lpBuffer) { WCHAR chinese[] = L"零一二三四五六七八九"; WCHAR temp[2] = { 0 }; int index; for (int i = 0; i < lstrlen(lpBuffer); i++) { if (lpBuffer[i] >= L'0'&&lpBuffer[i] <= L'9') { temp[0] = lpBuffer[i]; index = _wtoi(temp); lpBuffer[i] = chinese[index]; } } return ((TypeSetWindowTextW)funcBase)(hWnd, lpBuffer); }