diff --git a/.gitignore b/.gitignore index 2c7a15b..74cb0e0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ Release/ *.suo *.sdf *.opensdf +*.orig diff --git a/GleeBug/Debugger.Dll.cpp b/GleeBug/Debugger.Dll.cpp index 0fc593a..8ab8850 100644 --- a/GleeBug/Debugger.Dll.cpp +++ b/GleeBug/Debugger.Dll.cpp @@ -2,14 +2,14 @@ namespace GleeBug { - DllInfo::DllInfo() - { - } + DllInfo::DllInfo() + { + } - 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, ULONG_PTR sizeOfImage, LPVOID entryPoint) + { + this->lpBaseOfDll = reinterpret_cast(lpBaseOfDll); + this->sizeOfImage = sizeOfImage; + this->entryPoint = reinterpret_cast(entryPoint); + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Dll.h b/GleeBug/Debugger.Dll.h index 6782df4..db9ba42 100644 --- a/GleeBug/Debugger.Dll.h +++ b/GleeBug/Debugger.Dll.h @@ -5,29 +5,29 @@ namespace GleeBug { - /** - \brief DLL information structure. - */ - class DllInfo - { - public: - ULONG_PTR lpBaseOfDll; - DWORD sizeOfImage; - ULONG_PTR entryPoint; + /** + \brief DLL information structure. + */ + class DllInfo + { + public: + ULONG_PTR lpBaseOfDll; + ULONG_PTR sizeOfImage; + ULONG_PTR entryPoint; - /** - \brief Default constructor. - */ - DllInfo(); + /** + \brief Default constructor. + */ + DllInfo(); - /** - \brief Constructor. - \param lpBaseOfDll The base of DLL. - \param sizeOfImage Size of the image. - \param entryPoint The entry point. - */ - DllInfo(LPVOID lpBaseOfDll, DWORD sizeOfImage, LPVOID entryPoint); - }; + /** + \brief Constructor. + \param lpBaseOfDll The base of DLL. + \param sizeOfImage Size of the image. + \param entryPoint The entry point. + */ + DllInfo(LPVOID lpBaseOfDll, ULONG_PTR sizeOfImage, LPVOID entryPoint); + }; }; #endif //_DEBUGGER_DLL_H \ No newline at end of file diff --git a/GleeBug/Debugger.Global.h b/GleeBug/Debugger.Global.h index db8e746..9950a0c 100644 --- a/GleeBug/Debugger.Global.h +++ b/GleeBug/Debugger.Global.h @@ -14,35 +14,35 @@ namespace GleeBug { - typedef std::pair Range; + typedef std::pair Range; - struct RangeCompare - { - inline bool operator()(const Range & a, const Range & b) const //a before b? - { - return a.second < b.first; - } - }; + struct RangeCompare + { + inline bool operator()(const Range & a, const Range & b) const //a before b? + { + return a.second < b.first; + } + }; - //forward declarations - class Debugger; - class ProcessInfo; - class DllInfo; - class ThreadInfo; + //forward declarations + class Debugger; + class ProcessInfo; + class DllInfo; + class ThreadInfo; - //map typedefs - typedef std::map ProcessMap; - typedef std::map DllMap; - typedef std::map ThreadMap; - - //callback function typedefs - typedef std::function StepCallback; + //map typedefs + typedef std::map ProcessMap; + typedef std::map DllMap; + typedef std::map ThreadMap; - //vector typedefs - typedef std::vector StepCallbackVector; + //callback function typedefs + typedef std::function StepCallback; - //macros - #define BIND(thisPtr, funcPtr) std::bind(&funcPtr, thisPtr) + //vector typedefs + typedef std::vector StepCallbackVector; + + //macros +#define BIND(thisPtr, funcPtr) std::bind(&funcPtr, thisPtr) }; #endif //_DEBUGGER_GLOBAL_H \ No newline at end of file diff --git a/GleeBug/Debugger.Loop.DebugString.cpp b/GleeBug/Debugger.Loop.DebugString.cpp index 54d83c1..3f2b344 100644 --- a/GleeBug/Debugger.Loop.DebugString.cpp +++ b/GleeBug/Debugger.Loop.DebugString.cpp @@ -2,12 +2,12 @@ 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; + 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); - } + //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 index 1cc7397..6ba6116 100644 --- a/GleeBug/Debugger.Loop.Dll.cpp +++ b/GleeBug/Debugger.Loop.Dll.cpp @@ -2,37 +2,37 @@ namespace GleeBug { - void Debugger::loadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) - { - //DLL housekeeping - MODULEINFO modinfo; - memset(&modinfo, 0, sizeof(MODULEINFO)); - GetModuleInformation(_process->hProcess, - (HMODULE)loadDll.lpBaseOfDll, - &modinfo, - sizeof(MODULEINFO)); - DllInfo dll(loadDll.lpBaseOfDll, modinfo.SizeOfImage, modinfo.EntryPoint); - _process->dlls.insert({ Range(dll.lpBaseOfDll, dll.lpBaseOfDll + dll.sizeOfImage - 1), dll }); + void Debugger::loadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) + { + //DLL housekeeping + MODULEINFO modinfo; + memset(&modinfo, 0, sizeof(MODULEINFO)); + GetModuleInformation(_process->hProcess, + reinterpret_cast(loadDll.lpBaseOfDll), + &modinfo, + sizeof(MODULEINFO)); + DllInfo dll(loadDll.lpBaseOfDll, modinfo.SizeOfImage, modinfo.EntryPoint); + _process->dlls.insert({ Range(dll.lpBaseOfDll, dll.lpBaseOfDll + dll.sizeOfImage - 1), dll }); - //call the debug event callback - cbLoadDllEvent(loadDll, dll); + //call the debug event callback + cbLoadDllEvent(loadDll, dll); - //close the file handle - CloseHandle(loadDll.hFile); - } + //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 = _process->dlls.find(Range(lpBaseOfDll, lpBaseOfDll)); - if (dll != _process->dlls.end()) - cbUnloadDllEvent(unloadDll, dll->second); - else - cbUnloadDllEvent(unloadDll, DllInfo(unloadDll.lpBaseOfDll, 0, 0)); + void Debugger::unloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll) + { + //call the debug event callback + ULONG_PTR lpBaseOfDll = reinterpret_cast(unloadDll.lpBaseOfDll); + auto dll = _process->dlls.find(Range(lpBaseOfDll, lpBaseOfDll)); + if (dll != _process->dlls.end()) + cbUnloadDllEvent(unloadDll, dll->second); + else + cbUnloadDllEvent(unloadDll, DllInfo(unloadDll.lpBaseOfDll, 0, nullptr)); - //DLL housekeeping - if (dll != _process->dlls.end()) - _process->dlls.erase(dll); - } + //DLL housekeeping + if (dll != _process->dlls.end()) + _process->dlls.erase(dll); + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Loop.Exception.cpp b/GleeBug/Debugger.Loop.Exception.cpp index ca6feea..b815263 100644 --- a/GleeBug/Debugger.Loop.Exception.cpp +++ b/GleeBug/Debugger.Loop.Exception.cpp @@ -2,64 +2,61 @@ namespace GleeBug { - void Debugger::exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) - { - if (!_process->systemBreakpoint) //handle system breakpoint - { - _process->systemBreakpoint = true; - _continueStatus = DBG_CONTINUE; + void Debugger::exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) + { + if (!_process->systemBreakpoint) //handle system breakpoint + { + _process->systemBreakpoint = true; + _continueStatus = DBG_CONTINUE; - //call the callback - cbSystemBreakpoint(); - } - else //handle other breakpoint exceptions - { - } - } + //call the callback + cbSystemBreakpoint(); + } + } - void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) - { - if (_thread->isSingleStepping) //handle single step - { - _thread->isSingleStepping = false; - _continueStatus = DBG_CONTINUE; + void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) + { + if (_thread->isSingleStepping) //handle single step + { + _thread->isSingleStepping = false; + _continueStatus = DBG_CONTINUE; - //call the callbacks - StepCallbackVector cbStepCopy = _thread->stepCallbacks; - _thread->stepCallbacks.clear(); - for (auto cbStep : cbStepCopy) - cbStep(); - cbStep(); - } - else //handle other single step exceptions - { - } - } + //call the callbacks + StepCallbackVector cbStepCopy = _thread->stepCallbacks; + _thread->stepCallbacks.clear(); + for (auto cbStep : cbStepCopy) + cbStep(); + cbStep(); + } + else //handle other single step exceptions + { + } + } - void Debugger::exceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) - { - //let the debuggee handle exceptions per default - _continueStatus = DBG_EXCEPTION_NOT_HANDLED; + 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; + 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; - } + //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 unhandled exception callback + if (_continueStatus == DBG_EXCEPTION_NOT_HANDLED) + cbUnhandledException(exceptionRecord, firstChance); - //call the debug event callback - cbExceptionEvent(exceptionInfo); - } + //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 index a86675f..73dbf7f 100644 --- a/GleeBug/Debugger.Loop.Process.cpp +++ b/GleeBug/Debugger.Loop.Process.cpp @@ -2,47 +2,47 @@ namespace GleeBug { - void Debugger::createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess) - { - //process housekeeping - ProcessInfo process(_debugEvent.dwProcessId, - createProcess.hProcess, - _debugEvent.dwThreadId); - _processes.insert({ process.dwProcessId, process }); - _process = &_processes.find(process.dwProcessId)->second; + void Debugger::createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess) + { + //process housekeeping + ProcessInfo process(_debugEvent.dwProcessId, + createProcess.hProcess, + _debugEvent.dwThreadId); + _processes.insert({ process.dwProcessId, process }); + _process = &_processes.find(process.dwProcessId)->second; - //thread housekeeping (main thread is created implicitly) - ThreadInfo thread(_debugEvent.dwThreadId, - createProcess.hThread, - createProcess.lpThreadLocalBase, - createProcess.lpStartAddress); - _process->threads.insert({ thread.dwThreadId, thread }); - _thread = _process->thread = &_process->threads.find(thread.dwThreadId)->second; + //thread housekeeping (main thread is created implicitly) + ThreadInfo thread(_debugEvent.dwThreadId, + createProcess.hThread, + createProcess.lpThreadLocalBase, + createProcess.lpStartAddress); + _process->threads.insert({ thread.dwThreadId, thread }); + _thread = _process->thread = &_process->threads.find(thread.dwThreadId)->second; - //read thread context from main thread - if (!_thread->RegReadContext()) - cbInternalError("ThreadInfo::RegReadContext() failed!"); + //read thread context from main thread + if (!_thread->RegReadContext()) + cbInternalError("ThreadInfo::RegReadContext() failed!"); - //call the debug event callback - cbCreateProcessEvent(createProcess, *_process); + //call the debug event callback + cbCreateProcessEvent(createProcess, *_process); - //close the file handle - CloseHandle(createProcess.hFile); - } + //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; + 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, *_process); + //call the debug event callback + cbExitProcessEvent(exitProcess, *_process); - //process housekeeping - _processes.erase(_debugEvent.dwProcessId); + //process housekeeping + _processes.erase(_debugEvent.dwProcessId); - //set the current process - _process = nullptr; - } + //set the current process + _process = nullptr; + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Loop.Rip.cpp b/GleeBug/Debugger.Loop.Rip.cpp index f364f45..d62fd86 100644 --- a/GleeBug/Debugger.Loop.Rip.cpp +++ b/GleeBug/Debugger.Loop.Rip.cpp @@ -2,12 +2,12 @@ namespace GleeBug { - void Debugger::ripEvent(const RIP_INFO & rip) - { - //prevent anti-debug trick (RIP events are actually exceptions) - _continueStatus = DBG_EXCEPTION_NOT_HANDLED; + 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); - } + //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 index df09de3..bb3a479 100644 --- a/GleeBug/Debugger.Loop.Thread.cpp +++ b/GleeBug/Debugger.Loop.Thread.cpp @@ -2,30 +2,30 @@ namespace GleeBug { - void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread) - { - //thread housekeeping - _process->threads.insert({ _debugEvent.dwThreadId, - ThreadInfo(_debugEvent.dwThreadId, createThread.hThread, createThread.lpThreadLocalBase, createThread.lpStartAddress) }); + void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread) + { + //thread housekeeping + _process->threads.insert({ _debugEvent.dwThreadId, + ThreadInfo(_debugEvent.dwThreadId, createThread.hThread, createThread.lpThreadLocalBase, createThread.lpStartAddress) }); - //set the current thread - _thread = _process->thread = &_process->threads.find(_debugEvent.dwThreadId)->second; - if (!_thread->RegReadContext()) - cbInternalError("ThreadInfo::RegReadContext() failed!"); + //set the current thread + _thread = _process->thread = &_process->threads.find(_debugEvent.dwThreadId)->second; + if (!_thread->RegReadContext()) + cbInternalError("ThreadInfo::RegReadContext() failed!"); - //call the debug event callback - cbCreateThreadEvent(createThread, *_thread); - } + //call the debug event callback + cbCreateThreadEvent(createThread, *_thread); + } - void Debugger::exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread) - { - //call the debug event callback - cbExitThreadEvent(exitThread, *_thread); + void Debugger::exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread) + { + //call the debug event callback + cbExitThreadEvent(exitThread, *_thread); - //thread housekeeping - _process->threads.erase(_debugEvent.dwThreadId); + //thread housekeeping + _process->threads.erase(_debugEvent.dwThreadId); - //set the current thread - _thread = _process->thread = nullptr; - } + //set the current thread + _thread = _process->thread = nullptr; + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Loop.cpp b/GleeBug/Debugger.Loop.cpp index 2c33b68..9c5e9db 100644 --- a/GleeBug/Debugger.Loop.cpp +++ b/GleeBug/Debugger.Loop.cpp @@ -2,84 +2,84 @@ namespace GleeBug { - void Debugger::Start() - { - //initialize loop variables - _breakDebugger = false; + void Debugger::Start() + { + //initialize loop variables + _breakDebugger = false; - while (!_breakDebugger) - { - //wait for a debug event - _isRunning = true; - if (!WaitForDebugEvent(&_debugEvent, INFINITE)) - break; - _isRunning = false; + while (!_breakDebugger) + { + //wait for a debug event + _isRunning = true; + if (!WaitForDebugEvent(&_debugEvent, INFINITE)) + break; + _isRunning = false; - //set default continue status - _continueStatus = DBG_EXCEPTION_NOT_HANDLED; + //set default continue status + _continueStatus = DBG_EXCEPTION_NOT_HANDLED; - //set the current process and thread - if (_processes.count(_debugEvent.dwProcessId)) - { - _process = &_processes[_debugEvent.dwProcessId]; - if (_process->threads.count(_debugEvent.dwThreadId)) - { - _thread = _process->thread = &_process->threads[_debugEvent.dwThreadId]; - if (!_thread->RegReadContext()) - cbInternalError("ThreadInfo::RegReadContext() failed!"); - } - else - _thread = _process->thread = nullptr; - } - else - _process = nullptr; + //set the current process and thread + if (_processes.count(_debugEvent.dwProcessId)) + { + _process = &_processes[_debugEvent.dwProcessId]; + if (_process->threads.count(_debugEvent.dwThreadId)) + { + _thread = _process->thread = &_process->threads[_debugEvent.dwThreadId]; + if (!_thread->RegReadContext()) + cbInternalError("ThreadInfo::RegReadContext() failed!"); + } + else + _thread = _process->thread = nullptr; + } + else + _process = nullptr; - //dispatch the debug event - switch (_debugEvent.dwDebugEventCode) - { - case CREATE_PROCESS_DEBUG_EVENT: - createProcessEvent(_debugEvent.u.CreateProcessInfo); - break; - case EXIT_PROCESS_DEBUG_EVENT: - exitProcessEvent(_debugEvent.u.ExitProcess); - break; - case CREATE_THREAD_DEBUG_EVENT: - createThreadEvent(_debugEvent.u.CreateThread); - break; - case EXIT_THREAD_DEBUG_EVENT: - exitThreadEvent(_debugEvent.u.ExitThread); - break; - case LOAD_DLL_DEBUG_EVENT: - loadDllEvent(_debugEvent.u.LoadDll); - break; - case UNLOAD_DLL_DEBUG_EVENT: - unloadDllEvent(_debugEvent.u.UnloadDll); - break; - case EXCEPTION_DEBUG_EVENT: - exceptionEvent(_debugEvent.u.Exception); - break; - case OUTPUT_DEBUG_STRING_EVENT: - debugStringEvent(_debugEvent.u.DebugString); - break; - case RIP_EVENT: - ripEvent(_debugEvent.u.RipInfo); - break; - } + //dispatch the debug event + switch (_debugEvent.dwDebugEventCode) + { + case CREATE_PROCESS_DEBUG_EVENT: + createProcessEvent(_debugEvent.u.CreateProcessInfo); + break; + case EXIT_PROCESS_DEBUG_EVENT: + exitProcessEvent(_debugEvent.u.ExitProcess); + break; + case CREATE_THREAD_DEBUG_EVENT: + createThreadEvent(_debugEvent.u.CreateThread); + break; + case EXIT_THREAD_DEBUG_EVENT: + exitThreadEvent(_debugEvent.u.ExitThread); + break; + case LOAD_DLL_DEBUG_EVENT: + loadDllEvent(_debugEvent.u.LoadDll); + break; + case UNLOAD_DLL_DEBUG_EVENT: + unloadDllEvent(_debugEvent.u.UnloadDll); + break; + case EXCEPTION_DEBUG_EVENT: + exceptionEvent(_debugEvent.u.Exception); + break; + case OUTPUT_DEBUG_STRING_EVENT: + debugStringEvent(_debugEvent.u.DebugString); + break; + case RIP_EVENT: + ripEvent(_debugEvent.u.RipInfo); + break; + } - //write the register context - if (_thread) - { - if (!_thread->RegWriteContext()) - cbInternalError("ThreadInfo::RegWriteContext() failed!"); - } + //write the register context + if (_thread) + { + if (!_thread->RegWriteContext()) + cbInternalError("ThreadInfo::RegWriteContext() failed!"); + } - //continue the debug event - if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus)) - break; - } + //continue the debug event + if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus)) + break; + } - //cleanup - _processes.clear(); - _process = nullptr; - } + //cleanup + _processes.clear(); + _process = nullptr; + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Process.cpp b/GleeBug/Debugger.Process.cpp index 3e9f772..0e9472d 100644 --- a/GleeBug/Debugger.Process.cpp +++ b/GleeBug/Debugger.Process.cpp @@ -2,28 +2,28 @@ namespace GleeBug { - ProcessInfo::ProcessInfo() - { - this->thread = nullptr; - this->systemBreakpoint = false; - this->hProcess = INVALID_HANDLE_VALUE; - } + ProcessInfo::ProcessInfo() + { + this->thread = nullptr; + this->systemBreakpoint = false; + this->hProcess = INVALID_HANDLE_VALUE; + } - ProcessInfo::ProcessInfo(DWORD dwProcessId, HANDLE hProcess, DWORD dwMainThreadId) - { - this->systemBreakpoint = false; - this->hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); - this->dwProcessId = dwProcessId; - this->dwMainThreadId = dwMainThreadId; - } + ProcessInfo::ProcessInfo(DWORD dwProcessId, HANDLE hProcess, DWORD dwMainThreadId) + { + this->systemBreakpoint = false; + this->hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); + this->dwProcessId = dwProcessId; + this->dwMainThreadId = dwMainThreadId; + } - bool ProcessInfo::MemRead(ULONG_PTR address, const size_t size, void* buffer) - { - return !!ReadProcessMemory(this->hProcess, (const void*)address, buffer, size, NULL); - } + bool ProcessInfo::MemRead(ULONG_PTR address, const size_t size, void* buffer) + { + return !!ReadProcessMemory(this->hProcess, reinterpret_cast(address), buffer, size, nullptr); + } - bool ProcessInfo::MemWrite(ULONG_PTR address, const size_t size, const void* buffer) - { - return !!WriteProcessMemory(this->hProcess, (void*)address, buffer, size, NULL); - } + bool ProcessInfo::MemWrite(ULONG_PTR address, const size_t size, const void* buffer) + { + return !!WriteProcessMemory(this->hProcess, reinterpret_cast(address), buffer, size, nullptr); + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index c1bb2a2..ba182cc 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -7,52 +7,52 @@ namespace GleeBug { - /** - \brief Process information structure. - */ - class ProcessInfo - { - public: - HANDLE hProcess; - DWORD dwProcessId; - DWORD dwMainThreadId; + /** + \brief Process information structure. + */ + class ProcessInfo + { + public: + HANDLE hProcess; + DWORD dwProcessId; + DWORD dwMainThreadId; - ThreadInfo* thread; - bool systemBreakpoint; + ThreadInfo* thread; + bool systemBreakpoint; - ThreadMap threads; - DllMap dlls; + ThreadMap threads; + DllMap dlls; - /** - \brief Default constructor. - */ - ProcessInfo(); + /** + \brief Default constructor. + */ + ProcessInfo(); - /** - \brief Constructor. - \param dwProcessId Identifier for the process. - \param dwMainThreadId Identifier for the main thread. - */ - ProcessInfo(DWORD dwProcessId, HANDLE hProcess, DWORD dwMainThreadId); + /** + \brief Constructor. + \param dwProcessId Identifier for the process. + \param dwMainThreadId Identifier for the main thread. + */ + ProcessInfo(DWORD dwProcessId, HANDLE hProcess, DWORD dwMainThreadId); - /** - \brief Read memory from the process. - \param address The virtual address to read from. - \param size The size to read. - \param [out] buffer Destination buffer. Cannot be null. May be filled partially on failure. - \return true if it succeeds, false if it fails. - */ - bool MemRead(ULONG_PTR address, const size_t size, void* buffer); + /** + \brief Read memory from the process. + \param address The virtual address to read from. + \param size The size to read. + \param [out] buffer Destination buffer. Cannot be null. May be filled partially on failure. + \return true if it succeeds, false if it fails. + */ + bool MemRead(ULONG_PTR address, const size_t size, void* buffer); - /** - \brief Write memory to the process. - \param address The virtual address to write to. - \param size The size to write. - \param [in] buffer Source buffer. Cannot be null. - \return true if it succeeds, false if it fails. - */ - bool MemWrite(ULONG_PTR address, const size_t size, const void* buffer); - }; + /** + \brief Write memory to the process. + \param address The virtual address to write to. + \param size The size to write. + \param [in] buffer Source buffer. Cannot be null. + \return true if it succeeds, false if it fails. + */ + bool MemWrite(ULONG_PTR address, const size_t size, const void* buffer); + }; }; #endif //_DEBUGGER_PROCESS_H \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.Registers.cpp b/GleeBug/Debugger.Thread.Registers.cpp index b28d616..f508eba 100644 --- a/GleeBug/Debugger.Thread.Registers.cpp +++ b/GleeBug/Debugger.Thread.Registers.cpp @@ -2,106 +2,106 @@ namespace GleeBug { - RegistersInfo::RegistersInfo() - { - memset(&this->_context, 0, sizeof(CONTEXT)); - } + RegistersInfo::RegistersInfo() + { + memset(&this->_context, 0, sizeof(CONTEXT)); + } - const CONTEXT* RegistersInfo::GetContext() - { + const CONTEXT* RegistersInfo::GetContext() + { #ifdef _WIN64 - _context.Rax = this->Rax; - _context.Rbx = this->Rbx; - _context.Rcx = this->Rcx; - _context.Rdx = this->Rdx; - _context.Rsi = this->Rsi; - _context.Rdi = this->Rdi; - _context.Rbp = this->Rbp; - _context.Rsp = this->Rsp; - _context.Rip = this->Rip; - _context.R8 = this->R8; - _context.R9 = this->R9; - _context.R10 = this->R10; - _context.R11 = this->R11; - _context.R12 = this->R12; - _context.R13 = this->R13; - _context.R14 = this->R14; - _context.R15 = this->R15; - _context.EFlags = this->EFlags; + _context.Rax = this->Rax; + _context.Rbx = this->Rbx; + _context.Rcx = this->Rcx; + _context.Rdx = this->Rdx; + _context.Rsi = this->Rsi; + _context.Rdi = this->Rdi; + _context.Rbp = this->Rbp; + _context.Rsp = this->Rsp; + _context.Rip = this->Rip; + _context.R8 = this->R8; + _context.R9 = this->R9; + _context.R10 = this->R10; + _context.R11 = this->R11; + _context.R12 = this->R12; + _context.R13 = this->R13; + _context.R14 = this->R14; + _context.R15 = this->R15; + _context.EFlags = this->EFlags; #else //x86 - _context.Eax = this->Eax; - _context.Ebx = this->Ebx; - _context.Ecx = this->Ecx; - _context.Edx = this->Edx; - _context.Esi = this->Esi; - _context.Edi = this->Edi; - _context.Ebp = this->Ebp; - _context.Esp = this->Esp; - _context.Eip = this->Eip; - _context.EFlags = this->EFlags; + _context.Eax = this->Eax; + _context.Ebx = this->Ebx; + _context.Ecx = this->Ecx; + _context.Edx = this->Edx; + _context.Esi = this->Esi; + _context.Edi = this->Edi; + _context.Ebp = this->Ebp; + _context.Esp = this->Esp; + _context.Eip = this->Eip; + _context.EFlags = this->EFlags; #endif //_WIN64 - return &_context; - } + return &_context; + } - void RegistersInfo::SetContext(const CONTEXT & context) - { + void RegistersInfo::SetContext(const CONTEXT & context) + { #ifdef _WIN64 - this->Rax = context.Rax; - this->Rbx = context.Rbx; - this->Rcx = context.Rcx; - this->Rdx = context.Rdx; - this->Rsi = context.Rsi; - this->Rdi = context.Rdi; - this->Rbp = context.Rbp; - this->Rsp = context.Rsp; - this->Rip = context.Rip; - this->R8 = context.R8; - this->R9 = context.R9; - this->R10 = context.R10; - this->R11 = context.R11; - this->R12 = context.R12; - this->R13 = context.R13; - this->R14 = context.R14; - this->R15 = context.R15; - this->EFlags = context.EFlags; + this->Rax = context.Rax; + this->Rbx = context.Rbx; + this->Rcx = context.Rcx; + this->Rdx = context.Rdx; + this->Rsi = context.Rsi; + this->Rdi = context.Rdi; + this->Rbp = context.Rbp; + this->Rsp = context.Rsp; + this->Rip = context.Rip; + this->R8 = context.R8; + this->R9 = context.R9; + this->R10 = context.R10; + this->R11 = context.R11; + this->R12 = context.R12; + this->R13 = context.R13; + this->R14 = context.R14; + this->R15 = context.R15; + this->EFlags = context.EFlags; #else //x86 - this->Eax = context.Eax; - this->Ebx = context.Ebx; - this->Ecx = context.Ecx; - this->Edx = context.Edx; - this->Esi = context.Esi; - this->Edi = context.Edi; - this->Ebp = context.Ebp; - this->Esp = context.Esp; - this->Eip = context.Eip; - this->EFlags = context.EFlags; + this->Eax = context.Eax; + this->Ebx = context.Ebx; + this->Ecx = context.Ecx; + this->Edx = context.Edx; + this->Esi = context.Esi; + this->Edi = context.Edi; + this->Ebp = context.Ebp; + this->Esp = context.Esp; + this->Eip = context.Eip; + this->EFlags = context.EFlags; #endif //_WIN64 - this->_context = context; - } + this->_context = context; + } - void RegistersInfo::SetTrapFlag(bool set) - { - if (set) - this->EFlags |= TRAP_FLAG; - else - this->EFlags &= ~TRAP_FLAG; - } + void RegistersInfo::SetTrapFlag(bool set) + { + if (set) + this->EFlags |= TRAP_FLAG; + else + this->EFlags &= ~TRAP_FLAG; + } - bool RegistersInfo::GetTrapFlag() - { - return (this->EFlags & TRAP_FLAG) == TRAP_FLAG; - } + bool RegistersInfo::GetTrapFlag() + { + return (this->EFlags & TRAP_FLAG) == TRAP_FLAG; + } - void RegistersInfo::SetResumeFlag(bool set) - { - if (set) - this->EFlags |= RESUME_FLAG; - else - this->EFlags &= ~RESUME_FLAG; - } + void RegistersInfo::SetResumeFlag(bool set) + { + if (set) + this->EFlags |= RESUME_FLAG; + else + this->EFlags &= ~RESUME_FLAG; + } - bool RegistersInfo::GetResumeFlag() - { - return (this->EFlags & RESUME_FLAG) == RESUME_FLAG; - } + bool RegistersInfo::GetResumeFlag() + { + return (this->EFlags & RESUME_FLAG) == RESUME_FLAG; + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.Registers.h b/GleeBug/Debugger.Thread.Registers.h index a95afc5..a17d3a1 100644 --- a/GleeBug/Debugger.Thread.Registers.h +++ b/GleeBug/Debugger.Thread.Registers.h @@ -5,91 +5,91 @@ namespace GleeBug { - CONTEXT; - /** - \brief Thread register context. - */ - class RegistersInfo - { - public: + CONTEXT; + /** + \brief Thread register context. + */ + class RegistersInfo + { + public: #ifdef _WIN64 - DWORD64 Rax; - DWORD64 Rbx; - DWORD64 Rcx; - DWORD64 Rdx; - DWORD64 Rsi; - DWORD64 Rdi; - DWORD64 Rbp; - DWORD64 Rsp; - DWORD64 Rip; - DWORD64 R8; - DWORD64 R9; - DWORD64 R10; - DWORD64 R11; - DWORD64 R12; - DWORD64 R13; - DWORD64 R14; - DWORD64 R15; - DWORD EFlags; + DWORD64 Rax; + DWORD64 Rbx; + DWORD64 Rcx; + DWORD64 Rdx; + DWORD64 Rsi; + DWORD64 Rdi; + DWORD64 Rbp; + DWORD64 Rsp; + DWORD64 Rip; + DWORD64 R8; + DWORD64 R9; + DWORD64 R10; + DWORD64 R11; + DWORD64 R12; + DWORD64 R13; + DWORD64 R14; + DWORD64 R15; + DWORD EFlags; #else //x86 - DWORD Eax; - DWORD Ebx; - DWORD Ecx; - DWORD Edx; - DWORD Esi; - DWORD Edi; - DWORD Ebp; - DWORD Esp; - DWORD Eip; - DWORD EFlags; + DWORD Eax; + DWORD Ebx; + DWORD Ecx; + DWORD Edx; + DWORD Esi; + DWORD Edi; + DWORD Ebp; + DWORD Esp; + DWORD Eip; + DWORD EFlags; #endif //_WIN64 - /** - \brief Default constructor. - */ - RegistersInfo(); + /** + \brief Default constructor. + */ + RegistersInfo(); - /** - \brief Gets a pointer to the context object. - \return This function will never return a nullptr. - */ - const CONTEXT* GetContext(); + /** + \brief Gets a pointer to the context object. + \return This function will never return a nullptr. + */ + const CONTEXT* GetContext(); - /** - \brief Sets the CONTEXT. - \param context The context to set. - */ - void SetContext(const CONTEXT & context); + /** + \brief Sets the CONTEXT. + \param context The context to set. + */ + void SetContext(const CONTEXT & context); - /** - \brief Sets trap flag. - \param set (Optional) true to set, false to unset. - */ - void SetTrapFlag(bool set = true); + /** + \brief Sets trap flag. + \param set (Optional) true to set, false to unset. + */ + void SetTrapFlag(bool set = true); - /** - \brief Gets trap flag. - \return true if the flag is set, false otherwise. - */ - bool GetTrapFlag(); + /** + \brief Gets trap flag. + \return true if the flag is set, false otherwise. + */ + bool GetTrapFlag(); - /** - \brief Sets resume flag. - \param set (Optional) true to set, false to unset. - */ - void SetResumeFlag(bool set = true); + /** + \brief Sets resume flag. + \param set (Optional) true to set, false to unset. + */ + void SetResumeFlag(bool set = true); - /** - \brief Gets resume flag. - \return true if the flag is set, false otherwise. - */ - bool GetResumeFlag(); + /** + \brief Gets resume flag. + \return true if the flag is set, false otherwise. + */ + bool GetResumeFlag(); - private: - CONTEXT _context; - const int TRAP_FLAG = 0x100; - const int RESUME_FLAG = 0x10000; - }; + private: + CONTEXT _context; + const int TRAP_FLAG = 0x100; + const int RESUME_FLAG = 0x10000; + }; }; #endif //_DEBUGGER_THREAD_REGISTERS_H \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.cpp b/GleeBug/Debugger.Thread.cpp index 8877b08..f85d32a 100644 --- a/GleeBug/Debugger.Thread.cpp +++ b/GleeBug/Debugger.Thread.cpp @@ -2,55 +2,55 @@ namespace GleeBug { - ThreadInfo::ThreadInfo() - { - this->hThread = INVALID_HANDLE_VALUE; - } + ThreadInfo::ThreadInfo() + { + this->hThread = INVALID_HANDLE_VALUE; + } - 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, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress) + { + this->dwThreadId = dwThreadId; + this->hThread = hThread; + this->lpThreadLocalBase = reinterpret_cast(lpThreadLocalBase); + this->lpStartAddress = reinterpret_cast(lpStartAddress); + } - bool ThreadInfo::RegReadContext() - { - SuspendThread(this->hThread); - memset(&this->_oldContext, 0, sizeof(CONTEXT)); - this->_oldContext.ContextFlags = CONTEXT_ALL; - bool bReturn = false; - if (GetThreadContext(this->hThread, &this->_oldContext)) - { - this->registers.SetContext(this->_oldContext); - bReturn = true; - } - ResumeThread(this->hThread); - return bReturn; - } + bool ThreadInfo::RegReadContext() + { + SuspendThread(this->hThread); + memset(&this->_oldContext, 0, sizeof(CONTEXT)); + this->_oldContext.ContextFlags = CONTEXT_ALL; + bool bReturn = false; + if (GetThreadContext(this->hThread, &this->_oldContext)) + { + this->registers.SetContext(this->_oldContext); + bReturn = true; + } + ResumeThread(this->hThread); + return bReturn; + } - bool ThreadInfo::RegWriteContext() - { - //check if something actually changed - if (memcmp(&this->_oldContext, this->registers.GetContext(), sizeof(CONTEXT)) == 0) - return true; - //update the context - SuspendThread(this->hThread); - bool bReturn = !!SetThreadContext(this->hThread, this->registers.GetContext()); - ResumeThread(this->hThread); - return bReturn; - } + bool ThreadInfo::RegWriteContext() + { + //check if something actually changed + if (memcmp(&this->_oldContext, this->registers.GetContext(), sizeof(CONTEXT)) == 0) + return true; + //update the context + SuspendThread(this->hThread); + bool bReturn = !!SetThreadContext(this->hThread, this->registers.GetContext()); + ResumeThread(this->hThread); + return bReturn; + } - void ThreadInfo::StepInto(StepCallback cbStep) - { - StepInto(); - stepCallbacks.push_back(cbStep); - } + void ThreadInfo::StepInto(const StepCallback & cbStep) + { + StepInto(); + stepCallbacks.push_back(cbStep); + } - void ThreadInfo::StepInto() - { - registers.SetTrapFlag(); - isSingleStepping = true; - } + void ThreadInfo::StepInto() + { + registers.SetTrapFlag(); + isSingleStepping = true; + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.h b/GleeBug/Debugger.Thread.h index 57c71c6..5b9553c 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -6,73 +6,73 @@ namespace GleeBug { - /** - \brief Thread information structure. - */ - class ThreadInfo - { - public: - DWORD dwThreadId; - HANDLE hThread; - ULONG_PTR lpThreadLocalBase; - ULONG_PTR lpStartAddress; + /** + \brief Thread information structure. + */ + class ThreadInfo + { + public: + DWORD dwThreadId; + HANDLE hThread; + ULONG_PTR lpThreadLocalBase; + ULONG_PTR lpStartAddress; - RegistersInfo registers; - StepCallbackVector stepCallbacks; - bool isSingleStepping; + RegistersInfo registers; + StepCallbackVector stepCallbacks; + bool isSingleStepping; - /** - \brief Default constructor. - */ - ThreadInfo(); + /** + \brief Default constructor. + */ + ThreadInfo(); - /** - \brief Constructor. - \param dwThreadId Identifier for the thread. - \param lpThreadLocalBase The thread local base. - \param lpStartAddress The start address. - */ - ThreadInfo(DWORD dwThreadId, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress); + /** + \brief Constructor. + \param dwThreadId Identifier for the thread. + \param lpThreadLocalBase The thread local base. + \param lpStartAddress The start address. + */ + ThreadInfo(DWORD dwThreadId, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress); - /** - \brief Read the register context from the thread. This fills the RegistersInfo member. - \return true if it succeeds, false if it fails. - */ - bool RegReadContext(); + /** + \brief Read the register context from the thread. This fills the RegistersInfo member. + \return true if it succeeds, false if it fails. + */ + bool RegReadContext(); - /** - \brief Write the register context to the thread. This does nothing if the RegistersInfo member did not change. - \return true if it succeeds, false if it fails. - */ - bool RegWriteContext(); + /** + \brief Write the register context to the thread. This does nothing if the RegistersInfo member did not change. + \return true if it succeeds, false if it fails. + */ + bool RegWriteContext(); - /** - \brief Step into. - */ - void StepInto(); + /** + \brief Step into. + */ + void StepInto(); - /** - \brief Step into. - \param cbStep StepCallback. Can be written using BIND(this, MyDebugger::cb). - */ - void StepInto(StepCallback cbStep); + /** + \brief Step into. + \param cbStep StepCallback. Can be written using BIND(this, MyDebugger::cb). + */ + void StepInto(const StepCallback & cbStep); - /** - \brief Step into. - \tparam T Generic type parameter. Must be a subclass of Debugger. - \param debugger This pointer to a subclass of Debugger. - \param callback Pointer to the callback. Written like: &MyDebugger::cb - */ - template - void StepInto(T* debugger, void(T::*callback)()) - { - static_cast(static_cast(debugger)); - StepInto(std::bind(callback, debugger)); - } + /** + \brief Step into. + \tparam T Generic type parameter. Must be a subclass of Debugger. + \param debugger This pointer to a subclass of Debugger. + \param callback Pointer to the callback. Written like: &MyDebugger::cb + */ + template + void StepInto(T* debugger, void(T::*callback)()) + { + static_cast(static_cast(debugger)); + StepInto(std::bind(callback, debugger)); + } - private: - CONTEXT _oldContext; - }; + private: + CONTEXT _oldContext; + }; }; #endif //_DEBUGGER_THREADS_H \ No newline at end of file diff --git a/GleeBug/Debugger.cpp b/GleeBug/Debugger.cpp index 339d6c3..3b8fde4 100644 --- a/GleeBug/Debugger.cpp +++ b/GleeBug/Debugger.cpp @@ -2,51 +2,62 @@ namespace GleeBug { - Debugger::Debugger() - { - _processes.clear(); - } + Debugger::Debugger() + { + _processes.clear(); + } - bool Debugger::Init(const wchar_t* szFilePath, - const wchar_t* szCommandLine, - const wchar_t* szCurrentDirectory) - { - STARTUPINFOW si; - memset(&si, 0, sizeof(si)); - const wchar_t* szFileNameCreateProcess; - wchar_t* szCommandLineCreateProcess; - if (szCommandLine == NULL || !wcslen(szCommandLine)) - { - szCommandLineCreateProcess = 0; - szFileNameCreateProcess = szFilePath; - } - else - { - wchar_t szCreateWithCmdLine[1024]; - swprintf_s(szCreateWithCmdLine, L"\"%s\" %s", szFilePath, szCommandLine); - szCommandLineCreateProcess = szCreateWithCmdLine; - szFileNameCreateProcess = 0; - } + Debugger::~Debugger() + { + } - return !!CreateProcessW(szFileNameCreateProcess, - szCommandLineCreateProcess, - NULL, - NULL, - FALSE, - DEBUG_PROCESS | CREATE_NEW_CONSOLE, - NULL, - szCurrentDirectory, - &si, - &_mainProcess); - } + bool Debugger::Init(const wchar_t* szFilePath, + const wchar_t* szCommandLine, + const wchar_t* szCurrentDirectory) + { + STARTUPINFOW si; + memset(&si, 0, sizeof(si)); + const wchar_t* szFileNameCreateProcess; + wchar_t* szCommandLineCreateProcess = nullptr; + wchar_t* szCreateWithCmdLine = nullptr; + if (szCommandLine == nullptr || !wcslen(szCommandLine)) + { + szCommandLineCreateProcess = nullptr; + szFileNameCreateProcess = szFilePath; + } + else + { + auto size = 1 + wcslen(szFilePath) + 2 + wcslen(szCommandLine) + 1; + szCreateWithCmdLine = new wchar_t[size]; + swprintf_s(szCreateWithCmdLine, size, L"\"%s\" %s", szFilePath, szCommandLine); + szCommandLineCreateProcess = szCreateWithCmdLine; + szFileNameCreateProcess = nullptr; + } - bool Debugger::Stop() - { - return !!TerminateProcess(_mainProcess.hProcess, 0); - } + bool result = !!CreateProcessW(szFileNameCreateProcess, + szCommandLineCreateProcess, + nullptr, + nullptr, + FALSE, + DEBUG_PROCESS | CREATE_NEW_CONSOLE, + nullptr, + szCurrentDirectory, + &si, + &_mainProcess); - bool Debugger::Detach() - { - return !!DebugActiveProcessStop(_mainProcess.dwProcessId); - } + if (szCreateWithCmdLine) + delete[] szCreateWithCmdLine; + + return result; + } + + bool Debugger::Stop() + { + return !!TerminateProcess(_mainProcess.hProcess, 0); + } + + bool Debugger::Detach() + { + return !!DebugActiveProcessStop(_mainProcess.dwProcessId); + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.h b/GleeBug/Debugger.h index 30647d5..ec1308f 100644 --- a/GleeBug/Debugger.h +++ b/GleeBug/Debugger.h @@ -6,212 +6,217 @@ namespace GleeBug { - /** - \brief A debugger class. - */ - class Debugger - { - public: //public functionality - /** - \brief Constructs the Debugger instance. - */ - Debugger(); + /** + \brief A debugger class. + */ + class Debugger + { + public: //public functionality + /** + \brief Constructs the Debugger instance. + */ + Debugger(); - /** - \brief Start the debuggee. - \param szFilePath Full pathname of the file to debug. - \param szCommandLine The command line to pass to the debuggee. - \param szCurrentDirectory Pathname of the current directory. - \return true if the debuggee was started correctly, false otherwise. - */ - bool Init(const wchar_t* szFilePath, - const wchar_t* szCommandLine, - const wchar_t* szCurrentDirectory); + /** + \brief Destructs the Debugger instance. + */ + virtual ~Debugger(); - /** - \brief Stops the debuggee (terminate the process) - \return true if the debuggee was stopped correctly, false otherwise. - */ - bool Stop(); + /** + \brief Start the debuggee. + \param szFilePath Full pathname of the file to debug. + \param szCommandLine The command line to pass to the debuggee. + \param szCurrentDirectory Pathname of the current directory. + \return true if the debuggee was started correctly, false otherwise. + */ + bool Init(const wchar_t* szFilePath, + const wchar_t* szCommandLine, + const wchar_t* szCurrentDirectory); - /** - \brief Detaches the debuggee. - \return true if the debuggee was detached correctly, false otherwise. - */ - bool Detach(); + /** + \brief Stops the debuggee (terminate the process) + \return true if the debuggee was stopped correctly, false otherwise. + */ + bool Stop(); - /** - \brief Run the debug loop (does not return until the debuggee is detached or terminated). - */ - void Start(); + /** + \brief Detaches the debuggee. + \return true if the debuggee was detached correctly, false otherwise. + */ + bool Detach(); - protected: //debug event callbacks - /** - \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, const ProcessInfo & process) {}; + /** + \brief Run the debug loop (does not return until the debuggee is detached or terminated). + */ + void Start(); - /** - \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, const ProcessInfo & process) {}; + protected: //debug event callbacks + /** + \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, 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, const ThreadInfo & thread) {}; + /** + \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, const ProcessInfo & process) {}; - /** - \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, const ThreadInfo & thread) {}; + /** + \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, 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, const DllInfo & dll) {}; + /** + \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, const ThreadInfo & thread) {}; - /** - \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, const DllInfo & dll) {}; + /** + \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, const DllInfo & dll) {}; - /** - \brief Exception debug event callback. Provide an implementation to use this callback. - \param exceptionInfo Information about the exception. - */ - virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) {}; + /** + \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, const DllInfo & dll) {}; - /** - \brief Debug string debug event callback. Provide an implementation to use this callback. - \param debugString Information about the debug string. - */ - virtual void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) {}; + /** + \brief Exception debug event callback. Provide an implementation to use this callback. + \param exceptionInfo Information about the exception. + */ + virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) {}; - /** - \brief RIP debug event callback. Provide an implementation to use this callback. - \param rip Information about the RIP event. - */ - virtual void cbRipEvent(const RIP_INFO & rip) {}; + /** + \brief Debug string debug event callback. Provide an implementation to use this callback. + \param debugString Information about the debug string. + */ + virtual void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) {}; - protected: //other callbacks - /** - \brief Internal error callback. Provide an implementation to use this callback. - \param error The error message. - */ - virtual void cbInternalError(const std::string & error) {}; + /** + \brief RIP debug event callback. Provide an implementation to use this callback. + \param rip Information about the RIP event. + */ + virtual void cbRipEvent(const RIP_INFO & rip) {}; - /** - \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) {}; + protected: //other callbacks + /** + \brief Internal error callback. Provide an implementation to use this callback. + \param error The error message. + */ + virtual void cbInternalError(const std::string & error) {}; - /** - \brief System breakpoint callback. Provide an implementation to use this callback. - */ - virtual void cbSystemBreakpoint() {}; + /** + \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 Step callback. Provide an implementation to use this callback. - */ - virtual void cbStep() {}; + /** + \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. - */ - virtual void createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess); + /** + \brief Step callback. Provide an implementation to use this callback. + */ + virtual void cbStep() {}; - /** - \brief Process termination debug event. Do not override this unless you know what you are doing! - \param exitProcess Information about the process terminated. - */ - virtual void exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess); + 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. + */ + virtual void createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess); - /** - \brief Thread creation debug event. Do not override this unless you know what you are doing! - \param createThread Information about the thread created. - */ - virtual void createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread); + /** + \brief Process termination debug event. Do not override this unless you know what you are doing! + \param exitProcess Information about the process terminated. + */ + virtual void exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess); - /** - \brief Thread termination debug event. Do not override this unless you know what you are doing! - \param exitThread Information about the thread terminated. - */ - virtual void exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread); + /** + \brief Thread creation debug event. Do not override this unless you know what you are doing! + \param createThread Information about the thread created. + */ + virtual void createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread); - /** - \brief DLL load debug event. Do not override this unless you know what you are doing! - \param loadDll Information about the DLL loaded. - */ - virtual void loadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll); + /** + \brief Thread termination debug event. Do not override this unless you know what you are doing! + \param exitThread Information about the thread terminated. + */ + virtual void exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread); - /** - \brief DLL unload debug event. Do not override this unless you know what you are doing! - \param unloadDll Information about the DLL unloaded. - */ - virtual void unloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll); + /** + \brief DLL load debug event. Do not override this unless you know what you are doing! + \param loadDll Information about the DLL loaded. + */ + virtual void loadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll); - /** - \brief Exception debug event. Do not override this unless you know what you are doing! - \param exceptionInfo Information about the exception. - */ - virtual void exceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo); + /** + \brief DLL unload debug event. Do not override this unless you know what you are doing! + \param unloadDll Information about the DLL unloaded. + */ + virtual void unloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll); - /** - \brief Debug string debug event. Do not override this unless you know what you are doing! - \param debugString Information about the debug string. - */ - virtual void debugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString); + /** + \brief Exception debug event. Do not override this unless you know what you are doing! + \param exceptionInfo Information about the exception. + */ + virtual void exceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo); - /** - \brief RIP debug event. Do not override this unless you know what you are doing! - \param rip Information about the RIP event. - */ - virtual void ripEvent(const RIP_INFO & rip); + /** + \brief Debug string debug event. Do not override this unless you know what you are doing! + \param debugString Information about the debug string. + */ + virtual void debugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString); - 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 RIP debug event. Do not override this unless you know what you are doing! + \param rip Information about the RIP event. + */ + virtual void ripEvent(const RIP_INFO & rip); - /** - \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: //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); - protected: //variables - PROCESS_INFORMATION _mainProcess; - DWORD _continueStatus; - bool _breakDebugger; - DEBUG_EVENT _debugEvent; - ProcessMap _processes; - bool _isRunning; + /** + \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); - /** - \brief The current process (can be null in some cases). - */ - ProcessInfo* _process; + protected: //variables + PROCESS_INFORMATION _mainProcess; + DWORD _continueStatus; + bool _breakDebugger; + DEBUG_EVENT _debugEvent; + ProcessMap _processes; + bool _isRunning; - /** - \brief The current thread (can be null in some cases). Should be a copy of _process->thread. - */ - ThreadInfo* _thread; - }; + /** + \brief The current process (can be null in some cases). + */ + ProcessInfo* _process; + + /** + \brief The current thread (can be null in some cases). Should be a copy of _process->thread. + */ + ThreadInfo* _thread; + }; }; #endif //_DEBUGGER_H \ No newline at end of file diff --git a/GleeBug/GleeBug.vcxproj.filters b/GleeBug/GleeBug.vcxproj.filters index d02f2d2..be04ec1 100644 --- a/GleeBug/GleeBug.vcxproj.filters +++ b/GleeBug/GleeBug.vcxproj.filters @@ -9,10 +9,6 @@ {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - diff --git a/MyDebugger/MyDebugger.h b/MyDebugger/MyDebugger.h index 8486087..a1de2c4 100644 --- a/MyDebugger/MyDebugger.h +++ b/MyDebugger/MyDebugger.h @@ -8,85 +8,89 @@ using namespace GleeBug; class MyDebugger : public Debugger { protected: - 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); - }; + void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) override + { + printf("Process %d created with entry 0x%p\n", + _debugEvent.dwProcessId, + createProcess.lpStartAddress); + } - 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); - } + void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) override + { + printf("Process %u terminated with exit code 0x%08X\n", + _debugEvent.dwProcessId, + exitProcess.dwExitCode); + } - 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); - }; + void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const ThreadInfo & thread) override + { + printf("Thread %u created with entry 0x%p\n", + _debugEvent.dwThreadId, + createThread.lpStartAddress); + } - 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); - }; + void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const ThreadInfo & thread) override + { + printf("Thread %u terminated with exit code 0x%08X\n", + _debugEvent.dwThreadId, + exitThread.dwExitCode); + } - virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll, const DllInfo & dll) - { - printf("DLL loaded at 0x%p\n", - loadDll.lpBaseOfDll); - }; + void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll, const DllInfo & dll) override + { + printf("DLL loaded at 0x%p\n", + loadDll.lpBaseOfDll); + } - virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll, const DllInfo & dll) - { - printf("DLL 0x%p unloaded\n", - unloadDll.lpBaseOfDll); - }; + void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll, const DllInfo & dll) override + { + printf("DLL 0x%p unloaded\n", + unloadDll.lpBaseOfDll); + } - virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) - { - printf("Exception with code 0x%08X at 0x%p\n", - exceptionInfo.ExceptionRecord.ExceptionCode, - exceptionInfo.ExceptionRecord.ExceptionAddress); - }; + void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) override + { + printf("Exception with code 0x%08X at 0x%p\n", + exceptionInfo.ExceptionRecord.ExceptionCode, + exceptionInfo.ExceptionRecord.ExceptionAddress); + } - virtual void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) - { - printf("Debug string at 0x%p with length %d\n", - debugString.lpDebugStringData, - debugString.nDebugStringLength); - }; + void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) override + { + printf("Debug string at 0x%p with length %d\n", + debugString.lpDebugStringData, + debugString.nDebugStringLength); + } - virtual void cbRipEvent(const RIP_INFO & rip) - { - printf("RIP event type 0x%X, error 0x%X", - rip.dwType, - rip.dwError); - }; + void cbRipEvent(const RIP_INFO & rip) override + { + printf("RIP event type 0x%X, error 0x%X", + rip.dwType, + rip.dwError); + } - void boobs() - { - printf("(.)Y(.) 0x%p\n", - _thread->registers.Rip); - } + void boobs() + { + printf("(.)Y(.) 0x%p\n", +#ifdef _WIN64 + _thread->registers.Rip); +#else //x32 + _thread->registers.Eip); +#endif //_WIN64 + } - virtual void cbSystemBreakpoint() - { - printf("System breakpoint reached, CIP: 0x%p\n", - _thread->registers.Rip); - _thread->StepInto(BIND(this, MyDebugger::boobs)); - } + void cbSystemBreakpoint() override + { + printf("System breakpoint reached, CIP: 0x%p\n", + _thread->registers.Rip); + _thread->StepInto(BIND(this, MyDebugger::boobs)); + } - virtual void cbInternalError(const std::string & error) - { - printf("Internal Error: %s\n", - error.c_str()); - } + void cbInternalError(const std::string & error) override + { + printf("Internal Error: %s\n", + error.c_str()); + } }; #endif //_MYDEBUGGER_H \ No newline at end of file diff --git a/MyDebugger/main.cpp b/MyDebugger/main.cpp index e3398b4..93abbae 100644 --- a/MyDebugger/main.cpp +++ b/MyDebugger/main.cpp @@ -4,23 +4,23 @@ int main() { #ifdef _WIN64 - wchar_t szFilePath[256] = L"c:\\test64.exe"; + wchar_t szFilePath[256] = L"c:\\test64.exe"; #else //x86 - wchar_t szFilePath[256] = L"c:\\test32.exe"; + wchar_t szFilePath[256] = L"c:\\test32.exe"; #endif //_WIN64 - wchar_t szCommandLine[256] = L""; - wchar_t szCurrentDir[256] = L"c:\\"; - MyDebugger dbg; - if (dbg.Init(szFilePath, szCommandLine, szCurrentDir)) - { - puts("Debugger::Init success!"); - dbg.Start(); - puts("Debugger::Start finished!"); - } - else - { - puts("Debugger::Init failed!"); - } - system("pause"); - return 0; + wchar_t szCommandLine[256] = L""; + wchar_t szCurrentDir[256] = L"c:\\"; + MyDebugger dbg; + if (dbg.Init(szFilePath, szCommandLine, szCurrentDir)) + { + puts("Debugger::Init success!"); + dbg.Start(); + puts("Debugger::Start finished!"); + } + else + { + puts("Debugger::Init failed!"); + } + system("pause"); + return 0; } \ No newline at end of file