inline hook是通过修改目标函数开头若干字节(通常5字节)为jmp rel32指令,跳转至自定义函数;需先用virtualprotect设内存页为可写可执行,备份原指令,计算相对偏移target_addr - (original_func_addr + 5),再用writeprocessmemory写入跳转指令。

Windows上用WriteProcessMemory修改函数首字节实现Inline Hook
直接改函数机器码是最常见的运行时Hook手段,但必须满足:目标函数开头有足够空间(通常5字节)、所在内存页可写、且不能破坏调用约定。Windows下用VirtualProtect临时改页属性,再用WriteProcessMemory写入跳转指令。
- 典型跳转指令是
jmp rel32(E9 + 4字节相对地址),需计算目标函数与跳转目标之间的偏移:target_addr - (original_func_addr + 5) - 原函数前5字节必须先备份(用于后续还原或构造trampoline),否则无法调用原逻辑
- 若目标函数开头有
push ebp; mov esp, ebp等固定指令,硬编码覆盖会崩溃——务必用Disassemble确认前5字节是否“安全可覆写” - 32位和64位的
jmp指令长度相同,但相对地址计算方式一致;x64下注意RIP相对寻址,不是简单减5
Linux下用mprotect + memcpy实现函数热补丁
Linux没有WriteProcessMemory,得靠mprotect把函数所在页设为PROT_READ | PROT_WRITE | PROT_EXEC,再用memcpy写入jmp指令。关键难点在于获取函数真实地址——符号可能被strip,dlsym返回的地址不一定是代码起始地址。
- 用
objdump -d libxxx.so | grep "func_name"确认函数入口真实偏移,避免hook到plt stub上 -
mprotect作用范围必须对齐到页边界(addr & ~(getpagesize()-1)),只改一页内几个字节也得整页重设权限 - ARM64等架构需额外执行
__builtin___clear_cache刷新icache,否则新指令不生效 - 多线程环境下,必须在所有线程都离开该函数后才能patch,否则可能执行到一半的指令流里出现非法字节
跨平台Hook库Detours和frida-gum的适用边界
自己手写Inline Hook容易翻车,但直接上重型框架也不现实。Detours仅支持Windows且闭源免费版有签名限制;frida-gum跨平台但依赖Frida server注入,不适合嵌入式或生产环境静默Hook。
- Detours的
DetourAttach本质仍是改前几字节,但它自动处理了trampoline生成和线程同步,适合Win32 GUI程序调试 - frida-gum的
Interceptor.replace在Android Native层稳定,但在macOS上对系统dylib的hook可能被SIP拦截 - 两者都不解决“函数被内联”或“编译器优化掉调用”的问题——必须确保目标函数符号未被
static或inline修饰 - 如果只是想拦截自己写的类成员函数,优先考虑虚表劫持(修改vtable指针),比Inline Hook更轻量且不依赖指令集
Hook后调用原函数时栈和寄存器状态必须严格一致
Hook函数里想调原逻辑,不能简单call original_func就完事。x86-64 System V ABI要求%rax等寄存器在调用前后保持不变,Windows x64要求shadow space分配,任何遗漏都会导致后续函数崩溃或返回垃圾值。
- trampoline必须完整复制原函数开头若干字节(包括所有修改标志位/寄存器的指令),不能只复制
mov、call而漏掉test或setz - 用
objdump -M intel -d反汇编确认原函数开头是否含条件跳转(如jz),这类指令无法直接复制,得重写逻辑 - 浮点单元(XMM/YMM寄存器)在某些ABI中属于caller-saved,Hook函数若没保存就调原函数,会导致上层浮点计算出错
- 信号处理函数(
signalhandler)里禁止做任何Hook操作,mprotect和WriteProcessMemory都不是async-signal-safe
真正难的从来不是写那几行跳转指令,而是判断某个函数是否“能被安全hook”——它有没有被编译器优化掉?所在模块是否加载在不可写段?调用它的线程此刻是否正执行到第三条指令?这些信息不会报错,但会让hook行为变得完全不可预测。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











