【一分钟学C++】Windows API Hook基本原理

在这里插入图片描述

竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生~
公众号: C++学习与探索  |  个人主页: rainInSunny  |  个人专栏: Learn OpenGL In Qt

基本概念

  Detours定义了三个概念:

  • Target 函数:要拦截的函数,通常为 Windows 的 API。
  • Trampoline 函数:Target 函数的复制品。因为 Detours 将会改写 Target 函数,所以先把 Target 函数复制保存好,一方面仍然保存 Target 函数的过程调用语义,另一方面便于以后的恢复。
  • Detour 函数:用来替代 Target 函数的函数。

拦截过程

  拦截前:

targetFunction:
// targetFunction 入口,下面是常见的入口处指令,保存各个寄存器上下文环境
push ebp
mov ebp, esp
push eax
push ebx

// 后续为 targetFunction 继续部分
......

  拦截后:

targetFunction:
// 此时 targetFunction 入口被修改,跳转到 detourFunction
jmp detourFunction

// 后续为 targetFunction 继续部分
......
trampolineFunction:
// trampolineFunction 函数入口,开头的 5 个字节与 targetFunction 相同
push ebp
mov ebp, esp
push eax
push ebx
// 跳回去继续执行 trampolineFunction
jmp targetFunction + 5

  可以看出拦截前后相比,targetFunction 的入口处 5 个字节被修改了,改成了 jmp detourFunction(该指令也占 5 个字节),这样保证其它地方调用 targetFunction 时会走到我们定义的 detourFunction。其次 trampolineFunction 的入口会被设置为和原来 targetFunction 入口处 5 个字节相同的逻辑,然后会执行 jmp targetFunction + 5 的逻辑,这样在 detourFunction 中调用 trampolineFunction,经过 trampolineFunction 的重新路由,恢复了原来 targetFunction 的调用。

代码测试

  测试代码和前一篇文章中一样:

#include <Windows.h>
#include "detours/detours.h"

#pragma comment(lib, "detours.lib")

static int (WINAPI* OLD_MessageBoxW)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) = MessageBoxW;


int WINAPI New_MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCation, UINT uType)
{
	int ret = OLD_MessageBoxW(hWnd, L"HOOK完成", L"[测试]", uType);
	return ret;
}

void HOOK()
{
	DetourRestoreAfterWith();
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());

	DetourAttach(&(PVOID&)OLD_MessageBoxW, New_MessageBoxW);

	DetourTransactionCommit();
}

void UnHook()
{
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());

	DetourDetach(&(PVOID&)OLD_MessageBoxW, New_MessageBoxW);

	DetourTransactionCommit();
}

int main()
{
	::MessageBoxW(NULL, L"正常消息框", L"测试", MB_OK);
	HOOK();
	::MessageBoxW(NULL, L"正常消息框", L"测试", MB_OK);
	UnHook();
	return 0;
}

  这里测试环境为 x64,可能与上面描述稍有不同。
在这里插入图片描述
  图中是原始的 MessageBoxW 的汇编过程,也就是上面说的 targetFunction,这里第一二行可以认为是在进行寄存器上下文准备,第三行 00007FF82ACFA007 这个地址开始函数过程。
在这里插入图片描述
  图中是替换后的 MessageBoxW 的汇编过程,可以看出第一行变成了 jump 到一个地址。
在这里插入图片描述
  汇编单步调试发现最后 jump 到了 New_MessageBoxW 入口,也就是 detourFunction,在 New_MessageBoxW 中最后调用了 OLD_MessageBoxW,也就是上面说的 trampolineFunction。
在这里插入图片描述
  在调用 OLD_MessageBoxW 过程中,首先进行了寄存器上下文的准备,这和原始 MessageBoxW 汇编调用第一二行是相同的,然后进行了跳转。
在这里插入图片描述
  继续汇编调试,显示跳转的地址就是 00007FF82ACFA007,也就是原始 MessageBoxW 汇编开始函数过程的地方,这样就实现了恢复原始函数调用的目的。

关注公众号:C++学习与探索,有惊喜哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值