VEH Hook
一、VEH Hook 原理簡述
將目標 API 首地址頁設為 PAGE_EXECUTE_READ | PAGE_GUARD;
注冊一個 vectored handler(AddVectoredExceptionHandler);
每次調用該 API 時,訪問觸發 STATUS_GUARD_PAGE_VIOLATION 異常;
異常處理器中檢查上下文,判斷是否命中了 Hook;
修改 Context->Eip/Rip 跳轉到你自定義的函數。
二、VEH Hook 示例:劫持 MessageBoxW
使用 C++ + WinAPI,在 VS2022 中完整實現(x86 版本,x64 類似,但注意 RIP 與寄存器偏移不同)。
1. 定義 Hook 函數
#include <windows.h>
#include <iostream>
typedef int (WINAPI* MessageBoxW_t)(HWND, LPCWSTR, LPCWSTR, UINT);
MessageBoxW_t OriginalMessageBoxW = nullptr;
int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) {
return OriginalMessageBoxW(hWnd, L"[Hooked] Hello!", lpCaption, uType);
}
2. 注冊 VEH Hook
PVOID vehHandle = nullptr;
BYTE originalBytes[16] = { 0 }; // 保存原始字節
LPVOID targetAddr = nullptr;
LONG CALLBACK VectoredHandler(PEXCEPTION_POINTERS ExceptionInfo) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) {
CONTEXT* ctx = ExceptionInfo->ContextRecord;
#ifdef _M_IX86
if ((LPVOID)ctx->Eip == targetAddr) {
ctx->Eip = (DWORD)&MyMessageBoxW;
return EXCEPTION_CONTINUE_EXECUTION;
}
#else
if ((LPVOID)ctx->Rip == targetAddr) {
ctx->Rip = (DWORD64)&MyMessageBoxW;
return EXCEPTION_CONTINUE_EXECUTION;
}
#endif
}
return EXCEPTION_CONTINUE_SEARCH;
}
3. 安裝 Hook
void InstallVEHHook() {
HMODULE user32 = GetModuleHandleW(L"user32.dll");
targetAddr = (LPVOID)GetProcAddress(user32, "MessageBoxW");
OriginalMessageBoxW = (MessageBoxW_t)targetAddr;
// 設置 PAGE_GUARD
DWORD oldProtect;
VirtualProtect(targetAddr, 1, PAGE_EXECUTE_READ | PAGE_GUARD, &oldProtect);
// 注冊異常處理器
vehHandle = AddVectoredExceptionHandler(1, VectoredHandler);
}
4. 卸載 Hook(恢復頁面屬性)
void UninstallVEHHook() {
if (vehHandle)
RemoveVectoredExceptionHandler(vehHandle);
if (targetAddr) {
DWORD oldProtect;
VirtualProtect(targetAddr, 1, PAGE_EXECUTE_READ, &oldProtect);
}
}
5. 主程序入口
int main() {
InstallVEHHook();
MessageBoxW(NULL, L"Original Text", L"VEH Hook Test", MB_OK);
UninstallVEHHook();
return 0;
}
二、VEH Hook 的核心優勢
| 優點 | 說明 |
|---|---|
| 無需修改函數指令 | 不像 Inline Hook 會修改目標函數開頭的指令 |
| 不易被檢測 | 安全軟件難以檢測異常邏輯,兼具隱蔽性 |
| 動態可移除 | VEH 異常處理鏈支持動態注冊/移除 |
| 支持任意函數 | 只要可訪問內存的函數都可 Hook |
| 不依賴 IAT 或 Import Table | 可繞過導入表 Hook 檢測或修復 |
| ---- | ---- |
三、VEH Hook 的應用場景
- 安全防護與反調試
- 檢測非法訪問特定地址(如關鍵結構體、PEB);
- 捕捉斷點指令、調試器行為;
- 模擬 "抗調試" 行為:如 Hook NtReadVirtualMemory、IsDebuggerPresent 等 API。
- 逆向分析 / 動態追蹤
- 動態監控某個函數是否被調用(如 MessageBoxW、CreateFileA);
- 記錄 API 調用參數和調用棧,而不破壞原有流程;
- 動態流控跳轉,用于函數劫持或行為重定向。
- 行為監控 / 黑盒注入
- 無需修改原程序代碼,即可監視敏感行為(如網絡、IO 操作);
- 在被保護程序中注入 VEH Hook 實現輕量行為感知。
- 沙箱 / 虛擬化軟件
- 類似沙箱中使用 VEH 捕捉非法執行代碼行為;
- 實現用戶態保護,如監控執行任意 Shellcode 或注入 DLL。
- 自動化測試 / 接口劫持
- 在不修改程序的情況下替換某些 API 響應值;
- 模擬失敗調用、異常路徑測試(如 OpenProcess 返回 NULL);
四、典型 Hook 對比分析
| 技術 | 原理 | 可檢測性 | 修改內存 | 穩定性 |
|---|---|---|---|---|
| IAT Hook | 修改 Import Table | 中 | 是 | 高 |
| Inline Hook | 改寫函數入口指令 | 高 | 是 | 中 |
| VEH Hook | 異常 + 上下文跳轉 | 低 | 否 | 高 |
| Shadow SSDT/SSDT Hook | 修改內核函數表 | 極高 | 是 | 易藍屏(內核) |
五、VEH Hook 的限制
- 無法 Hook 已被內聯展開的函數(比如 Release 模式某些 C 函數);
- 一次訪問后 PAGE_GUARD 會被清除,需手動恢復;
- 對一些地址(如只讀頁、DEP 頁)設置保護無效;
- 不能用于純內核態(但可結合 R3-R0 通信);
六、總結:何時選擇 VEH Hook?
選擇 VEH Hook 通常是在:
- 你想要“隱蔽監控函數調用”;
- 不想觸碰目標函數的指令或 IAT;
- 避免被殺軟、EDR 檢測(反檢測);
- 你正在開發調試工具、注入器、反調試殼等;

浙公網安備 33010602011771號