如何截获API函数
我曾经写过一个截获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.