various fixes to memory breakpoints

This commit is contained in:
mrexodia 2016-08-20 06:06:16 +02:00
parent eb4262d8ec
commit 1cf82cb3cc
5 changed files with 80 additions and 14 deletions

View File

@ -40,6 +40,9 @@ namespace GleeBug
return; return;
const auto info = foundInfo->second; const auto info = foundInfo->second;
if (!info.enabled)
return; //not a valid software breakpoint
//set continue status //set continue status
mContinueStatus = DBG_CONTINUE; mContinueStatus = DBG_CONTINUE;
@ -135,7 +138,7 @@ namespace GleeBug
if (foundInfo == mProcess->breakpoints.end()) if (foundInfo == mProcess->breakpoints.end())
return; //not a valid hardware breakpoint return; //not a valid hardware breakpoint
const auto info = foundInfo->second; const auto info = foundInfo->second;
if (info.internal.hardware.slot != breakpointSlot) if (info.internal.hardware.slot != breakpointSlot || !info.enabled)
return; //not a valid hardware breakpoint return; //not a valid hardware breakpoint
//set continue status //set continue status
@ -163,6 +166,47 @@ namespace GleeBug
mProcess->DeleteGenericBreakpoint(info); mProcess->DeleteGenericBreakpoint(info);
} }
void Debugger::exceptionGuardPage(const EXCEPTION_RECORD & exceptionRecord, bool firstChance)
{
char error[128] = "";
auto exceptionAddress = ptr(exceptionRecord.ExceptionAddress);
auto foundRange = mProcess->memoryBreakpointRanges.find(Range(exceptionAddress, exceptionAddress));
if (foundRange == mProcess->memoryBreakpointRanges.end())
{
auto foundPage = mProcess->memoryBreakpointPages.find(exceptionAddress & ~(PAGE_SIZE - 1));
if (foundPage != mProcess->memoryBreakpointPages.end())
{
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;
}
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;
}
const auto info = foundInfo->second;
if (!info.enabled)
return;
//exceptionRecord.
}
void Debugger::exceptionAccessViolation(const EXCEPTION_RECORD & exceptionRecord, bool firstChance)
{
}
void Debugger::exceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) void Debugger::exceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo)
{ {
//let the debuggee handle exceptions per default //let the debuggee handle exceptions per default
@ -183,6 +227,12 @@ namespace GleeBug
case STATUS_SINGLE_STEP: case STATUS_SINGLE_STEP:
exceptionSingleStep(exceptionRecord, firstChance); exceptionSingleStep(exceptionRecord, firstChance);
break; break;
case STATUS_GUARD_PAGE_VIOLATION:
exceptionGuardPage(exceptionRecord, firstChance);
break;
case STATUS_ACCESS_VIOLATION:
exceptionAccessViolation(exceptionRecord, firstChance);
break;
} }
//call the unhandled exception callback //call the unhandled exception callback

View File

