只能HOOK 本地的API,适用于入门学习
HOOK API的一般步骤:
1.定义假API函数
假API函数,除了函数名称和真API不一样之外,其它的都要跟真API的定义相同,如参数类型和返回值、调用形式等。
int WINAPI MyMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)
{
//定义假API时,具体的函数体代码暂时可不写…
return 0;
}
2.定义API函数类型
定义API函数类型,来定义一个变量保存获取到的真API函数的地址
//原函数类型定义
typedef int (WINAPI* MsgBoxW)(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType);
原函数类型定义中的函数返回值和参数类型要跟MessageBoxW的定义相同。
定义一个变量保存获取到的真API函数的地址
MsgBoxW OldMsgBoxW=NULL;//指向原函数的指针
因为系统API是在dll文件中的,有了API函数类型后,还需要一个远指针类型的变量
FARPROC pfOldMsgBoxW; //指向函数的远指针
3.获取API函数入口
有了保存原API函数地址的变量OldMsgBox和指向原API函数的远指针,就可以获取真API的地址了
//获取原API入口地址
HMODULE hmod=::LoadLibrary(_T(“User32.dll”));
OldMsgBoxW=(MsgBoxW)::GetProcAddress(hmod,“MessageBoxW”);
pfOldMsgBoxW=(FARPROC)OldMsgBoxW;
4.保存原API入口的前5个字节
保存的目的是为了恢复,HOOK了API后,还需要调用真实的API。
// 将原API的入口前5个字节代码保存到OldCode[]
BYTE OldCode[5];
_asm
{
lea edi,OldCode //获取OldCode数组的地址,放到edi
mov esi,pfOldMsgBoxW //获取原API入口地址,放到esi
cld //方向标志位,为以下两条指令做准备
movsd //复制原API入口前4个字节到OldCode数组
movsb //复制原API入口第5个字节到OldCode数组
}
5.获取新入口的前5个字节
修改真API入口的前5个字节,使其跳转到我们假API函数的入口地址。
该地址公式:
int nAddr= UserFunAddr – SysFunAddr - (定制的这条指令的大小);
Jmp nAddr; //要获取的就是nAddr的值
UserFunAddr等于假API地址,SysFunAddr等于真API地址,这里指令的大小为5。
/获取MyMessageBoxW的相对地址,为Jmp做准备
//int nAddr= UserFunAddr – SysFunAddr - (定制的这条指令的大小);
//Jmp nAddr;
//(定制的这条指令的大小), 这里是5个字节
BYTE NewCode[5];
_asm
{
lea eax,MyMessageBoxW //获取我们的MyMessageBoxW函数地址
mov ebx,pfOldMsgBoxW //原系统API函数地址
sub eax,ebx //int nAddr= UserFunAddr – SysFunAddr
sub eax,5 //nAddr=nAddr-5
mov dword ptr [NewCode+1],eax //将算出的地址nAddr保存到NewCode后面4个字节
//注:一个函数地址占4个字节
}
6.修改真实API入口的前5个字节
void HookOn()
{
ASSERT(hProcess!=NULL);
DWORD dwTemp=0;
DWORD dwOldProtect;
//修改API函数入口前5个字节为jmp 地址
VirtualProtectEx(hProcess,pfOldMsgBoxW,5,PAGE_READWRITE,&dwOldProtect);
WriteProcessMemory(hProcess,pfOldMsgBoxW,NewCode,5,0);
VirtualProtectEx(hProcess,pfOldMsgBoxW,5,dwOldProtect,&dwTemp);
}
hProcess是进程句柄,可以这样获取:
DWORD dwPid=::GetCurrentProcessId();
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,0,dwPid);
7.恢复API函数入口前5个字节
//关闭钩子的函数
void HookOff()
{
ASSERT(hProcess!=NULL);
DWORD dwTemp=0;
DWORD dwOldProtect;
//恢复API函数入口前5个字节
VirtualProtectEx(hProcess,pfOldMsgBoxW,5,PAGE_READWRITE,&dwOldProtect);
WriteProcessMemory(hProcess,pfOldMsgBoxW,OldCode,5,0);
VirtualProtectEx(hProcess,pfOldMsgBoxW,5,dwOldProtect,&dwTemp);
}
以上就是大致步骤。