mirror of https://github.com/x64dbg/GleeBug
Port the fixes from https://github.com/x64dbg/TitanEngine/pull/14
This commit is contained in:
parent
a9a339ad45
commit
37b6606d58
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -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));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue