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

为什么要使用硬件断点?
有些程序会启动一个线程,实时检测代码节是否被修改,这样可以防止作弊者使用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)
{
	if ((DWORD)pExceptionInfo->ExceptionRecord->ExceptionAddress == g_dwBreakpoint)
	{
		pExceptionInfo->ContextRecord->Eip += 6;
		// 已经处理了异常,不需要调用下一个异常处理来处理该异常
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	return EXCEPTION_CONTINUE_SEARCH;
}



// 入口函数
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
	if (dwReason == DLL_PROCESS_ATTACH)
	{	
		DisableThreadLibraryCalls(hModule);
		AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER) ExceptionHandler);
		SetHardwareBreakPoint(); // 关键跳,希望跳过这条指令
		return Load();
	}
	else if (dwReason == DLL_PROCESS_DETACH)
	{
		Free();
	}

	return TRUE;
}

WIN10示例代码

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

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

// 异常处理函数
DWORD NTAPI ExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
{
	if ((DWORD)pExceptionInfo->ExceptionRecord->ExceptionAddress == g_dwBreakpoint)
	{
		pExceptionInfo->ContextRecord->Eip += 6;
		// 已经处理了异常,不需要调用下一个异常处理来处理该异常
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	return EXCEPTION_CONTINUE_SEARCH;
}

// 设置硬件断点WIN10版本:挂起主线程->设置硬件断点->恢复主线程
DWORD WINAPI SetHardwareBreakPointWIN10Version(LPVOID lpMainThreadId)
{
	HANDLE hMainThread = OpenThread(THREAD_ALL_ACCESS,TRUE,(DWORD)lpMainThreadId);
	SuspendThread(hMainThread);
	CONTEXT ctx;
	ctx.ContextFlags = CONTEXT_ALL;
	GetThreadContext(hMainThread, &ctx);
	ctx.Dr7 = (DWORD)0x1; // 启用Dr0
	ctx.Dr0 = g_dwBreakpoint; // 设置硬件断点	
	SetThreadContext(hMainThread, &ctx);
	ResumeThread(hMainThread);
	return 0;
}



// 入口函数
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
	if (dwReason == DLL_PROCESS_ATTACH)
	{	
		DisableThreadLibraryCalls(hModule);
		AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER) ExceptionHandler);
		//SetHardwareBreakPoint(); // 关键跳,希望跳过这条指令
		CreateThread(0, 0, SetHardwareBreakPointWIN10Version, (LPVOID)GetCurrentThreadId(), 0, 0);
		return Load();
	}
	else if (dwReason == DLL_PROCESS_DETACH)
	{
		Free();
	}

	return TRUE;
}

在WIN10的运行结果
WIN10使用VEH+硬件断点实现不修改代码完成破解_第1张图片

你可能感兴趣的:(WINDOWS逆向)