免杀基础-硬断Hook
字数 1146 2025-08-22 12:23:30
硬件断点Hook技术详解
1. 硬件断点Hook概述
硬件断点Hook是一种通过CPU调试寄存器实现函数拦截的技术,相比传统的Inline Hook(通过修改内存指令实现跳转)具有以下优势:
- 无需修改内存:Inline Hook需要修改目标函数指令(如E8/E9跳转),容易被内存保护机制检测
- 线程级控制:硬件断点只影响安装了它们的线程
- 难以检测:不修改原始代码,检测难度较高
2. 硬件断点原理
2.1 调试寄存器
x86/x64架构提供了8个调试寄存器DR0-DR7:
- DR0-DR3:存储硬件断点的线性地址
- DR6:调试状态寄存器
- DR7:调试控制寄存器(最重要)
2.2 DR7寄存器详解
DR7寄存器控制硬件断点的行为,其结构如下(以64位为例):
typedef struct _DR7 {
DWORD L0 : 1; // DR0局部启用
DWORD G0 : 1; // DR0全局启用
DWORD L1 : 1; // DR1局部启用
DWORD G1 : 1; // DR1全局启用
DWORD L2 : 1; // DR2局部启用
DWORD G2 : 1; // DR2全局启用
DWORD L3 : 1; // DR3局部启用
DWORD G3 : 1; // DR3全局启用
DWORD LE : 1; // 局部精确断点
DWORD GE : 1; // 全局精确断点
DWORD Reserved1 : 3;
DWORD GD : 1; // 调试寄存器访问保护
DWORD Reserved2 : 2;
DWORD RW0 : 2; // DR0触发条件
DWORD LEN0 : 2; // DR0监控长度
DWORD RW1 : 2; // DR1触发条件
DWORD LEN1 : 2; // DR1监控长度
DWORD RW2 : 2; // DR2触发条件
DWORD LEN2 : 2; // DR2监控长度
DWORD RW3 : 2; // DR3触发条件
DWORD LEN3 : 2; // DR3监控长度
DWORD Reserved : 32;
} DR7, *PDR7;
关键字段说明:
- RWx:触发条件
- 00:执行断点
- 01:写入断点
- 10:未使用
- 11:读写断点
- LENx:监控长度
- 00:1字节
- 01:2字节
- 10:8字节(64位)或4字节(32位)
- 11:4字节
3. 硬件断点Hook实现
3.1 基本实现步骤
- 获取线程上下文(GetThreadContext)
- 设置DR0-DR3寄存器(存储断点地址)
- 配置DR7寄存器(控制断点行为)
- 设置线程上下文(SetThreadContext)
- 注册异常处理程序(VEH)
3.2 核心代码实现
3.2.1 设置硬件断点
VOID setBP(HANDLE hThread, DRR dbgR) {
CONTEXT Context = {0};
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(hThread, &Context);
Context.Dr0 = dbgR.DR0;
Context.Dr7 = ConvertDr7(&dbgR.DR7);
SetThreadContext(hThread, &Context);
}
3.2.2 移除硬件断点
VOID removeBP(HANDLE hThread) {
CONTEXT Context = {0};
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(hThread, &Context);
Context.Dr0 = 0;
Context.Dr7 = 0;
SetThreadContext(hThread, &Context);
GetThreadContext(hThread, &Context);
}
3.2.3 异常处理回调
LONG NTAPI ExceptionCallBack(_EXCEPTION_POINTERS* ExceptionInfo) {
if(ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) {
if(ExceptionInfo->ExceptionRecord->ExceptionAddress == (PVOID)ExceptionInfo->ContextRecord->Dr0) {
removeBP(hThread);
ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // RF标志位
// 自定义逻辑
// 修改返回值
ExceptionInfo->ContextRecord->Rax = 1;
// 跳过原函数执行
#ifdef _WIN64
ExceptionInfo->ContextRecord->Rip = (DWORD_PTR)ucRet;
#else
ExceptionInfo->ContextRecord->Eip = (DWORD_PTR)ucRet;
#endif
setBP(hThread, dbgR);
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
3.3 关键点说明
- RF标志位:恢复标志位,防止重复触发断点
- 返回值修改:通过修改RAX/EAX寄存器实现
- 跳过原函数:将RIP/EIP指向ret指令(0xC3)
- 线程安全:每次异常处理后需要重新设置断点
4. 多线程Hook实现
4.1 枚举进程线程
void EnumThreadSetBp(DRR dbgR) {
HMODULE hNtdll = GetModuleHandle(L"ntdll.dll");
pNtQuerySystemInformation NtQuerySystemInformation =
(pNtQuerySystemInformation)(GetProcAddress(hNtdll, "NtQuerySystemInformation"));
ULONG retLen1, retLen2;
NtQuerySystemInformation(SystemProcessInformation, NULL, NULL, &retLen1);
PVOID lpMem = VirtualAlloc(NULL, retLen1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
NTSTATUS status = NtQuerySystemInformation(SystemProcessInformation, lpMem, retLen1, &retLen2);
if(NT_SUCCESS(status)) {
PSYSTEM_PROCESS_INFORMATION processInfo = (PSYSTEM_PROCESS_INFORMATION)lpMem;
while(processInfo->NextEntryOffset != 0) {
PVOID CurrentPid = (PVOID)GetCurrentProcessId();
if(processInfo->UniqueProcessId != 0) {
if((PVOID)processInfo->UniqueProcessId == CurrentPid) {
PSYSTEM_THREAD_INFORMATION threadInfo = (PSYSTEM_THREAD_INFORMATION)processInfo->Threads;
for(ULONG i = 0; i < processInfo->NumberOfThreads; i++) {
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE,
(DWORD)threadInfo->ClientId.UniqueThread);
setBP(hThread, dbgR);
threadInfo++;
}
}
}
processInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)processInfo + processInfo->NextEntryOffset);
}
}
VirtualFree(lpMem, 0, MEM_RELEASE);
}
4.2 多线程Hook注意事项
- 线程权限:需要THREAD_ALL_ACCESS权限
- 线程同步:确保线程在设置断点时处于安全状态
- 性能考虑:每个线程最多4个硬件断点(DR0-DR3限制)
5. 实际应用示例
5.1 修改函数返回值
BOOLEAN testRoutine() {
return (1 > 100); // 原返回FALSE
}
// 在异常处理中修改返回值
ExceptionInfo->ContextRecord->Rax = 1; // 改为返回TRUE
5.2 修改函数参数
// 修改MessageBox参数
ExceptionInfo->ContextRecord->Rcx = (DWORD_PTR)L"New Title";
ExceptionInfo->ContextRecord->Rdx = (DWORD_PTR)L"New Text";
6. 检测与反制
6.1 检测硬件断点
- 检查DR0-DR7寄存器值
- 使用GetThreadContext获取线程上下文
6.2 反制措施
- 随机化断点位置:不在函数入口下断点
- 动态启用/禁用:只在需要时启用断点
- 结合其他Hook技术:与Inline Hook交替使用
7. 总结
硬件断点Hook是一种强大的函数拦截技术,相比传统Hook方法具有更好的隐蔽性。通过合理使用调试寄存器,可以实现:
- 函数调用监控
- 参数修改
- 返回值修改
- 函数执行流程控制
关键点在于正确配置DR7寄存器、妥善处理异常以及管理多线程环境下的断点状态。