windows中如何检测自己的程序被下了硬件断点

发布于 2022-08-24 13:41:52 字数 3160 浏览 13 评论 0

写了调试器A(好吧这是个外挂)和测试程序B
用A给B下硬件断点,hook了Wow64GetThreadContext,处理断点异常时,先取ESP+8(最先进栈的最右参,寄存器的缓存结构体),对着*(*(ESP+8)+4)WriteProcessMemory了24位0(**(ESP)是寄存器结构体的第一个字节,从4至28是DR0,DR1,DR2,DR3,DR6,DR7)。在B中用Wow64GetThreadContextGetThreadContext都读不出DR0-DR7了。测了无数遍调试器A和程序B都没bug。

但是在11对战平台还是被检测了,log上Wow64GetThreadContext都没被执行。。。

所以想问除了Wow64GetThreadContextGetThreadContext之外有其他的获取硬件断点的方法吗?11又是用了哪种?

调试器A处理异常的代码如下

#define Wow64GetThreadContext_ADDRESS		0x279BC
#define Wow64GetThreadContext_ADDRESS_END	0x279CF
#define BREAK_OPEN 0x405

//hopen是B进程句柄,FindKernel32是自己写的暴力搜索Kernel32基址的方法,保证没bug,11也没隐藏Kernel32
FindKernel32(hopen,&kernel32Handle);

DWORD wow64GetThreadContextBreakBegin = kernel32Handle + Wow64GetThreadContext_ADDRESS;
DWORD wow64GetThreadContextBreakEnd = kernel32Handle + Wow64GetThreadContext_ADDRESS_END;



if(exceptionAddress == wow64GetThreadContextBreakBegin)
{
	HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, DebugEv.dwThreadId);
	SuspendThread(hThread);
	CONTEXT Regs = {0};
	Regs.ContextFlags = CONTEXT_DEBUG_REGISTERS|CONTEXT_INTEGER|CONTEXT_CONTROL;
	::GetThreadContext(hThread, &Regs);
	Regs.Dr1=wow64GetThreadContextBreakEnd;
	Regs.Dr7=BREAK_OPEN;
	DWORD contextPointer = Regs.Esp + 0x8;
	bret=ReadProcessMemory(hopen,(LPVOID)(contextPointer),&wow64GetContextEAX,4,0);
	::SetThreadContext(hThread, &Regs);
	ResumeThread(hThread);
	CloseHandle(hThread);
}
if(exceptionAddress == wow64GetThreadContextBreakEnd)
{
	HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, DebugEv.dwThreadId);
	SuspendThread(hThread);
	CONTEXT Regs = {0};
	Regs.ContextFlags = CONTEXT_ALL;//CONTEXT_DEBUG_REGISTERS|CONTEXT_INTEGER;
	::GetThreadContext(hThread, &Regs);
	Regs.Dr1=wow64GetThreadContextBreakBegin;
	Regs.Dr7=BREAK_OPEN;
	if(wow64GetContextEAX)
	{
		DWORD buffer[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
		SIZE_T writedCount;
		bret=WriteProcessMemory(hopen, (LPVOID)(wow64GetContextEAX + 4), &buffer, 24, &writedCount);
	}
	::SetThreadContext(hThread, &Regs);
	ResumeThread(hThread);
	CloseHandle(hThread);
}

测试程序B的代码

int main(int argc, char* argv[])
{
	while(1)
	{
		Sleep(1000);
		HANDLE thread = GetCurrentThread();
		{
			WOW64_CONTEXT context;
			context.ContextFlags = CONTEXT_ALL;
			BOOL status = Wow64GetThreadContext(thread, &context);

			if (!status)
			{
				return -1;
			}
			
			printf("WGTC %08x %08x %08x %08x %08x %08x %08x %08x\n", &context, context.ContextFlags, context.Dr0, context.Dr1, context.Dr2, context.Dr3, context.Dr6, context.Dr7);
		}

		{
			static CONTEXT threadContext;
			memset(&threadContext, 0, sizeof(CONTEXT));
			threadContext.ContextFlags = CONTEXT_ALL;
			BOOL status = GetThreadContext(thread, &threadContext);

			printf("GTC %08x %08x %08x %08x %08x %08x %08x %08x\n",
				&threadContext,
				threadContext.ContextFlags,
				threadContext.Dr0,
				threadContext.Dr1,
				threadContext.Dr2,
				threadContext.Dr3,
				threadContext.Dr6,
				threadContext.Dr7);
		}
	}

	return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

执妄 2022-08-31 13:41:52

内核模式PSGetThreadContext和捕获异常也可以拿到寄存器

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文