C/C++ inline-hook(x86)高级函数内联钩子

🧵 C/C++ inline-hook(x86)高级函数内联钩子

引用

  1. fetch-x86-64-asm-il-size
  2. C++ i386/AMD64平台汇编指令对齐长度获取实现

🧠 一、Inline Hook技术体系架构

Inline Hook是一种二进制指令劫持技术,通过修改目标函数的机器码,将执行流重定向到自定义函数。其核心价值在于无需源码即可监控或修改程序行为,广泛应用于调试器(如x64dbg)、安全软件(如杀毒引擎)和性能分析工具(如VTune)。

1.1 技术实现全流程
定位目标函数
修改内存权限
备份原始指令
写入跳转指令
构建跳板Trampoline
劫持执行流至Hook函数
通过Trampoline调用原函数
  • 关键步骤详解
    • 指令覆盖:x86覆盖5字节(E9+4字节偏移),x64覆盖12-14字节(FF25+8字节绝对地址)
    • 偏移计算
      // x86示例:跳转偏移 = Hook函数地址 - (目标函数地址 + 5)
      DWORD offset = (DWORD)HookedFunc - (DWORD)TargetFunc - 5;
      BYTE jmp[5] = {0xE9, *(BYTE*)&offset}; 
      

⚙️ 二、跳板(Trampoline)机制深度解构

直接调用原函数会导致 ​​递归死循环​​(因原函数入口已被 JMP Hook 覆盖)。跳板通过 ​​分离指令备份与执行流恢复​​ 解决此问题。

2.1 跳板结构设计​
入口指令被覆盖
目标函数
JMP Hook函数
Hook函数
调用跳板
执行备份指令
JMP 原函数 + N
2.2 跳板结构与生成算法
LPVOID CreateTrampoline(uint8_t* target, size_t len) {LPVOID tramp = VirtualAlloc(NULL, len+5, MEM_COMMIT, PAGE_EXECUTE_READWRITE);// 1. 复制原始指令memcpy(tramp, target, len); // 2. 追加跳回指令(JMP回原函数+len)uint8_t* jmp_pos = (uint8_t*)tramp + len;*jmp_pos = 0xE9; *(DWORD*)(jmp_pos+1) = (DWORD)(target + len) - (DWORD)(jmp_pos + 5);return tramp;
}
  • 指令级还原原理
    • 备份指令必须完整覆盖被破坏的原始指令(如x86的5字节)
    • 跳回地址需精确计算至目标函数+备份长度,避开被篡改区域
2.3 执行流恢复的线程安全挑战

当多线程并发调用被Hook函数时:

  1. 寄存器一致性:跳板执行时需保持所有寄存器状态与原函数入口一致
  2. 栈平衡机制:x86通过push ebp; mov ebp, esp建立栈帧,跳板需模拟此过程
  3. 调用约定兼容:确保stdcall/fastcall等约定不被破坏

🔒 三、多线程环境下的原子性与安全性保障

3.1 指令修改的竞态风险

当线程A正在写入跳转指令时,若线程B执行到该区域:

  • 撕裂读取:可能读取到半写入状态的无效指令(如仅写入3字节)
  • CPU缓存失效:旧指令残留在L1 Cache导致执行错误
3.2 工业级解决方案
方案原理优缺点
线程挂起通过SuspendThread暂停所有线程,确保无并发执行安全但导致进程卡顿
原子写入使用InterlockedExchange64单指令完成8字节写入仅限x64,且需指令长度对齐
热补丁(Hot Patch)利用函数头部的MOV EDI,EDI(2字节)构造短跳转,避免覆盖执行中的指令需编译器支持(/hotpatch)
// 热补丁实现示例(覆盖7字节)
void HotPatchHook() {// 1. 在函数头部上方5字节处写入长跳转(E9 xxxxxxxx)WriteJump((PVOID)((DWORD)TargetFunc - 5), HookFunc); // 2. 覆盖头2字节为短跳转(EB F9)BYTE shortJump[2] = {0xEB, 0xF9}; WriteMemory(TargetFunc, shortJump, 2);
}

🧩 四、跨平台实现差异与技术挑战

