windows中如何检测自己的程序被下了硬件断点
写了调试器A(好吧这是个外挂)和测试程序B
用A给B下硬件断点,hook了
Wow64GetThreadContext
,处理断点异常时,先取ESP+8(最先进栈的最右参,寄存器的缓存结构体),对着*(*(ESP+8)+4)WriteProcessMemory了24位0(**(ESP)是寄存器结构体的第一个字节,从4至28是DR0,DR1,DR2,DR3,DR6,DR7)。在B中用
Wow64GetThreadContext
和
GetThreadContext
都读不出DR0-DR7了。测了无数遍调试器A和程序B都没bug。
但是在11对战平台还是被检测了,log上
Wow64GetThreadContext
都没被执行。。。
所以想问除了
Wow64GetThreadContext
和
GetThreadContext
之外有其他的获取硬件断点的方法吗?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;
}