even more code separation

This commit is contained in:
Mr. eXoDia 2015-03-28 15:21:54 +01:00
parent 30036a9fb6
commit b92b32b146
13 changed files with 258 additions and 113 deletions

View File

@ -0,0 +1,13 @@
#include "Debugger.h"
namespace GleeBug
{
void Debugger::debugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString)
{
//prevent anti-debug trick (debug string events are actually exceptions)
_continueStatus = DBG_EXCEPTION_NOT_HANDLED;
//call the debug event callback
cbDebugStringEvent(debugString);
}
};

View File

@ -0,0 +1,38 @@
#include "Debugger.h"
namespace GleeBug
{
void Debugger::loadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll)
{
//DLL housekeeping
MODULEINFO modinfo;
memset(&modinfo, 0, sizeof(MODULEINFO));
GetModuleInformation(_curProcess->hProcess,
(HMODULE)loadDll.lpBaseOfDll,
&modinfo,
sizeof(MODULEINFO));
DllInfo dll(loadDll.lpBaseOfDll, modinfo.SizeOfImage, modinfo.EntryPoint);
_curProcess->dlls.insert({ Range(dll.lpBaseOfDll, dll.lpBaseOfDll + dll.sizeOfImage - 1), dll });
//call the debug event callback
cbLoadDllEvent(loadDll, dll);
//close the file handle
CloseHandle(loadDll.hFile);
}
void Debugger::unloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll)
{
//call the debug event callback
ULONG_PTR lpBaseOfDll = (ULONG_PTR)unloadDll.lpBaseOfDll;
auto dll = _curProcess->dlls.find(Range(lpBaseOfDll, lpBaseOfDll));
if (dll != _curProcess->dlls.end())
cbUnloadDllEvent(unloadDll, dll->second);
else
cbUnloadDllEvent(unloadDll, DllInfo(unloadDll.lpBaseOfDll, 0, 0));
//DLL housekeeping
if (dll != _curProcess->dlls.end())
_curProcess->dlls.erase(dll);
}
};

View File

@ -0,0 +1,50 @@
#include "Debugger.h"
namespace GleeBug
{
void Debugger::exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance)
{
if (!_curProcess->systemBreakpoint) //handle system breakpoint
{
_curProcess->systemBreakpoint = true;
_continueStatus = DBG_CONTINUE;
//call the callback
cbSystemBreakpoint();
}
else //handle other breakpoint exceptions
{
}
}
void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance)
{
}
void Debugger::exceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo)
{
//let the debuggee handle exceptions per default
_continueStatus = DBG_EXCEPTION_NOT_HANDLED;
const EXCEPTION_RECORD & exceptionRecord = exceptionInfo.ExceptionRecord;
const bool firstChance = exceptionInfo.dwFirstChance == 1;
//dispatch the exception
switch (exceptionInfo.ExceptionRecord.ExceptionCode)
{
case STATUS_BREAKPOINT:
exceptionBreakpoint(exceptionRecord, firstChance);
break;
case STATUS_SINGLE_STEP:
exceptionSingleStep(exceptionRecord, firstChance);
break;
}
//call the unhandled exception callback
if (_continueStatus == DBG_EXCEPTION_NOT_HANDLED)
cbUnhandledException(exceptionRecord, firstChance);
//call the debug event callback
cbExceptionEvent(exceptionInfo);
}
};

View File

@ -0,0 +1,38 @@
#include "Debugger.h"
namespace GleeBug
{
void Debugger::createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess)
{
//process housekeeping
ProcessInfo process(_debugEvent.dwProcessId,
_debugEvent.dwThreadId);
_processes.insert({ process.dwProcessId, process });
//set the current process and current thread
_curProcess = &_processes[process.dwProcessId];
_curProcess->curThread = &_curProcess->threads[process.dwMainThreadId];
//call the debug event callback
cbCreateProcessEvent(createProcess, *_curProcess);
//close the file handle
CloseHandle(createProcess.hFile);
}
void Debugger::exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess)
{
//check if the terminated process is the main debuggee
if (_debugEvent.dwProcessId == _mainProcess.dwProcessId)
_breakDebugger = true;
//call the debug event callback
cbExitProcessEvent(exitProcess, *_curProcess);
//process housekeeping
_processes.erase(_debugEvent.dwProcessId);
//set the current process
_curProcess = nullptr;
}
};

View File

@ -0,0 +1,13 @@
#include "Debugger.h"
namespace GleeBug
{
void Debugger::ripEvent(const RIP_INFO & rip)
{
//prevent anti-debug trick (RIP events are actually exceptions)
_continueStatus = DBG_EXCEPTION_NOT_HANDLED;
//call the debug event callback
cbRipEvent(rip);
}
};

