From cd6b15fd8c118caac01dbe47c71627bde1072898 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sat, 28 Mar 2015 01:37:49 +0100 Subject: [PATCH 1/4] initial structure --- GleeBug/Debugger.Dll.h | 17 +++++++++++++++++ GleeBug/GleeBug.vcxproj | 1 + GleeBug/GleeBug.vcxproj.filters | 3 +++ 3 files changed, 21 insertions(+) create mode 100644 GleeBug/Debugger.Dll.h diff --git a/GleeBug/Debugger.Dll.h b/GleeBug/Debugger.Dll.h new file mode 100644 index 0000000..6c8e2bb --- /dev/null +++ b/GleeBug/Debugger.Dll.h @@ -0,0 +1,17 @@ +#ifndef _DEBUGGER_DLL_H +#define _DEBUGGER_DLL_H + +#include "_global.h" + +namespace GleeBug +{ + /** + \brief DLL information structure. + */ + struct DllInfo + { + + }; +}; + +#endif //_DEBUGGER_DLL_H \ No newline at end of file diff --git a/GleeBug/GleeBug.vcxproj b/GleeBug/GleeBug.vcxproj index 467b3c2..5ec4e44 100644 --- a/GleeBug/GleeBug.vcxproj +++ b/GleeBug/GleeBug.vcxproj @@ -139,6 +139,7 @@ + diff --git a/GleeBug/GleeBug.vcxproj.filters b/GleeBug/GleeBug.vcxproj.filters index ce2c369..307fe2d 100644 --- a/GleeBug/GleeBug.vcxproj.filters +++ b/GleeBug/GleeBug.vcxproj.filters @@ -38,5 +38,8 @@ Header Files + + Header Files + \ No newline at end of file From a3529f8b27c5ef8f05f7dd02ba7eda0490eedede Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sat, 28 Mar 2015 02:27:10 +0100 Subject: [PATCH 2/4] dll housekeeping done --- GleeBug/Debugger.Dll.h | 15 +++++++++++- GleeBug/Debugger.Global.h | 26 ++++++++++++++++++++ GleeBug/Debugger.Loop.cpp | 42 ++++++++++++++++++++++++++++----- GleeBug/Debugger.Process.h | 4 +++- GleeBug/Debugger.Thread.h | 2 +- GleeBug/Debugger.h | 14 +++++------ GleeBug/GleeBug.vcxproj | 15 ++++++++++-- GleeBug/GleeBug.vcxproj.filters | 9 +++---- GleeBug/_global.cpp | 1 - GleeBug/_global.h | 11 --------- MyDebugger/MyDebugger.h | 26 +++++++------------- 11 files changed, 112 insertions(+), 53 deletions(-) create mode 100644 GleeBug/Debugger.Global.h delete mode 100644 GleeBug/_global.cpp delete mode 100644 GleeBug/_global.h diff --git a/GleeBug/Debugger.Dll.h b/GleeBug/Debugger.Dll.h index 6c8e2bb..0b79313 100644 --- a/GleeBug/Debugger.Dll.h +++ b/GleeBug/Debugger.Dll.h @@ -1,7 +1,7 @@ #ifndef _DEBUGGER_DLL_H #define _DEBUGGER_DLL_H -#include "_global.h" +#include "Debugger.Global.h" namespace GleeBug { @@ -10,8 +10,21 @@ namespace GleeBug */ struct DllInfo { + ULONG_PTR lpBaseOfDll; + DWORD sizeOfImage; + ULONG_PTR entryPoint; + DllInfo() {} + + DllInfo(LPVOID lpBaseOfDll, DWORD sizeOfImage, LPVOID entryPoint) + { + this->lpBaseOfDll = (ULONG_PTR)lpBaseOfDll; + this->sizeOfImage = sizeOfImage; + this->entryPoint = (ULONG_PTR)entryPoint; + } }; + + typedef std::map DllMap; }; #endif //_DEBUGGER_DLL_H \ No newline at end of file diff --git a/GleeBug/Debugger.Global.h b/GleeBug/Debugger.Global.h new file mode 100644 index 0000000..8aaa312 --- /dev/null +++ b/GleeBug/Debugger.Global.h @@ -0,0 +1,26 @@ +#ifndef _DEBUGGER_GLOBAL_H +#define _DEBUGGER_GLOBAL_H + +#include +#include +#include +#include +#include + +#include +#include + +namespace GleeBug +{ + typedef std::pair Range; + + struct RangeCompare + { + inline bool operator()(const Range & a, const Range & b) const //a before b? + { + return a.second < b.first; + } + }; +}; + +#endif //_DEBUGGER_GLOBAL_H \ No newline at end of file diff --git a/GleeBug/Debugger.Loop.cpp b/GleeBug/Debugger.Loop.cpp index 39c56d0..cdded68 100644 --- a/GleeBug/Debugger.Loop.cpp +++ b/GleeBug/Debugger.Loop.cpp @@ -16,7 +16,10 @@ namespace GleeBug _curProcess->curThread = &_curProcess->threads[process.dwMainThreadId]; //call the callback - cbCreateProcessEvent(createProcess); + cbCreateProcessEvent(createProcess, *_curProcess); + + //close the file handle + CloseHandle(createProcess.hFile); } void Debugger::exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess) @@ -26,7 +29,7 @@ namespace GleeBug _breakDebugger = true; //call the callback - cbExitProcessEvent(exitProcess); + cbExitProcessEvent(exitProcess, *_curProcess); //process housekeeping _processes.erase(_debugEvent.dwProcessId); @@ -45,13 +48,13 @@ namespace GleeBug _curProcess->curThread = &_curProcess->threads[thread.dwThreadId]; //call the callback - cbCreateThreadEvent(createThread); + cbCreateThreadEvent(createThread, *_curProcess->curThread); } void Debugger::exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread) { //call the callback - cbExitThreadEvent(exitThread); + cbExitThreadEvent(exitThread, *_curProcess->curThread); //thread housekeeping _curProcess->threads.erase(_debugEvent.dwThreadId); @@ -62,12 +65,36 @@ namespace GleeBug void Debugger::loadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) { - cbLoadDllEvent(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) { - cbUnloadDllEvent(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) @@ -140,5 +167,8 @@ namespace GleeBug if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus)) break; } + + _processes.clear(); + _curProcess = nullptr; } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index baadca8..df5616f 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -1,8 +1,9 @@ #ifndef _DEBUGGER_PROCESS_H #define _DEBUGGER_PROCESS_H -#include "_global.h" +#include "Debugger.Global.h" #include "Debugger.Thread.h" +#include "Debugger.Dll.h" namespace GleeBug { @@ -18,6 +19,7 @@ namespace GleeBug ThreadMap threads; ThreadInfo* curThread; + DllMap dlls; ProcessInfo() {} //fixes a 'no default constructor available' error diff --git a/GleeBug/Debugger.Thread.h b/GleeBug/Debugger.Thread.h index 7dddb53..7bb15c2 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -1,7 +1,7 @@ #ifndef _DEBUGGER_THREADS_H #define _DEBUGGER_THREADS_H -#include "_global.h" +#include "Debugger.Global.h" namespace GleeBug { diff --git a/GleeBug/Debugger.h b/GleeBug/Debugger.h index c004c2f..027e534 100644 --- a/GleeBug/Debugger.h +++ b/GleeBug/Debugger.h @@ -1,7 +1,7 @@ #ifndef _DEBUGGER_H #define _DEBUGGER_H -#include "_global.h" +#include "Debugger.Global.h" #include "Debugger.Process.h" namespace GleeBug @@ -50,37 +50,37 @@ namespace GleeBug \brief Process creation debug event callback. Provide an implementation to use this callback. \param createProcess Information about the process created. */ - virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess) {}; + virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) {}; /** \brief Process termination debug event callback. Provide an implementation to use this callback. \param exitProcess Information about the process terminated. */ - virtual void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess) {}; + virtual void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) {}; /** \brief Thread creation debug event callback. Provide an implementation to use this callback. \param createThread Information about the thread created. */ - virtual void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread) {}; + virtual void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const ThreadInfo & thread) {}; /** \brief Thread termination debug event callback. Provide an implementation to use this callback. \param exitThread Information about the thread terminated. */ - virtual void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread) {}; + virtual void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const ThreadInfo & thread) {}; /** \brief DLL load debug event callback. Provide an implementation to use this callback. \param loadDll Information about the DLL loaded. */ - virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) {}; + virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll, const DllInfo & dll) {}; /** \brief DLL unload debug event callback. Provide an implementation to use this callback. \param unloadDll Information about the DLL unloaded. */ - virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll) {}; + virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll, const DllInfo & dll) {}; /** \brief Exception debug event callback. Provide an implementation to use this callback. diff --git a/GleeBug/GleeBug.vcxproj b/GleeBug/GleeBug.vcxproj index 5ec4e44..23e52aa 100644 --- a/GleeBug/GleeBug.vcxproj +++ b/GleeBug/GleeBug.vcxproj @@ -91,6 +91,9 @@ true + + psapi.lib;%(AdditionalDependencies) + @@ -102,6 +105,9 @@ true + + psapi.lib;%(AdditionalDependencies) + @@ -117,6 +123,9 @@ true true + + psapi.lib;%(AdditionalDependencies) + @@ -132,18 +141,20 @@ true true + + psapi.lib;%(AdditionalDependencies) + - - + diff --git a/GleeBug/GleeBug.vcxproj.filters b/GleeBug/GleeBug.vcxproj.filters index 307fe2d..8d837a2 100644 --- a/GleeBug/GleeBug.vcxproj.filters +++ b/GleeBug/GleeBug.vcxproj.filters @@ -15,9 +15,6 @@ - - Source Files - Source Files @@ -26,9 +23,6 @@ - - Header Files - Header Files @@ -41,5 +35,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/GleeBug/_global.cpp b/GleeBug/_global.cpp deleted file mode 100644 index fc065f4..0000000 --- a/GleeBug/_global.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "_global.h" \ No newline at end of file diff --git a/GleeBug/_global.h b/GleeBug/_global.h deleted file mode 100644 index ef4de98..0000000 --- a/GleeBug/_global.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _GLOBAL_H -#define _GLOBAL_H - -#include -#include -#include -#include -#include -#include - -#endif //_GLOBAL_H \ No newline at end of file diff --git a/MyDebugger/MyDebugger.h b/MyDebugger/MyDebugger.h index 86b18ee..764907f 100644 --- a/MyDebugger/MyDebugger.h +++ b/MyDebugger/MyDebugger.h @@ -3,45 +3,37 @@ #include "../GleeBug/Debugger.h" -class MyDebugger : public GleeBug::Debugger +using namespace GleeBug; + +class MyDebugger : public Debugger { protected: - virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess) + virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) { printf("Process %d created with entry 0x%p\n", _debugEvent.dwProcessId, createProcess.lpStartAddress); }; - virtual void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess) + virtual void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) { printf("Process %d terminated with exit code 0x%08X\n", _debugEvent.dwProcessId, exitProcess.dwExitCode); } - virtual void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread) + virtual void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const ThreadInfo & thread) { printf("Thread %d created with entry 0x%p\n", _debugEvent.dwThreadId, createThread.lpStartAddress); }; - virtual void cbException_single_spep(EXCEPTION_RECORD & except_inf) - { - printf("a single step occurred at location 0x%X", except_inf.ExceptionAddress); - }; - - virtual void cbExcpetion_breakpoint(EXCEPTION_RECORD & except_inf) - { - printf("a breakpoint occurred at location 0x%X", except_inf.ExceptionAddress); - }; - - virtual void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread) + virtual void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const ThreadInfo & thread) { printf("Thread %d terminated with exit code 0x%08X\n", _debugEvent.dwThreadId, exitThread.dwExitCode); }; - virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) + virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll, const DllInfo & dll) { printf("DLL loaded at 0x%p\n", loadDll.lpBaseOfDll); }; - virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll) + virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll, const DllInfo & dll) { printf("DLL 0x%p unloaded\n", unloadDll.lpBaseOfDll); }; From 30036a9fb6a4bc9e1a11b09fe90bb9d065d52feb Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sat, 28 Mar 2015 03:45:48 +0100 Subject: [PATCH 3/4] better separation of code and definitions --- GleeBug/Debugger.Dll.cpp | 15 +++++++++++++++ GleeBug/Debugger.Dll.h | 10 ++-------- GleeBug/Debugger.Loop.cpp | 6 ++---- GleeBug/Debugger.Process.cpp | 24 ++++++++++++++++++++++++ GleeBug/Debugger.Process.h | 14 +++----------- GleeBug/Debugger.Thread.cpp | 23 +++++++++++++++++++++++ GleeBug/Debugger.Thread.h | 12 +++--------- GleeBug/GleeBug.vcxproj | 3 +++ GleeBug/GleeBug.vcxproj.filters | 9 +++++++++ 9 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 GleeBug/Debugger.Dll.cpp create mode 100644 GleeBug/Debugger.Process.cpp create mode 100644 GleeBug/Debugger.Thread.cpp diff --git a/GleeBug/Debugger.Dll.cpp b/GleeBug/Debugger.Dll.cpp new file mode 100644 index 0000000..0fc593a --- /dev/null +++ b/GleeBug/Debugger.Dll.cpp @@ -0,0 +1,15 @@ +#include "Debugger.Dll.h" + +namespace GleeBug +{ + DllInfo::DllInfo() + { + } + + DllInfo::DllInfo(LPVOID lpBaseOfDll, DWORD sizeOfImage, LPVOID entryPoint) + { + this->lpBaseOfDll = (ULONG_PTR)lpBaseOfDll; + this->sizeOfImage = sizeOfImage; + this->entryPoint = (ULONG_PTR)entryPoint; + } +}; \ No newline at end of file diff --git a/GleeBug/Debugger.Dll.h b/GleeBug/Debugger.Dll.h index 0b79313..810c4d0 100644 --- a/GleeBug/Debugger.Dll.h +++ b/GleeBug/Debugger.Dll.h @@ -14,14 +14,8 @@ namespace GleeBug DWORD sizeOfImage; ULONG_PTR entryPoint; - DllInfo() {} - - DllInfo(LPVOID lpBaseOfDll, DWORD sizeOfImage, LPVOID entryPoint) - { - this->lpBaseOfDll = (ULONG_PTR)lpBaseOfDll; - this->sizeOfImage = sizeOfImage; - this->entryPoint = (ULONG_PTR)entryPoint; - } + DllInfo(); + DllInfo(LPVOID lpBaseOfDll, DWORD sizeOfImage, LPVOID entryPoint); }; typedef std::map DllMap; diff --git a/GleeBug/Debugger.Loop.cpp b/GleeBug/Debugger.Loop.cpp index cdded68..50f932e 100644 --- a/GleeBug/Debugger.Loop.cpp +++ b/GleeBug/Debugger.Loop.cpp @@ -5,9 +5,7 @@ namespace GleeBug void Debugger::createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess) { //process housekeeping - ProcessInfo process(createProcess.hProcess, - createProcess.hThread, - _debugEvent.dwProcessId, + ProcessInfo process(_debugEvent.dwProcessId, _debugEvent.dwThreadId); _processes.insert({ process.dwProcessId, process }); @@ -41,7 +39,7 @@ namespace GleeBug void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread) { //thread housekeeping - ThreadInfo thread(_debugEvent.dwThreadId, createThread.hThread, createThread.lpThreadLocalBase, createThread.lpStartAddress); + ThreadInfo thread(_debugEvent.dwThreadId, createThread.lpThreadLocalBase, createThread.lpStartAddress); _curProcess->threads.insert({ thread.dwThreadId, thread }); //set the current thread diff --git a/GleeBug/Debugger.Process.cpp b/GleeBug/Debugger.Process.cpp new file mode 100644 index 0000000..68434bb --- /dev/null +++ b/GleeBug/Debugger.Process.cpp @@ -0,0 +1,24 @@ +#include "Debugger.Process.h" + +namespace GleeBug +{ + ProcessInfo::ProcessInfo() + { + this->curThread = nullptr; + this->hProcess = INVALID_HANDLE_VALUE; + } + + ProcessInfo::ProcessInfo(DWORD dwProcessId, DWORD dwMainThreadId) + { + this->hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); + this->dwProcessId = dwProcessId; + this->dwMainThreadId = dwMainThreadId; + this->threads.clear(); + } + + ProcessInfo::~ProcessInfo() + { + if (this->hProcess != INVALID_HANDLE_VALUE) + CloseHandle(hProcess); + } +}; \ No newline at end of file diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index df5616f..f3e8f10 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -13,7 +13,6 @@ namespace GleeBug struct ProcessInfo { HANDLE hProcess; - HANDLE hThread; DWORD dwProcessId; DWORD dwMainThreadId; @@ -21,16 +20,9 @@ namespace GleeBug ThreadInfo* curThread; DllMap dlls; - ProcessInfo() {} //fixes a 'no default constructor available' error - - ProcessInfo(HANDLE hProcess, HANDLE hThread, DWORD dwProcessId, DWORD dwMainThreadId) - { - this->hProcess = hProcess; - this->hThread = hThread; - this->dwProcessId = dwProcessId; - this->dwMainThreadId = dwMainThreadId; - this->threads.clear(); - } + ProcessInfo(); + ProcessInfo(DWORD dwProcessId, DWORD dwMainThreadId); + ~ProcessInfo(); }; typedef std::map ProcessMap; diff --git a/GleeBug/Debugger.Thread.cpp b/GleeBug/Debugger.Thread.cpp new file mode 100644 index 0000000..5c9f3ff --- /dev/null +++ b/GleeBug/Debugger.Thread.cpp @@ -0,0 +1,23 @@ +#include "Debugger.Thread.h" + +namespace GleeBug +{ + ThreadInfo::ThreadInfo() + { + this->hThread = INVALID_HANDLE_VALUE; + } + + ThreadInfo::ThreadInfo(DWORD dwThreadId, LPVOID lpThreadLocalBase, LPVOID lpStartAddress) + { + this->dwThreadId = dwThreadId; + this->hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId); + this->lpThreadLocalBase = (ULONG_PTR)lpThreadLocalBase; + this->lpStartAddress = (ULONG_PTR)lpStartAddress; + } + + ThreadInfo::~ThreadInfo() + { + if (this->hThread != INVALID_HANDLE_VALUE) + CloseHandle(hThread); + } +}; \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.h b/GleeBug/Debugger.Thread.h index 7bb15c2..1ea2ae9 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -15,15 +15,9 @@ namespace GleeBug ULONG_PTR lpThreadLocalBase; ULONG_PTR lpStartAddress; - ThreadInfo() {} - - ThreadInfo(DWORD dwThreadId, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress) - { - this->dwThreadId = dwThreadId; - this->hThread = hThread; - this->lpThreadLocalBase = (ULONG_PTR)lpThreadLocalBase; - this->lpStartAddress = (ULONG_PTR)lpStartAddress; - } + ThreadInfo(); + ThreadInfo(DWORD dwThreadId, LPVOID lpThreadLocalBase, LPVOID lpStartAddress); + ~ThreadInfo(); }; typedef std::map ThreadMap; diff --git a/GleeBug/GleeBug.vcxproj b/GleeBug/GleeBug.vcxproj index 23e52aa..01c5a9b 100644 --- a/GleeBug/GleeBug.vcxproj +++ b/GleeBug/GleeBug.vcxproj @@ -147,7 +147,10 @@ + + + diff --git a/GleeBug/GleeBug.vcxproj.filters b/GleeBug/GleeBug.vcxproj.filters index 8d837a2..b53def9 100644 --- a/GleeBug/GleeBug.vcxproj.filters +++ b/GleeBug/GleeBug.vcxproj.filters @@ -21,6 +21,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + From b92b32b1463f6ab6ee2713649901200a3b2c3317 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sat, 28 Mar 2015 15:21:54 +0100 Subject: [PATCH 4/4] even more code separation --- GleeBug/Debugger.Loop.DebugString.cpp | 13 +++ GleeBug/Debugger.Loop.Dll.cpp | 38 ++++++++ GleeBug/Debugger.Loop.Exception.cpp | 50 +++++++++++ GleeBug/Debugger.Loop.Process.cpp | 38 ++++++++ GleeBug/Debugger.Loop.Rip.cpp | 13 +++ GleeBug/Debugger.Loop.Thread.cpp | 29 +++++++ GleeBug/Debugger.Loop.cpp | 120 +++----------------------- GleeBug/Debugger.Process.cpp | 2 + GleeBug/Debugger.Process.h | 4 +- GleeBug/Debugger.h | 33 ++++++- GleeBug/GleeBug.vcxproj | 6 ++ GleeBug/GleeBug.vcxproj.filters | 18 ++++ MyDebugger/MyDebugger.h | 7 +- 13 files changed, 258 insertions(+), 113 deletions(-) create mode 100644 GleeBug/Debugger.Loop.DebugString.cpp create mode 100644 GleeBug/Debugger.Loop.Dll.cpp create mode 100644 GleeBug/Debugger.Loop.Exception.cpp create mode 100644 GleeBug/Debugger.Loop.Process.cpp create mode 100644 GleeBug/Debugger.Loop.Rip.cpp create mode 100644 GleeBug/Debugger.Loop.Thread.cpp 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