4.1 架构差异与应对策略
问题x86方案x64方案ARM方案
跳转范围±2GB(近跳转)全64位地址(远跳转)±32MB(B指令)
指令长度5字节(JMP rel32)14字节(MOVABS + JMP)4-8字节(LDR+BR)
寄存器保护依赖栈保存需手动保存XMM0-XMM5保护AAPCS定义的易失寄存器
// x64远跳转实现(14字节)
void WriteX64Jump(PVOID target, PVOID hook) {BYTE code[14] = {0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // FF25 00000000: JMP [RIP+0]0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // 绝对地址};*(ULONG_PTR*)(code + 6) = (ULONG_PTR)hook;WriteMemory(target, code, 14);
}
4.2 变长指令处理的可靠性设计
  • 问题本质:x86指令长度不定(1-15字节),覆盖5字节可能截断指令
    ; 危险案例:覆盖5字节破坏完整指令
    MOV [EAX+ECX*4], 12345678h ; 完整指令占10字节
    
  • 解决方案
    1. 反汇编引擎:使用Zydis/Capstone动态计算最小完整指令边界
    2. 跳板扩展:备份跨越指令所需全部字节,追加修复逻辑

🛠️ 五、生产环境最佳实践与演进方向

5.1 现代安全机制的规避策略
安全机制影响破解方案
DEP阻止数据区执行跳板申请PAGE_EXECUTE_READWRITE权限
ASLR函数地址随机化动态解析API地址(GetProcAddress)
PatchGuardWindows内核代码签名校验挂钩非校验区域(如KiFilterFiberContext)
5.2 性能优化与稳定增强
  1. 跳板池复用:预生成常用函数跳板,减少运行时分配开销
  2. 延迟挂钩:首次调用时再安装Hook,避免启动卡顿
  3. 栈帧探测:通过RBP链校验调用路径,防止递归崩溃

🚀 六、内联钩子及跳板的实现

1.1 演示效果

在这里插入图片描述

1.2 工程实现
#include <windows.h>
#include <cstdint>
#include <cstring>#ifdef _WIN64
#include <intrin.h>
#pragma intrinsic(_mm_sfence)
#endif// 函数指针类型定义
using message_box_ptr = int(WINAPI*)(HWND, LPCSTR, LPCSTR, UINT);// 全局变量
static message_box_ptr original_message_box = NULL;
static LPVOID trampoline_shellcode = NULL;
static size_t backup_length = 0;// 内存屏障
void memory_barrier() {
#ifdef _WIN64_mm_sfence();
#endif_ReadWriteBarrier();
}// 计算备份长度 (固定长度简化版)
size_t calculate_backup_length() {return 5;  // x86需要5字节覆盖
}// 创建跳板shellcode
LPVOID create_trampoline(uint8_t* target, size_t length) {// 计算跳回地址uintptr_t return_address = reinterpret_cast<uintptr_t>(target) + length;// 分配可执行内存LPVOID exec_mem = VirtualAlloc(NULL, length + 5,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);if (!exec_mem) return NULL;uint8_t* shellcode_ptr = static_cast<uint8_t*>(exec_mem);// 1. 复制原始指令memcpy(shellcode_ptr, target, length);// 2. 添加跳回指令// x86: JMP rel32shellcode_ptr += length;*shellcode_ptr++ = 0xE9; // JMPDWORD jmp_offset = (DWORD)return_address - (DWORD)shellcode_ptr;*reinterpret_cast<DWORD*>(shellcode_ptr) = jmp_offset;// 刷新内存memory_barrier();FlushInstructionCache(GetCurrentProcess(), exec_mem, length + 5);return exec_mem;
}// Hook 函数实现
int WINAPI hooked_message_box(HWND hwnd, LPCSTR lp_text, LPCSTR lp_caption, UINT u_type) {char hooked_text[256] = { 0 };const char* prefix = "[HOOKED] ";// 安全组合新消息strcpy_s(hooked_text, sizeof(hooked_text), prefix);if (lp_text) {// 防止缓冲区溢出size_t prefix_len = strlen(prefix);size_t max_copy = sizeof(hooked_text) - prefix_len - 1;strncat_s(hooked_text, sizeof(hooked_text), lp_text, max_copy);}// 调用原始功能using trampoline_func = int(WINAPI*)(HWND, LPCSTR, LPCSTR, UINT);trampoline_func trampoline = reinterpret_cast<trampoline_func>(trampoline_shellcode);// 调试输出OutputDebugStringA("Hooked function called");OutputDebugStringA(hooked_text);return trampoline(hwnd, hooked_text, lp_caption ? lp_caption : "Hooked MessageBox", u_type);
}// 安装 Hook
bool install_hook() {// 1. 使用自定义函数作为源original_message_box = &MessageBoxA;// 2. 计算备份长度backup_length = calculate_backup_length();// 3. 创建跳板 Shellcodetrampoline_shellcode = create_trampoline(reinterpret_cast<uint8_t*>(original_message_box), backup_length);if (!trampoline_shellcode) {OutputDebugStringA("Failed to create trampoline shellcode");return false;}// 4. 构造跳转指令到 Hook 函数uint8_t jump_code[16] = { 0 };uintptr_t hook_address = reinterpret_cast<uintptr_t>(&hooked_message_box);size_t jump_size = 0;// x86: JMP rel32 (5字节)jump_code[0] = 0xE9; // JMPDWORD jmp_offset = static_cast<DWORD>(hook_address) -(reinterpret_cast<DWORD>(original_message_box) + 5);*reinterpret_cast<DWORD*>(jump_code + 1) = jmp_offset;jump_size = 5;// 5. 写入跳转指令DWORD old_protect;if (!VirtualProtect(original_message_box, jump_size, PAGE_EXECUTE_READWRITE, &old_protect)) {OutputDebugStringA("VirtualProtect failed");return false;}// 使用内存屏障保证顺序memory_barrier();// 写入跳转代码memcpy(original_message_box, jump_code, jump_size);memory_barrier();FlushInstructionCache(GetCurrentProcess(), original_message_box, jump_size);DWORD temp;VirtualProtect(original_message_box, jump_size, old_protect, &temp);return true;
}// 示例用法
int main() {// 安装Hook前测试MessageBoxA(NULL, "Pre-Hook Test", "Original", MB_OK);// 安装Hookif (!install_hook()) {MessageBoxA(NULL, "Hook installation failed", "Error", MB_OK);return 1;}// 使用HookMessageBoxA(NULL, "Hello World", "Test", MB_OK);return 0;
}

💎 结论:跳板钩子的技术本质与价值

跳板(Trampoline)是Inline Hook的安全执行引擎,通过三阶协作实现无损劫持:

  1. 劫持层:通过JMP指令重定向执行流(原子化写入保障线程安全)
  2. 过滤层:Hook函数实现参数过滤/日志记录(上下文一致性是关键)
  3. 还原层:跳板执行备份指令并跳回原函数(精确计算跳回地址)

在多线程场景下,需结合热补丁机制指令缓存刷新_mm_sfence() + FlushInstructionCache)确保原子可见性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90202.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90202.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云服务器的安全防护指南:从基础安全设置到高级威胁防御