View File

@ -0,0 +1,29 @@
#include "Debugger.h"
namespace GleeBug
{
void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread)
{
//thread housekeeping
ThreadInfo thread(_debugEvent.dwThreadId, createThread.lpThreadLocalBase, createThread.lpStartAddress);
_curProcess->threads.insert({ thread.dwThreadId, thread });
//set the current thread
_curProcess->curThread = &_curProcess->threads[thread.dwThreadId];
//call the debug event callback
cbCreateThreadEvent(createThread, *_curProcess->curThread);
}
void Debugger::exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread)
{
//call the debug event callback
cbExitThreadEvent(exitThread, *_curProcess->curThread);
//thread housekeeping
_curProcess->threads.erase(_debugEvent.dwThreadId);
//set the current thread
_curProcess->curThread = nullptr;
}
};

View File

@ -2,122 +2,21 @@
namespace GleeBug
{
void Debugger::createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess)
{
//process housekeeping
ProcessInfo process(_debugEvent.dwProcessId,
_debugEvent.dwThreadId);
_processes.insert({ process.dwProcessId, process });
//set the current process and current thread
_curProcess = &_processes[process.dwProcessId];
_curProcess->curThread = &_curProcess->threads[process.dwMainThreadId];
//call the callback
cbCreateProcessEvent(createProcess, *_curProcess);
//close the file handle
CloseHandle(createProcess.hFile);
}
void Debugger::exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess)
{
//check if the terminated process is the main debuggee
if (_debugEvent.dwProcessId == _mainProcess.dwProcessId)
_breakDebugger = true;
//call the callback
cbExitProcessEvent(exitProcess, *_curProcess);
//process housekeeping
_processes.erase(_debugEvent.dwProcessId);
//set the current process
_curProcess = nullptr;
}
void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread)
{
//thread housekeeping
ThreadInfo thread(_debugEvent.dwThreadId, createThread.lpThreadLocalBase, createThread.lpStartAddress);
_curProcess->threads.insert({ thread.dwThreadId, thread });
//set the current thread
_curProcess->curThread = &_curProcess->threads[thread.dwThreadId];
//call the callback
cbCreateThreadEvent(createThread, *_curProcess->curThread);
}
void Debugger::exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread)
{
//call the callback
cbExitThreadEvent(exitThread, *_curProcess->curThread);
//thread housekeeping
_curProcess->threads.erase(_debugEvent.dwThreadId);
//set the current thread
_curProcess->curThread = nullptr;
}
void Debugger::loadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll)
{
//DLL housekeeping
MODULEINFO modinfo;
memset(&modinfo, 0, sizeof(MODULEINFO));
GetModuleInformation(_curProcess->hProcess,
(HMODULE)loadDll.lpBaseOfDll,
&modinfo,
sizeof(MODULEINFO));
DllInfo dll(loadDll.lpBaseOfDll, modinfo.SizeOfImage, modinfo.EntryPoint);
_curProcess->dlls.insert({ Range(dll.lpBaseOfDll, dll.lpBaseOfDll + dll.sizeOfImage - 1), dll });
//call the callback
cbLoadDllEvent(loadDll, dll);
//close the file handle
CloseHandle(loadDll.hFile);
}
void Debugger::unloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll)
{
//call the callback
ULONG_PTR lpBaseOfDll = (ULONG_PTR)unloadDll.lpBaseOfDll;
auto dll = _curProcess->dlls.find(Range(lpBaseOfDll, lpBaseOfDll));
if (dll != _curProcess->dlls.end())
cbUnloadDllEvent(unloadDll, dll->second);
else
cbUnloadDllEvent(unloadDll, DllInfo(unloadDll.lpBaseOfDll, 0, 0));
//DLL housekeeping
if (dll != _curProcess->dlls.end())
_curProcess->dlls.erase(dll);
}
void Debugger::exceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo)
{
cbExceptionEvent(exceptionInfo);
}
void Debugger::debugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString)
{
cbDebugStringEvent(debugString);
}
void Debugger::ripEvent(const RIP_INFO & rip)
{
cbRipEvent(rip);
}
void Debugger::Start()
{
_continueStatus = DBG_EXCEPTION_NOT_HANDLED;
//initialize loop variables
_breakDebugger = false;
while (!_breakDebugger)
{
//wait for a debug event
_isRunning = true;
if (!WaitForDebugEvent(&_debugEvent, INFINITE))
break;
_isRunning = false;
//set default continue status
_continueStatus = DBG_CONTINUE;
//set the current process and thread
if (_processes.count(_debugEvent.dwProcessId))
@ -131,6 +30,7 @@ namespace GleeBug
else
_curProcess = nullptr;
//dispatch the debug event
switch (_debugEvent.dwDebugEventCode)
{
case CREATE_PROCESS_DEBUG_EVENT:
@ -162,10 +62,12 @@ namespace GleeBug
break;
}
//continue the debug event
if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus))
break;
}
//cleanup
_processes.clear();
_curProcess = nullptr;
}

