HOOK专题
5、VEH INT3Hook
一、课程目标
本节课主要学习VEH INT3 Hook技术,这是一种基于Windows异常处理机制的高级Hook方法。通过本课的学习,你将能够:
- 理解VEH(Vectored Exception Handler)的基本概念和工作机制
- 掌握INT3断点指令的使用方法
- 实现基于VEH和INT3的Hook框架
- 理解异常处理在Hook技术中的应用
- 学习VEH Hook的检测和防护方法
二、名词解释表
| 名词 | 解释 |
|---|---|
| VEH | Vectored Exception Handler,向量化异常处理程序 |
| INT3 | 中断3指令,用于软件断点的特殊指令(0xCC) |
| 异常处理 | Windows系统处理程序运行时异常的机制 |
| 断点 | 调试器用来暂停程序执行的机制 |
| 调试寄存器 | CPU提供的用于硬件断点的寄存器(DR0-DR7) |
| SEH | Structured Exception Handling,结构化异常处理 |
三、技术原理
3.1 VEH概述
VEH(Vectored Exception Handler)是Windows Vista及以后版本提供的异常处理机制。与传统的SEH不同,VEH采用链表结构管理异常处理程序,并且优先级更高。VEH通过AddVectoredExceptionHandler函数注册,通过RemoveVectoredExceptionHandler函数注销。
3.2 INT3指令
INT3(0xCC)是x86/x64架构中的调试中断指令,专门用于设置软件断点。当CPU执行到INT3指令时,会产生一个异常,调试器或其他异常处理程序可以捕获这个异常并进行相应处理。
3.3 VEH INT3 Hook原理
VEH INT3 Hook结合了VEH异常处理机制和INT3断点指令:
- 在目标函数入口处插入INT3指令(0xCC)
- 注册VEH异常处理程序
- 当程序执行到INT3指令时,触发异常
- VEH处理程序捕获异常,执行Hook逻辑
- 恢复原始指令并继续执行
3.4 技术优势
- 隐蔽性强:不修改函数代码结构
- 兼容性好:适用于各种类型的函数
- 灵活性高:可以在异常处理程序中执行任意逻辑
- 稳定性佳:基于系统异常处理机制
四、代码实现
4.1 核心数据结构
#include <windows.h>
#include <stdio.h>
// VEH Hook信息结构体
typedef struct _VEH_HOOK_INFO {
CHAR szFunctionName[64]; // 函数名称
PVOID pTargetAddress; // 目标函数地址
BYTE originalByte; // 原始字节
PVOID pHookFunction; // Hook函数地址
PVOID pTrampoline; // Trampoline地址
BOOL bIsHooked; // 是否已Hook
BOOL bInException; // 是否正在异常处理中
} VEH_HOOK_INFO, * PVEH_HOOK_INFO;
// VEH Hook管理器
typedef struct _VEH_HOOK_MANAGER {
VEH_HOOK_INFO* pHooks; // Hook信息数组
INT nHookCount; // Hook数量
PVOID pExceptionHandler; // 异常处理程序句柄
} VEH_HOOK_MANAGER, * PVEH_HOOK_MANAGER;
4.2 异常处理程序实现
// 全局VEH管理器指针
PVEH_HOOK_MANAGER g_pVEHManager = NULL;
// VEH异常处理程序
LONG WINAPI VEHExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
// 检查是否为INT3异常
if (pExceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_BREAKPOINT) {
return EXCEPTION_CONTINUE_SEARCH;
}
// 获取异常发生的地址
PVOID exceptionAddr = (PVOID)pExceptionInfo->ExceptionRecord->ExceptionAddress;
// 查找对应的Hook信息
for (INT i = 0; i < g_pVEHManager->nHookCount; i++) {
PVEH_HOOK_INFO pHook = &g_pVEHManager->pHooks[i];
// 检查是否是我们设置的断点
if (pHook->pTargetAddress == exceptionAddr && pHook->bIsHooked) {
// 标记正在异常处理中
pHook->bInException = TRUE;
// 恢复原始字节
DWORD oldProtect;
VirtualProtect(pHook->pTargetAddress, 1, PAGE_EXECUTE_READWRITE, &oldProtect);
*(PBYTE)pHook->pTargetAddress = pHook->originalByte;
VirtualProtect(pHook->pTargetAddress, 1, oldProtect, &oldProtect);
// 设置返回地址(跳过INT3指令)
pExceptionInfo->ContextRecord->Rip++; // x64
// 调用Hook函数(如果提供了的话)
if (pHook->pHookFunction) {
// 这里可以根据需要调用自定义Hook函数
// 为了简化,我们只记录日志
printf("[VEH Hook] Function %s called at address %p\n", pHook->szFunctionName, pHook->pTargetAddress);
}
return EXCEPTION_CONTINUE_EXECUTION;
}
}
// 不是我们的断点,继续搜索其他处理程序
return EXCEPTION_CONTINUE_SEARCH;
}
// 初始化VEH Hook管理器
PVEH_HOOK_MANAGER InitVEHHookManager() {
PVEH_HOOK_MANAGER pManager = (PVEH_HOOK_MANAGER)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VEH_HOOK_MANAGER));
if (!pManager) {
return NULL;
}
// 注册VEH异常处理程序
pManager->pExceptionHandler = AddVectoredExceptionHandler(1, VEHExceptionHandler);
if (!pManager->pExceptionHandler) {
HeapFree(GetProcessHeap(), 0, pManager);
return NULL;
}
// 设置全局指针
g_pVEHManager = pManager;
return pManager;
}
4.3 VEH INT3 Hook核心实现
// 安装VEH INT3 Hook
BOOL InstallVEHInt3Hook(PVEH_HOOK_INFO pHookInfo) {
if (!pHookInfo || !pHookInfo->pTargetAddress) {
return FALSE;
}
// 备份原始字节
pHookInfo->originalByte = *(PBYTE)pHookInfo->pTargetAddress;
// 修改内存保护属性
DWORD oldProtect;
if (!VirtualProtect(pHookInfo->pTargetAddress, 1, PAGE_EXECUTE_READWRITE, &oldProtect)) {
return FALSE;
}
// 插入INT3指令(0xCC)
*(PBYTE)pHookInfo->pTargetAddress = 0xCC;
// 恢复内存保护属性
VirtualProtect(pHookInfo->pTargetAddress, 1, oldProtect, &oldProtect);
pHookInfo->bIsHooked = TRUE;
pHookInfo->bInException = FALSE;
return TRUE;
}
// 卸载VEH INT3 Hook
BOOL UninstallVEHInt3Hook(PVEH_HOOK_INFO pHookInfo) {
if (!pHookInfo || !pHookInfo->bIsHooked) {
return FALSE;
}
// 如果正在异常处理中,等待处理完成
while (pHookInfo->bInException) {
Sleep(1);
}
// 恢复原始字节
DWORD oldProtect;
if (!VirtualProtect(pHookInfo->pTargetAddress, 1, PAGE_EXECUTE_READWRITE, &oldProtect)) {
return FALSE;
}
*(PBYTE)pHookInfo->pTargetAddress = pHookInfo->originalByte;
// 恢复内存保护属性
VirtualProtect(pHookInfo->pTargetAddress, 1, oldProtect, &oldProtect);
pHookInfo->bIsHooked = FALSE;
return TRUE;
}
// 添加Hook到管理器
BOOL AddVEHInt3Hook(PVEH_HOOK_MANAGER pManager, LPCSTR functionName, PVOID targetAddress, PVOID hookFunction) {
// 重新分配内存
PVEH_HOOK_INFO pNewHooks = (PVEH_HOOK_INFO)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
pManager->pHooks, sizeof(VEH_HOOK_INFO) * (pManager->nHookCount + 1));
if (!pNewHooks) {
return FALSE;
}
pManager->pHooks = pNewHooks;
// 填充Hook信息
PVEH_HOOK_INFO pHook = &pManager->pHooks[pManager->nHookCount];
strcpy_s(pHook->szFunctionName, sizeof(pHook->szFunctionName), functionName);
pHook->pTargetAddress = targetAddress;
pHook->pHookFunction = hookFunction;
pHook->bIsHooked = FALSE;
pHook->bInException = FALSE;
// 安装Hook
if (!InstallVEHInt3Hook(pHook)) {
return FALSE;
}
pManager->nHookCount++;
return TRUE;
}
4.4 完整VEH Hook管理器
// 移除所有VEH Hook
VOID RemoveAllVEHInt3Hooks(PVEH_HOOK_MANAGER pManager) {
if (!pManager) {
return;
}
// 卸载所有Hook
for (INT i = 0; i < pManager->nHookCount; i++) {
UninstallVEHInt3Hook(&pManager->pHooks[i]);
}
// 注销VEH异常处理程序
if (pManager->pExceptionHandler) {
RemoveVectoredExceptionHandler(pManager->pExceptionHandler);
}
// 释放内存
if (pManager->pHooks) {
HeapFree(GetProcessHeap(), 0, pManager->pHooks);
}
// 清理全局指针
g_pVEHManager = NULL;
HeapFree(GetProcessHeap(), 0, pManager);
}
// 获取函数地址的辅助函数
PVOID GetFunctionAddress(LPCSTR moduleName, LPCSTR functionName) {
HMODULE hModule = GetModuleHandleA(moduleName);
if (!hModule) {
return NULL;
}
return GetProcAddress(hModule, functionName);
}
4.5 示例应用
// 示例Hook函数
VOID MyMessageBoxHook() {
printf("[VEH INT3 Hook] MessageBox function called!\n");
}
VOID MySleepHook() {
printf("[VEH INT3 Hook] Sleep function called!\n");
}
// 使用示例
VOID DemoVEHInt3Hook() {
// 初始化VEH Hook管理器
PVEH_HOOK_MANAGER pManager = InitVEHHookManager();
if (!pManager) {
printf("Failed to initialize VEH Hook manager.\n");
return;
}
// 获取目标函数地址
PVOID pMessageBoxAddr = GetFunctionAddress("user32.dll", "MessageBoxW");
PVOID pSleepAddr = GetFunctionAddress("kernel32.dll", "Sleep");
if (pMessageBoxAddr) {
if (AddVEHInt3Hook(pManager, "MessageBoxW", pMessageBoxAddr, (PVOID)MyMessageBoxHook)) {
printf("MessageBoxW VEH INT3 Hook installed successfully.\n");
}
}
if (pSleepAddr) {
if (AddVEHInt3Hook(pManager, "Sleep", pSleepAddr, (PVOID)MySleepHook)) {
printf("Sleep VEH INT3 Hook installed successfully.\n");
}
}
// 测试Hook效果
printf("Testing MessageBoxW...\n");
MessageBoxW(NULL, L"Test Message", L"VEH INT3 Hook Test", MB_OK);
printf("Testing Sleep...\n");
Sleep(1000);
// 清理Hook
RemoveAllVEHInt3Hooks(pManager);
printf("All VEH INT3 Hooks removed.\n");
}
4.6 增强版VEH Hook实现
// 带返回值处理的VEH Hook
typedef struct _ENHANCED_VEH_HOOK_INFO {
CHAR szFunctionName[64]; // 函数名称
PVOID pTargetAddress; // 目标函数地址
BYTE originalByte; // 原始字节
PVOID pHookFunction; // Hook函数地址
PVOID pOriginalFunction; // 原始函数指针
BOOL bIsHooked; // 是否已Hook
BOOL bInException; // 是否正在异常处理中
DWORD dwCallCount; // 调用次数统计
ULONGLONG ullTotalTime; // 总执行时间(纳秒)
} ENHANCED_VEH_HOOK_INFO, * PENHANCED_VEH_HOOK_INFO;
// 增强版异常处理程序
LONG WINAPI EnhancedVEHExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
if (pExceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_BREAKPOINT) {
return EXCEPTION_CONTINUE_SEARCH;
}
PVOID exceptionAddr = (PVOID)pExceptionInfo->ExceptionRecord->ExceptionAddress;
for (INT i = 0; i < g_pVEHManager->nHookCount; i++) {
PENHANCED_VEH_HOOK_INFO pHook = (PENHANCED_VEH_HOOK_INFO)&g_pVEHManager->pHooks[i];
if (pHook->pTargetAddress == exceptionAddr && pHook->bIsHooked) {
// 记录开始时间
LARGE_INTEGER freq, start, end;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&start);
pHook->bInException = TRUE;
pHook->dwCallCount++;
// 恢复原始字节
DWORD oldProtect;
VirtualProtect(pHook->pTargetAddress, 1, PAGE_EXECUTE_READWRITE, &oldProtect);
*(PBYTE)pHook->pTargetAddress = pHook->originalByte;
VirtualProtect(pHook->pTargetAddress, 1, oldProtect, &oldProtect);
// 如果有Hook函数,则调用它
if (pHook->pHookFunction) {
// 这里可以传递参数给Hook函数
printf("[Enhanced VEH Hook] Function %s called (count: %lu)\n",
pHook->szFunctionName, pHook->dwCallCount);
}
// 设置返回地址
pExceptionInfo->ContextRecord->Rip++;
// 记录结束时间
QueryPerformanceCounter(&end);
ULONGLONG elapsed = (end.QuadPart - start.QuadPart) * 1000000000ULL / freq.QuadPart;
pHook->ullTotalTime += elapsed;
pHook->bInException = FALSE;
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
五、课后作业
-
基础练习:
- 编写一个程序,使用VEH INT3 Hook技术Hook
CreateFileW函数,记录所有文件创建操作 - 实现Hook
WriteFile函数,监控程序的写文件行为并统计性能数据
- 编写一个程序,使用VEH INT3 Hook技术Hook
-
进阶练习:
- 实现支持函数参数捕获和修改的VEH Hook框架
- 添加Hook函数的返回值处理功能
- 实现Hook调用的性能分析和统计功能
-
思考题:
- VEH INT3 Hook与传统的调试器断点有何区别?
- 如何检测和防范VEH INT3 Hook攻击?
- 多线程环境下VEH INT3 Hook会有哪些并发问题?如何解决?
-
扩展阅读:
- 研究Windows异常处理机制的内部实现
- 了解硬件断点(调试寄存器)的使用方法
- 学习现代调试器如何实现断点功能