mirror of https://github.com/x64dbg/GleeBug
(hopefully) high performance safe memory read function
This commit is contained in:
parent
abc8a41a8d
commit
8f62768690
|
|
@ -32,6 +32,7 @@ namespace GleeBug
|
||||||
typedef std::map<uint32, ThreadInfo> ThreadMap;
|
typedef std::map<uint32, ThreadInfo> ThreadMap;
|
||||||
typedef std::map<BreakpointKey, BreakpointInfo> BreakpointMap;
|
typedef std::map<BreakpointKey, BreakpointInfo> BreakpointMap;
|
||||||
typedef std::map<BreakpointKey, BreakpointCallback> BreakpointCallbackMap;
|
typedef std::map<BreakpointKey, BreakpointCallback> BreakpointCallbackMap;
|
||||||
|
typedef std::unordered_map<ptr, BreakpointMap::iterator> SoftwareBreakpointMap;
|
||||||
|
|
||||||
//vector typedefs
|
//vector typedefs
|
||||||
typedef std::vector<StepCallback> StepCallbackVector;
|
typedef std::vector<StepCallback> StepCallbackVector;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@ namespace GleeBug
|
||||||
FlushInstructionCache(hProcess, nullptr, 0);
|
FlushInstructionCache(hProcess, nullptr, 0);
|
||||||
|
|
||||||
//insert in the breakpoint map
|
//insert in the breakpoint map
|
||||||
breakpoints.insert({ { info.type, info.address }, info });
|
auto itr = breakpoints.insert({ { info.type, info.address }, info });
|
||||||
|
softwareBreakpointReferences[info.address] = itr.first;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -72,6 +73,7 @@ namespace GleeBug
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove the breakpoint from the maps
|
//remove the breakpoint from the maps
|
||||||
|
softwareBreakpointReferences.erase(info.address);
|
||||||
breakpoints.erase(found);
|
breakpoints.erase(found);
|
||||||
breakpointCallbacks.erase({ BreakpointType::Software, address });
|
breakpointCallbacks.erase({ BreakpointType::Software, address });
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -156,7 +158,7 @@ namespace GleeBug
|
||||||
if (found == breakpoints.end())
|
if (found == breakpoints.end())
|
||||||
return false;
|
return false;
|
||||||
const auto & info = found->second;
|
const auto & info = found->second;
|
||||||
|
|
||||||
//delete the hardware breakpoint from the internal buffer
|
//delete the hardware breakpoint from the internal buffer
|
||||||
hardwareBreakpoints[int(info.internal.hardware.slot)].enabled = false;
|
hardwareBreakpoints[int(info.internal.hardware.slot)].enabled = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,60 @@ namespace GleeBug
|
||||||
return !!ReadProcessMemory(this->hProcess, reinterpret_cast<const void*>(address), buffer, size, nullptr);
|
return !!ReadProcessMemory(this->hProcess, reinterpret_cast<const void*>(address), buffer, size, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProcessInfo::MemReadSafe(ptr address, void* buffer, ptr size) const
|
||||||
|
{
|
||||||
|
if (!MemRead(address, buffer, size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//choose the filter method that has the lowest cost
|
||||||
|
auto start = address;
|
||||||
|
auto end = start + size;
|
||||||
|
if (size > breakpoints.size())
|
||||||
|
{
|
||||||
|
for (const auto & breakpoint : breakpoints)
|
||||||
|
{
|
||||||
|
if (breakpoint.first.first != BreakpointType::Software)
|
||||||
|
continue;
|
||||||
|
const auto & info = breakpoint.second;
|
||||||
|
auto curAddress = info.address;
|
||||||
|
for (ptr j = 0; j < info.internal.software.size; j++)
|
||||||
|
{
|
||||||
|
if (curAddress + j >= start && curAddress + j < end)
|
||||||
|
((uint8*)buffer)[curAddress + j - start] = info.internal.software.oldbytes[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (ptr i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
auto found = softwareBreakpointReferences.find(i);
|
||||||
|
if (found == softwareBreakpointReferences.end())
|
||||||
|
continue;
|
||||||
|
const auto & info = found->second->second;
|
||||||
|
auto curAddress = info.address;
|
||||||
|
for (ptr j = 0; j < info.internal.software.size && i < end; j++, i++)
|
||||||
|
{
|
||||||
|
if (curAddress + j >= start && curAddress + j < end)
|
||||||
|
((uint8*)buffer)[curAddress + j - start] = info.internal.software.oldbytes[j];
|
||||||
|
}
|
||||||
|
i += info.internal.software.size - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ProcessInfo::MemWrite(ptr address, const void* buffer, ptr size)
|
bool ProcessInfo::MemWrite(ptr address, const void* buffer, ptr size)
|
||||||
{
|
{
|
||||||
return !!WriteProcessMemory(this->hProcess, reinterpret_cast<void*>(address), buffer, size, nullptr);
|
return !!WriteProcessMemory(this->hProcess, reinterpret_cast<void*>(address), buffer, size, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProcessInfo::MemWriteSafe(ptr address, const void* buffer, ptr size)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ProcessInfo::MemIsValidPtr(ptr address) const
|
bool ProcessInfo::MemIsValidPtr(ptr address) const
|
||||||
{
|
{
|
||||||
uint8 byte;
|
uint8 byte;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ namespace GleeBug
|
||||||
ThreadMap threads; //DO NOT COPY THESE OBJECTS!
|
ThreadMap threads; //DO NOT COPY THESE OBJECTS!
|
||||||
DllMap dlls;
|
DllMap dlls;
|
||||||
BreakpointMap breakpoints;
|
BreakpointMap breakpoints;
|
||||||
|
SoftwareBreakpointMap softwareBreakpointReferences;
|
||||||
BreakpointCallbackMap breakpointCallbacks;
|
BreakpointCallbackMap breakpointCallbacks;
|
||||||
BreakpointInfo hardwareBreakpoints[4];
|
BreakpointInfo hardwareBreakpoints[4];
|
||||||
|
|
||||||
|
|
@ -44,6 +45,15 @@ namespace GleeBug
|
||||||
*/
|
*/
|
||||||
bool MemRead(ptr address, void* buffer, ptr size) const;
|
bool MemRead(ptr address, void* buffer, ptr size) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Safely read memory from the process, filtering out breakpoint bytes.
|
||||||
|
\param address The virtual address to read from.
|
||||||
|
\param [out] buffer Destination buffer. Cannot be null. May be filled partially on failure.
|
||||||
|
\param size The size to read.
|
||||||
|
\return true if it succeeds, false if it fails.
|
||||||
|
*/
|
||||||
|
bool MemReadSafe(ptr address, void* buffer, ptr size) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Write memory to the process.
|
\brief Write memory to the process.
|
||||||
\param address The virtual address to write to.
|
\param address The virtual address to write to.
|
||||||
|
|
@ -53,6 +63,15 @@ namespace GleeBug
|
||||||
*/
|
*/
|
||||||
bool MemWrite(ptr address, const void* buffer, ptr size);
|
bool MemWrite(ptr address, const void* buffer, ptr size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Safely write memory to the process, preserving breakpoint bytes.
|
||||||
|
\param address The virtual address to write to.
|
||||||
|
\param [in] buffer Source buffer. Cannot be null.
|
||||||
|
\param size The size to write.
|
||||||
|
\return true if it succeeds, false if it fails.
|
||||||
|
*/
|
||||||
|
bool MemWriteSafe(ptr address, const void* buffer, ptr size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Check if an address is a valid read pointer.
|
\brief Check if an address is a valid read pointer.
|
||||||
\param address The address to check.
|
\param address The address to check.
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ protected:
|
||||||
printf("Process %d created with entry 0x%p\n",
|
printf("Process %d created with entry 0x%p\n",
|
||||||
_debugEvent.dwProcessId,
|
_debugEvent.dwProcessId,
|
||||||
entry);
|
entry);
|
||||||
HardwareBreakpointSlot slot;
|
/*HardwareBreakpointSlot slot;
|
||||||
if (_process->GetFreeHardwareBreakpointSlot(slot))
|
if (_process->GetFreeHardwareBreakpointSlot(slot))
|
||||||
{
|
{
|
||||||
if (_process->SetHardwareBreakpoint(entry, slot, this, &MyDebugger::cbEntryHardwareBreakpoint, HardwareBreakpointType::Execute, HardwareBreakpointSize::SizeByte))
|
if (_process->SetHardwareBreakpoint(entry, slot, this, &MyDebugger::cbEntryHardwareBreakpoint, HardwareBreakpointType::Execute, HardwareBreakpointSize::SizeByte))
|
||||||
|
|
@ -59,12 +59,24 @@ protected:
|
||||||
printf("Failed to set hardware breakpoint at 0x%p\n", entry);
|
printf("Failed to set hardware breakpoint at 0x%p\n", entry);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf("No free hardware breakpoint slot...\n");
|
printf("No free hardware breakpoint slot...\n");*/
|
||||||
|
|
||||||
/*if(_process->SetBreakpoint(entry, this, &MyDebugger::cbEntryBreakpoint))
|
if(_process->SetBreakpoint(entry, this, &MyDebugger::cbEntryBreakpoint))
|
||||||
printf("Breakpoint set at 0x%p!\n", entry);
|
printf("Breakpoint set at 0x%p!\n", entry);
|
||||||
else
|
else
|
||||||
printf("Failed to set breakpoint at 0x%p...\b", entry);*/
|
printf("Failed to set breakpoint at 0x%p...\b", entry);
|
||||||
|
uint8 test[5];
|
||||||
|
ptr start = entry - 2;
|
||||||
|
printf("unsafe: ");
|
||||||
|
_process->MemRead(start, test, sizeof(test));
|
||||||
|
for (int i = 0; i < sizeof(test); i++)
|
||||||
|
printf("%02X ", test[i]);
|
||||||
|
puts("");
|
||||||
|
_process->MemReadSafe(start, test, sizeof(test));
|
||||||
|
printf(" safe: ");
|
||||||
|
for (int i = 0; i < sizeof(test); i++)
|
||||||
|
printf("%02X ", test[i]);
|
||||||
|
puts("");
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) override
|
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) override
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue