1. 什么是API Hook?
简单理解:假设我现在Hook了A函数,当其他线程调用了A函数,但实际上确是执行了B函数,而调用者却完全不知情。
例如
int A() { // 这一个是正常的函数,一般是游戏开发者编写的 return 1;
} int B() { // 这个是恶意的函数(一般是你模块注入成功后你编写的函数) // 通常是先保存A的地址,然后 return 0;
} int main() { // Hook(A, B); // 在其他线程中,A函数被Hook为B函数 int res = A(); // 这里调用者不知情,实际上调用的是B函数 }
分享Hook MessageBox弹窗的例子。
#include <windows.h> //定义函数原型: MessageBoxA typedef int WINAPI OLD_MessageBoxA( __in_opt HWND hWnd, __in_opt LPCSTR lpText, __in_opt LPCSTR lpCaption, __in UINT uType);
DWORD addr1; // 保存源码MeesageBoxA的地址 __declspec(naked) int __stdcall My_MessageBoxA( __in_opt HWND hWnd, __in_opt LPCSTR lpText, __in_opt LPCSTR lpCaption, __in UINT uType)
{
__asm
{
mov edi, edi
push ebp
mov ebp ,esp
}
lpText="已被HOOK"; // 修改数据 __asm
{
mov eax,addr1
add eax,5 // 前5字节是我们的长jump指令 jmp eax // 跳到MessageBox真正的代码区域 }
} int _tmain(int argc, _TCHAR* argv[])
{
DWORD jump_code=0;
byte mye9 = 0xe9;
HMODULE DLLHANDLE= LoadLibraryA("USER32.DLL");
addr1= (DWORD)(GetProcAddress(DLLHANDLE,"MessageBoxA")); //改变内存读写属性 VirtualProtect((LPVOID)addr1,10,PAGE_EXECUTE_READWRITE,NULL); //修改第一字节 if (WriteProcessMemory(GetCurrentProcess(),(LPVOID)addr1,&mye9,1,NULL)==0)
{ printf("写入HOOK数据失败");
} //修改后4字节 :跳转码 JMP 1234 //跳转码=将要跳到的函数-原来的函数地址-5 //我们的跳转码=My_MessageBoxA-addr1-5 jump_code=(DWORD)&My_MessageBoxA-addr1-5; if (WriteProcessMemory(GetCurrentProcess(),(DWORD*)(addr1+1),&jump_code,4,NULL)==0)
{ printf("写入HOOK数据失败");
} ::MessageBoxA(0,"HOOK1","提示",0); ::MessageBoxA(0,"HOOK2","提示",0); ::MessageBoxA(0,"HOOK3","提示",0); return 0;
}
运行之后调用MessageBoxA,窗口中的内容都是"已被Hook"。
这种Hook方法称为Inline Hook,因为在windows api中,如果函数被声明为__stdcall的话,汇编后的前5个字节是这样的
mov edi, edi // 2字节 push ebp // 1字节 mov ebp, esp // 2字节
这5个字节刚好可以组成一条长jump指令,只要修改函数代码段即可。
至于怎么实现辅助花里花哨的功能,我们下期再讲~
评论列表: