Detours学习2 - 函数拦截原理
Interception of Binary Functions
Detours可以拦截目标函数。拦截代码在运行时动态调用。Detours通过替换目标函数的前几条指令直接跳转到用户提供的函数。来自目标函数的指令保留在Trampoline函数中。从目标函数中删除的指令和到目标函数其余部分的直接跳转部分组成Trampoline函数
当执行到目标函数时,控制权将直接跳转到用户提供的Detour函数。Detour函数可以将控制权返回给源函数,也可以调用Trampoline函数,该功能可以在不拦截的情况下调用目标功能。目标函数执行完成后,它将控制权返回给Trampoline函数。Detour函数执行相应的处理,并将控制权返回给源函数。

Detours通过重写目标函数的进程内二进制映像来拦截目标函数。对于每个目标函数,Detours实际上重写了两个函数,即目标函数和与之匹配的Trampoline函数,以及一个函数指针,即目标指针。Trampoline函数由Detours动态分配。在插入detour之前,Trampoline仅包含指向目标函数的一条跳转指令。插入后,Trampoline会包含来自目标函数的初始指令,并跳转到目标函数的其余部分。
用户初始化目标指针并指向目标函数。当DetourAttach到目标函数之后,目标指针被修改并指向Trampoline函数。当目标函数DetourDetach后,目标指针将指向原始目标函数。

要绕开目标函数,Detours首先为动态Trampoline函数分配内存(如果未提供静态Trampoline函数),然后启用对目标和Trampoline函数的写访问。从第一条指令开始,Detours将指令从目标函数复制到Trampoline函数,至少复制5个字节(足够用于跳转指令)。如果目标函数少于5个字节,则Detours中止并返回错误代码。
为了复制指令,Detours使用了一个简单的表驱动反汇编程序。Detours在Trampoline函数的末尾添加了一条跳转指令指向目标函数的未复制部分的头部。Detours将跳转指令写入到detour函数中,作为目标函数的第一条指令。最后,Detours还原了目标函数和Trampoline函数的原始页面权限(PAGE_EXECUTE_),并通过调用FlushInstructionCache刷新了CPU指令缓存。

浙公网安备 33010602011771号