correctly handle breakpoints happening before the system breakpoint

This commit is contained in:
Duncan Ogilvie 2017-12-28 21:07:19 +01:00
parent 2dd2cb1e3d
commit 7dc011516d
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
1 changed files with 56 additions and 56 deletions

View File

@ -4,72 +4,72 @@ namespace GleeBug
{ {
void Debugger::exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) void Debugger::exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance)
{ {
if (!mProcess->systemBreakpoint) //handle system breakpoint //check if the breakpoint exists
auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Software, ptr(exceptionRecord.ExceptionAddress) });
if(foundInfo == mProcess->breakpoints.end())
{ {
//set internal state if(!mProcess->systemBreakpoint) //handle system breakpoint
mProcess->systemBreakpoint = true;
mContinueStatus = DBG_CONTINUE;
//get process DEP policy
#ifndef _WIN64
typedef BOOL(WINAPI * GETPROCESSDEPPOLICY)(
_In_ HANDLE /*hProcess*/,
_Out_ LPDWORD /*lpFlags*/,
_Out_ PBOOL /*lpPermanent*/
);
static auto GPDP = GETPROCESSDEPPOLICY(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetProcessDEPPolicy"));
if (GPDP)
{ {
//If you use mProcess->hProcess GetProcessDEPPolicy will put garbage in bPermanent. //set internal state
auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, mProcess->dwProcessId); mProcess->systemBreakpoint = true;
DWORD lpFlags; mContinueStatus = DBG_CONTINUE;
BOOL bPermanent;
if (GPDP(hProcess, &lpFlags, &bPermanent)) //get process DEP policy (TODO: what happens if a breakpoint is hit before the system breakpoint?)
mProcess->permanentDep = lpFlags != 0 && bPermanent; #ifndef _WIN64
CloseHandle(hProcess); typedef BOOL(WINAPI * GETPROCESSDEPPOLICY)(
} _In_ HANDLE /*hProcess*/,
_Out_ LPDWORD /*lpFlags*/,
_Out_ PBOOL /*lpPermanent*/
);
static auto GPDP = GETPROCESSDEPPOLICY(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetProcessDEPPolicy"));
if(GPDP)
{
//If you use mProcess->hProcess GetProcessDEPPolicy will put garbage in bPermanent.
auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, mProcess->dwProcessId);
DWORD lpFlags;
BOOL bPermanent;
if(GPDP(hProcess, &lpFlags, &bPermanent))
mProcess->permanentDep = lpFlags != 0 && bPermanent;
CloseHandle(hProcess);
}
#else #else
mProcess->permanentDep = true; mProcess->permanentDep = true;
#endif //_WIN64 #endif //_WIN64
//call the callback //call the callback
cbSystemBreakpoint(); cbSystemBreakpoint();
}
return;
} }
else
const auto info = foundInfo->second;
//set continue status
mContinueStatus = DBG_CONTINUE;
//set back the instruction pointer
mRegisters->Gip = info.address;
//restore the original breakpoint byte and do an internal step
mProcess->MemWriteUnsafe(info.address, info.internal.software.oldbytes, info.internal.software.size);
mThread->StepInternal(std::bind([this, info]()
{ {
//check if the breakpoint exists //only restore the bytes if the breakpoint still exists
auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Software, ptr(exceptionRecord.ExceptionAddress) }); if(mProcess->breakpoints.find({ BreakpointType::Software, info.address }) != mProcess->breakpoints.end())
if (foundInfo == mProcess->breakpoints.end()) mProcess->MemWriteUnsafe(info.address, info.internal.software.newbytes, info.internal.software.size);
return; }));
const auto info = foundInfo->second;
//set continue status //call the generic callback
mContinueStatus = DBG_CONTINUE; cbBreakpoint(info);
//set back the instruction pointer //call the user callback
mRegisters->Gip = info.address; auto foundCallback = mProcess->breakpointCallbacks.find({ BreakpointType::Software, info.address });
if(foundCallback != mProcess->breakpointCallbacks.end())
foundCallback->second(info);
//restore the original breakpoint byte and do an internal step //delete the breakpoint if it is singleshoot
mProcess->MemWriteUnsafe(info.address, info.internal.software.oldbytes, info.internal.software.size); if(info.singleshoot)
mThread->StepInternal(std::bind([this, info]() mProcess->DeleteGenericBreakpoint(info);
{
//only restore the bytes if the breakpoint still exists
if (mProcess->breakpoints.find({ BreakpointType::Software, info.address }) != mProcess->breakpoints.end())
mProcess->MemWriteUnsafe(info.address, info.internal.software.newbytes, info.internal.software.size);
}));
//call the generic callback
cbBreakpoint(info);
//call the user callback
auto foundCallback = mProcess->breakpointCallbacks.find({ BreakpointType::Software, info.address });
if (foundCallback != mProcess->breakpointCallbacks.end())
foundCallback->second(info);
//delete the breakpoint if it is singleshoot
if (info.singleshoot)
mProcess->DeleteGenericBreakpoint(info);
}
} }
void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance)