mirror of https://github.com/x64dbg/GleeBug
renaming fest continued (and probably finished)
This commit is contained in:
parent
3c1f141949
commit
362cba7830
|
|
@ -5,7 +5,7 @@ namespace GleeBug
|
||||||
void Debugger::debugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString)
|
void Debugger::debugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString)
|
||||||
{
|
{
|
||||||
//prevent anti-debug trick (debug string events are actually exceptions)
|
//prevent anti-debug trick (debug string events are actually exceptions)
|
||||||
_continueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
mContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
|
|
||||||
//call the debug event callback
|
//call the debug event callback
|
||||||
cbDebugStringEvent(debugString);
|
cbDebugStringEvent(debugString);
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@ namespace GleeBug
|
||||||
//DLL housekeeping
|
//DLL housekeeping
|
||||||
MODULEINFO modinfo;
|
MODULEINFO modinfo;
|
||||||
memset(&modinfo, 0, sizeof(MODULEINFO));
|
memset(&modinfo, 0, sizeof(MODULEINFO));
|
||||||
GetModuleInformation(_process->hProcess,
|
GetModuleInformation(mProcess->hProcess,
|
||||||
HMODULE(loadDll.lpBaseOfDll),
|
HMODULE(loadDll.lpBaseOfDll),
|
||||||
&modinfo,
|
&modinfo,
|
||||||
sizeof(MODULEINFO));
|
sizeof(MODULEINFO));
|
||||||
DllInfo dll(loadDll.lpBaseOfDll, modinfo.SizeOfImage, modinfo.EntryPoint);
|
DllInfo dll(loadDll.lpBaseOfDll, modinfo.SizeOfImage, modinfo.EntryPoint);
|
||||||
_process->dlls.insert({ Range(dll.lpBaseOfDll, dll.lpBaseOfDll + dll.sizeOfImage - 1), dll });
|
mProcess->dlls.insert({ Range(dll.lpBaseOfDll, dll.lpBaseOfDll + dll.sizeOfImage - 1), dll });
|
||||||
|
|
||||||
//call the debug event callback
|
//call the debug event callback
|
||||||
cbLoadDllEvent(loadDll, dll);
|
cbLoadDllEvent(loadDll, dll);
|
||||||
|
|
@ -25,14 +25,14 @@ namespace GleeBug
|
||||||
{
|
{
|
||||||
//call the debug event callback
|
//call the debug event callback
|
||||||
ptr lpBaseOfDll = ptr(unloadDll.lpBaseOfDll);
|
ptr lpBaseOfDll = ptr(unloadDll.lpBaseOfDll);
|
||||||
auto dll = _process->dlls.find(Range(lpBaseOfDll, lpBaseOfDll));
|
auto dll = mProcess->dlls.find(Range(lpBaseOfDll, lpBaseOfDll));
|
||||||
if (dll != _process->dlls.end())
|
if (dll != mProcess->dlls.end())
|
||||||
cbUnloadDllEvent(unloadDll, dll->second);
|
cbUnloadDllEvent(unloadDll, dll->second);
|
||||||
else
|
else
|
||||||
cbUnloadDllEvent(unloadDll, DllInfo(unloadDll.lpBaseOfDll, 0, nullptr));
|
cbUnloadDllEvent(unloadDll, DllInfo(unloadDll.lpBaseOfDll, 0, nullptr));
|
||||||
|
|
||||||
//DLL housekeeping
|
//DLL housekeeping
|
||||||
if (dll != _process->dlls.end())
|
if (dll != mProcess->dlls.end())
|
||||||
_process->dlls.erase(dll);
|
mProcess->dlls.erase(dll);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -4,11 +4,11 @@ namespace GleeBug
|
||||||
{
|
{
|
||||||
void Debugger::exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance)
|
void Debugger::exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance)
|
||||||
{
|
{
|
||||||
if (!_process->systemBreakpoint) //handle system breakpoint
|
if (!mProcess->systemBreakpoint) //handle system breakpoint
|
||||||
{
|
{
|
||||||
//set internal state
|
//set internal state
|
||||||
_process->systemBreakpoint = true;
|
mProcess->systemBreakpoint = true;
|
||||||
_continueStatus = DBG_CONTINUE;
|
mContinueStatus = DBG_CONTINUE;
|
||||||
|
|
||||||
//call the callback
|
//call the callback
|
||||||
cbSystemBreakpoint();
|
cbSystemBreakpoint();
|
||||||
|
|
@ -16,63 +16,63 @@ namespace GleeBug
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//check if the breakpoint exists
|
//check if the breakpoint exists
|
||||||
auto foundInfo = _process->breakpoints.find({ BreakpointType::Software, ptr(exceptionRecord.ExceptionAddress) });
|
auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Software, ptr(exceptionRecord.ExceptionAddress) });
|
||||||
if (foundInfo == _process->breakpoints.end())
|
if (foundInfo == mProcess->breakpoints.end())
|
||||||
return;
|
return;
|
||||||
const auto info = foundInfo->second;
|
const auto info = foundInfo->second;
|
||||||
|
|
||||||
//set continue status
|
//set continue status
|
||||||
_continueStatus = DBG_CONTINUE;
|
mContinueStatus = DBG_CONTINUE;
|
||||||
|
|
||||||
//set back the instruction pointer
|
//set back the instruction pointer
|
||||||
_registers->Gip = info.address;
|
mRegisters->Gip = info.address;
|
||||||
|
|
||||||
//restore the original breakpoint byte and do an internal step
|
//restore the original breakpoint byte and do an internal step
|
||||||
_process->MemWrite(info.address, info.internal.software.oldbytes, info.internal.software.size);
|
mProcess->MemWrite(info.address, info.internal.software.oldbytes, info.internal.software.size);
|
||||||
_thread->StepInternal(std::bind([this, info]()
|
mThread->StepInternal(std::bind([this, info]()
|
||||||
{
|
{
|
||||||
//only restore the bytes if the breakpoint still exists
|
//only restore the bytes if the breakpoint still exists
|
||||||
if (_process->breakpoints.find({ BreakpointType::Software, info.address }) != _process->breakpoints.end())
|
if (mProcess->breakpoints.find({ BreakpointType::Software, info.address }) != mProcess->breakpoints.end())
|
||||||
_process->MemWrite(info.address, info.internal.software.newbytes, info.internal.software.size);
|
mProcess->MemWrite(info.address, info.internal.software.newbytes, info.internal.software.size);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
//call the generic callback
|
//call the generic callback
|
||||||
cbBreakpoint(info);
|
cbBreakpoint(info);
|
||||||
|
|
||||||
//call the user callback
|
//call the user callback
|
||||||
auto foundCallback = _process->breakpointCallbacks.find({ BreakpointType::Software, info.address });
|
auto foundCallback = mProcess->breakpointCallbacks.find({ BreakpointType::Software, info.address });
|
||||||
if (foundCallback != _process->breakpointCallbacks.end())
|
if (foundCallback != mProcess->breakpointCallbacks.end())
|
||||||
foundCallback->second(info);
|
foundCallback->second(info);
|
||||||
|
|
||||||
//delete the breakpoint if it is singleshoot
|
//delete the breakpoint if it is singleshoot
|
||||||
if (info.singleshoot)
|
if (info.singleshoot)
|
||||||
_process->DeleteGenericBreakpoint(info);
|
mProcess->DeleteGenericBreakpoint(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance)
|
void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance)
|
||||||
{
|
{
|
||||||
if (_thread->isInternalStepping) //handle internal steps
|
if (mThread->isInternalStepping) //handle internal steps
|
||||||
{
|
{
|
||||||
//set internal status
|
//set internal status
|
||||||
_thread->isInternalStepping = false;
|
mThread->isInternalStepping = false;
|
||||||
_continueStatus = DBG_CONTINUE;
|
mContinueStatus = DBG_CONTINUE;
|
||||||
|
|
||||||
//call the internal step callback
|
//call the internal step callback
|
||||||
_thread->cbInternalStep();
|
mThread->cbInternalStep();
|
||||||
}
|
}
|
||||||
if (_thread->isSingleStepping) //handle single step
|
if (mThread->isSingleStepping) //handle single step
|
||||||
{
|
{
|
||||||
//set internal status
|
//set internal status
|
||||||
_thread->isSingleStepping = false;
|
mThread->isSingleStepping = false;
|
||||||
_continueStatus = DBG_CONTINUE;
|
mContinueStatus = DBG_CONTINUE;
|
||||||
|
|
||||||
//call the generic callback
|
//call the generic callback
|
||||||
cbStep();
|
cbStep();
|
||||||
|
|
||||||
//call the user callbacks
|
//call the user callbacks
|
||||||
auto cbStepCopy = _thread->stepCallbacks;
|
auto cbStepCopy = mThread->stepCallbacks;
|
||||||
_thread->stepCallbacks.clear();
|
mThread->stepCallbacks.clear();
|
||||||
for (auto cbStep : cbStepCopy)
|
for (auto cbStep : cbStepCopy)
|
||||||
cbStep();
|
cbStep();
|
||||||
}
|
}
|
||||||
|
|
@ -85,69 +85,69 @@ namespace GleeBug
|
||||||
void Debugger::exceptionHardwareBreakpoint(ptr exceptionAddress)
|
void Debugger::exceptionHardwareBreakpoint(ptr exceptionAddress)
|
||||||
{
|
{
|
||||||
//determine the hardware breakpoint triggered
|
//determine the hardware breakpoint triggered
|
||||||
ptr dr6 = _registers->Dr6();
|
ptr dr6 = mRegisters->Dr6();
|
||||||
HardwareSlot breakpointSlot;
|
HardwareSlot breakpointSlot;
|
||||||
ptr breakpointAddress;
|
ptr breakpointAddress;
|
||||||
if (exceptionAddress == _registers->Dr0() || dr6 & 0x1)
|
if (exceptionAddress == mRegisters->Dr0() || dr6 & 0x1)
|
||||||
{
|
{
|
||||||
breakpointAddress = _registers->Dr0();
|
breakpointAddress = mRegisters->Dr0();
|
||||||
breakpointSlot = HardwareSlot::Dr0;
|
breakpointSlot = HardwareSlot::Dr0;
|
||||||
}
|
}
|
||||||
else if (exceptionAddress == _registers->Dr1() || dr6 & 0x2)
|
else if (exceptionAddress == mRegisters->Dr1() || dr6 & 0x2)
|
||||||
{
|
{
|
||||||
breakpointAddress = _registers->Dr1();
|
breakpointAddress = mRegisters->Dr1();
|
||||||
breakpointSlot = HardwareSlot::Dr1;
|
breakpointSlot = HardwareSlot::Dr1;
|
||||||
}
|
}
|
||||||
else if (exceptionAddress == _registers->Dr2() || dr6 & 0x4)
|
else if (exceptionAddress == mRegisters->Dr2() || dr6 & 0x4)
|
||||||
{
|
{
|
||||||
breakpointAddress = _registers->Dr2();
|
breakpointAddress = mRegisters->Dr2();
|
||||||
breakpointSlot = HardwareSlot::Dr2;
|
breakpointSlot = HardwareSlot::Dr2;
|
||||||
}
|
}
|
||||||
else if (exceptionAddress == _registers->Dr3() || dr6 & 0x8)
|
else if (exceptionAddress == mRegisters->Dr3() || dr6 & 0x8)
|
||||||
{
|
{
|
||||||
breakpointAddress = _registers->Dr3();
|
breakpointAddress = mRegisters->Dr3();
|
||||||
breakpointSlot = HardwareSlot::Dr3;
|
breakpointSlot = HardwareSlot::Dr3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return; //not a hardware breakpoint
|
return; //not a hardware breakpoint
|
||||||
|
|
||||||
//find the breakpoint in the internal structures
|
//find the breakpoint in the internal structures
|
||||||
auto foundInfo = _process->breakpoints.find({ BreakpointType::Hardware, breakpointAddress });
|
auto foundInfo = mProcess->breakpoints.find({ BreakpointType::Hardware, breakpointAddress });
|
||||||
if (foundInfo == _process->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)
|
||||||
return; //not a valid hardware breakpoint
|
return; //not a valid hardware breakpoint
|
||||||
|
|
||||||
//set continue status
|
//set continue status
|
||||||
_continueStatus = DBG_CONTINUE;
|
mContinueStatus = DBG_CONTINUE;
|
||||||
|
|
||||||
//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?)
|
||||||
_thread->DeleteHardwareBreakpoint(breakpointSlot);
|
mThread->DeleteHardwareBreakpoint(breakpointSlot);
|
||||||
_thread->StepInternal(std::bind([this, info]()
|
mThread->StepInternal(std::bind([this, info]()
|
||||||
{
|
{
|
||||||
//only restore if the breakpoint still exists
|
//only restore if the breakpoint still exists
|
||||||
if (_process->breakpoints.find({ BreakpointType::Hardware, info.address }) != _process->breakpoints.end())
|
if (mProcess->breakpoints.find({ BreakpointType::Hardware, info.address }) != mProcess->breakpoints.end())
|
||||||
_thread->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);
|
||||||
|
|
||||||
//call the user callback
|
//call the user callback
|
||||||
auto foundCallback = _process->breakpointCallbacks.find({ BreakpointType::Hardware, info.address });
|
auto foundCallback = mProcess->breakpointCallbacks.find({ BreakpointType::Hardware, info.address });
|
||||||
if (foundCallback != _process->breakpointCallbacks.end())
|
if (foundCallback != mProcess->breakpointCallbacks.end())
|
||||||
foundCallback->second(info);
|
foundCallback->second(info);
|
||||||
|
|
||||||
//delete the breakpoint if it is singleshoot
|
//delete the breakpoint if it is singleshoot
|
||||||
if (info.singleshoot)
|
if (info.singleshoot)
|
||||||
_process->DeleteGenericBreakpoint(info);
|
mProcess->DeleteGenericBreakpoint(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
_continueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
mContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
|
|
||||||
const EXCEPTION_RECORD & exceptionRecord = exceptionInfo.ExceptionRecord;
|
const EXCEPTION_RECORD & exceptionRecord = exceptionInfo.ExceptionRecord;
|
||||||
bool firstChance = exceptionInfo.dwFirstChance == 1;
|
bool firstChance = exceptionInfo.dwFirstChance == 1;
|
||||||
|
|
@ -167,7 +167,7 @@ namespace GleeBug
|
||||||
}
|
}
|
||||||
|
|
||||||
//call the unhandled exception callback
|
//call the unhandled exception callback
|
||||||
if (_continueStatus == DBG_EXCEPTION_NOT_HANDLED)
|
if (mContinueStatus == DBG_EXCEPTION_NOT_HANDLED)
|
||||||
cbUnhandledException(exceptionRecord, firstChance);
|
cbUnhandledException(exceptionRecord, firstChance);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -5,27 +5,27 @@ namespace GleeBug
|
||||||
void Debugger::createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess)
|
void Debugger::createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess)
|
||||||
{
|
{
|
||||||
//process housekeeping
|
//process housekeeping
|
||||||
_processes.insert({ _debugEvent.dwProcessId,
|
mProcesses.insert({ mDebugEvent.dwProcessId,
|
||||||
ProcessInfo(createProcess.hProcess,
|
ProcessInfo(createProcess.hProcess,
|
||||||
_debugEvent.dwProcessId,
|
mDebugEvent.dwProcessId,
|
||||||
_debugEvent.dwThreadId) });
|
mDebugEvent.dwThreadId) });
|
||||||
_process = &_processes.find(_debugEvent.dwProcessId)->second;
|
mProcess = &mProcesses.find(mDebugEvent.dwProcessId)->second;
|
||||||
|
|
||||||
//thread housekeeping (main thread is created implicitly)
|
//thread housekeeping (main thread is created implicitly)
|
||||||
_process->threads.insert({ _debugEvent.dwThreadId,
|
mProcess->threads.insert({ mDebugEvent.dwThreadId,
|
||||||
ThreadInfo(createProcess.hThread,
|
ThreadInfo(createProcess.hThread,
|
||||||
_debugEvent.dwThreadId,
|
mDebugEvent.dwThreadId,
|
||||||
createProcess.lpThreadLocalBase,
|
createProcess.lpThreadLocalBase,
|
||||||
createProcess.lpStartAddress) });
|
createProcess.lpStartAddress) });
|
||||||
_thread = _process->thread = &_process->threads.find(_debugEvent.dwThreadId)->second;
|
mThread = mProcess->thread = &mProcess->threads.find(mDebugEvent.dwThreadId)->second;
|
||||||
_registers = &_thread->registers;
|
mRegisters = &mThread->registers;
|
||||||
|
|
||||||
//read thread context from main thread
|
//read thread context from main thread
|
||||||
if (!_thread->RegReadContext())
|
if (!mThread->RegReadContext())
|
||||||
cbInternalError("ThreadInfo::RegReadContext() failed!");
|
cbInternalError("ThreadInfo::RegReadContext() failed!");
|
||||||
|
|
||||||
//call the debug event callback
|
//call the debug event callback
|
||||||
cbCreateProcessEvent(createProcess, *_process);
|
cbCreateProcessEvent(createProcess, *mProcess);
|
||||||
|
|
||||||
//close the file handle
|
//close the file handle
|
||||||
CloseHandle(createProcess.hFile);
|
CloseHandle(createProcess.hFile);
|
||||||
|
|
@ -34,18 +34,18 @@ namespace GleeBug
|
||||||
void Debugger::exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess)
|
void Debugger::exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess)
|
||||||
{
|
{
|
||||||
//check if the terminated process is the main debuggee
|
//check if the terminated process is the main debuggee
|
||||||
if (_debugEvent.dwProcessId == _mainProcess.dwProcessId)
|
if (mDebugEvent.dwProcessId == mMainProcess.dwProcessId)
|
||||||
_breakDebugger = true;
|
mBreakDebugger = true;
|
||||||
|
|
||||||
//call the debug event callback
|
//call the debug event callback
|
||||||
cbExitProcessEvent(exitProcess, *_process);
|
cbExitProcessEvent(exitProcess, *mProcess);
|
||||||
|
|
||||||
//process housekeeping
|
//process housekeeping
|
||||||
_processes.erase(_debugEvent.dwProcessId);
|
mProcesses.erase(mDebugEvent.dwProcessId);
|
||||||
|
|
||||||
//set the current process
|
//set the current process
|
||||||
_process = nullptr;
|
mProcess = nullptr;
|
||||||
_thread = nullptr;
|
mThread = nullptr;
|
||||||
_registers = nullptr;
|
mRegisters = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -5,7 +5,7 @@ namespace GleeBug
|
||||||
void Debugger::ripEvent(const RIP_INFO & rip)
|
void Debugger::ripEvent(const RIP_INFO & rip)
|
||||||
{
|
{
|
||||||
//prevent anti-debug trick (RIP events are actually exceptions)
|
//prevent anti-debug trick (RIP events are actually exceptions)
|
||||||
_continueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
mContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
|
|
||||||
//call the debug event callback
|
//call the debug event callback
|
||||||
cbRipEvent(rip);
|
cbRipEvent(rip);
|
||||||
|
|
|
||||||
|
|
@ -5,32 +5,32 @@ namespace GleeBug
|
||||||
void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread)
|
void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread)
|
||||||
{
|
{
|
||||||
//thread housekeeping
|
//thread housekeeping
|
||||||
_process->threads.insert({ _debugEvent.dwThreadId,
|
mProcess->threads.insert({ mDebugEvent.dwThreadId,
|
||||||
ThreadInfo(createThread.hThread,
|
ThreadInfo(createThread.hThread,
|
||||||
_debugEvent.dwThreadId,
|
mDebugEvent.dwThreadId,
|
||||||
createThread.lpThreadLocalBase,
|
createThread.lpThreadLocalBase,
|
||||||
createThread.lpStartAddress) });
|
createThread.lpStartAddress) });
|
||||||
|
|
||||||
//set the current thread
|
//set the current thread
|
||||||
_thread = _process->thread = &_process->threads.find(_debugEvent.dwThreadId)->second;
|
mThread = mProcess->thread = &mProcess->threads.find(mDebugEvent.dwThreadId)->second;
|
||||||
_registers = &_thread->registers;
|
mRegisters = &mThread->registers;
|
||||||
if (!_thread->RegReadContext())
|
if (!mThread->RegReadContext())
|
||||||
cbInternalError("ThreadInfo::RegReadContext() failed!");
|
cbInternalError("ThreadInfo::RegReadContext() failed!");
|
||||||
|
|
||||||
//call the debug event callback
|
//call the debug event callback
|
||||||
cbCreateThreadEvent(createThread, *_thread);
|
cbCreateThreadEvent(createThread, *mThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread)
|
void Debugger::exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread)
|
||||||
{
|
{
|
||||||
//call the debug event callback
|
//call the debug event callback
|
||||||
cbExitThreadEvent(exitThread, *_thread);
|
cbExitThreadEvent(exitThread, *mThread);
|
||||||
|
|
||||||
//thread housekeeping
|
//thread housekeeping
|
||||||
_process->threads.erase(_debugEvent.dwThreadId);
|
mProcess->threads.erase(mDebugEvent.dwThreadId);
|
||||||
|
|
||||||
//set the current thread
|
//set the current thread
|
||||||
_thread = _process->thread = nullptr;
|
mThread = mProcess->thread = nullptr;
|
||||||
_registers = nullptr;
|
mRegisters = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -5,7 +5,7 @@ namespace GleeBug
|
||||||
void Debugger::unknownEvent(DWORD debugEventCode)
|
void Debugger::unknownEvent(DWORD debugEventCode)
|
||||||
{
|
{
|
||||||
//prevent possible anti-debug trick
|
//prevent possible anti-debug trick
|
||||||
_continueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
mContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
|
|
||||||
//call the debug event callback
|
//call the debug event callback
|
||||||
cbUnknownEvent(debugEventCode);
|
cbUnknownEvent(debugEventCode);
|
||||||
|
|
|
||||||
|
|
@ -5,106 +5,106 @@ namespace GleeBug
|
||||||
void Debugger::Start()
|
void Debugger::Start()
|
||||||
{
|
{
|
||||||
//initialize loop variables
|
//initialize loop variables
|
||||||
_breakDebugger = false;
|
mBreakDebugger = false;
|
||||||
_isDebugging = true;
|
mIsDebugging = true;
|
||||||
|
|
||||||
while (!_breakDebugger)
|
while (!mBreakDebugger)
|
||||||
{
|
{
|
||||||
//wait for a debug event
|
//wait for a debug event
|
||||||
_isRunning = true;
|
mIsRunning = true;
|
||||||
if (!WaitForDebugEvent(&_debugEvent, INFINITE))
|
if (!WaitForDebugEvent(&mDebugEvent, INFINITE))
|
||||||
break;
|
break;
|
||||||
_isRunning = false;
|
mIsRunning = false;
|
||||||
|
|
||||||
//set default continue status
|
//set default continue status
|
||||||
_continueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
mContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
|
|
||||||
//set the current process and thread
|
//set the current process and thread
|
||||||
auto processFound = _processes.find(_debugEvent.dwProcessId);
|
auto processFound = mProcesses.find(mDebugEvent.dwProcessId);
|
||||||
if (processFound != _processes.end())
|
if (processFound != mProcesses.end())
|
||||||
{
|
{
|
||||||
_process = &processFound->second;
|
mProcess = &processFound->second;
|
||||||
auto threadFound = _process->threads.find(_debugEvent.dwThreadId);
|
auto threadFound = mProcess->threads.find(mDebugEvent.dwThreadId);
|
||||||
if (threadFound != _process->threads.end())
|
if (threadFound != mProcess->threads.end())
|
||||||
{
|
{
|
||||||
_thread = _process->thread = &threadFound->second;
|
mThread = mProcess->thread = &threadFound->second;
|
||||||
_registers = &_thread->registers;
|
mRegisters = &mThread->registers;
|
||||||
if (!_thread->RegReadContext())
|
if (!mThread->RegReadContext())
|
||||||
cbInternalError("ThreadInfo::RegReadContext() failed!");
|
cbInternalError("ThreadInfo::RegReadContext() failed!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_thread = _process->thread = nullptr;
|
mThread = mProcess->thread = nullptr;
|
||||||
_registers = nullptr;
|
mRegisters = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_registers = nullptr;
|
mRegisters = nullptr;
|
||||||
_thread = nullptr;
|
mThread = nullptr;
|
||||||
if (_process)
|
if (mProcess)
|
||||||
{
|
{
|
||||||
_process->thread = nullptr;
|
mProcess->thread = nullptr;
|
||||||
_process = nullptr;
|
mProcess = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//call the pre debug event callback
|
//call the pre debug event callback
|
||||||
cbPostDebugEvent(_debugEvent);
|
cbPostDebugEvent(mDebugEvent);
|
||||||
|
|
||||||
//dispatch the debug event
|
//dispatch the debug event
|
||||||
switch (_debugEvent.dwDebugEventCode)
|
switch (mDebugEvent.dwDebugEventCode)
|
||||||
{
|
{
|
||||||
case CREATE_PROCESS_DEBUG_EVENT:
|
case CREATE_PROCESS_DEBUG_EVENT:
|
||||||
createProcessEvent(_debugEvent.u.CreateProcessInfo);
|
createProcessEvent(mDebugEvent.u.CreateProcessInfo);
|
||||||
break;
|
break;
|
||||||
case EXIT_PROCESS_DEBUG_EVENT:
|
case EXIT_PROCESS_DEBUG_EVENT:
|
||||||
exitProcessEvent(_debugEvent.u.ExitProcess);
|
exitProcessEvent(mDebugEvent.u.ExitProcess);
|
||||||
break;
|
break;
|
||||||
case CREATE_THREAD_DEBUG_EVENT:
|
case CREATE_THREAD_DEBUG_EVENT:
|
||||||
createThreadEvent(_debugEvent.u.CreateThread);
|
createThreadEvent(mDebugEvent.u.CreateThread);
|
||||||
break;
|
break;
|
||||||
case EXIT_THREAD_DEBUG_EVENT:
|
case EXIT_THREAD_DEBUG_EVENT:
|
||||||
exitThreadEvent(_debugEvent.u.ExitThread);
|
exitThreadEvent(mDebugEvent.u.ExitThread);
|
||||||
break;
|
break;
|
||||||
case LOAD_DLL_DEBUG_EVENT:
|
case LOAD_DLL_DEBUG_EVENT:
|
||||||
loadDllEvent(_debugEvent.u.LoadDll);
|
loadDllEvent(mDebugEvent.u.LoadDll);
|
||||||
break;
|
break;
|
||||||
case UNLOAD_DLL_DEBUG_EVENT:
|
case UNLOAD_DLL_DEBUG_EVENT:
|
||||||
unloadDllEvent(_debugEvent.u.UnloadDll);
|
unloadDllEvent(mDebugEvent.u.UnloadDll);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_DEBUG_EVENT:
|
case EXCEPTION_DEBUG_EVENT:
|
||||||
exceptionEvent(_debugEvent.u.Exception);
|
exceptionEvent(mDebugEvent.u.Exception);
|
||||||
break;
|
break;
|
||||||
case OUTPUT_DEBUG_STRING_EVENT:
|
case OUTPUT_DEBUG_STRING_EVENT:
|
||||||
debugStringEvent(_debugEvent.u.DebugString);
|
debugStringEvent(mDebugEvent.u.DebugString);
|
||||||
break;
|
break;
|
||||||
case RIP_EVENT:
|
case RIP_EVENT:
|
||||||
ripEvent(_debugEvent.u.RipInfo);
|
ripEvent(mDebugEvent.u.RipInfo);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
unknownEvent(_debugEvent.dwDebugEventCode);
|
unknownEvent(mDebugEvent.dwDebugEventCode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//call the post debug event callback
|
//call the post debug event callback
|
||||||
cbPostDebugEvent(_debugEvent);
|
cbPostDebugEvent(mDebugEvent);
|
||||||
|
|
||||||
//write the register context
|
//write the register context
|
||||||
if (_thread)
|
if (mThread)
|
||||||
{
|
{
|
||||||
if (!_thread->RegWriteContext())
|
if (!mThread->RegWriteContext())
|
||||||
cbInternalError("ThreadInfo::RegWriteContext() failed!");
|
cbInternalError("ThreadInfo::RegWriteContext() failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
//continue the debug event
|
//continue the debug event
|
||||||
if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus))
|
if (!ContinueDebugEvent(mDebugEvent.dwProcessId, mDebugEvent.dwThreadId, mContinueStatus))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
_processes.clear();
|
mProcesses.clear();
|
||||||
_process = nullptr;
|
mProcess = nullptr;
|
||||||
_isDebugging = false;
|
mIsDebugging = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -25,7 +25,10 @@ public:
|
||||||
\brief Constructor.
|
\brief Constructor.
|
||||||
\param registers Pointer to the registers object.
|
\param registers Pointer to the registers object.
|
||||||
*/
|
*/
|
||||||
explicit Flag(Registers* registers) : _registers(registers) {}
|
explicit Flag(Registers* registers)
|
||||||
|
: mRegisters(registers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Gets the flag.
|
\brief Gets the flag.
|
||||||
|
|
@ -33,7 +36,7 @@ public:
|
||||||
*/
|
*/
|
||||||
bool Get() const
|
bool Get() const
|
||||||
{
|
{
|
||||||
return _registers->GetFlag(FlagIndex);
|
return mRegisters->GetFlag(FlagIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,7 +45,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void Set(bool value = true)
|
void Set(bool value = true)
|
||||||
{
|
{
|
||||||
_registers->SetFlag(FlagIndex, value);
|
mRegisters->SetFlag(FlagIndex, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -108,7 +111,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Registers* _registers;
|
Registers* mRegisters;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //DEBUGGER_THREAD_REGISTERS_FLAG_H
|
#endif //DEBUGGER_THREAD_REGISTERS_FLAG_H
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
#include "Debugger.Thread.Registers.h"
|
#include "Debugger.Thread.Registers.h"
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
#define contextGax _context.Rax
|
#define contextGax mContext.Rax
|
||||||
#define contextGbx _context.Rbx
|
#define contextGbx mContext.Rbx
|
||||||
#define contextGcx _context.Rcx
|
#define contextGcx mContext.Rcx
|
||||||
#define contextGdx _context.Rdx
|
#define contextGdx mContext.Rdx
|
||||||
#define contextGdi _context.Rdi
|
#define contextGdi mContext.Rdi
|
||||||
#define contextGsi _context.Rsi
|
#define contextGsi mContext.Rsi
|
||||||
#define contextGbp _context.Rbp
|
#define contextGbp mContext.Rbp
|
||||||
#define contextGsp _context.Rsp
|
#define contextGsp mContext.Rsp
|
||||||
#define contextGip _context.Rip
|
#define contextGip mContext.Rip
|
||||||
#else //x32
|
#else //x32
|
||||||
#define contextGax _context.Eax
|
#define contextGax mContext.Eax
|
||||||
#define contextGbx _context.Ebx
|
#define contextGbx mContext.Ebx
|
||||||
#define contextGcx _context.Ecx
|
#define contextGcx mContext.Ecx
|
||||||
#define contextGdx _context.Edx
|
#define contextGdx mContext.Edx
|
||||||
#define contextGdi _context.Edi
|
#define contextGdi mContext.Edi
|
||||||
#define contextGsi _context.Esi
|
#define contextGsi mContext.Esi
|
||||||
#define contextGbp _context.Ebp
|
#define contextGbp mContext.Ebp
|
||||||
#define contextGsp _context.Esp
|
#define contextGsp mContext.Esp
|
||||||
#define contextGip _context.Eip
|
#define contextGip mContext.Eip
|
||||||
#endif //_WIN64
|
#endif //_WIN64
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
|
@ -50,20 +50,20 @@ namespace GleeBug
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
case R::DR0:
|
case R::DR0:
|
||||||
return ptr(_context.Dr0);
|
return ptr(mContext.Dr0);
|
||||||
case R::DR1:
|
case R::DR1:
|
||||||
return ptr(_context.Dr1);
|
return ptr(mContext.Dr1);
|
||||||
case R::DR2:
|
case R::DR2:
|
||||||
return ptr(_context.Dr2);
|
return ptr(mContext.Dr2);
|
||||||
case R::DR3:
|
case R::DR3:
|
||||||
return ptr(_context.Dr3);
|
return ptr(mContext.Dr3);
|
||||||
case R::DR6:
|
case R::DR6:
|
||||||
return ptr(_context.Dr6);
|
return ptr(mContext.Dr6);
|
||||||
case R::DR7:
|
case R::DR7:
|
||||||
return ptr(_context.Dr7);
|
return ptr(mContext.Dr7);
|
||||||
|
|
||||||
case R::EFlags:
|
case R::EFlags:
|
||||||
return ptr(_context.EFlags);
|
return ptr(mContext.EFlags);
|
||||||
|
|
||||||
case R::EAX:
|
case R::EAX:
|
||||||
return uint32_lo(contextGax);
|
return uint32_lo(contextGax);
|
||||||
|
|
@ -238,26 +238,26 @@ namespace GleeBug
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
case R::DR0:
|
case R::DR0:
|
||||||
_context.Dr0 = value;
|
mContext.Dr0 = value;
|
||||||
break;
|
break;
|
||||||
case R::DR1:
|
case R::DR1:
|
||||||
_context.Dr1 = value;
|
mContext.Dr1 = value;
|
||||||
break;
|
break;
|
||||||
case R::DR2:
|
case R::DR2:
|
||||||
_context.Dr2 = value;
|
mContext.Dr2 = value;
|
||||||
break;
|
break;
|
||||||
case R::DR3:
|
case R::DR3:
|
||||||
_context.Dr3 = value;
|
mContext.Dr3 = value;
|
||||||
break;
|
break;
|
||||||
case R::DR6:
|
case R::DR6:
|
||||||
_context.Dr6 = value;
|
mContext.Dr6 = value;
|
||||||
break;
|
break;
|
||||||
case R::DR7:
|
case R::DR7:
|
||||||
_context.Dr7 = value;
|
mContext.Dr7 = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R::EFlags:
|
case R::EFlags:
|
||||||
_context.EFlags = uint32(value);
|
mContext.EFlags = uint32(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R::EAX:
|
case R::EAX:
|
||||||
|
|
@ -506,14 +506,14 @@ namespace GleeBug
|
||||||
|
|
||||||
bool Registers::GetFlag(F flag) const
|
bool Registers::GetFlag(F flag) const
|
||||||
{
|
{
|
||||||
return (_context.EFlags & ptr(flag)) == ptr(flag);
|
return (mContext.EFlags & ptr(flag)) == ptr(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Registers::SetFlag(F flag, bool set)
|
void Registers::SetFlag(F flag, bool set)
|
||||||
{
|
{
|
||||||
if (set)
|
if (set)
|
||||||
_context.EFlags |= ptr(flag);
|
mContext.EFlags |= ptr(flag);
|
||||||
else
|
else
|
||||||
_context.EFlags &= ~ptr(flag);
|
mContext.EFlags &= ~ptr(flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +116,10 @@ public:
|
||||||
\brief Constructor.
|
\brief Constructor.
|
||||||
\param registers Pointer to the registers.
|
\param registers Pointer to the registers.
|
||||||
*/
|
*/
|
||||||
explicit Register(Registers* registers) : _registers(registers) {}
|
explicit Register(Registers* registers)
|
||||||
|
: mRegisters(registers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Gets the register value.
|
\brief Gets the register value.
|
||||||
|
|
@ -124,7 +127,7 @@ public:
|
||||||
*/
|
*/
|
||||||
Type Get() const
|
Type Get() const
|
||||||
{
|
{
|
||||||
return Type(_registers->Get(RegisterIndex));
|
return Type(mRegisters->Get(RegisterIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -133,7 +136,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void Set(Type value)
|
void Set(Type value)
|
||||||
{
|
{
|
||||||
_registers->Set(RegisterIndex, ptr(value));
|
mRegisters->Set(RegisterIndex, ptr(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -285,7 +288,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Registers* _registers;
|
Registers* mRegisters;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //DEBUGGER_THREAD_REGISTERS_REGISTER_H
|
#endif //DEBUGGER_THREAD_REGISTERS_REGISTER_H
|
||||||
|
|
@ -99,16 +99,16 @@ namespace GleeBug
|
||||||
TrapFlag(this),
|
TrapFlag(this),
|
||||||
ResumeFlag(this)
|
ResumeFlag(this)
|
||||||
{
|
{
|
||||||
memset(&this->_context, 0, sizeof(CONTEXT));
|
memset(&this->mContext, 0, sizeof(CONTEXT));
|
||||||
}
|
}
|
||||||
|
|
||||||
const CONTEXT* Registers::GetContext() const
|
const CONTEXT* Registers::GetContext() const
|
||||||
{
|
{
|
||||||
return &_context;
|
return &mContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Registers::SetContext(const CONTEXT & context)
|
void Registers::SetContext(const CONTEXT & context)
|
||||||
{
|
{
|
||||||
this->_context = context;
|
this->mContext = context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -156,7 +156,7 @@ namespace GleeBug
|
||||||
void SetContext(const CONTEXT & context);
|
void SetContext(const CONTEXT & context);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CONTEXT _context;
|
CONTEXT mContext;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,12 +43,12 @@ namespace GleeBug
|
||||||
bool ThreadInfo::RegReadContext()
|
bool ThreadInfo::RegReadContext()
|
||||||
{
|
{
|
||||||
SuspendThread(this->hThread);
|
SuspendThread(this->hThread);
|
||||||
memset(&this->_oldContext, 0, sizeof(CONTEXT));
|
memset(&this->mOldContext, 0, sizeof(CONTEXT));
|
||||||
this->_oldContext.ContextFlags = CONTEXT_ALL;
|
this->mOldContext.ContextFlags = CONTEXT_ALL;
|
||||||
bool bReturn = false;
|
bool bReturn = false;
|
||||||
if (GetThreadContext(this->hThread, &this->_oldContext))
|
if (GetThreadContext(this->hThread, &this->mOldContext))
|
||||||
{
|
{
|
||||||
this->registers.SetContext(this->_oldContext);
|
this->registers.SetContext(this->mOldContext);
|
||||||
bReturn = true;
|
bReturn = true;
|
||||||
}
|
}
|
||||||
ResumeThread(this->hThread);
|
ResumeThread(this->hThread);
|
||||||
|
|
@ -58,7 +58,7 @@ namespace GleeBug
|
||||||
bool ThreadInfo::RegWriteContext() const
|
bool ThreadInfo::RegWriteContext() const
|
||||||
{
|
{
|
||||||
//check if something actually changed
|
//check if something actually changed
|
||||||
if (memcmp(&this->_oldContext, this->registers.GetContext(), sizeof(CONTEXT)) == 0)
|
if (memcmp(&this->mOldContext, this->registers.GetContext(), sizeof(CONTEXT)) == 0)
|
||||||
return true;
|
return true;
|
||||||
//update the context
|
//update the context
|
||||||
SuspendThread(this->hThread);
|
SuspendThread(this->hThread);
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ namespace GleeBug
|
||||||
bool DeleteHardwareBreakpoint(HardwareSlot slot);
|
bool DeleteHardwareBreakpoint(HardwareSlot slot);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CONTEXT _oldContext;
|
CONTEXT mOldContext;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ namespace GleeBug
|
||||||
{
|
{
|
||||||
Debugger::Debugger()
|
Debugger::Debugger()
|
||||||
{
|
{
|
||||||
_processes.clear();
|
mProcesses.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Debugger::~Debugger()
|
Debugger::~Debugger()
|
||||||
|
|
@ -43,7 +43,7 @@ namespace GleeBug
|
||||||
nullptr,
|
nullptr,
|
||||||
szCurrentDirectory,
|
szCurrentDirectory,
|
||||||
&si,
|
&si,
|
||||||
&_mainProcess);
|
&mMainProcess);
|
||||||
|
|
||||||
delete[] szCreateWithCmdLine;
|
delete[] szCreateWithCmdLine;
|
||||||
|
|
||||||
|
|
@ -52,11 +52,11 @@ namespace GleeBug
|
||||||
|
|
||||||
bool Debugger::Stop() const
|
bool Debugger::Stop() const
|
||||||
{
|
{
|
||||||
return !!TerminateProcess(_mainProcess.hProcess, 0);
|
return !!TerminateProcess(mMainProcess.hProcess, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::Detach() const
|
bool Debugger::Detach() const
|
||||||
{
|
{
|
||||||
return !!DebugActiveProcessStop(_mainProcess.dwProcessId);
|
return !!DebugActiveProcessStop(mMainProcess.dwProcessId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -243,28 +243,28 @@ namespace GleeBug
|
||||||
virtual void exceptionHardwareBreakpoint(ptr exceptionAddress);
|
virtual void exceptionHardwareBreakpoint(ptr exceptionAddress);
|
||||||
|
|
||||||
protected: //variables
|
protected: //variables
|
||||||
PROCESS_INFORMATION _mainProcess;
|
PROCESS_INFORMATION mMainProcess;
|
||||||
uint32 _continueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
uint32 mContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
bool _breakDebugger = false;
|
bool mBreakDebugger = false;
|
||||||
DEBUG_EVENT _debugEvent;
|
DEBUG_EVENT mDebugEvent;
|
||||||
ProcessMap _processes;
|
ProcessMap mProcesses;
|
||||||
bool _isRunning = false;
|
bool mIsRunning = false;
|
||||||
bool _isDebugging = false;
|
bool mIsDebugging = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief The current process (can be null in some cases).
|
\brief The current process (can be null in some cases).
|
||||||
*/
|
*/
|
||||||
ProcessInfo* _process = nullptr;
|
ProcessInfo* mProcess = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief The current thread (can be null in some cases). Should be a copy of _process->thread.
|
\brief The current thread (can be null in some cases). Should be a copy of mProcess->thread.
|
||||||
*/
|
*/
|
||||||
ThreadInfo* _thread = nullptr;
|
ThreadInfo* mThread = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief The current thread registers (can be null in some cases). Should be a copy of _thread->registers.
|
\brief The current thread registers (can be null in some cases). Should be a copy of mThread->registers.
|
||||||
*/
|
*/
|
||||||
Registers* _registers = nullptr;
|
Registers* mRegisters = nullptr;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ namespace GleeBug
|
||||||
{
|
{
|
||||||
BufferFile::BufferFile(void* data, uint32 size)
|
BufferFile::BufferFile(void* data, uint32 size)
|
||||||
: File(nullptr),
|
: File(nullptr),
|
||||||
_data(data),
|
mData(data),
|
||||||
_size(size)
|
mSize(size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace GleeBug
|
||||||
|
|
||||||
bool BufferFile::IsOpen() const
|
bool BufferFile::IsOpen() const
|
||||||
{
|
{
|
||||||
return !!_data;
|
return !!mData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferFile::Close()
|
void BufferFile::Close()
|
||||||
|
|
@ -30,21 +30,21 @@ namespace GleeBug
|
||||||
|
|
||||||
uint32 BufferFile::GetSize() const
|
uint32 BufferFile::GetSize() const
|
||||||
{
|
{
|
||||||
return _size;
|
return mSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferFile::Read(uint32 offset, void* data, uint32 size, uint32* bytesRead) const
|
bool BufferFile::Read(uint32 offset, void* data, uint32 size, uint32* bytesRead) const
|
||||||
{
|
{
|
||||||
if (offset >= _size)
|
if (offset >= mSize)
|
||||||
return false;
|
return false;
|
||||||
auto readSize = size;
|
auto readSize = size;
|
||||||
auto result = true;
|
auto result = true;
|
||||||
if (offset + size > _size)
|
if (offset + size > mSize)
|
||||||
{
|
{
|
||||||
readSize = _size - offset;
|
readSize = mSize - offset;
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
memcpy(data, (uint8*)_data + offset, readSize);
|
memcpy(data, (uint8*)mData + offset, readSize);
|
||||||
if (bytesRead)
|
if (bytesRead)
|
||||||
*bytesRead = readSize;
|
*bytesRead = readSize;
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -52,16 +52,16 @@ namespace GleeBug
|
||||||
|
|
||||||
bool BufferFile::Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten)
|
bool BufferFile::Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten)
|
||||||
{
|
{
|
||||||
if (offset >= _size)
|
if (offset >= mSize)
|
||||||
return false;
|
return false;
|
||||||
auto writeSize = size;
|
auto writeSize = size;
|
||||||
auto result = true;
|
auto result = true;
|
||||||
if (offset + size > _size)
|
if (offset + size > mSize)
|
||||||
{
|
{
|
||||||
writeSize = _size - offset;
|
writeSize = mSize - offset;
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
memcpy((uint8*)_data + offset, data, writeSize);
|
memcpy((uint8*)mData + offset, data, writeSize);
|
||||||
if (bytesWritten)
|
if (bytesWritten)
|
||||||
*bytesWritten = writeSize;
|
*bytesWritten = writeSize;
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ namespace GleeBug
|
||||||
virtual bool Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten = nullptr) override;
|
virtual bool Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten = nullptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void* _data;
|
void* mData;
|
||||||
uint32 _size;
|
uint32 mSize;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
namespace GleeBug
|
namespace GleeBug
|
||||||
{
|
{
|
||||||
File::File(const wchar_t* szFileName, File::Mode mode)
|
File::File(const wchar_t* szFileName, File::Mode mode)
|
||||||
: _fileName(szFileName ? szFileName : L""),
|
: mFileName(szFileName ? szFileName : L""),
|
||||||
_mode(mode),
|
mMode(mode),
|
||||||
_hFile(INVALID_HANDLE_VALUE)
|
mhFile(INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,33 +26,33 @@ namespace GleeBug
|
||||||
|
|
||||||
bool File::IsOpen() const
|
bool File::IsOpen() const
|
||||||
{
|
{
|
||||||
return _hFile != INVALID_HANDLE_VALUE;
|
return mhFile != INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::Close()
|
void File::Close()
|
||||||
{
|
{
|
||||||
if (IsOpen())
|
if (IsOpen())
|
||||||
{
|
{
|
||||||
CloseHandle(_hFile);
|
CloseHandle(mhFile);
|
||||||
_hFile = INVALID_HANDLE_VALUE;
|
mhFile = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 File::GetSize() const
|
uint32 File::GetSize() const
|
||||||
{
|
{
|
||||||
return IsOpen() ? GetFileSize(_hFile, nullptr) : 0;
|
return IsOpen() ? GetFileSize(mhFile, nullptr) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool File::Read(uint32 offset, void* data, uint32 size, uint32* bytesRead) const
|
bool File::Read(uint32 offset, void* data, uint32 size, uint32* bytesRead) const
|
||||||
{
|
{
|
||||||
if (!IsOpen() || SetFilePointer(_hFile, offset, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
if (!IsOpen() || SetFilePointer(mhFile, offset, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||||
{
|
{
|
||||||
if (bytesRead)
|
if (bytesRead)
|
||||||
*bytesRead = 0;
|
*bytesRead = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DWORD NumberOfBytesRead = 0;
|
DWORD NumberOfBytesRead = 0;
|
||||||
auto result = !!ReadFile(_hFile, data, size, &NumberOfBytesRead, nullptr);
|
auto result = !!ReadFile(mhFile, data, size, &NumberOfBytesRead, nullptr);
|
||||||
if (bytesRead)
|
if (bytesRead)
|
||||||
*bytesRead = uint32(NumberOfBytesRead);
|
*bytesRead = uint32(NumberOfBytesRead);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -60,14 +60,14 @@ namespace GleeBug
|
||||||
|
|
||||||
bool File::Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten)
|
bool File::Write(uint32 offset, const void* data, uint32 size, uint32* bytesWritten)
|
||||||
{
|
{
|
||||||
if (!IsOpen() || SetFilePointer(_hFile, offset, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
if (!IsOpen() || SetFilePointer(mhFile, offset, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||||
{
|
{
|
||||||
if (bytesWritten)
|
if (bytesWritten)
|
||||||
*bytesWritten = 0;
|
*bytesWritten = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DWORD NumberOfBytesWritten = 0;
|
DWORD NumberOfBytesWritten = 0;
|
||||||
auto result = !!WriteFile(_hFile, data, size, &NumberOfBytesWritten, nullptr);
|
auto result = !!WriteFile(mhFile, data, size, &NumberOfBytesWritten, nullptr);
|
||||||
if (bytesWritten)
|
if (bytesWritten)
|
||||||
*bytesWritten = uint32(NumberOfBytesWritten);
|
*bytesWritten = uint32(NumberOfBytesWritten);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -77,7 +77,7 @@ namespace GleeBug
|
||||||
{
|
{
|
||||||
//get the access and sharemode flags
|
//get the access and sharemode flags
|
||||||
DWORD access, sharemode;
|
DWORD access, sharemode;
|
||||||
switch (_mode)
|
switch (mMode)
|
||||||
{
|
{
|
||||||
case ReadOnly:
|
case ReadOnly:
|
||||||
access = GENERIC_READ;
|
access = GENERIC_READ;
|
||||||
|
|
@ -95,7 +95,7 @@ namespace GleeBug
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
//use WinAPI to get the file handle
|
//use WinAPI to get the file handle
|
||||||
_hFile = CreateFileW(_fileName.c_str(), access, sharemode, nullptr, creation, 0, nullptr);
|
mhFile = CreateFileW(mFileName.c_str(), access, sharemode, nullptr, creation, 0, nullptr);
|
||||||
return IsOpen();
|
return IsOpen();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -83,9 +83,9 @@ namespace GleeBug
|
||||||
private:
|
private:
|
||||||
bool internalOpen(DWORD creation);
|
bool internalOpen(DWORD creation);
|
||||||
|
|
||||||
std::wstring _fileName;
|
std::wstring mFileName;
|
||||||
Mode _mode;
|
Mode mMode;
|
||||||
HANDLE _hFile;
|
HANDLE mhFile;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
namespace GleeBug
|
namespace GleeBug
|
||||||
{
|
{
|
||||||
Pe::Pe(File & file)
|
Pe::Pe(File & file)
|
||||||
: _file(file)
|
: mFile(file)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
setupErrorMap();
|
setupErrorMap();
|
||||||
|
|
@ -11,14 +11,14 @@ namespace GleeBug
|
||||||
|
|
||||||
void Pe::Clear()
|
void Pe::Clear()
|
||||||
{
|
{
|
||||||
_fileSize = 0;
|
mFileSize = 0;
|
||||||
_data.clear();
|
mData.clear();
|
||||||
_offset = 0;
|
mOffset = 0;
|
||||||
_dosHeader = Region<IMAGE_DOS_HEADER>();
|
mDosHeader = Region<IMAGE_DOS_HEADER>();
|
||||||
_afterDosData = Region<uint8>();
|
mAfterDosData = Region<uint8>();
|
||||||
_ntHeaders32 = Region<IMAGE_NT_HEADERS32>();
|
mNtHeaders32 = Region<IMAGE_NT_HEADERS32>();
|
||||||
_ntHeaders64 = Region<IMAGE_NT_HEADERS64>();
|
mNtHeaders64 = Region<IMAGE_NT_HEADERS64>();
|
||||||
_sectionHeaders = Region<IMAGE_SECTION_HEADER>();
|
mSectionHeaders = Region<IMAGE_SECTION_HEADER>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pe::Error Pe::ParseHeaders()
|
Pe::Error Pe::ParseHeaders()
|
||||||
|
|
@ -27,29 +27,29 @@ namespace GleeBug
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
//read the DOS header
|
//read the DOS header
|
||||||
_dosHeader = readRegion<IMAGE_DOS_HEADER>();
|
mDosHeader = readRegion<IMAGE_DOS_HEADER>();
|
||||||
if (!_dosHeader)
|
if (!mDosHeader)
|
||||||
return ErrorDosHeaderRead;
|
return ErrorDosHeaderRead;
|
||||||
|
|
||||||
//verify the DOS header
|
//verify the DOS header
|
||||||
if (_dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
if (mDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||||
return ErrorDosHeaderMagic;
|
return ErrorDosHeaderMagic;
|
||||||
|
|
||||||
//get the NT headers offset
|
//get the NT headers offset
|
||||||
auto newOffset = _dosHeader->e_lfanew;
|
auto newOffset = mDosHeader->e_lfanew;
|
||||||
|
|
||||||
//verify the new offset
|
//verify the new offset
|
||||||
if (newOffset < 0 || uint32(newOffset) >= _file.GetSize())
|
if (newOffset < 0 || uint32(newOffset) >= mFile.GetSize())
|
||||||
return ErrorDosHeaderNtHeaderOffset;
|
return ErrorDosHeaderNtHeaderOffset;
|
||||||
|
|
||||||
//TODO: special case where DOS and PE header overlap (tinygui.exe)
|
//TODO: special case where DOS and PE header overlap (tinygui.exe)
|
||||||
if (uint32(newOffset) < _offset)
|
if (uint32(newOffset) < mOffset)
|
||||||
return ErrorDosHeaderNtHeaderOffsetOverlap;
|
return ErrorDosHeaderNtHeaderOffsetOverlap;
|
||||||
|
|
||||||
//read & verify the data between the DOS header and the NT headers
|
//read & verify the data between the DOS header and the NT headers
|
||||||
auto afterDosCount = newOffset - _offset;
|
auto afterDosCount = newOffset - mOffset;
|
||||||
_afterDosData = readRegion<uint8>(afterDosCount);
|
mAfterDosData = readRegion<uint8>(afterDosCount);
|
||||||
if (!_afterDosData)
|
if (!mAfterDosData)
|
||||||
return ErrorAfterDosHeaderData;
|
return ErrorAfterDosHeaderData;
|
||||||
|
|
||||||
//read & verify the signature
|
//read & verify the signature
|
||||||
|
|
@ -79,8 +79,8 @@ namespace GleeBug
|
||||||
return ErrorNtOptionalHeaderMagic;
|
return ErrorNtOptionalHeaderMagic;
|
||||||
|
|
||||||
//construct & verify the NT headers region
|
//construct & verify the NT headers region
|
||||||
_ntHeaders32 = Region<IMAGE_NT_HEADERS32>(&_data, signature.Offset());
|
mNtHeaders32 = Region<IMAGE_NT_HEADERS32>(&mData, signature.Offset());
|
||||||
if (!_ntHeaders32)
|
if (!mNtHeaders32)
|
||||||
return ErrorNtHeadersRegionSize;
|
return ErrorNtHeadersRegionSize;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -96,8 +96,8 @@ namespace GleeBug
|
||||||
return ErrorNtOptionalHeaderMagic;
|
return ErrorNtOptionalHeaderMagic;
|
||||||
|
|
||||||
//construct & verify the NT headers region
|
//construct & verify the NT headers region
|
||||||
_ntHeaders64 = Region<IMAGE_NT_HEADERS64>(&_data, signature.Offset());
|
mNtHeaders64 = Region<IMAGE_NT_HEADERS64>(&mData, signature.Offset());
|
||||||
if (!_ntHeaders64)
|
if (!mNtHeaders64)
|
||||||
return ErrorNtHeadersRegionSize;
|
return ErrorNtHeadersRegionSize;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -109,8 +109,8 @@ namespace GleeBug
|
||||||
if (!ioh)
|
if (!ioh)
|
||||||
return ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead;
|
return ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead;
|
||||||
|
|
||||||
_ntHeaders32 = Region<IMAGE_NT_HEADERS32>(&_data, signature.Offset());
|
mNtHeaders32 = Region<IMAGE_NT_HEADERS32>(&mData, signature.Offset());
|
||||||
if (!_ntHeaders32)
|
if (!mNtHeaders32)
|
||||||
return ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize;
|
return ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize;
|
||||||
|
|
||||||
return ErrorNtFileHeaderUnsupportedMachine;
|
return ErrorNtFileHeaderUnsupportedMachine;
|
||||||
|
|
@ -124,55 +124,55 @@ namespace GleeBug
|
||||||
|
|
||||||
//read data after the optional header (TODO: check if this is even possible)
|
//read data after the optional header (TODO: check if this is even possible)
|
||||||
uint32 afterOptionalCount = sizeOfIoh > realSizeOfIoh ? sizeOfIoh - realSizeOfIoh : 0;
|
uint32 afterOptionalCount = sizeOfIoh > realSizeOfIoh ? sizeOfIoh - realSizeOfIoh : 0;
|
||||||
_afterOptionalData = readRegion<uint8>(afterOptionalCount);
|
mAfterOptionalData = readRegion<uint8>(afterOptionalCount);
|
||||||
|
|
||||||
//read the section headers
|
//read the section headers
|
||||||
auto sectionCount = ifh->NumberOfSections;
|
auto sectionCount = ifh->NumberOfSections;
|
||||||
_sectionHeaders = readRegion<IMAGE_SECTION_HEADER>(sectionCount);
|
mSectionHeaders = readRegion<IMAGE_SECTION_HEADER>(sectionCount);
|
||||||
|
|
||||||
return ErrorOk;
|
return ErrorOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Pe::IsValidPe() const
|
bool Pe::IsValidPe() const
|
||||||
{
|
{
|
||||||
return _sectionHeaders.Valid();
|
return mSectionHeaders.Valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Pe::IsPe64() const
|
bool Pe::IsPe64() const
|
||||||
{
|
{
|
||||||
return IsValidPe() ? _ntHeaders64.Valid() : false;
|
return IsValidPe() ? mNtHeaders64.Valid() : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Pe::readData(uint32 size)
|
uint32 Pe::readData(uint32 size)
|
||||||
{
|
{
|
||||||
std::vector<uint8> temp(size);
|
std::vector<uint8> temp(size);
|
||||||
|
|
||||||
if (!_file.Read(_offset, temp.data(), size))
|
if (!mFile.Read(mOffset, temp.data(), size))
|
||||||
return INVALID_VALUE;
|
return INVALID_VALUE;
|
||||||
|
|
||||||
auto result = _offset;
|
auto result = mOffset;
|
||||||
_offset += size;
|
mOffset += size;
|
||||||
_data.insert(_data.end(), temp.begin(), temp.end());
|
mData.insert(mData.end(), temp.begin(), temp.end());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pe::setupErrorMap()
|
void Pe::setupErrorMap()
|
||||||
{
|
{
|
||||||
_errorMap.insert({ ErrorOk, "ErrorOk" });
|
mErrorMap.insert({ ErrorOk, "ErrorOk" });
|
||||||
_errorMap.insert({ ErrorDosHeaderRead, "ErrorDosHeaderRead" });
|
mErrorMap.insert({ ErrorDosHeaderRead, "ErrorDosHeaderRead" });
|
||||||
_errorMap.insert({ ErrorDosHeaderMagic, "ErrorDosHeaderMagic" });
|
mErrorMap.insert({ ErrorDosHeaderMagic, "ErrorDosHeaderMagic" });
|
||||||
_errorMap.insert({ ErrorDosHeaderNtHeaderOffset, "ErrorDosHeaderNtHeaderOffset" });
|
mErrorMap.insert({ ErrorDosHeaderNtHeaderOffset, "ErrorDosHeaderNtHeaderOffset" });
|
||||||
_errorMap.insert({ ErrorDosHeaderNtHeaderOffsetOverlap, "ErrorDosHeaderNtHeaderOffsetOverlap" });
|
mErrorMap.insert({ ErrorDosHeaderNtHeaderOffsetOverlap, "ErrorDosHeaderNtHeaderOffsetOverlap" });
|
||||||
_errorMap.insert({ ErrorAfterDosHeaderData, "ErrorAfterDosHeaderData" });
|
mErrorMap.insert({ ErrorAfterDosHeaderData, "ErrorAfterDosHeaderData" });
|
||||||
_errorMap.insert({ ErrorNtSignatureRead, "ErrorNtSignatureRead" });
|
mErrorMap.insert({ ErrorNtSignatureRead, "ErrorNtSignatureRead" });
|
||||||
_errorMap.insert({ ErrorNtSignatureMagic, "ErrorNtSignatureMagic" });
|
mErrorMap.insert({ ErrorNtSignatureMagic, "ErrorNtSignatureMagic" });
|
||||||
_errorMap.insert({ ErrorNtFileHeaderRead, "ErrorNtFileHeaderRead" });
|
mErrorMap.insert({ ErrorNtFileHeaderRead, "ErrorNtFileHeaderRead" });
|
||||||
_errorMap.insert({ ErrorNtFileHeaderSizeOfOptionalHeaderOverlap, "ErrorNtFileHeaderSizeOfOptionalHeaderOverlap" });
|
mErrorMap.insert({ ErrorNtFileHeaderSizeOfOptionalHeaderOverlap, "ErrorNtFileHeaderSizeOfOptionalHeaderOverlap" });
|
||||||
_errorMap.insert({ ErrorNtFileHeaderUnsupportedMachine, "ErrorNtFileHeaderUnsupportedMachine" });
|
mErrorMap.insert({ ErrorNtFileHeaderUnsupportedMachine, "ErrorNtFileHeaderUnsupportedMachine" });
|
||||||
_errorMap.insert({ ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead, "ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead" });
|
mErrorMap.insert({ ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead, "ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead" });
|
||||||
_errorMap.insert({ ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize, "ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize" });
|
mErrorMap.insert({ ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize, "ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize" });
|
||||||
_errorMap.insert({ ErrorNtOptionalHeaderRead, "ErrorNtOptionalHeaderRead" });
|
mErrorMap.insert({ ErrorNtOptionalHeaderRead, "ErrorNtOptionalHeaderRead" });
|
||||||
_errorMap.insert({ ErrorNtOptionalHeaderMagic, "ErrorNtOptionalHeaderMagic" });
|
mErrorMap.insert({ ErrorNtOptionalHeaderMagic, "ErrorNtOptionalHeaderMagic" });
|
||||||
_errorMap.insert({ ErrorNtHeadersRegionSize, "ErrorNtHeadersRegionSize" });
|
mErrorMap.insert({ ErrorNtHeadersRegionSize, "ErrorNtHeadersRegionSize" });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -36,12 +36,12 @@ namespace GleeBug
|
||||||
bool IsValidPe() const;
|
bool IsValidPe() const;
|
||||||
bool IsPe64() const;
|
bool IsPe64() const;
|
||||||
|
|
||||||
const Region<IMAGE_DOS_HEADER> & GetDosHeader() const { return _dosHeader; }
|
const Region<IMAGE_DOS_HEADER> & GetDosHeader() const { return mDosHeader; }
|
||||||
const Region<uint8> & GetAfterDosData() const { return _afterDosData; }
|
const Region<uint8> & GetAfterDosData() const { return mAfterDosData; }
|
||||||
const Region<IMAGE_NT_HEADERS32> & GetNtHeaders32() const { return _ntHeaders32; }
|
const Region<IMAGE_NT_HEADERS32> & GetNtHeaders32() const { return mNtHeaders32; }
|
||||||
const Region<IMAGE_NT_HEADERS64> & GetNtHeaders64() const { return _ntHeaders64; }
|
const Region<IMAGE_NT_HEADERS64> & GetNtHeaders64() const { return mNtHeaders64; }
|
||||||
const Region<uint8> & GetAfterOptionalData() const { return _afterOptionalData; }
|
const Region<uint8> & GetAfterOptionalData() const { return mAfterOptionalData; }
|
||||||
const Region<IMAGE_SECTION_HEADER> & GetSectionHeaders() const { return _sectionHeaders; }
|
const Region<IMAGE_SECTION_HEADER> & GetSectionHeaders() const { return mSectionHeaders; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32 readData(uint32 size);
|
uint32 readData(uint32 size);
|
||||||
|
|
@ -50,21 +50,21 @@ namespace GleeBug
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline Region<T> readRegion(uint32 count = 1)
|
inline Region<T> readRegion(uint32 count = 1)
|
||||||
{
|
{
|
||||||
return Region<T>(&_data, readData(sizeof(T) * count), count);
|
return Region<T>(&mData, readData(sizeof(T) * count), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<Error, const char*> _errorMap;
|
std::unordered_map<Error, const char*> mErrorMap;
|
||||||
File & _file;
|
File & mFile;
|
||||||
uint32 _fileSize;
|
uint32 mFileSize;
|
||||||
std::vector<uint8> _data;
|
std::vector<uint8> mData;
|
||||||
uint32 _offset;
|
uint32 mOffset;
|
||||||
|
|
||||||
Region<IMAGE_DOS_HEADER> _dosHeader;
|
Region<IMAGE_DOS_HEADER> mDosHeader;
|
||||||
Region<uint8> _afterDosData;
|
Region<uint8> mAfterDosData;
|
||||||
Region<IMAGE_NT_HEADERS32> _ntHeaders32;
|
Region<IMAGE_NT_HEADERS32> mNtHeaders32;
|
||||||
Region<IMAGE_NT_HEADERS64> _ntHeaders64;
|
Region<IMAGE_NT_HEADERS64> mNtHeaders64;
|
||||||
Region<uint8> _afterOptionalData;
|
Region<uint8> mAfterOptionalData;
|
||||||
Region<IMAGE_SECTION_HEADER> _sectionHeaders;
|
Region<IMAGE_SECTION_HEADER> mSectionHeaders;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@ namespace GleeBug
|
||||||
\param count (Optional) Number of Ts in the region. Use INVALID_VALUE to create an invalid region.
|
\param count (Optional) Number of Ts in the region. Use INVALID_VALUE to create an invalid region.
|
||||||
*/
|
*/
|
||||||
explicit Region(std::vector<uint8>* data, uint32 offset, uint32 count = 1)
|
explicit Region(std::vector<uint8>* data, uint32 offset, uint32 count = 1)
|
||||||
: _data(data),
|
: mData(data),
|
||||||
_offset(offset),
|
mOffset(offset),
|
||||||
_count(count)
|
mCount(count)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,7 +42,7 @@ namespace GleeBug
|
||||||
{
|
{
|
||||||
if (!Valid())
|
if (!Valid())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return (T*)(_data->data() + _offset);
|
return (T*)(mData->data() + mOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -50,7 +50,7 @@ namespace GleeBug
|
||||||
*/
|
*/
|
||||||
uint32 Offset() const
|
uint32 Offset() const
|
||||||
{
|
{
|
||||||
return _offset;
|
return mOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -58,7 +58,7 @@ namespace GleeBug
|
||||||
*/
|
*/
|
||||||
uint32 Count() const
|
uint32 Count() const
|
||||||
{
|
{
|
||||||
return _count;
|
return mCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -66,7 +66,7 @@ namespace GleeBug
|
||||||
*/
|
*/
|
||||||
uint32 Size() const
|
uint32 Size() const
|
||||||
{
|
{
|
||||||
return Valid() ? _count * sizeof(T) : INVALID_VALUE;
|
return Valid() ? mCount * sizeof(T) : INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -74,10 +74,10 @@ namespace GleeBug
|
||||||
*/
|
*/
|
||||||
bool Valid() const
|
bool Valid() const
|
||||||
{
|
{
|
||||||
return _offset != INVALID_VALUE &&
|
return mOffset != INVALID_VALUE &&
|
||||||
_count != INVALID_VALUE &&
|
mCount != INVALID_VALUE &&
|
||||||
_data && _data->data() &&
|
mData && mData->data() &&
|
||||||
_offset + _count * sizeof(T) <= _data->size();
|
mOffset + mCount * sizeof(T) <= mData->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -110,9 +110,9 @@ namespace GleeBug
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<uint8>* _data;
|
std::vector<uint8>* mData;
|
||||||
uint32 _offset;
|
uint32 mOffset;
|
||||||
uint32 _count;
|
uint32 mCount;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,49 +11,49 @@ protected:
|
||||||
void cbEntryBreakpoint(const BreakpointInfo & info)
|
void cbEntryBreakpoint(const BreakpointInfo & info)
|
||||||
{
|
{
|
||||||
printf("Reached entry breakpoint! GIP: 0x%p\n",
|
printf("Reached entry breakpoint! GIP: 0x%p\n",
|
||||||
_registers->Gip());
|
mRegisters->Gip());
|
||||||
if (_process->DeleteBreakpoint(info.address))
|
if (mProcess->DeleteBreakpoint(info.address))
|
||||||
printf("Entry breakpoint deleted!\n");
|
printf("Entry breakpoint deleted!\n");
|
||||||
else
|
else
|
||||||
printf("Failed to delete entry breakpoint...\n");
|
printf("Failed to delete entry breakpoint...\n");
|
||||||
_thread->StepInto(std::bind([this]()
|
mThread->StepInto(std::bind([this]()
|
||||||
{
|
{
|
||||||
printf("Step after entry breakpoint! GIP: 0x%p\n",
|
printf("Step after entry breakpoint! GIP: 0x%p\n",
|
||||||
_registers->Gip());
|
mRegisters->Gip());
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbEntryHardwareBreakpoint(const BreakpointInfo & info)
|
void cbEntryHardwareBreakpoint(const BreakpointInfo & info)
|
||||||
{
|
{
|
||||||
printf("Reached entry hardware breakpoint! GIP: 0x%p\n",
|
printf("Reached entry hardware breakpoint! GIP: 0x%p\n",
|
||||||
_registers->Gip());
|
mRegisters->Gip());
|
||||||
if (_process->DeleteHardwareBreakpoint(info.address))
|
if (mProcess->DeleteHardwareBreakpoint(info.address))
|
||||||
printf("Entry hardware breakpoint deleted!\n");
|
printf("Entry hardware breakpoint deleted!\n");
|
||||||
else
|
else
|
||||||
printf("Failed to delete entry hardware breakpoint...\n");
|
printf("Failed to delete entry hardware breakpoint...\n");
|
||||||
_thread->StepInto(std::bind([this]()
|
mThread->StepInto(std::bind([this]()
|
||||||
{
|
{
|
||||||
printf("Step after entry hardware breakpoint! GIP: 0x%p\n",
|
printf("Step after entry hardware breakpoint! GIP: 0x%p\n",
|
||||||
_registers->Gip());
|
mRegisters->Gip());
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbStepSystem()
|
void cbStepSystem()
|
||||||
{
|
{
|
||||||
printf("Reached step after system breakpoint, GIP: 0x%p!\n",
|
printf("Reached step after system breakpoint, GIP: 0x%p!\n",
|
||||||
_registers->Gip());
|
mRegisters->Gip());
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) override
|
void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) override
|
||||||
{
|
{
|
||||||
ptr entry = ptr(createProcess.lpStartAddress);
|
ptr entry = ptr(createProcess.lpStartAddress);
|
||||||
printf("Process %d created with entry 0x%p\n",
|
printf("Process %d created with entry 0x%p\n",
|
||||||
_debugEvent.dwProcessId,
|
mDebugEvent.dwProcessId,
|
||||||
entry);
|
entry);
|
||||||
/*HardwareSlot slot;
|
/*HardwareSlot slot;
|
||||||
if (_process->GetFreeHardwareBreakpointSlot(slot))
|
if (mProcess->GetFreeHardwareBreakpointSlot(slot))
|
||||||
{
|
{
|
||||||
if (_process->SetHardwareBreakpoint(entry, slot, this, &MyDebugger::cbEntryHardwareBreakpoint, HardwareType::Execute, HardwareSize::SizeByte))
|
if (mProcess->SetHardwareBreakpoint(entry, slot, this, &MyDebugger::cbEntryHardwareBreakpoint, HardwareType::Execute, HardwareSize::SizeByte))
|
||||||
printf("Hardware breakpoint set at 0x%p!\n", entry);
|
printf("Hardware breakpoint set at 0x%p!\n", entry);
|
||||||
else
|
else
|
||||||
printf("Failed to set hardware breakpoint at 0x%p\n", entry);
|
printf("Failed to set hardware breakpoint at 0x%p\n", entry);
|
||||||
|
|
@ -61,18 +61,18 @@ protected:
|
||||||
else
|
else
|
||||||
printf("No free hardware breakpoint slot...\n");*/
|
printf("No free hardware breakpoint slot...\n");*/
|
||||||
|
|
||||||
if(_process->SetBreakpoint(entry, this, &MyDebugger::cbEntryBreakpoint))
|
if(mProcess->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];
|
uint8 test[5];
|
||||||
ptr start = entry - 2;
|
ptr start = entry - 2;
|
||||||
printf("unsafe: ");
|
printf("unsafe: ");
|
||||||
_process->MemRead(start, test, sizeof(test));
|
mProcess->MemRead(start, test, sizeof(test));
|
||||||
for (int i = 0; i < sizeof(test); i++)
|
for (int i = 0; i < sizeof(test); i++)
|
||||||
printf("%02X ", test[i]);
|
printf("%02X ", test[i]);
|
||||||
puts("");
|
puts("");
|
||||||
_process->MemReadSafe(start, test, sizeof(test));
|
mProcess->MemReadSafe(start, test, sizeof(test));
|
||||||
printf(" safe: ");
|
printf(" safe: ");
|
||||||
for (int i = 0; i < sizeof(test); i++)
|
for (int i = 0; i < sizeof(test); i++)
|
||||||
printf("%02X ", test[i]);
|
printf("%02X ", test[i]);
|
||||||
|
|
@ -82,21 +82,21 @@ protected:
|
||||||
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) override
|
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) override
|
||||||
{
|
{
|
||||||
printf("Process %u terminated with exit code 0x%08X\n",
|
printf("Process %u terminated with exit code 0x%08X\n",
|
||||||
_debugEvent.dwProcessId,
|
mDebugEvent.dwProcessId,
|
||||||
exitProcess.dwExitCode);
|
exitProcess.dwExitCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const ThreadInfo & thread) override
|
void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const ThreadInfo & thread) override
|
||||||
{
|
{
|
||||||
printf("Thread %u created with entry 0x%p\n",
|
printf("Thread %u created with entry 0x%p\n",
|
||||||
_debugEvent.dwThreadId,
|
mDebugEvent.dwThreadId,
|
||||||
createThread.lpStartAddress);
|
createThread.lpStartAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const ThreadInfo & thread) override
|
void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const ThreadInfo & thread) override
|
||||||
{
|
{
|
||||||
printf("Thread %u terminated with exit code 0x%08X\n",
|
printf("Thread %u terminated with exit code 0x%08X\n",
|
||||||
_debugEvent.dwThreadId,
|
mDebugEvent.dwThreadId,
|
||||||
exitThread.dwExitCode);
|
exitThread.dwExitCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,8 +138,8 @@ protected:
|
||||||
void cbSystemBreakpoint() override
|
void cbSystemBreakpoint() override
|
||||||
{
|
{
|
||||||
printf("System breakpoint reached, GIP: 0x%p\n",
|
printf("System breakpoint reached, GIP: 0x%p\n",
|
||||||
_registers->Gip());
|
mRegisters->Gip());
|
||||||
_thread->StepInto(this, &MyDebugger::cbStepSystem);
|
mThread->StepInto(this, &MyDebugger::cbStepSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbInternalError(const std::string & error) override
|
void cbInternalError(const std::string & error) override
|
||||||
|
|
@ -160,7 +160,7 @@ protected:
|
||||||
firstChance ? "first chance" : "second chance",
|
firstChance ? "first chance" : "second chance",
|
||||||
exceptionRecord.ExceptionCode,
|
exceptionRecord.ExceptionCode,
|
||||||
exceptionRecord.ExceptionAddress,
|
exceptionRecord.ExceptionAddress,
|
||||||
_registers->Gip());
|
mRegisters->Gip());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ public:
|
||||||
{
|
{
|
||||||
if (!Init(szFileName, szCommandLine, szCurrentFolder))
|
if (!Init(szFileName, szCommandLine, szCurrentFolder))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &_mainProcess;
|
return &mMainProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
PROCESS_INFORMATION* InitDLLDebugW(const wchar_t* szFileName, bool ReserveModuleBase, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder, LPVOID EntryCallBack)
|
PROCESS_INFORMATION* InitDLLDebugW(const wchar_t* szFileName, bool ReserveModuleBase, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder, LPVOID EntryCallBack)
|
||||||
|
|
@ -44,7 +44,7 @@ public:
|
||||||
|
|
||||||
void SetNextDbgContinueStatus(DWORD SetDbgCode)
|
void SetNextDbgContinueStatus(DWORD SetDbgCode)
|
||||||
{
|
{
|
||||||
this->_continueStatus = SetDbgCode;
|
this->mContinueStatus = SetDbgCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Memory
|
//Memory
|
||||||
|
|
@ -67,11 +67,11 @@ public:
|
||||||
|
|
||||||
bool Fill(LPVOID MemoryStart, DWORD MemorySize, PBYTE FillByte)
|
bool Fill(LPVOID MemoryStart, DWORD MemorySize, PBYTE FillByte)
|
||||||
{
|
{
|
||||||
if (!_process)
|
if (!mProcess)
|
||||||
return false;
|
return false;
|
||||||
for (DWORD i = 0; i < MemorySize; i++)
|
for (DWORD i = 0; i < MemorySize; i++)
|
||||||
{
|
{
|
||||||
if (!_process->MemWriteSafe(ptr(MemoryStart) + i, FillByte, 1))
|
if (!mProcess->MemWriteSafe(ptr(MemoryStart) + i, FillByte, 1))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -87,12 +87,12 @@ public:
|
||||||
|
|
||||||
bool IsFileBeingDebugged() const
|
bool IsFileBeingDebugged() const
|
||||||
{
|
{
|
||||||
return _isDebugging;
|
return mIsDebugging;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_EVENT* GetDebugData()
|
DEBUG_EVENT* GetDebugData()
|
||||||
{
|
{
|
||||||
return &_debugEvent;
|
return &mDebugEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCustomHandler(DWORD ExceptionId, PVOID CallBack)
|
void SetCustomHandler(DWORD ExceptionId, PVOID CallBack)
|
||||||
|
|
@ -100,34 +100,34 @@ public:
|
||||||
switch (ExceptionId)
|
switch (ExceptionId)
|
||||||
{
|
{
|
||||||
case UE_CH_CREATEPROCESS:
|
case UE_CH_CREATEPROCESS:
|
||||||
_cbCREATEPROCESS = CUSTOMHANDLER(CallBack);
|
mCbCREATEPROCESS = CUSTOMHANDLER(CallBack);
|
||||||
break;
|
break;
|
||||||
case UE_CH_EXITPROCESS:
|
case UE_CH_EXITPROCESS:
|
||||||
_cbEXITPROCESS = CUSTOMHANDLER(CallBack);
|
mCbEXITPROCESS = CUSTOMHANDLER(CallBack);
|
||||||
break;
|
break;
|
||||||
case UE_CH_CREATETHREAD:
|
case UE_CH_CREATETHREAD:
|
||||||
_cbCREATETHREAD = CUSTOMHANDLER(CallBack);
|
mCbCREATETHREAD = CUSTOMHANDLER(CallBack);
|
||||||
break;
|
break;
|
||||||
case UE_CH_EXITTHREAD:
|
case UE_CH_EXITTHREAD:
|
||||||
_cbEXITTHREAD = CUSTOMHANDLER(CallBack);
|
mCbEXITTHREAD = CUSTOMHANDLER(CallBack);
|
||||||
break;
|
break;
|
||||||
case UE_CH_SYSTEMBREAKPOINT:
|
case UE_CH_SYSTEMBREAKPOINT:
|
||||||
_cbSYSTEMBREAKPOINT = CUSTOMHANDLER(CallBack);
|
mCbSYSTEMBREAKPOINT = CUSTOMHANDLER(CallBack);
|
||||||
break;
|
break;
|
||||||
case UE_CH_LOADDLL:
|
case UE_CH_LOADDLL:
|
||||||
_cbLOADDLL = CUSTOMHANDLER(CallBack);
|
mCbLOADDLL = CUSTOMHANDLER(CallBack);
|
||||||
break;
|
break;
|
||||||
case UE_CH_UNLOADDLL:
|
case UE_CH_UNLOADDLL:
|
||||||
_cbUNLOADDLL = CUSTOMHANDLER(CallBack);
|
mCbUNLOADDLL = CUSTOMHANDLER(CallBack);
|
||||||
break;
|
break;
|
||||||
case UE_CH_OUTPUTDEBUGSTRING:
|
case UE_CH_OUTPUTDEBUGSTRING:
|
||||||
_cbOUTPUTDEBUGSTRING = CUSTOMHANDLER(CallBack);
|
mCbOUTPUTDEBUGSTRING = CUSTOMHANDLER(CallBack);
|
||||||
break;
|
break;
|
||||||
case UE_CH_UNHANDLEDEXCEPTION:
|
case UE_CH_UNHANDLEDEXCEPTION:
|
||||||
_cbUNHANDLEDEXCEPTION = CUSTOMHANDLER(CallBack);
|
mCbUNHANDLEDEXCEPTION = CUSTOMHANDLER(CallBack);
|
||||||
break;
|
break;
|
||||||
case UE_CH_DEBUGEVENT:
|
case UE_CH_DEBUGEVENT:
|
||||||
_cbDEBUGEVENT = CUSTOMHANDLER(CallBack);
|
mCbDEBUGEVENT = CUSTOMHANDLER(CallBack);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -137,7 +137,7 @@ public:
|
||||||
void SetEngineVariable(DWORD VariableId, bool VariableSet)
|
void SetEngineVariable(DWORD VariableId, bool VariableSet)
|
||||||
{
|
{
|
||||||
if (VariableId == UE_ENGINE_SET_DEBUG_PRIVILEGE)
|
if (VariableId == UE_ENGINE_SET_DEBUG_PRIVILEGE)
|
||||||
_setDebugPrivilege = VariableSet;
|
mSetDebugPrivilege = VariableSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Misc
|
//Misc
|
||||||
|
|
@ -180,9 +180,9 @@ public:
|
||||||
|
|
||||||
void SingleStep(DWORD StepCount, LPVOID CallBack)
|
void SingleStep(DWORD StepCount, LPVOID CallBack)
|
||||||
{
|
{
|
||||||
if (!_thread || !CallBack)
|
if (!mThread || !CallBack)
|
||||||
return;
|
return;
|
||||||
_thread->StepInto([this, StepCount, CallBack]()
|
mThread->StepInto([this, StepCount, CallBack]()
|
||||||
{
|
{
|
||||||
if (!StepCount)
|
if (!StepCount)
|
||||||
{
|
{
|
||||||
|
|
@ -196,9 +196,9 @@ public:
|
||||||
|
|
||||||
void StepInto(LPVOID CallBack)
|
void StepInto(LPVOID CallBack)
|
||||||
{
|
{
|
||||||
if (!_thread || !CallBack)
|
if (!mThread || !CallBack)
|
||||||
return;
|
return;
|
||||||
_thread->StepInto(STEPCALLBACK(CallBack));
|
mThread->StepInto(STEPCALLBACK(CallBack));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Registers
|
//Registers
|
||||||
|
|
@ -373,9 +373,9 @@ public:
|
||||||
//Software Breakpoints
|
//Software Breakpoints
|
||||||
bool SetBPX(ULONG_PTR bpxAddress, DWORD bpxType, LPVOID bpxCallBack)
|
bool SetBPX(ULONG_PTR bpxAddress, DWORD bpxType, LPVOID bpxCallBack)
|
||||||
{
|
{
|
||||||
if (!_process)
|
if (!mProcess)
|
||||||
return false;
|
return false;
|
||||||
return _process->SetBreakpoint(bpxAddress, [bpxCallBack](const BreakpointInfo &)
|
return mProcess->SetBreakpoint(bpxAddress, [bpxCallBack](const BreakpointInfo &)
|
||||||
{
|
{
|
||||||
(BPCALLBACK(bpxCallBack))();
|
(BPCALLBACK(bpxCallBack))();
|
||||||
}, (bpxType & UE_SINGLESHOOT) == UE_SINGLESHOOT);
|
}, (bpxType & UE_SINGLESHOOT) == UE_SINGLESHOOT);
|
||||||
|
|
@ -383,15 +383,15 @@ public:
|
||||||
|
|
||||||
bool DeleteBPX(ULONG_PTR bpxAddress)
|
bool DeleteBPX(ULONG_PTR bpxAddress)
|
||||||
{
|
{
|
||||||
if (!_process)
|
if (!mProcess)
|
||||||
return false;
|
return false;
|
||||||
return _process->DeleteBreakpoint(bpxAddress);
|
return mProcess->DeleteBreakpoint(bpxAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsBPXEnabled(ULONG_PTR bpxAddress)
|
bool IsBPXEnabled(ULONG_PTR bpxAddress)
|
||||||
{
|
{
|
||||||
return (_process->MemIsValidPtr(bpxAddress) &&
|
return (mProcess->MemIsValidPtr(bpxAddress) &&
|
||||||
_process->breakpoints.find({ BreakpointType::Software, bpxAddress }) != _process->breakpoints.end());
|
mProcess->breakpoints.find({ BreakpointType::Software, bpxAddress }) != mProcess->breakpoints.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetBPXOptions(long DefaultBreakPointType)
|
void SetBPXOptions(long DefaultBreakPointType)
|
||||||
|
|
@ -414,9 +414,9 @@ public:
|
||||||
//Hardware Breakpoints
|
//Hardware Breakpoints
|
||||||
bool SetHardwareBreakPoint(ULONG_PTR bpxAddress, DWORD IndexOfRegister, DWORD bpxType, DWORD bpxSize, LPVOID bpxCallBack)
|
bool SetHardwareBreakPoint(ULONG_PTR bpxAddress, DWORD IndexOfRegister, DWORD bpxType, DWORD bpxSize, LPVOID bpxCallBack)
|
||||||
{
|
{
|
||||||
if (!_process)
|
if (!mProcess)
|
||||||
return false;
|
return false;
|
||||||
return _process->SetHardwareBreakpoint(bpxAddress,
|
return mProcess->SetHardwareBreakpoint(bpxAddress,
|
||||||
(HardwareSlot)IndexOfRegister, [bpxCallBack](const BreakpointInfo & info)
|
(HardwareSlot)IndexOfRegister, [bpxCallBack](const BreakpointInfo & info)
|
||||||
{
|
{
|
||||||
(HWBPCALLBACK(bpxCallBack))((const void*)info.address);
|
(HWBPCALLBACK(bpxCallBack))((const void*)info.address);
|
||||||
|
|
@ -425,18 +425,18 @@ public:
|
||||||
|
|
||||||
bool DeleteHardwareBreakPoint(DWORD IndexOfRegister)
|
bool DeleteHardwareBreakPoint(DWORD IndexOfRegister)
|
||||||
{
|
{
|
||||||
if (!_process || IndexOfRegister < 0 || IndexOfRegister > 3)
|
if (!mProcess || IndexOfRegister < 0 || IndexOfRegister > 3)
|
||||||
return false;
|
return false;
|
||||||
auto address = _process->hardwareBreakpoints[IndexOfRegister].address;
|
auto address = mProcess->hardwareBreakpoints[IndexOfRegister].address;
|
||||||
return _process->DeleteHardwareBreakpoint(address);
|
return mProcess->DeleteHardwareBreakpoint(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetUnusedHardwareBreakPointRegister(LPDWORD RegisterIndex)
|
bool GetUnusedHardwareBreakPointRegister(LPDWORD RegisterIndex)
|
||||||
{
|
{
|
||||||
if (!_process || !RegisterIndex)
|
if (!mProcess || !RegisterIndex)
|
||||||
return false;
|
return false;
|
||||||
HardwareSlot slot;
|
HardwareSlot slot;
|
||||||
bool result = _process->GetFreeHardwareBreakpointSlot(slot);
|
bool result = mProcess->GetFreeHardwareBreakpointSlot(slot);
|
||||||
if (result)
|
if (result)
|
||||||
*RegisterIndex = (DWORD)slot;
|
*RegisterIndex = (DWORD)slot;
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -465,62 +465,62 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) override
|
void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) override
|
||||||
{
|
{
|
||||||
if (_cbCREATEPROCESS)
|
if (mCbCREATEPROCESS)
|
||||||
_cbCREATEPROCESS(&createProcess);
|
mCbCREATEPROCESS(&createProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) override
|
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) override
|
||||||
{
|
{
|
||||||
if (_cbEXITPROCESS)
|
if (mCbEXITPROCESS)
|
||||||
_cbEXITPROCESS(&exitProcess);
|
mCbEXITPROCESS(&exitProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const ThreadInfo & thread) override
|
void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const ThreadInfo & thread) override
|
||||||
{
|
{
|
||||||
if (_cbCREATETHREAD)
|
if (mCbCREATETHREAD)
|
||||||
_cbCREATETHREAD(&createThread);
|
mCbCREATETHREAD(&createThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const ThreadInfo & thread) override
|
void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const ThreadInfo & thread) override
|
||||||
{
|
{
|
||||||
if (_cbEXITTHREAD)
|
if (mCbEXITTHREAD)
|
||||||
_cbEXITTHREAD(&exitThread);
|
mCbEXITTHREAD(&exitThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll, const DllInfo & dll) override
|
void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll, const DllInfo & dll) override
|
||||||
{
|
{
|
||||||
if (_cbLOADDLL)
|
if (mCbLOADDLL)
|
||||||
_cbLOADDLL(&loadDll);
|
mCbLOADDLL(&loadDll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll, const DllInfo & dll) override
|
void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll, const DllInfo & dll) override
|
||||||
{
|
{
|
||||||
if (_cbUNLOADDLL)
|
if (mCbUNLOADDLL)
|
||||||
_cbUNLOADDLL(&unloadDll);
|
mCbUNLOADDLL(&unloadDll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) override
|
void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) override
|
||||||
{
|
{
|
||||||
if (_cbUNHANDLEDEXCEPTION)
|
if (mCbUNHANDLEDEXCEPTION)
|
||||||
_cbUNHANDLEDEXCEPTION(&_debugEvent.u.Exception);
|
mCbUNHANDLEDEXCEPTION(&mDebugEvent.u.Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) override
|
void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) override
|
||||||
{
|
{
|
||||||
if (_cbOUTPUTDEBUGSTRING)
|
if (mCbOUTPUTDEBUGSTRING)
|
||||||
_cbOUTPUTDEBUGSTRING(&debugString);
|
mCbOUTPUTDEBUGSTRING(&debugString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbPreDebugEvent(const DEBUG_EVENT & debugEvent) override
|
void cbPreDebugEvent(const DEBUG_EVENT & debugEvent) override
|
||||||
{
|
{
|
||||||
if (_cbDEBUGEVENT)
|
if (mCbDEBUGEVENT)
|
||||||
_cbDEBUGEVENT(&debugEvent);
|
mCbDEBUGEVENT(&debugEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbSystemBreakpoint() override
|
void cbSystemBreakpoint() override
|
||||||
{
|
{
|
||||||
if (_cbSYSTEMBREAKPOINT)
|
if (mCbSYSTEMBREAKPOINT)
|
||||||
_cbSYSTEMBREAKPOINT(&_debugEvent.u.Exception);
|
mCbSYSTEMBREAKPOINT(&mDebugEvent.u.Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
private: //functions
|
private: //functions
|
||||||
|
|
@ -574,13 +574,13 @@ private: //functions
|
||||||
inline ThreadInfo* threadFromHandle(HANDLE hThread) const
|
inline ThreadInfo* threadFromHandle(HANDLE hThread) const
|
||||||
{
|
{
|
||||||
//TODO: properly implement this
|
//TODO: properly implement this
|
||||||
return _thread;
|
return mThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ProcessInfo* processFromHandle(HANDLE hProcess) const
|
inline ProcessInfo* processFromHandle(HANDLE hProcess) const
|
||||||
{
|
{
|
||||||
//TODO: properly implement this
|
//TODO: properly implement this
|
||||||
return _process;
|
return mProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline HardwareType hwtypeFromTitan(DWORD type)
|
static inline HardwareType hwtypeFromTitan(DWORD type)
|
||||||
|
|
@ -618,19 +618,19 @@ private: //functions
|
||||||
}
|
}
|
||||||
|
|
||||||
private: //variables
|
private: //variables
|
||||||
bool _setDebugPrivilege = false;
|
bool mSetDebugPrivilege = false;
|
||||||
typedef void(*CUSTOMHANDLER)(const void*);
|
typedef void(*CUSTOMHANDLER)(const void*);
|
||||||
typedef void(*STEPCALLBACK)();
|
typedef void(*STEPCALLBACK)();
|
||||||
typedef STEPCALLBACK BPCALLBACK;
|
typedef STEPCALLBACK BPCALLBACK;
|
||||||
typedef CUSTOMHANDLER HWBPCALLBACK;
|
typedef CUSTOMHANDLER HWBPCALLBACK;
|
||||||
CUSTOMHANDLER _cbCREATEPROCESS = nullptr;
|
CUSTOMHANDLER mCbCREATEPROCESS = nullptr;
|
||||||
CUSTOMHANDLER _cbEXITPROCESS = nullptr;
|
CUSTOMHANDLER mCbEXITPROCESS = nullptr;
|
||||||
CUSTOMHANDLER _cbCREATETHREAD = nullptr;
|
CUSTOMHANDLER mCbCREATETHREAD = nullptr;
|
||||||
CUSTOMHANDLER _cbEXITTHREAD = nullptr;
|
CUSTOMHANDLER mCbEXITTHREAD = nullptr;
|
||||||
CUSTOMHANDLER _cbSYSTEMBREAKPOINT = nullptr;
|
CUSTOMHANDLER mCbSYSTEMBREAKPOINT = nullptr;
|
||||||
CUSTOMHANDLER _cbLOADDLL = nullptr;
|
CUSTOMHANDLER mCbLOADDLL = nullptr;
|
||||||
CUSTOMHANDLER _cbUNLOADDLL = nullptr;
|
CUSTOMHANDLER mCbUNLOADDLL = nullptr;
|
||||||
CUSTOMHANDLER _cbOUTPUTDEBUGSTRING = nullptr;
|
CUSTOMHANDLER mCbOUTPUTDEBUGSTRING = nullptr;
|
||||||
CUSTOMHANDLER _cbUNHANDLEDEXCEPTION = nullptr;
|
CUSTOMHANDLER mCbUNHANDLEDEXCEPTION = nullptr;
|
||||||
CUSTOMHANDLER _cbDEBUGEVENT = nullptr;
|
CUSTOMHANDLER mCbDEBUGEVENT = nullptr;
|
||||||
};
|
};
|
||||||
Loading…
Reference in New Issue