I’m currently trying to write a small application in C++ which sets a hardware breakpoint in an external program, edits a register and then continues the run of the debuggee. My code is working pretty well so far but there are a few problems I am facing when it comes to triggering the hardware breakpoint again.
First off this is my code. I can assure that the process id, the handles and the permissions aren’t causing the trouble.
while (true)
{
if (WaitForDebugEvent(&dbgEvent, INFINITE) == 0)
break;
if(dbgEvent.dwDebugEventCode == EXCEPTION_BREAKPOINT)
{
if (dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)lpAddress)
{
CONTEXT ctx;
ctx.ContextFlags = CONTEXT_ALL;
GetThreadContext(hThread, &ctx);
if (ctx.Rip != (DWORD64)lpAddress) {
ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE);
continue;
}
ctx.Rbp = 1;
ctx.Dr0 = 0;
ctx.Dr1 = 0;
ctx.Dr2 = 0;
ctx.Dr3 = 0;
ctx.Dr7 = 0;
SetThreadContext(hThread, &ctx);
once = true;
}
}
else if (once) {
CONTEXT ctx;
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
GetThreadContext(hThread, &ctx);
ctx.Dr0 = reinterpret_cast<DWORD_PTR>(lpAddress);
ctx.Dr7 |= 1;
SetThreadContext(hThread, &ctx);
once = false;
}
ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE);
}
Before entering the while loop i am doing the following:
LPVOID lpAddress = (LPVOID)breakaddress;
CONTEXT context;
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
if (!DebugActiveProcess(dwProcessId))
{
return 1;
}
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, threadID);
if (hThread == NULL)
{
DebugActiveProcessStop(dwProcessId);
return 1;
}
DWORD dwSuspendCount = SuspendThread(hThread);
if (dwSuspendCount == (DWORD)-1)
{
CloseHandle(hThread);
DebugActiveProcessStop(dwProcessId);
return 1;
}
if (!GetThreadContext(hThread, &context))
{
CloseHandle(hThread);
DebugActiveProcessStop(dwProcessId);
return 1;
}
context.Dr0 = reinterpret_cast<DWORD_PTR>(lpAddress);
context.Dr7 |= 1;
if (!SetThreadContext(hThread, &context))
{
CloseHandle(hThread);
DebugActiveProcessStop(dwProcessId);
return 1;
}
ResumeThread(hThread);
None of those error catches are getting triggered so those calls shouldn’t be the problem.
Now to my problems:
The first and most annoying problem is that the breakpoint only hits once. As soon as the function executes at the hardware breakpoint address again. It doesn’t break.
I already tried tons of different approaches from clearing only the DR7 register to clearing every debug register. Nothing seems to work here for some very odd reason.
The second problem is that the if statements hits way to often for some reason. Thats why I had to insert the rip check to really ensure that the code only executes when the program runs into my hardware breakpoint.
What I tried so far?
Pretty much everything. I tested almost every combination of possible exceptions in the if statement. I tried restarting my application as soon as the first hit got handled to then reattach my program. All that without any success.
I hope anyone here can help me
Thanks
Gero B. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.