This commit is contained in:
Duncan Ogilvie 2023-07-08 14:37:23 +02:00
parent a9a339ad45
commit 37b6606d58
5 changed files with 86 additions and 45 deletions

View File

@ -31,12 +31,12 @@ namespace GleeBug
//restore the original breakpoint byte and do an internal step //restore the original breakpoint byte and do an internal step
mProcess->MemWriteUnsafe(info.address, info.internal.software.oldbytes, info.internal.software.size); mProcess->MemWriteUnsafe(info.address, info.internal.software.oldbytes, info.internal.software.size);
mThread->StepInternal(std::bind([this, info]() mProcess->StepInternal([this, info]()
{ {
//only restore the bytes if the breakpoint still exists //only restore the bytes if the breakpoint still exists
if(mProcess->breakpoints.find({ BreakpointType::Software, info.address }) != mProcess->breakpoints.end()) if(mProcess->breakpoints.find({ BreakpointType::Software, info.address }) != mProcess->breakpoints.end())
mProcess->MemWriteUnsafe(info.address, info.internal.software.newbytes, info.internal.software.size); mProcess->MemWriteUnsafe(info.address, info.internal.software.newbytes, info.internal.software.size);
})); });
//call the generic callback //call the generic callback
cbBreakpoint(info); cbBreakpoint(info);
@ -126,12 +126,12 @@ namespace GleeBug
//delete the hardware breakpoint from the thread (not the breakpoint buffer) and do an internal step (TODO: maybe delete from all threads?) //delete the hardware breakpoint from the thread (not the breakpoint buffer) and do an internal step (TODO: maybe delete from all threads?)
mThread->DeleteHardwareBreakpoint(breakpointSlot); mThread->DeleteHardwareBreakpoint(breakpointSlot);
mThread->StepInternal(std::bind([this, info]() mProcess->StepInternal([this, info]()
{ {
//only restore if the breakpoint still exists //only restore if the breakpoint still exists
if(mProcess->breakpoints.find({ BreakpointType::Hardware, info.address }) != mProcess->breakpoints.end()) if(mProcess->breakpoints.find({ BreakpointType::Hardware, info.address }) != mProcess->breakpoints.end())
mThread->SetHardwareBreakpoint(info.address, info.internal.hardware.slot, info.internal.hardware.type, info.internal.hardware.size); mThread->SetHardwareBreakpoint(info.address, info.internal.hardware.slot, info.internal.hardware.type, info.internal.hardware.size);
})); });
//call the generic callback //call the generic callback
cbBreakpoint(info); cbBreakpoint(info);
@ -182,7 +182,7 @@ namespace GleeBug
// -add more memory breakpoints // -add more memory breakpoints
//The solution: We just try to see if the page is mapped into memoryBreakpointPages. If the page is in deed being used by any memory breakpoint, //The solution: We just try to see if the page is mapped into memoryBreakpointPages. If the page is in deed being used by any memory breakpoint,
// then we ought to restore the protection. // then we ought to restore the protection.
mThread->StepInternal(std::bind([this, pBaseAddr]() mProcess->StepInternal([this, pBaseAddr]()
{ {
//seek out the page address //seek out the page address
auto found_page = mProcess->memoryBreakpointPages.find(pBaseAddr); auto found_page = mProcess->memoryBreakpointPages.find(pBaseAddr);
@ -193,7 +193,7 @@ namespace GleeBug
} }
mProcess->MemProtect(pBaseAddr, PAGE_SIZE, found_page->second.NewProtect); mProcess->MemProtect(pBaseAddr, PAGE_SIZE, found_page->second.NewProtect);
return; return;
})); });
} }
return; return;
} }
@ -243,7 +243,7 @@ namespace GleeBug
cbInternalError(error); cbInternalError(error);
} }
mThread->StepInternal(std::bind([this, pageAddr]() mProcess->StepInternal([this, pageAddr]()
{ {
//seek out the page address //seek out the page address
auto found_page = mProcess->memoryBreakpointPages.find(pageAddr); auto found_page = mProcess->memoryBreakpointPages.find(pageAddr);
@ -254,7 +254,7 @@ namespace GleeBug
} }
mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect); mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect);
return; return;
})); });
return; return;
} }
else if(((pageProperties.Type & 0x1) != 0)) else if(((pageProperties.Type & 0x1) != 0))
@ -306,7 +306,7 @@ namespace GleeBug
cbInternalError(error); cbInternalError(error);
} }
//Pass info as well //Pass info as well
mThread->StepInternal(std::bind([this, pageAddr]() mProcess->StepInternal([this, pageAddr]()
{ {
//With page check this should work better: So when we reach this part of the code we are sure that: //With page check this should work better: So when we reach this part of the code we are sure that:
//-The exception Address In deed corresponded to an existing (now possibly deleted) memory breakpoint range //-The exception Address In deed corresponded to an existing (now possibly deleted) memory breakpoint range
@ -327,7 +327,7 @@ namespace GleeBug
mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect); mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect);
} }
return; return;
})); });
if(info.singleshoot) if(info.singleshoot)
{ {
@ -373,7 +373,7 @@ namespace GleeBug
// -add more memory breakpoints // -add more memory breakpoints
//The solution: We just try to see if the page is mapped into memoryBreakpointPages. If the page is in deed being used by any memory breakpoint, //The solution: We just try to see if the page is mapped into memoryBreakpointPages. If the page is in deed being used by any memory breakpoint,
// then we ought to restore the protection. // then we ought to restore the protection.
mThread->StepInternal(std::bind([this, pBaseAddr]() mProcess->StepInternal([this, pBaseAddr]()
{ {
//seek out the page address //seek out the page address
auto found_page = mProcess->memoryBreakpointPages.find(pBaseAddr); auto found_page = mProcess->memoryBreakpointPages.find(pBaseAddr);
@ -384,7 +384,7 @@ namespace GleeBug
} }
mProcess->MemProtect(pBaseAddr, PAGE_SIZE, found_page->second.NewProtect); mProcess->MemProtect(pBaseAddr, PAGE_SIZE, found_page->second.NewProtect);
return; return;
})); });
} }
return; return;
} }
@ -462,7 +462,7 @@ namespace GleeBug
cbInternalError(error); cbInternalError(error);
} }
//Pass info as well //Pass info as well
mThread->StepInternal(std::bind([this, pageAddr]() mProcess->StepInternal([this, pageAddr]()
{ {
//With page check this should work better: So when we reach this part of the code we are sure that: //With page check this should work better: So when we reach this part of the code we are sure that:
//-The exception Address In deed corresponded to an existing (now possibly deleted) memory breakpoint range //-The exception Address In deed corresponded to an existing (now possibly deleted) memory breakpoint range
@ -483,7 +483,7 @@ namespace GleeBug
mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect); mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect);
} }
return; return;
})); });
if(info.singleshoot) if(info.singleshoot)
{ {

View File

@ -101,14 +101,62 @@ namespace GleeBug
} }
thread->StepInto(cbStep); thread->StepInto(cbStep);
} }
void Process::StepInternal(const StepCallback & cbStep)
{ {
SetBreakpoint(gip + info.length, [cbStep](const BreakpointInfo & info) Registers registers(thread->hThread, CONTEXT_CONTROL);
registers.TrapFlag.Set();
thread->isInternalStepping = true;
// Check if we're currently stepping on a pushf instruction
auto isPushf = false;
{ {
auto gip = registers.Gip();
unsigned char data[16];
if(MemReadSafe(gip, data, sizeof(data)))
{
ZydisDisassembledInstruction instruction;
if(ZYAN_SUCCESS(ZydisDisassembleIntel(
GleeArchValue(ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_MACHINE_MODE_LONG_COMPAT_32),
gip,
data,
sizeof(data),
&instruction
)))
{
switch(instruction.info.mnemonic)
{
case ZYDIS_MNEMONIC_PUSHF:
case ZYDIS_MNEMONIC_PUSHFD:
case ZYDIS_MNEMONIC_PUSHFQ:
isPushf = true;
break;
default:
break;
}
}
}
}
if(isPushf)
{
thread->cbInternalStep = [this, cbStep]()
{
// Remove the trap flag from the stack
auto gsp = Registers(this->thread->hThread).Gsp();
GleeBug::ptr data;
if(MemReadUnsafe(gsp, &data, sizeof(data)))
{
data &= ~(int)Registers::F::Trap;
MemWriteUnsafe(gsp, &data, sizeof(data));
}
cbStep(); cbStep();
}, true, SoftwareType::ShortInt3); };
return;
} }
else
{
thread->cbInternalStep = cbStep;
} }
thread->StepInto(cbStep);
} }
}; };