随着云计算的广泛应用&#xff0c;云服务器已成为企业和个人存储数据、运行应用的重要基础设施。然而&#xff0c;随之而来的安全威胁也日益增多——从常见的网络攻击&#xff08;如 DDoS、SQL 注入&#xff09;到复杂的恶意软件和零日漏洞&#xff0c;无一不考验着系统的安全性…

状态机管家:MeScroll 的交互秩序维护

一、核心架构设计与性能基石 MeScroll作为高性能滚动解决方案&#xff0c;其架构设计遵循"分层解耦、精准控制、多端适配"的原则&#xff0c;通过四大核心模块实现流畅的滚动体验&#xff1a; 事件控制层&#xff1a;精准捕获触摸行为&#xff0c;区分滚动方向与距…

数据出海的隐形冰山:企业如何避开跨境传输的“合规漩涡”?

首席数据官高鹏律师数字经济团队创作&#xff0c;AI辅助凌晨三点的写字楼&#xff0c;某跨境电商的技术总监盯着屏幕上的报错提示&#xff0c;指尖悬在键盘上迟迟没落下。刚从新加坡服务器调取的用户行为数据&#xff0c;在传输到国内分析系统时被拦截了——系统提示“不符合跨…

【Rust base64库】Rust bas64编码解码详细解析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Rust开发…

如何利用AI大模型对已有创意进行评估,打造杀手级的广告创意

摘要 广告创意是影响广告效果的最重要的因素之一&#xff0c;但是如何评估和优化广告创意&#xff0c;一直是一个难题。传统的方法&#xff0c;如人工评审、A/B测试、点击率等&#xff0c;都有各自的局限性和缺陷。本文将介绍一种新的方法&#xff0c;即利用人工智能大模型&am…

OSCP - HTB - Cicada

主要知识点 SMB 用户爆破Backup Operator 组提权 具体步骤 nmap扫描一下先&#xff0c;就像典型的windows 靶机一样&#xff0c;开放了N多个端口 Nmap scan report for 10.10.11.35 Host is up (0.19s latency). Not shown: 65522 filtered tcp ports (no-response) PORT …

10046 解决 Oracle error

How to Offline a PDB Datafile in NOARCHIVELOG mode CDB which is not Open in Read Write (Doc ID 2240730.1)1. pdb 下的datafile 只能在pdb下操作&#xff0c;不能在cdb下操作For the purposes of this document, the following fictitious environment is used as an exa…

在HP暗影精灵Ubuntu20.04上修复IntelAX211Wi-Fi不可用的全过程记录——系统安装以后没有WIFI图标无法使用无线网

