inline Hook简单介绍

What is Inline Hook ?

就是一个函数钩子而已,把程序原本要调用的函数改成另一个函数,就是对原函数的一个挂钩(hook) 。

 

How did this work ?

让我们看看调用一个函数控制流的跳转图:

fun_b 调用 fun_a

 

如果我们需要修改、截获对fun_a 函数调用的参数该怎么做呢?

Definitely 对 fun_a 的调用进行Hook操作,看看Hook后的控制流跳转图:

 

       虽然在fun_hook函数中没有修改、截获fun_a 的参数,但是我们演示了Hook一个函数

的实质。就是修改指令call fun_a 的跳转地址,把它改成我们的Hook函数的地址。

Hook函数想做啥就做啥,可以对原函数调用,也可以不对原函数进行调用,如果要

保证程序在Hook函数调用后能正常继续运行,最好保存下调用Hook函数时的Context现场。

用pushad 和 popad 指令就可以完成咯。

       进行Inline Hook并调用原函数需要两个关键地址:

1. 调用原函数的指令位置 。以修改指令跳转到钩子函数.

2.原函数的地址。钩子函数处理完后,调用原函数,保证程序继续正常运行。

 

下面以Hook某程序中的某个函数调用为例,实战下:

目标:用我的 evil.dll 中的导出函数 Hook_fun 勾住某程序的某个函数调用。

DWORD jmpAddr;		//hook 函数结束后跳转的原函数的地址

//获取目标指令地址 和 原函数的地址
DWORD GetHookAddr(void)
{
	HMODULE hDll = GetModuleHandle(L"xxnetwork.dll");
	jmpAddr = (DWORD)hDll + 0x581C;		//hook 函数结束后跳转的原函数的地址
	return (DWORD)hDll + 0x42855;		//要 Hook 的指令的地址
}


//安装 Inline hook
bool MakeInlineHook(void)
{
	//1.获取 hook 地址
	DWORD targetAddr = GetHookAddr();

	//2.计算相对跳转偏移
	HMODULE hDll1 = GetModuleHandle(L"evil.dll");
	DWORD HookFunAddr = (DWORD)GetProcAddress(hDll1, "HookFun")+6 - targetAddr - 5;	//注意,这里+6是为了跳过 vs2015 为函数生成的保护现场的指令(push ebp,mov ebp,esp)
//-5 是因为call 指令的偏移计算是按照下一条指令的首地址计算的

	//3.修改内存属性,并写入hook 代码
	DWORD oldP,tmp;
	unsigned char code[5];
	if (VirtualProtect((LPVOID)targetAddr, 5, PAGE_EXECUTE_READWRITE, &oldP))
	{
		code[0] = 0xe8;			//call 指令opcode
		memcpy(&code[1], &HookFunAddr,4);	//addr
		memcpy((void*)targetAddr, (void*)code, sizeof(code));		//修改代码
		VirtualProtect((LPVOID)targetAddr, 5, oldP, &tmp);			//还原保护属性
		return true;
	}
	return false;
}

//DLL 导出钩子函数
DLLEXPORT void HookFun(void)
{


	_asm {
		pushad
                //在这里可以截获原函数的参数,修改……
                //用你的想象力,随意发挥……

hookRet :
		popad
			//跳转到原来的函数执行
			jmp jmpAddr
             }

}

//DLL main 函数,当载入程序的时候按照 Inline Hook

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
            MakeInlineHook();
            break;
        }
}

 

OK,以上就是Inline hook 的基本介绍,是不是很简单呢~~~

 

 

好的,以下是一个简单inline hook 示例代码,可以用于 hook 指定的函数,在调用该函数时打印日志信息: ```c++ #include <stdio.h> #include <unistd.h> #include <stdint.h> #include <sys/mman.h> #define HOOK_SIZE 12 // 用于 hook函数 void my_function() { printf("my_function called\n"); } // 原始函数 void (*original_function)(); void original_function_impl() { // 执行原始函数实现 } // Hook 函数 void hook_function() { printf("hook_function called\n"); // 调用原始函数 original_function(); } // Hook 函数的字节码 unsigned char hook_code[HOOK_SIZE] = { 0x68, 0x00, 0x00, 0x00, 0x00, // push 0x00000000 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp hook_function 0x90 // nop }; // inline hook 函数 void inline_hook(void *target, void *hook) { // 将目标函数的前 HOOK_SIZE 字节设置为可写 mprotect(target, HOOK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC); // 保存原始函数地址 original_function = (void (*)())target; // 将 Hook 函数地址写入 Hook 代码中 *(uint32_t *)(hook_code + 1) = (uint32_t)hook - (uint32_t)target - HOOK_SIZE; // 将 Hook 代码写入目标函数中 memcpy(target, hook_code, HOOK_SIZE); // 将目标函数的前 HOOK_SIZE 字节设置为只读可执行 mprotect(target, HOOK_SIZE, PROT_READ | PROT_EXEC); } int main() { // 执行原始函数 original_function_impl(); // inline hook 目标函数 inline_hook((void *)original_function_impl, (void *)hook_function); // 再次执行原始函数 original_function_impl(); return 0; } ``` 请注意,该示例代码仅用于演示 inline hook 的原理,实际使用中可能需要更加复杂的实现。此外,inline hook 可能会涉及到一些风险,需要谨慎使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值