WIN10使用VEH+硬件断点实现不修改代码完成破解

文章介绍了如何在WIN10系统下,通过硬件断点(硬件HOOK)来绕过全代码检测,以实现不修改代码的破解。硬件断点原理是利用DR0寄存器触发异常,通过异常处理函数执行特定操作。在WIN7中可直接应用,而在WIN10中由于限制,需先挂起线程再设置断点。作者提供了WIN7和WIN10的示例代码,帮助理解实施过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么要使用硬件断点?
有些程序会启动一个线程,实时检测代码节是否被修改,这样可以防止作弊者使用OD调试程序时下CC断点,这种技术叫全代码检测或CRC检测。为了绕过这种检测,大佬们想出了很多办法:

  • 干掉CRC线程
  • 干掉CRC函数的判断
  • 绕过CRC检测的位置,到更底层去修改
  • 硬件HOOK
  • 其他HOOK,欺骗CRC检测函数(虚表HOOK)
  • 干掉退出函数(ExitProcess)

本文介绍的是硬件断点(硬件HOOK)。

硬件断点原理

当执行到某个指令,DR0寄存器中存储了这条指令的地址,就会触发异常。如果使用 AddVectoredExceptionHandler 函数注册了全局异常处理,则程序会跳转到异常处理函数。在异常处理函数内,做相应的操作(或者什么也不做),最后JMP到触发异常的下一条指令,就完成了HOOK破解。
在异常处理函数内,可以通过 PEXCEPTION_POINTERS 参数判断触发异常的指令是不是我们定位的关键指令,如果是,才执行上述操作。

WIN7示例代码
本例使用DLL劫持技术,劫持winspool.drv。您也可以使用其他DLL注入技术,无所谓的。

winspool.drv VEH+硬件断点部分代码
注意,这段代码只能在WIN7上运行,在WIN10则无法断下,在WIN10中设置硬件断点必须先挂起线程,因此我们需要创建一个子线程,将主线程挂起后,再在主线程中设置硬件断点。可以参考这篇文章:https://bbs.pediy.com/thread-258083.htm

DWORD g_dwBreakpoint = 0x401053; // 关键指令,希望跳过这条指令

// 设置硬件断点函数
void SetHardwareBreakPoint()
{
   
   
	CONTEXT ctx;
	ctx.ContextFlags = CONTEXT_ALL;
	GetThreadContext(GetCurrentThread(), &ctx);
	ctx.Dr7 = (DWORD)1; // 启用Dr0
	ctx.Dr0 = g_dwBreakpoint; // 设置硬件断点	
	SetThreadContext(GetCurrentThread(), &ctx);
}

// 异常处理函数
DWORD NTAPI ExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
#include <windows.h> #include <iostream> // 全局变量 DWORD g_BreakpointAddr = 0; // Hook目标地址 PVOID g_VehHandler = nullptr; // VEH句柄 // VEH异常处理函数 LONG WINAPI MyExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) { if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress == g_BreakpointAddr) { std::cout << ">>> MessageBoxA Hooked! <<<\n"; // 获取参数 const char* text = (const char*)ExceptionInfo->ContextRecord->Ecx; const char* caption = (const char*)ExceptionInfo->ContextRecord->Edx; std::cout << "Text: " << (text ? text : "NULL") << "\n"; std::cout << "Caption: " << (caption ? caption : "NULL") << "\n"; // 修改参数(演示如何篡改) if (text && strcmp(text, "aaa") == 0) { ExceptionInfo->ContextRecord->Ecx = (DWORD)"HACKED!"; } // 跳过原始调用(设置返回值) ExceptionInfo->ContextRecord->Eax = IDOK; // 继续执行(跳过2字节的call指令) ExceptionInfo->ContextRecord->Eip += 2; return EXCEPTION_CONTINUE_EXECUTION; } } return EXCEPTION_CONTINUE_SEARCH; } int main() { // 1. 获取MessageBoxA地址 HMODULE hUser32 = LoadLibraryA("user32.dll"); if (!hUser32) { std::cerr << "Failed to load user32.dll\n"; return 1; } g_BreakpointAddr = (DWORD)GetProcAddress(hUser32, "MessageBoxA"); if (!g_BreakpointAddr) { std::cerr << "Failed to find MessageBoxA\n"; return 1; } std::cout << "MessageBoxA address: 0x" << std::hex << g_BreakpointAddr << "\n"; // 2. 设置硬件断点 CONTEXT ctx = { 0 }; ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; ctx.Dr0 = g_BreakpointAddr; // 断点地址 ctx.Dr7 = 0x00000001; // DR0启用执行断点 if (!SetThreadContext(GetCurrentThread(), &ctx)) { std::cerr << "SetThreadContext failed: " << GetLastError() << "\n"; return 1; } // 3. 注册VEH异常处理 g_VehHandler = AddVectoredExceptionHandler(1, MyExceptionHandler); if (!g_VehHandler) { std::cerr << "AddVectoredExceptionHandler failed\n"; return 1; } std::cout << "VEH handler registered. Testing hook...\n\n"; // 4. 测试Hook MessageBoxA(NULL, "aaa", "Original Caption", MB_OK); MessageBoxA(NULL, "bbb", "Another Test", MB_OK); // 5. 清理 RemoveVectoredExceptionHandler(g_VehHandler); std::cout << "\nHook unregistered. Program exiting.\n"; return 0; } 把这个代码修改win10 x64版本的
最新发布
07-25
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值