生病并调养近半年了,也好久没有写博文了,真是有些抱歉,总有心有余力不足的感觉。
最近,遇到一种使用情形,需要覆盖Windows系统API的默认行为,而且可能不光涉及到Win32 x86,x64,可能还要涉及到wince平台。
本文只是一个简要的技术介绍,有兴趣的朋友可以一步步摸索下去。
首先是Win32 x86/x64下边,比如,我要覆盖'MessageBoxA'的调用(e.g.只是举例,实际可能更复杂一些)
典型的,效率也蛮高的方法是通过改写原API的函数地址,从而达到”覆盖“的目的。
示例如下:
-
-
-
-
#include "stdafx.h"
-
-
#define FLATJMPCODE_LENGTH 5 //x86 平坦内存模式下,绝对跳转指令长度
-
#define FLATJMPCMD_LENGTH 1 //机械码0xe9长度
-
#define FLATJMPCMD 0xe9
-
-
-
-
BOOL HookApi(LPVOID ApiFun,LPVOID HookFun)
-
{
-
BOOL IsSuccess = FALSE;
-
DWORD TempProtectVar;
-
MEMORY_BASIC_INFORMATION MemInfo;
-
-
VirtualQuery(ApiFun,&MemInfo,sizeof(MEMORY_BASIC_INFORMATION));
-
-
if(VirtualProtect(MemInfo.BaseAddress,MemInfo.RegionSize,
-
PAGE_READWRITE,&MemInfo.Protect))
-
{
-
*(BYTE*)ApiFun = FLATJMPCMD;
-
*(DWORD*)((BYTE*)ApiFun + FLATJMPCMD_LENGTH) = (DWORD)HookFun -
-
(DWORD)ApiFun - FLATJMPCODE_LENGTH;
-
-
VirtualProtect(MemInfo.BaseAddress,MemInfo.RegionSize,
-
MemInfo.Protect,&TempProtectVar);
-
-
IsSuccess = TRUE;
-
}
-
-
return IsSuccess;
-
}
-
-
-
int __stdcall MyHookFn(HWND hwnd,char* sztext,char* szTitle,int stly)
-
{
-
-
return printf("%s - %s\n",sztext,"原API函数已被HOOK!");
-
}
-
-
void* MyMalloc(int size)
-
{
-
printf("size = %d\n", size);
-
return NULL;
-
}
-
-
-
void MyHookFn2(char* szTxt)
-
{
-
char* pBuf = (char*)malloc(strlen(szTxt) + sizeof(char*) * 32);
-
-
__try
-
{
-
sprintf(pBuf,"%s - %s",szTxt," 原函数已被HOOK!");
-
printf("%s\n",pBuf);
-
}
-
__finally
-
{
-
free(pBuf);
-
}
-
}
-
-
-
void TestFn(char* szTitle)
-
{
-
printf("%s",szTitle);
-
}
-
-
int _tmain(int argc, _TCHAR* argv[])
-
{
-
printf("hello\n");
-
-
-
HMODULE hDll, hDll2;
-
LPVOID OldFun, of2;
-
-
-
-
__try
-
{
-
hDll = GetModuleHandle("User32.dll");
-
OldFun = GetProcAddress(hDll,"MessageBoxA");
-
hDll2 = GetModuleHandle("msvcr90.dll");
-
of2 = GetProcAddress(hDll2, "malloc");
-
if(OldFun)
-
{
-
if(HookApi(OldFun,MyHookFn))
-
MessageBoxA(0,"call Api MessageBox","Is Hookd?",MB_OK);
-
-
if (HookApi(of2, MyMalloc))
-
malloc(1);
-
-
if(HookApi(TestFn,MyHookFn2))
-
TestFn("Private Function Hook Test");
-
}
-
}
-
__finally
-
{
-
if(hDll)
-
FreeLibrary(hDll);
-
}
-
-
return 0;
-
}
在release模式下,malloc也会被覆盖。
这样,我的目的还真能达到,我可以随心所欲的覆盖malloc和free,从而让当前进程使用我定制的malloc和free。
这种方式是通过改写函数调用地址的方式来实现的,在x86/x64下边运行没什么障碍,可惜在WinCE平台下边,无法实现。
WinCE下边,上边那些API函数的地址并不是明确固定的。需要专门的Hook API来控制。多年前微软自行开发了套Hook工具库detour,相信这个可以在系统API的拦截和覆盖应用里派上用场。
由于我的场景里头,只需要定制new和delete,所以还没有使用专门的Hook API来实现,而是使用了全局重载操作符new 和 delete来实现,虽然有一定风险,但最终也还是可行的。
在Unix平台下,可以使用PRE_LOAD DLL的相关编译指令,优先加载你定制的DLL(在这个DLL里实现要覆盖的API)来简单实现API覆盖,那是非常简单的技术。有兴趣的可以GOOGLE一下。
阅读(4708) | 评论(0) | 转发(0) |