View File

@ -5,11 +5,13 @@ namespace GleeBug
ProcessInfo::ProcessInfo()
{
this->curThread = nullptr;
this->systemBreakpoint = false;
this->hProcess = INVALID_HANDLE_VALUE;
}
ProcessInfo::ProcessInfo(DWORD dwProcessId, DWORD dwMainThreadId)
{
this->systemBreakpoint = false;
this->hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
this->dwProcessId = dwProcessId;
this->dwMainThreadId = dwMainThreadId;

View File

@ -16,8 +16,10 @@ namespace GleeBug
DWORD dwProcessId;
DWORD dwMainThreadId;
ThreadMap threads;
ThreadInfo* curThread;
bool systemBreakpoint;
ThreadMap threads;
DllMap dlls;
ProcessInfo();

View File

@ -45,7 +45,7 @@ namespace GleeBug
*/
void Start();
protected: //callbacks
protected: //debug event callbacks
/**
\brief Process creation debug event callback. Provide an implementation to use this callback.
\param createProcess Information about the process created.
@ -100,7 +100,20 @@ namespace GleeBug
*/
virtual void cbRipEvent(const RIP_INFO & rip) {};
protected: //core functionality
protected: //other callbacks
/**
\brief Unhandled exception callback. Provide an implementation to use this callback.
\param exceptionRecord The exception record.
\param firstChance True if the exception is a first chance exception, false otherwise.
*/
virtual void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) {};
/**
\brief System breakpoint callback. Provide an implementation to use this callback.
*/
virtual void cbSystemBreakpoint() {};
protected: //core debug event handlers
/**
\brief Process creation debug event. Do not override this unless you know what you are doing!
\param createProcess Information about the process created.
@ -155,6 +168,21 @@ namespace GleeBug
*/
virtual void ripEvent(const RIP_INFO & rip);
protected: //core exception handlers
/**
\brief Breakpoint exception handler. Do not override this unless you know what you are doing!
\param exceptionRecord The exception record.
\param firstChance True if the exception is a first chance exception, false otherwise.
*/
virtual void exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance);
/**
\brief Single step exception handler. Do not override this unless you know what you are doing!
\param exceptionRecord The exception record.
\param firstChance True if the exception is a first chance exception, false otherwise.
*/
virtual void exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance);
protected: //variables
PROCESS_INFORMATION _mainProcess;
DWORD _continueStatus;
@ -162,6 +190,7 @@ namespace GleeBug
DEBUG_EVENT _debugEvent;
ProcessMap _processes;
ProcessInfo* _curProcess;
bool _isRunning;
};
};

View File

@ -149,6 +149,12 @@
<ClCompile Include="Debugger.cpp" />
<ClCompile Include="Debugger.Dll.cpp" />
<ClCompile Include="Debugger.Loop.cpp" />
<ClCompile Include="Debugger.Loop.DebugString.cpp" />
<ClCompile Include="Debugger.Loop.Dll.cpp" />
<ClCompile Include="Debugger.Loop.Exception.cpp" />
<ClCompile Include="Debugger.Loop.Process.cpp" />
<ClCompile Include="Debugger.Loop.Rip.cpp" />
<ClCompile Include="Debugger.Loop.Thread.cpp" />
<ClCompile Include="Debugger.Process.cpp" />
<ClCompile Include="Debugger.Thread.cpp" />
</ItemGroup>

View File

@ -30,6 +30,24 @@
<ClCompile Include="Debugger.Dll.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Debugger.Loop.Dll.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Debugger.Loop.Exception.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Debugger.Loop.Process.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Debugger.Loop.Thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Debugger.Loop.DebugString.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Debugger.Loop.Rip.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Debugger.h">

View File

@ -40,7 +40,7 @@ protected:
virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo)
{
printf("Exception with code 0x%08X\n", exceptionInfo.ExceptionRecord);
printf("Exception with code 0x%08X\n", exceptionInfo.ExceptionRecord.ExceptionCode);
};
virtual void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString)
@ -52,6 +52,11 @@ protected:
{
printf("RIP event type 0x%X, error 0x%X", rip.dwType, rip.dwError);
};
virtual void cbSystemBreakpoint()
{
printf("System breakpoint reached!");
}
};
#endif //_MYDEBUGGER_H