mirror of https://github.com/x64dbg/GleeBug
added 'DetachAndBreak' function
This commit is contained in:
parent
8652a6aa66
commit
4b7be626fa
|
|
@ -7,6 +7,8 @@ namespace GleeBug
|
||||||
//initialize loop variables
|
//initialize loop variables
|
||||||
mBreakDebugger = false;
|
mBreakDebugger = false;
|
||||||
mIsDebugging = true;
|
mIsDebugging = true;
|
||||||
|
mDetach = false;
|
||||||
|
mDetachAndBreak = false;
|
||||||
|
|
||||||
//use correct WaitForDebugEvent function
|
//use correct WaitForDebugEvent function
|
||||||
typedef BOOL(WINAPI *MYWAITFORDEBUGEVENT)(
|
typedef BOOL(WINAPI *MYWAITFORDEBUGEVENT)(
|
||||||
|
|
@ -23,6 +25,20 @@ namespace GleeBug
|
||||||
|
|
||||||
while (!mBreakDebugger)
|
while (!mBreakDebugger)
|
||||||
{
|
{
|
||||||
|
//execute the delayed-detach
|
||||||
|
if (mDetach)
|
||||||
|
{
|
||||||
|
if (!UnsafeDetach())
|
||||||
|
cbInternalError("Debugger::Detach failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mDetachAndBreak)
|
||||||
|
{
|
||||||
|
if (!UnsafeDetachAndBreak())
|
||||||
|
cbInternalError("Debugger::DetachAndBreak failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//wait for a debug event
|
//wait for a debug event
|
||||||
mIsRunning = true;
|
mIsRunning = true;
|
||||||
if (!MyWaitForDebugEvent(&mDebugEvent, INFINITE))
|
if (!MyWaitForDebugEvent(&mDebugEvent, INFINITE))
|
||||||
|
|
@ -63,7 +79,7 @@ namespace GleeBug
|
||||||
}
|
}
|
||||||
|
|
||||||
//call the pre debug event callback
|
//call the pre debug event callback
|
||||||
cbPostDebugEvent(mDebugEvent);
|
cbPreDebugEvent(mDebugEvent);
|
||||||
|
|
||||||
//dispatch the debug event (documented here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms679302(v=vs.85).aspx)
|
//dispatch the debug event (documented here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms679302(v=vs.85).aspx)
|
||||||
switch (mDebugEvent.dwDebugEventCode)
|
switch (mDebugEvent.dwDebugEventCode)
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,50 @@ namespace GleeBug
|
||||||
return !!TerminateProcess(mMainProcess.hProcess, 0);
|
return !!TerminateProcess(mMainProcess.hProcess, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Detach() const
|
bool Debugger::UnsafeDetach()
|
||||||
{
|
{
|
||||||
return !!DebugActiveProcessStop(mMainProcess.dwProcessId);
|
return !!DebugActiveProcessStop(mMainProcess.dwProcessId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Debugger::Detach()
|
||||||
|
{
|
||||||
|
mDetach = true;
|
||||||
|
mDetachAndBreak = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Debugger::UnsafeDetachAndBreak() //TODO check with child processes
|
||||||
|
{
|
||||||
|
if (!mProcess || !mThread || !mRegisters) //fail when there is no process or thread currently specified
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//write the code that breaks the process
|
||||||
|
auto codePtr = ptr(VirtualAllocEx(mProcess->hProcess, nullptr, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE));
|
||||||
|
if (!codePtr)
|
||||||
|
{
|
||||||
|
cbInternalError("Debugger::UnsafeDetachAndBreak, VirtualAllocEx failed!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8 code[] = { 0xCC, 0xC3 };
|
||||||
|
mProcess->MemWriteUnsafe(codePtr, code, sizeof(code));
|
||||||
|
|
||||||
|
//push the return address (current GIP) on the stack
|
||||||
|
mRegisters->Gsp -= sizeof(ptr);
|
||||||
|
auto gip = mRegisters->Gip();
|
||||||
|
mProcess->MemWriteUnsafe(mRegisters->Gsp(), &gip, sizeof(gip));
|
||||||
|
|
||||||
|
//change the GIP to the code
|
||||||
|
mRegisters->Gip = codePtr;
|
||||||
|
|
||||||
|
//flush the register cache (needed here explicitly because control will be out of the debugger after this).
|
||||||
|
mThread->RegWriteContext();
|
||||||
|
|
||||||
|
//detach from the process
|
||||||
|
return UnsafeDetach();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debugger::DetachAndBreak()
|
||||||
|
{
|
||||||
|
mDetachAndBreak = true;
|
||||||
|
mDetach = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -45,7 +45,23 @@ namespace GleeBug
|
||||||
\brief Detaches the debuggee.
|
\brief Detaches the debuggee.
|
||||||
\return true if the debuggee was detached correctly, false otherwise.
|
\return true if the debuggee was detached correctly, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool Detach() const;
|
bool UnsafeDetach();
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Detaches the debuggee. The detach happens at the end of the debug loop.
|
||||||
|
*/
|
||||||
|
void Detach();
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Detaches the debuggee and breaks with an INT3 (to invoke the JIT debugger).
|
||||||
|
\return true if the debuggee was detached correctly, false otherwise.
|
||||||
|
*/
|
||||||
|
bool UnsafeDetachAndBreak();
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Detaches the debuggee and breaks with an INT3 (to invoke the JIT debugger). The detach happens at the end of the debug loop.
|
||||||
|
*/
|
||||||
|
void DetachAndBreak();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Run the debug loop (does not return until the debuggee is detached or terminated). This function should be run from the same thread as you ran Init.
|
\brief Run the debug loop (does not return until the debuggee is detached or terminated). This function should be run from the same thread as you ran Init.
|
||||||
|
|
@ -251,6 +267,8 @@ namespace GleeBug
|
||||||
ProcessMap mProcesses;
|
ProcessMap mProcesses;
|
||||||
bool mIsRunning = false;
|
bool mIsRunning = false;
|
||||||
bool mIsDebugging = false;
|
bool mIsDebugging = false;
|
||||||
|
bool mDetach = false;
|
||||||
|
bool mDetachAndBreak = false;
|
||||||
Capstone mCapstone;
|
Capstone mCapstone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ public:
|
||||||
bool DetachDebuggerEx(DWORD ProcessId)
|
bool DetachDebuggerEx(DWORD ProcessId)
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
return Detach();
|
Detach();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugLoop()
|
void DebugLoop()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue