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
英文地址,請注明出處:http://en.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;能夠在任意相機配置下僅使用單目…