diff --git a/GleeBug/Debugger.Loop.Exception.cpp b/GleeBug/Debugger.Loop.Exception.cpp index c4c515b..35ef6e7 100644 --- a/GleeBug/Debugger.Loop.Exception.cpp +++ b/GleeBug/Debugger.Loop.Exception.cpp @@ -31,12 +31,12 @@ namespace GleeBug //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]() + mProcess->StepInternal([this, 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); @@ -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?) mThread->DeleteHardwareBreakpoint(breakpointSlot); - mThread->StepInternal(std::bind([this, info]() + mProcess->StepInternal([this, info]() { //only restore if the breakpoint still exists 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); - })); + }); //call the generic callback cbBreakpoint(info); @@ -182,7 +182,7 @@ namespace GleeBug // -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, // then we ought to restore the protection. - mThread->StepInternal(std::bind([this, pBaseAddr]() + mProcess->StepInternal([this, pBaseAddr]() { //seek out the page address auto found_page = mProcess->memoryBreakpointPages.find(pBaseAddr); @@ -193,7 +193,7 @@ namespace GleeBug } mProcess->MemProtect(pBaseAddr, PAGE_SIZE, found_page->second.NewProtect); return; - })); + }); } return; } @@ -243,7 +243,7 @@ namespace GleeBug cbInternalError(error); } - mThread->StepInternal(std::bind([this, pageAddr]() + mProcess->StepInternal([this, pageAddr]() { //seek out the page address auto found_page = mProcess->memoryBreakpointPages.find(pageAddr); @@ -254,7 +254,7 @@ namespace GleeBug } mProcess->MemProtect(pageAddr, PAGE_SIZE, found_page->second.NewProtect); return; - })); + }); return; } else if(((pageProperties.Type & 0x1) != 0)) @@ -306,7 +306,7 @@ namespace GleeBug cbInternalError(error); } //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: //-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); } return; - })); + }); if(info.singleshoot) { @@ -373,7 +373,7 @@ namespace GleeBug // -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, // then we ought to restore the protection. - mThread->StepInternal(std::bind([this, pBaseAddr]() + mProcess->StepInternal([this, pBaseAddr]() { //seek out the page address auto found_page = mProcess->memoryBreakpointPages.find(pBaseAddr); @@ -384,7 +384,7 @@ namespace GleeBug } mProcess->MemProtect(pBaseAddr, PAGE_SIZE, found_page->second.NewProtect); return; - })); + }); } return; } @@ -462,7 +462,7 @@ namespace GleeBug cbInternalError(error); } //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: //-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); } return; - })); + }); if(info.singleshoot) { diff --git a/GleeBug/Debugger.Process.cpp b/GleeBug/Debugger.Process.cpp index dba613b..4e4f775 100644 --- a/GleeBug/Debugger.Process.cpp +++ b/GleeBug/Debugger.Process.cpp @@ -101,14 +101,62 @@ namespace GleeBug } thread->StepInto(cbStep); } + + void Process::StepInternal(const StepCallback & cbStep) + { + 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))) { - SetBreakpoint(gip + info.length, [cbStep](const BreakpointInfo & info) + ZydisDisassembledInstruction instruction; + if(ZYAN_SUCCESS(ZydisDisassembleIntel( + GleeArchValue(ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_MACHINE_MODE_LONG_COMPAT_32), + gip, + data, + sizeof(data), + &instruction + ))) { - cbStep(); - }, true, SoftwareType::ShortInt3); - return; + switch(instruction.info.mnemonic) + { + case ZYDIS_MNEMONIC_PUSHF: + case ZYDIS_MNEMONIC_PUSHFD: + case ZYDIS_MNEMONIC_PUSHFQ: + isPushf = true; + break; + default: + break; + } + } } } - thread->StepInto(cbStep); + + 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(); + }; + } + else + { + thread->cbInternalStep = cbStep; + } } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index f2afc9b..fd604f1 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -396,6 +396,25 @@ namespace GleeBug static_cast(static_cast(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 + void StepInternal(T* debugger, void(T::*callback)()) + { + static_cast(static_cast(debugger)); + StepInternal(std::bind(callback, debugger)); + } }; }; diff --git a/GleeBug/Debugger.Thread.cpp b/GleeBug/Debugger.Thread.cpp index 5852dda..a25fa37 100644 --- a/GleeBug/Debugger.Thread.cpp +++ b/GleeBug/Debugger.Thread.cpp @@ -36,13 +36,6 @@ namespace GleeBug stepCallbacks.push_back(cbStep); } - void Thread::StepInternal(const StepCallback & cbStep) - { - Registers(hThread).TrapFlag.Set(); - isInternalStepping = true; - cbInternalStep = cbStep; - } - bool Thread::Suspend() { return SuspendThread(hThread) != -1; diff --git a/GleeBug/Debugger.Thread.h b/GleeBug/Debugger.Thread.h index 54e405e..14cd41b 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -60,25 +60,6 @@ namespace GleeBug 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 - void StepInternal(T* debugger, void(T::*callback)()) - { - static_cast(static_cast(debugger)); - StepInternal(std::bind(callback, debugger)); - } - /** \brief Sets a hardware breakpoint. \param address The address to set the hardware breakpoint on.