在 HP 暗影精灵 Ubuntu 20.04 上修复 Intel AX211 Wi-Fi 不可用的全过程记录 2025 年 7 月初 系统环境&#xff1a;HP OMEN&#xff08;暗影精灵&#xff09;笔记本 | 双系统 Windows 11 & Ubuntu 20.04 | 内核 5.15 / 6.15 mainline 问题关键词&#xff1a;Intel AX21…

Sql server 中关闭ID自增字段(SQL取消ID自动增长)

sql server在导入数据的时候&#xff0c;有时候要考虑id不变&#xff0c;就要先取消自动增长再导入数据&#xff0c;导完后恢复自增。 比如网站改版从旧数据库导入新数据库&#xff0c;数据库结构不相同&#xff0c;可能会使用insert into xx select ..from yy的语句导入数据。…

Python实现文件夹中文件名与Excel中存在的文件名进行对比,并进行删除操作

以下python程序版本为Python3.13.01.请写一个python程序&#xff0c;实现以下逻辑&#xff1a;从文件夹获取所有文件名&#xff0c;与Excel中的fileName列进行对比&#xff0c;凡是不在该文件夹下的文件名&#xff0c;从Excel文档中删除后&#xff0c;并将Excel中fileName和fil…

广告业务动态查询架构设计:从数据建模到可视化呈现

在数字化营销领域&#xff0c;广告主每天面临着海量数据带来的分析挑战&#xff1a;从账户整体投放效果&#xff0c;到分渠道、分地域的精细化运营&#xff0c;每一层级的数据洞察都需要灵活高效的查询能力。我们的广告业务动态查询系统&#xff0c;正是为解决这类需求而生 &am…

pytorch、torchvision与python版本对应关系

pytorch、torchvision与python版本对应关系 可以查看官网&#xff1a; https://github.com/pytorch/vision#installation

【机器学习笔记 Ⅲ】3 异常检测算法

异常检测算法&#xff08;Anomaly Detection&#xff09;详解 异常检测是识别数据中显著偏离正常模式的样本&#xff08;离群点&#xff09;的技术&#xff0c;广泛应用于欺诈检测、故障诊断、网络安全等领域。以下是系统化的解析&#xff1a;1. 异常类型类型描述示例点异常单个…

【ssh】在 Windows 上生成 SSH 公钥并实现免密登录 Linux

在 Windows 上生成 SSH 公钥并实现免密登录 Linux&#xff0c;可以使用 ssh-keygen 命令&#xff0c;这是 Windows 10 和 Windows 11 中默认包含的 OpenSSH 工具的一部分。下面是详细步骤&#xff1a; 在 Windows 上生成 SSH 公钥 打开 PowerShell 或命令提示符&#xff1a; 在…

MS51224 一款 16 位、3MSPS、双通道、同步采样模数转换器(ADC)

MS51224 是一款 16 位、3MSPS、双通道、同步采样模数转换器&#xff08;ADC&#xff09;&#xff0c;具有集成的内部参考和参考电压缓冲器。芯片可由 5V 单电源供电&#xff0c;支持单极性和全差分模拟信号输入&#xff0c;具有出色的直流和交流性能。芯片模拟输入信号频率高达…

WPF学习(四)

文章目录一、用户控价1.1 依赖属性的注册1.2 具体使用一、用户控价 1.1 依赖属性的注册 using System.Windows; using System.Windows.Controls;namespace WpfApp {public partial class MyUserControl : UserControl{// 依赖属性&#xff1a;外部可绑定的文本public static …

vue3+typescript项目配置路径别名@

1. vite.config.ts配置//方法1 import { defineConfig } from vite; import vue from vitejs/plugin-vue; import path from path;export default defineConfig({plugins: [vue()],resolve: {alias: {: path.resolve(__dirname, src)}} });//方法2,需要执行npm install -D type…

MySql 常用SQL语句、 SQL优化

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨SQL语句主要分为哪几类 SQL&#xff08;结构化查询语言&#xff09;是用于管理和操作关系型数据库的标准语言&#xff0c;其语句通常根据功能划分为以下几大类&#xff0c;每类包含不同的子句和命令&#xff0c;用于实现特定的数据库操作需求&am…

代理模式实战指南:打造高性能RPC调用与智能图片加载系统

代理模式实战指南&#xff1a;打造高性能RPC调用与智能图片加载系统 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不停歇的探索者。 ✨ 用代码丈量…

登山第二十六梯:单目3D检测一切——一只眼看世界

文章目录 一 摘要 二 资源 三 内容 一 摘要 尽管深度学习在近距离 3D 对象检测方面取得了成功&#xff0c;但现有方法难以实现对新对象和相机配置的零镜头泛化。我们介绍了 DetAny3D&#xff0c;这是一种可提示的 3D 检测基础模型&#xff0c;能够在任意相机配置下仅使用单目…