C++辅导:如何截获API函数
来源:优易学  2011-11-16 12:23:51   【优易学:中国教育考试门户网】   资料下载   IT书店
  该程序是基于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.

责任编辑:虫虫

文章搜索:
 相关文章
热点资讯
资讯快报
热门课程培训