HOOK Windows API

HOOK Windows API

只能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);
}

以上就是大致步骤。

你可能感兴趣的:(笔记)