我曾经写过一个截获MessageBoxW的程序,可以看看,或许对你有一些帮助.
该程序是基于HOOK原理,主要是将自己的函数放到目标PROCESS的地址空间,这里是使用HOOK实现.首先建立一个MOUSE的HOOK程序,然后在全局鼠标HOOK的DLL中做截获动作,可以在PROCESS_ATTACH时做,也可以在鼠标的HOOK链函数中做.
建立全局HOOK我就不说了,可以在网上很多地方看到.主要是截获动作.我是通过PE格式(使用IMAGE)改变API函数在调用时的地址.DLL部分参考如下代码:
static int WINAPI MyMessageBoxW(HWND hWnd , LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)//自己的MessageBoxW函数 {return MessageBox(hWnd, "TNT"/*lpText*/, "TNT"/*lpCaption*/, uType); } 我定义了一个结构 typedef struct tag_HOOKAPI { LPCSTR szFunc;//待HOOK的API函数名 PROC pNewProc;//新的函数指针 PROC pOldProc;//老的函数指针 }HOOKAPI, *LPHOOKAPI; extern "C" __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szImportMod) { //首先是DOS头 PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule; if(pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL; PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDOSHeader + (DWORD)(pDOSHeader->e_lfanew)); if(pNTHeader->Signature != IMAGE_NT_SIGNATURE) return NULL; //如果没有Import部分,返回失败 if(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0) return NULL; //取Import部分 PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ((DWORD)pDOSHeader + (DWORD)(pNTHeader->OptionalHeader. DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); //寻找与szImportMod相配部分 while (pImportDesc->Name) { PSTR szCurrMod = (PSTR)((DWORD)pDOSHeader + (DWORD)(pImportDesc->Name)); if (stricmp(szCurrMod, szImportMod) == 0) break; //找到 pImportDesc++; } if(pImportDesc->Name == NULL) return NULL; return pImportDesc; } extern "C" __declspec(dllexport) HookAPIByName(HMODULE hModule/*被HOOK的目标进程MODULE*/, LPCSTR szImportMod/*如GDI32.DLL*/,LPHOOKAPI pHookApi/*指定函数名,如"MessageBoxW"*/) { PIMAGE_IMPORT_DESCRIPTOR pImportDesc = GetNamedImportDescriptor(hModule, szImportMod); if (pImportDesc == NULL) return FALSE; //需要改换的API不能取到正确描PIMAGE_THUNK_DATA pOrigThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->OriginalFirstThunk)); PIMAGE_THUNK_DATA pRealThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->FirstThunk)); while(pOrigThunk->u1.Function) { if((pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG) { PIMAGE_IMPORT_BY_NAME pByName = (PIMAGE_IMPORT_BY_NAME)((DWORD)hModule + (DWORD)(pOrigThunk->u1.AddressOfData)); if(pByName->Name[0] == ''\0'') return FALSE; //失败 if(strcmpi(pHookApi->szFunc, (char*)pByName->Name) == 0) { //改变thunk保护属性 MEMORY_BASIC_INFORMATION mbi_thunk; VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)); VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect); //保存原来的API函数指针 if(pHookApi->pOldProc == NULL) pHookApi->pOldProc = (PROC)pRealThunk->u1.Function; //改变API函数指针 pRealThunk->u1.Function = (PDWORD)pHookApi->pNewProc; //将thunk保护属性改回来 DWORD dwOldProtect; VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect); } } pOrigThunk++; pRealThunk++; } SetLastError(ERROR_SUCCESS); return TRUE; }
EXE部分很简单,将该DLL载入,开启鼠标HOOK. |