mirror of https://github.com/x64dbg/GleeBug
correctly handle breakpoints happening before the system breakpoint
This commit is contained in:
parent
2dd2cb1e3d
commit
7dc011516d
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue