From 642fe757428c7952204736dcb791cf7766563421 Mon Sep 17 00:00:00 2001 From: _0xbadc0de Date: Wed, 8 Feb 2017 10:56:02 +0000 Subject: [PATCH] Provided implementation for : Debugger::exceptionGuardPage(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) --- GleeBug/Debugger.Loop.Exception.cpp | 217 +++++++++++++++++++++++----- GleeBug/Debugger.cpp | 2 +- 2 files changed, 178 insertions(+), 41 deletions(-) diff --git a/GleeBug/Debugger.Loop.Exception.cpp b/GleeBug/Debugger.Loop.Exception.cpp index 1b70f64..8a08111 100644 --- a/GleeBug/Debugger.Loop.Exception.cpp +++ b/GleeBug/Debugger.Loop.Exception.cpp @@ -171,51 +171,188 @@ namespace GleeBug } void Debugger::exceptionGuardPage(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) - { - char error[128] = ""; - auto exceptionAddress = ptr(exceptionRecord.ExceptionInformation[1]); + { - //check if the exception address is directly in the range of a memory breakpoint - auto foundRange = mProcess->memoryBreakpointRanges.find(Range(exceptionAddress, exceptionAddress)); - if (foundRange == mProcess->memoryBreakpointRanges.end()) - { - //if not in range, check if a memory breakpoint is in the accessed page - auto foundPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1)); - if (foundPage != mProcess->memoryBreakpointPages.end()) - { - //if the page contains a memory breakpoint we have to restore the old protection to correctly resume the debuggee - const auto & page = foundPage->second; - //TODO: single step and page protection changes - if (!mProcess->MemProtect(foundPage->first, PAGE_SIZE, foundPage->second.NewProtect)) - { - sprintf_s(error, "MemProtect failed on 0x%p", foundPage->first); - cbInternalError(error); - } - } - return; - } + /* old code ~Duncan~ + char error[128] = ""; + auto exceptionAddress = ptr(exceptionRecord.ExceptionInformation[1]); - //find the breakpoint associated with the hit breakpoint range - auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Memory, foundRange->first }); - if (foundInfo == mProcess->breakpoints.end()) - { - sprintf_s(error, "inconsistent memory breakpoint at 0x%p", exceptionAddress); - cbInternalError(error); - return; - } + //check if the exception address is directly in the range of a memory breakpoint + auto foundRange = mProcess->memoryBreakpointRanges.find(Range(exceptionAddress, exceptionAddress)); + if (foundRange == mProcess->memoryBreakpointRanges.end()) + { + //if not in range, check if a memory breakpoint is in the accessed page + auto foundPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1)); + if (foundPage != mProcess->memoryBreakpointPages.end()) + { + //if the page contains a memory breakpoint we have to restore the old protection to correctly resume the debuggee + const auto & page = foundPage->second; + //TODO: single step and page protection changes + if (!mProcess->MemProtect(foundPage->first, PAGE_SIZE, foundPage->second.NewProtect)) + { + sprintf_s(error, "MemProtect failed on 0x%p", foundPage->first); + cbInternalError(error); + } + } + return; + } - //check if the memory breakpoint is disabled (meaning we shouldn't intercept the exception) - //TODO: think about what happens with multiple breakpoints in one page where only one is disabled - const auto info = foundInfo->second; - if (!info.enabled) - return; + //find the breakpoint associated with the hit breakpoint range + auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Memory, foundRange->first }); + if (foundInfo == mProcess->breakpoints.end()) + { + sprintf_s(error, "inconsistent memory breakpoint at 0x%p", exceptionAddress); + cbInternalError(error); + return; + } - printf("memory breakpoint: 0x%p (size: %d)\n", info.address, info.internal.memory.size); + //check if the memory breakpoint is disabled (meaning we shouldn't intercept the exception) + //TODO: think about what happens with multiple breakpoints in one page where only one is disabled + const auto info = foundInfo->second; + if (!info.enabled) + return; + + printf("memory breakpoint: 0x%p (size: %d)\n", info.address, info.internal.memory.size); + + //TODO: check if the right type is accessed (ExceptionInformation[0]) + //TODO: execute the user callback (if present) + //TODO: single step and restore page protection + */ + + //New code ~Marques~ + + /* 0xcc breakpoing + mThread->StepInternal(std::bind([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); + })); + + */ + + char error[128] = ""; + auto exceptionAddress = ptr(exceptionRecord.ExceptionInformation[1]); + + //check if the exception address is directly in the range of a memory breakpoint + auto foundRange = mProcess->memoryBreakpointRanges.find(Range(exceptionAddress, exceptionAddress)); + if (foundRange == mProcess->memoryBreakpointRanges.end()) + { + //if not in range, check if a memory breakpoint is in the accessed page + auto foundPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1)); + if (foundPage != mProcess->memoryBreakpointPages.end()) + { + //if the page contains a memory breakpoint we have to restore the old protection to correctly resume the debuggee + const auto & page = foundPage->second; + //TODO: single step and page protection changes + //FIXED (marques): + //restored *OLD* page protection settings + if (!mProcess->MemProtect(foundPage->first, PAGE_SIZE, foundPage->second.OldProtect)) + { + sprintf_s(error, "MemProtect failed on 0x%p", foundPage->first); + cbInternalError(error); + } + mThread->StepInternal(std::bind([this]() + { + return; + })); + } + return; + } + + //find the breakpoint associated with the hit breakpoint range + auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Memory, foundRange->first }); + if (foundInfo == mProcess->breakpoints.end()) + { + sprintf_s(error, "inconsistent memory breakpoint at 0x%p", exceptionAddress); + cbInternalError(error); + return; + } + + //check if the memory breakpoint is disabled (meaning we shouldn't intercept the exception) + //TODO: think about what happens with multiple breakpoints in one page where only one is disabled + //There is really no problem about this because enabled is a property of a range and ranges do not overlap. + const auto info = foundInfo->second; + if (!info.enabled) + return; + + printf("memory breakpoint: 0x%p (size: %d)\n", info.address, info.internal.memory.size); + + //TODO: check if the right type is accessed (ExceptionInformation[0]) + //FIXED: Marques + auto bpxPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1)); + if (bpxPage == mProcess->memoryBreakpointPages.end()) + { + sprintf_s(error, "Process::memoryBreakPointPages data structure is incosistent, should dump page at 0x%p", exceptionAddress & ~(PAGE_SIZE - 1)); + cbInternalError(error); + return; + } + /* + Access = 1, + Read = 2, + Write = 4, + Execute = 8 + */ + //Read but our bpx page is not bp on Read + if ((exceptionRecord.ExceptionInformation[0]) && (!(bpxPage->second.Type & 0x2))) + { + //perhaps the program generated such exception + return; + } + + //Exception on write but page bp information does not have bp on write + if ((exceptionRecord.ExceptionInformation[0] == 1) && (!(bpxPage->second.Type & 0x4))) + { + return; + } + + //caused by data execution prevention but page bp information does not have bp on exec + if ((exceptionRecord.ExceptionInformation[0] == 8) && (!(bpxPage->second.Type & 0x8))) + { + return; + } + + //generic breakpoint callback function. + cbBreakpoint(info); + + //TODO: execute the user callback (if present) + //FIXED: Marques + auto bpxCb = mProcess->breakpointCallbacks.find({ BreakpointType::Memory, info.address }); + if (bpxCb != mProcess->breakpointCallbacks.end()) + { + bpxCb->second(info); + } + + + mContinueStatus = DBG_CONTINUE; + //TODO: single step and restore page protection + //FIXED: + if (!mProcess->MemProtect(bpxPage->first, PAGE_SIZE, bpxPage->second.OldProtect)) + { + sprintf_s(error, "MemProtect failed on 0x%p", bpxPage->first); + cbInternalError(error); + } + //Pass info as well + auto pageAddr = bpxPage->first; + auto pageProperties = bpxPage->second; + mThread->StepInternal(std::bind([this, info, pageAddr, pageProperties]() + { + //Check if the bpx still exists + auto found_range = mProcess->memoryBreakpointRanges.find(Range(info.address, info.address)); + if (found_range != mProcess->memoryBreakpointRanges.end()) + { + mProcess->MemProtect(pageAddr, PAGE_SIZE, pageProperties.NewProtect); + } + return; + })); + + if (foundInfo->second.singleshoot) + { + mProcess->DeleteMemoryBreakpoint(exceptionAddress); + } + + } - //TODO: check if the right type is accessed (ExceptionInformation[0]) - //TODO: execute the user callback (if present) - //TODO: single step and restore page protection - } void Debugger::exceptionAccessViolation(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) { diff --git a/GleeBug/Debugger.cpp b/GleeBug/Debugger.cpp index facf5c7..1d710f8 100644 --- a/GleeBug/Debugger.cpp +++ b/GleeBug/Debugger.cpp @@ -39,7 +39,7 @@ namespace GleeBug nullptr, nullptr, FALSE, - DEBUG_PROCESS | CREATE_NEW_CONSOLE, + DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE, nullptr, szCurrentDirectory, &mMainStartupInfo,