View File

@ -396,6 +396,25 @@ namespace GleeBug
static_cast<void>(static_cast<Debugger*>(debugger)); static_cast<void>(static_cast<Debugger*>(debugger));
StepOver(std::bind(callback, debugger)); StepOver(std::bind(callback, debugger));
} }
/**
\brief Perform an internal step (not reported to the outside)
\param cbStep Step callback. Can be written using BIND(this, MyDebugger::cb).
*/
void StepInternal(const StepCallback & cbStep);
/**
\brief Perform an internal step (not reported to the outside)
\tparam T Generic type parameter. Must be a subclass of Debugger.
\param debugger This pointer to a subclass of Debugger.
\param callback Pointer to the callback. Written like: &MyDebugger::cb
*/
template<typename T>
void StepInternal(T* debugger, void(T::*callback)())
{
static_cast<void>(static_cast<Debugger*>(debugger));
StepInternal(std::bind(callback, debugger));
}
}; };
}; };

View File

@ -36,13 +36,6 @@ namespace GleeBug
stepCallbacks.push_back(cbStep); stepCallbacks.push_back(cbStep);
} }
void Thread::StepInternal(const StepCallback & cbStep)
{
Registers(hThread).TrapFlag.Set();
isInternalStepping = true;
cbInternalStep = cbStep;
}
bool Thread::Suspend() bool Thread::Suspend()
{ {
return SuspendThread(hThread) != -1; return SuspendThread(hThread) != -1;

View File

@ -60,25 +60,6 @@ namespace GleeBug
StepInto(std::bind(callback, debugger)); StepInto(std::bind(callback, debugger));
} }
/**
\brief Perform an internal step (not reported to the outside)
\param cbStep Step callback. Can be written using BIND(this, MyDebugger::cb).
*/
void StepInternal(const StepCallback & cbStep);
/**
\brief Perform an internal step (not reported to the outside)
\tparam T Generic type parameter. Must be a subclass of Debugger.
\param debugger This pointer to a subclass of Debugger.
\param callback Pointer to the callback. Written like: &MyDebugger::cb
*/
template<typename T>
void StepInternal(T* debugger, void(T::*callback)())
{
static_cast<void>(static_cast<Debugger*>(debugger));
StepInternal(std::bind(callback, debugger));
}
/** /**
\brief Sets a hardware breakpoint. \brief Sets a hardware breakpoint.
\param address The address to set the hardware breakpoint on. \param address The address to set the hardware breakpoint on.