diff --git a/GleeBug/Debugger.Loop.DebugString.cpp b/GleeBug/Debugger.Loop.DebugString.cpp
new file mode 100644
index 0000000..54d83c1
--- /dev/null
+++ b/GleeBug/Debugger.Loop.DebugString.cpp
@@ -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);
+ }
+};
\ No newline at end of file
diff --git a/GleeBug/Debugger.Loop.Dll.cpp b/GleeBug/Debugger.Loop.Dll.cpp
new file mode 100644
index 0000000..ee0ddcc
--- /dev/null
+++ b/GleeBug/Debugger.Loop.Dll.cpp
@@ -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);
+ }
+};
\ No newline at end of file
diff --git a/GleeBug/Debugger.Loop.Exception.cpp b/GleeBug/Debugger.Loop.Exception.cpp
new file mode 100644
index 0000000..9be1187
--- /dev/null
+++ b/GleeBug/Debugger.Loop.Exception.cpp
@@ -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);
+ }
+};
\ No newline at end of file
diff --git a/GleeBug/Debugger.Loop.Process.cpp b/GleeBug/Debugger.Loop.Process.cpp
new file mode 100644
index 0000000..d4e6883
--- /dev/null
+++ b/GleeBug/Debugger.Loop.Process.cpp
@@ -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;
+ }
+};
\ No newline at end of file
diff --git a/GleeBug/Debugger.Loop.Rip.cpp b/GleeBug/Debugger.Loop.Rip.cpp
new file mode 100644
index 0000000..f364f45
--- /dev/null
+++ b/GleeBug/Debugger.Loop.Rip.cpp
@@ -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);
+ }
+};
\ No newline at end of file
diff --git a/GleeBug/Debugger.Loop.Thread.cpp b/GleeBug/Debugger.Loop.Thread.cpp
new file mode 100644
index 0000000..5fad0c0
--- /dev/null
+++ b/GleeBug/Debugger.Loop.Thread.cpp
@@ -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;
+ }
+};
\ No newline at end of file
diff --git a/GleeBug/Debugger.Loop.cpp b/GleeBug/Debugger.Loop.cpp
index 50f932e..02ef305 100644
--- a/GleeBug/Debugger.Loop.cpp
+++ b/GleeBug/Debugger.Loop.cpp
@@ -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;
}
diff --git a/GleeBug/Debugger.Process.cpp b/GleeBug/Debugger.Process.cpp
index 68434bb..7a126a3 100644
--- a/GleeBug/Debugger.Process.cpp
+++ b/GleeBug/Debugger.Process.cpp
@@ -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;
diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h
index f3e8f10..0343da7 100644
--- a/GleeBug/Debugger.Process.h
+++ b/GleeBug/Debugger.Process.h
@@ -16,8 +16,10 @@ namespace GleeBug
DWORD dwProcessId;
DWORD dwMainThreadId;
- ThreadMap threads;
ThreadInfo* curThread;
+ bool systemBreakpoint;
+
+ ThreadMap threads;
DllMap dlls;
ProcessInfo();
diff --git a/GleeBug/Debugger.h b/GleeBug/Debugger.h
index 027e534..c8327ae 100644
--- a/GleeBug/Debugger.h
+++ b/GleeBug/Debugger.h
@@ -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;
};
};
diff --git a/GleeBug/GleeBug.vcxproj b/GleeBug/GleeBug.vcxproj
index 01c5a9b..ef28bcf 100644
--- a/GleeBug/GleeBug.vcxproj
+++ b/GleeBug/GleeBug.vcxproj
@@ -149,6 +149,12 @@
+
+
+
+
+
+
diff --git a/GleeBug/GleeBug.vcxproj.filters b/GleeBug/GleeBug.vcxproj.filters
index b53def9..3c4e522 100644
--- a/GleeBug/GleeBug.vcxproj.filters
+++ b/GleeBug/GleeBug.vcxproj.filters
@@ -30,6 +30,24 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
diff --git a/MyDebugger/MyDebugger.h b/MyDebugger/MyDebugger.h
index 764907f..c49741f 100644
--- a/MyDebugger/MyDebugger.h
+++ b/MyDebugger/MyDebugger.h
@@ -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
\ No newline at end of file