@ -261,10 +261,7 @@ namespace GleeBug
data.NewProtect = permanentDep ? RemoveExecuteAccess(RemoveWriteAccess(data.OldProtect)) : data.OldProtect | PAGE_GUARD; data.NewProtect = permanentDep ? RemoveExecuteAccess(RemoveWriteAccess(data.OldProtect)) : data.OldProtect | PAGE_GUARD;
} }
DWORD oldProtect; return MemProtect(page, PAGE_SIZE, data.NewProtect);
auto vps = !!VirtualProtectEx(hProcess, LPVOID(page), PAGE_SIZE, data.NewProtect, &oldProtect);
printf("VirtualProtect(0x%p, 0x%X, %08X, %08X) = %d\n", page, PAGE_SIZE, data.NewProtect, oldProtect, vps);
return vps;
} }
bool Process::SetMemoryBreakpoint(ptr address, ptr size, MemoryType type, bool singleshoot) bool Process::SetMemoryBreakpoint(ptr address, ptr size, MemoryType type, bool singleshoot)
@ -320,11 +317,7 @@ namespace GleeBug
if (!success) if (!success)
{ {
for (const auto & page : breakpointData) for (const auto & page : breakpointData)
{ MemProtect(page.addr, PAGE_SIZE, page.OldProtect);
DWORD oldProtect;
auto vps = !!VirtualProtectEx(hProcess, LPVOID(page.addr), PAGE_SIZE, page.OldProtect, &oldProtect);
printf("VirtualProtect(0x%p, 0x%X, %08X, %08X) = %d\n", page, PAGE_SIZE, page.OldProtect, oldProtect, vps);
}
return false; return false;
} }
@ -389,10 +382,7 @@ namespace GleeBug
} }
else else
Protect = data.OldProtect; Protect = data.OldProtect;
DWORD oldProtect; if (!MemProtect(page, PAGE_SIZE, Protect))
auto vps = !!VirtualProtectEx(hProcess, LPVOID(page), PAGE_SIZE, Protect, &oldProtect);
printf("VirtualProtect(0x%p, 0x%X, %08X, %08X) = %d\n", page, PAGE_SIZE, Protect, oldProtect, vps);
if (!vps)
success = false; success = false;
if (!data.Refcount) if (!data.Refcount)
memoryBreakpointPages.erase(foundData); memoryBreakpointPages.erase(foundData);

View File

@ -74,6 +74,18 @@ namespace GleeBug
return MemReadUnsafe(address, &byte, sizeof(byte)); return MemReadUnsafe(address, &byte, sizeof(byte));
} }
bool Process::MemProtect(ptr address, ptr size, DWORD newProtect, DWORD* oldProtect)
{
DWORD dwOldProtect;
auto vps = VirtualProtectEx(hProcess, LPVOID(address), size, newProtect, &dwOldProtect);
printf("MemProtect(0x%p, 0x%X, %08X, %08X) = %d\n", address, size, newProtect, dwOldProtect, vps);
if (!vps)
return false;
if (oldProtect)
*oldProtect = dwOldProtect;
return true;
}
ptr Process::MemFindPattern(ptr data, size_t datasize, const Pattern::WildcardPattern & pattern, bool safe) const ptr Process::MemFindPattern(ptr data, size_t datasize, const Pattern::WildcardPattern & pattern, bool safe) const
{ {
std::vector<uint8> buffer(datasize); std::vector<uint8> buffer(datasize);

View File

@ -122,6 +122,16 @@ namespace GleeBug
*/ */
bool MemIsValidPtr(ptr address) const; bool MemIsValidPtr(ptr address) const;
/**
\brief Memory protect (execute VirtualProtect in the context of the process).
\param address The address to change protection for.
\param size The size to change protection for.
\param newProtect The new protection.
\param [out] oldProtect The old protection.
\return true if it succeeds, false if it fails.
*/
bool MemProtect(ptr address, ptr size, DWORD newProtect, DWORD* oldProtect = nullptr);
/** /**
\brief Finds the first occurrence of a pattern in process memory. \brief Finds the first occurrence of a pattern in process memory.
\param data The address to start searching from. \param data The address to start searching from.

View File

@ -259,6 +259,10 @@ namespace GleeBug
*/ */
virtual void exceptionHardwareBreakpoint(ptr exceptionAddress); virtual void exceptionHardwareBreakpoint(ptr exceptionAddress);
virtual void exceptionGuardPage(const EXCEPTION_RECORD & exceptionRecord, bool firstChance);
virtual void exceptionAccessViolation(const EXCEPTION_RECORD & exceptionRecord, bool firstChance);
protected: //variables protected: //variables
PROCESS_INFORMATION mMainProcess; PROCESS_INFORMATION mMainProcess;
uint32 mContinueStatus = DBG_EXCEPTION_NOT_HANDLED; uint32 mContinueStatus = DBG_EXCEPTION_NOT_HANDLED;