added 'DetachAndBreak' function

This commit is contained in:
Mr. eXoDia 2016-02-11 16:49:45 +01:00
parent 8652a6aa66
commit 4b7be626fa
4 changed files with 81 additions and 4 deletions

View File

@ -7,6 +7,8 @@ namespace GleeBug
//initialize loop variables
mBreakDebugger = false;
mIsDebugging = true;
mDetach = false;
mDetachAndBreak = false;
//use correct WaitForDebugEvent function
typedef BOOL(WINAPI *MYWAITFORDEBUGEVENT)(
@ -23,6 +25,20 @@ namespace GleeBug
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
mIsRunning = true;
if (!MyWaitForDebugEvent(&mDebugEvent, INFINITE))
@ -63,7 +79,7 @@ namespace GleeBug
}
//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)
switch (mDebugEvent.dwDebugEventCode)

View File

@ -57,8 +57,50 @@ namespace GleeBug
return !!TerminateProcess(mMainProcess.hProcess, 0);
}
bool Debugger::Detach() const
bool Debugger::UnsafeDetach()
{
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;
}
};

View File

@ -45,7 +45,23 @@ namespace GleeBug
\brief Detaches the debuggee.
\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.
@ -251,6 +267,8 @@ namespace GleeBug
ProcessMap mProcesses;
bool mIsRunning = false;
bool mIsDebugging = false;
bool mDetach = false;
bool mDetachAndBreak = false;
Capstone mCapstone;
/**

View File

@ -34,7 +34,8 @@ public:
bool DetachDebuggerEx(DWORD ProcessId)
{
//TODO
return Detach();
Detach();
return true;
}
void DebugLoop()