diff --git a/GleeBug/Debugger.Dll.h b/GleeBug/Debugger.Dll.h index a91d7a6..413c070 100644 --- a/GleeBug/Debugger.Dll.h +++ b/GleeBug/Debugger.Dll.h @@ -8,8 +8,9 @@ namespace GleeBug /** \brief DLL information structure. */ - struct DllInfo + class DllInfo { + public: ULONG_PTR lpBaseOfDll; DWORD sizeOfImage; ULONG_PTR entryPoint; diff --git a/GleeBug/Debugger.Loop.Process.cpp b/GleeBug/Debugger.Loop.Process.cpp index d4e6883..aeb9951 100644 --- a/GleeBug/Debugger.Loop.Process.cpp +++ b/GleeBug/Debugger.Loop.Process.cpp @@ -6,12 +6,22 @@ namespace GleeBug { //process housekeeping ProcessInfo process(_debugEvent.dwProcessId, + createProcess.hProcess, _debugEvent.dwThreadId); _processes.insert({ process.dwProcessId, process }); + _curProcess = &_processes.find(process.dwProcessId)->second; - //set the current process and current thread - _curProcess = &_processes[process.dwProcessId]; - _curProcess->curThread = &_curProcess->threads[process.dwMainThreadId]; + //thread housekeeping (main thread is created implicitly) + ThreadInfo thread(_debugEvent.dwThreadId, + createProcess.hThread, + createProcess.lpThreadLocalBase, + createProcess.lpStartAddress); + _curProcess->threads.insert({ thread.dwThreadId, thread }); + _curProcess->curThread = &_curProcess->threads.find(thread.dwThreadId)->second; + + //read thread context from main thread + if (!_curProcess->curThread->RegReadContext()) + cbInternalError("ThreadInfo::RegReadContext() failed!"); //call the debug event callback cbCreateProcessEvent(createProcess, *_curProcess); diff --git a/GleeBug/Debugger.Loop.Thread.cpp b/GleeBug/Debugger.Loop.Thread.cpp index b396a62..fcb92be 100644 --- a/GleeBug/Debugger.Loop.Thread.cpp +++ b/GleeBug/Debugger.Loop.Thread.cpp @@ -5,12 +5,13 @@ 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 }); + _curProcess->threads.insert({ _debugEvent.dwThreadId, + ThreadInfo(_debugEvent.dwThreadId, createThread.hThread, createThread.lpThreadLocalBase, createThread.lpStartAddress) }); //set the current thread - _curProcess->curThread = &_curProcess->threads[thread.dwThreadId]; - _curProcess->curThread->RegReadContext(); + _curProcess->curThread = &_curProcess->threads.find(_debugEvent.dwThreadId)->second; + if (!_curProcess->curThread->RegReadContext()) + cbInternalError("ThreadInfo::RegReadContext() failed!"); //call the debug event callback cbCreateThreadEvent(createThread, *_curProcess->curThread); diff --git a/GleeBug/Debugger.Loop.cpp b/GleeBug/Debugger.Loop.cpp index 9bec7bf..6fa63ce 100644 --- a/GleeBug/Debugger.Loop.cpp +++ b/GleeBug/Debugger.Loop.cpp @@ -16,7 +16,7 @@ namespace GleeBug _isRunning = false; //set default continue status - _continueStatus = DBG_CONTINUE; + _continueStatus = DBG_EXCEPTION_NOT_HANDLED; //set the current process and thread if (_processes.count(_debugEvent.dwProcessId)) @@ -25,7 +25,8 @@ namespace GleeBug if (_curProcess->threads.count(_debugEvent.dwThreadId)) { _curProcess->curThread = &_curProcess->threads[_debugEvent.dwThreadId]; - _curProcess->curThread->RegReadContext(); + if (!_curProcess->curThread->RegReadContext()) + cbInternalError("ThreadInfo::RegReadContext() failed!"); } else _curProcess->curThread = nullptr; @@ -66,8 +67,11 @@ namespace GleeBug } //write the register context - if (_curProcess->curThread) - _curProcess->curThread->RegWriteContext(); + if (_curProcess && _curProcess->curThread) + { + if (!_curProcess->curThread->RegWriteContext()) + cbInternalError("ThreadInfo::RegWriteContext() failed!"); + } //continue the debug event if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus)) diff --git a/GleeBug/Debugger.Process.cpp b/GleeBug/Debugger.Process.cpp index 99e99be..7c96cce 100644 --- a/GleeBug/Debugger.Process.cpp +++ b/GleeBug/Debugger.Process.cpp @@ -9,19 +9,12 @@ namespace GleeBug this->hProcess = INVALID_HANDLE_VALUE; } - ProcessInfo::ProcessInfo(DWORD dwProcessId, DWORD 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; - this->threads.clear(); - } - - ProcessInfo::~ProcessInfo() - { - if (this->hProcess != INVALID_HANDLE_VALUE) - CloseHandle(hProcess); } bool ProcessInfo::MemRead(ULONG_PTR address, const size_t size, void* buffer) diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index b227792..402d239 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -10,8 +10,9 @@ namespace GleeBug /** \brief Process information structure. */ - struct ProcessInfo + class ProcessInfo { + public: HANDLE hProcess; DWORD dwProcessId; DWORD dwMainThreadId; @@ -32,12 +33,7 @@ namespace GleeBug \param dwProcessId Identifier for the process. \param dwMainThreadId Identifier for the main thread. */ - ProcessInfo(DWORD dwProcessId, DWORD dwMainThreadId); - - /** - \brief Destructor. - */ - ~ProcessInfo(); + ProcessInfo(DWORD dwProcessId, HANDLE hProcess, DWORD dwMainThreadId); /** \brief Read memory from the process. diff --git a/GleeBug/Debugger.Thread.Registers.cpp b/GleeBug/Debugger.Thread.Registers.cpp index 8b955de..b28d616 100644 --- a/GleeBug/Debugger.Thread.Registers.cpp +++ b/GleeBug/Debugger.Thread.Registers.cpp @@ -9,11 +9,99 @@ namespace GleeBug 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; +#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; +#endif //_WIN64 return &_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; +#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; +#endif //_WIN64 this->_context = context; } + + 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; + } + + 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; + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.Registers.h b/GleeBug/Debugger.Thread.Registers.h index 6e99bd3..a95afc5 100644 --- a/GleeBug/Debugger.Thread.Registers.h +++ b/GleeBug/Debugger.Thread.Registers.h @@ -7,38 +7,41 @@ namespace GleeBug { CONTEXT; /** - \brief Thread register context. #lovethetrash + \brief Thread register context. */ - struct RegistersInfo + class RegistersInfo { + public: #ifdef _WIN64 - ULONG_PTR & Rax = _context.Rax; - ULONG_PTR & Rbx = _context.Rbx; - ULONG_PTR & Rcx = _context.Rcx; - ULONG_PTR & Rdx = _context.Rdx; - ULONG_PTR & Rsi = _context.Rsi; - ULONG_PTR & Rdi = _context.Rdi; - ULONG_PTR & Rbp = _context.Rbp; - ULONG_PTR & Rsp = _context.Rsp; - ULONG_PTR & Rip = _context.Rip; - ULONG_PTR & R8 = _context.R8; - ULONG_PTR & R9 = _context.R9; - ULONG_PTR & R10 = _context.R10; - ULONG_PTR & R11 = _context.R11; - ULONG_PTR & R12 = _context.R12; - ULONG_PTR & R13 = _context.R13; - ULONG_PTR & R14 = _context.R14; - ULONG_PTR & R15 = _context.R15; + 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 - ULONG_PTR & Eax = _context.Eax; - ULONG_PTR & Ebx = _context.Ebx; - ULONG_PTR & Ecx = _context.Ecx; - ULONG_PTR & Edx = _context.Edx; - ULONG_PTR & Esi = _context.Esi; - ULONG_PTR & Edi = _context.Edi; - ULONG_PTR & Ebp = _context.Ebp; - ULONG_PTR & Esp = _context.Esp; - ULONG_PTR & Eip = _context.Eip; + DWORD Eax; + DWORD Ebx; + DWORD Ecx; + DWORD Edx; + DWORD Esi; + DWORD Edi; + DWORD Ebp; + DWORD Esp; + DWORD Eip; + DWORD EFlags; #endif //_WIN64 /** @@ -58,8 +61,34 @@ namespace GleeBug */ void SetContext(const CONTEXT & context); + /** + \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 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(); + private: CONTEXT _context; + const int TRAP_FLAG = 0x100; + const int RESUME_FLAG = 0x10000; }; }; diff --git a/GleeBug/Debugger.Thread.cpp b/GleeBug/Debugger.Thread.cpp index ae9b532..1272e8e 100644 --- a/GleeBug/Debugger.Thread.cpp +++ b/GleeBug/Debugger.Thread.cpp @@ -7,20 +7,14 @@ namespace GleeBug this->hThread = INVALID_HANDLE_VALUE; } - ThreadInfo::ThreadInfo(DWORD dwThreadId, LPVOID lpThreadLocalBase, LPVOID lpStartAddress) + ThreadInfo::ThreadInfo(DWORD dwThreadId, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress) { this->dwThreadId = dwThreadId; - this->hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId); + this->hThread = hThread; this->lpThreadLocalBase = (ULONG_PTR)lpThreadLocalBase; this->lpStartAddress = (ULONG_PTR)lpStartAddress; } - ThreadInfo::~ThreadInfo() - { - if (this->hThread != INVALID_HANDLE_VALUE) - CloseHandle(this->hThread); - } - bool ThreadInfo::RegReadContext() { SuspendThread(this->hThread); diff --git a/GleeBug/Debugger.Thread.h b/GleeBug/Debugger.Thread.h index a8e9b6d..46684d0 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -9,8 +9,9 @@ namespace GleeBug /** \brief Thread information structure. */ - struct ThreadInfo + class ThreadInfo { + public: DWORD dwThreadId; HANDLE hThread; ULONG_PTR lpThreadLocalBase; @@ -28,12 +29,7 @@ namespace GleeBug \param lpThreadLocalBase The thread local base. \param lpStartAddress The start address. */ - ThreadInfo(DWORD dwThreadId, LPVOID lpThreadLocalBase, LPVOID lpStartAddress); - - /** - \brief Destructor. - */ - ~ThreadInfo(); + ThreadInfo(DWORD dwThreadId, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress); /** \brief Read the register context from the thread. This fills the RegistersInfo member. diff --git a/MyDebugger/MyDebugger.h b/MyDebugger/MyDebugger.h index 7216b6f..9c1a54b 100644 --- a/MyDebugger/MyDebugger.h +++ b/MyDebugger/MyDebugger.h @@ -10,52 +10,75 @@ 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); + 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); + printf("Process %d 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); + printf("Thread %d 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); + printf("Thread %d 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); + 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); + printf("DLL 0x%p unloaded\n", + unloadDll.lpBaseOfDll); }; virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) { - printf("Exception with code 0x%08X\n", exceptionInfo.ExceptionRecord.ExceptionCode); + 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); + 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); + printf("RIP event type 0x%X, error 0x%X", + rip.dwType, + rip.dwError); }; virtual void cbSystemBreakpoint() { - printf("System breakpoint reached!\n"); + printf("System breakpoint reached, CIP: 0x%p\n", + _curProcess->curThread->registers.Rip); + } + + virtual void cbInternalError(const std::string & error) + { + printf("Internal Error: %s\n", + error.c_str()); } };