From c1bb981c16046fcc8849eff2ee6965d20b44f521 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sun, 5 Apr 2015 01:23:21 +0200 Subject: [PATCH] some very amazing coding was done here (documentation + RegistersInfo with cache) --- GleeBug/Debugger.Dll.h | 10 ++++ GleeBug/Debugger.Loop.Thread.cpp | 1 + GleeBug/Debugger.Loop.cpp | 7 +++ GleeBug/Debugger.Process.h | 29 ++++++++++++ GleeBug/Debugger.Thread.Registers.cpp | 19 ++++++++ GleeBug/Debugger.Thread.Registers.h | 66 +++++++++++++++++++++++++++ GleeBug/Debugger.Thread.cpp | 29 +++++++++++- GleeBug/Debugger.Thread.h | 35 +++++++++++++- GleeBug/Debugger.h | 6 +++ GleeBug/GleeBug.vcxproj | 2 + GleeBug/GleeBug.vcxproj.filters | 6 +++ MyDebugger/MyDebugger.h | 2 +- 12 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 GleeBug/Debugger.Thread.Registers.cpp create mode 100644 GleeBug/Debugger.Thread.Registers.h diff --git a/GleeBug/Debugger.Dll.h b/GleeBug/Debugger.Dll.h index 810c4d0..a91d7a6 100644 --- a/GleeBug/Debugger.Dll.h +++ b/GleeBug/Debugger.Dll.h @@ -14,7 +14,17 @@ namespace GleeBug DWORD sizeOfImage; ULONG_PTR entryPoint; + /** + \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); }; diff --git a/GleeBug/Debugger.Loop.Thread.cpp b/GleeBug/Debugger.Loop.Thread.cpp index 5fad0c0..b396a62 100644 --- a/GleeBug/Debugger.Loop.Thread.cpp +++ b/GleeBug/Debugger.Loop.Thread.cpp @@ -10,6 +10,7 @@ namespace GleeBug //set the current thread _curProcess->curThread = &_curProcess->threads[thread.dwThreadId]; + _curProcess->curThread->RegReadContext(); //call the debug event callback cbCreateThreadEvent(createThread, *_curProcess->curThread); diff --git a/GleeBug/Debugger.Loop.cpp b/GleeBug/Debugger.Loop.cpp index 02ef305..9bec7bf 100644 --- a/GleeBug/Debugger.Loop.cpp +++ b/GleeBug/Debugger.Loop.cpp @@ -23,7 +23,10 @@ namespace GleeBug { _curProcess = &_processes[_debugEvent.dwProcessId]; if (_curProcess->threads.count(_debugEvent.dwThreadId)) + { _curProcess->curThread = &_curProcess->threads[_debugEvent.dwThreadId]; + _curProcess->curThread->RegReadContext(); + } else _curProcess->curThread = nullptr; } @@ -62,6 +65,10 @@ namespace GleeBug break; } + //write the register context + if (_curProcess->curThread) + _curProcess->curThread->RegWriteContext(); + //continue the debug event if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus)) break; diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index 902ad1f..b227792 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -22,10 +22,39 @@ namespace GleeBug ThreadMap threads; DllMap dlls; + /** + \brief Default constructor. + */ ProcessInfo(); + + /** + \brief Constructor. + \param dwProcessId Identifier for the process. + \param dwMainThreadId Identifier for the main thread. + */ ProcessInfo(DWORD dwProcessId, DWORD dwMainThreadId); + + /** + \brief Destructor. + */ ~ProcessInfo(); + + /** + \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); }; diff --git a/GleeBug/Debugger.Thread.Registers.cpp b/GleeBug/Debugger.Thread.Registers.cpp new file mode 100644 index 0000000..8b955de --- /dev/null +++ b/GleeBug/Debugger.Thread.Registers.cpp @@ -0,0 +1,19 @@ +#include "Debugger.Thread.Registers.h" + +namespace GleeBug +{ + RegistersInfo::RegistersInfo() + { + memset(&this->_context, 0, sizeof(CONTEXT)); + } + + const CONTEXT* RegistersInfo::GetContext() + { + return &_context; + } + + void RegistersInfo::SetContext(const CONTEXT & context) + { + this->_context = context; + } +}; \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.Registers.h b/GleeBug/Debugger.Thread.Registers.h new file mode 100644 index 0000000..6e99bd3 --- /dev/null +++ b/GleeBug/Debugger.Thread.Registers.h @@ -0,0 +1,66 @@ +#ifndef _DEBUGGER_THREAD_REGISTERS_H +#define _DEBUGGER_THREAD_REGISTERS_H + +#include "Debugger.Global.h" + +namespace GleeBug +{ + CONTEXT; + /** + \brief Thread register context. #lovethetrash + */ + struct RegistersInfo + { +#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; +#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; +#endif //_WIN64 + + /** + \brief Default constructor. + */ + RegistersInfo(); + + /** + \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); + + private: + CONTEXT _context; + }; +}; + +#endif //_DEBUGGER_THREAD_REGISTERS_H \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.cpp b/GleeBug/Debugger.Thread.cpp index 5c9f3ff..ae9b532 100644 --- a/GleeBug/Debugger.Thread.cpp +++ b/GleeBug/Debugger.Thread.cpp @@ -18,6 +18,33 @@ namespace GleeBug ThreadInfo::~ThreadInfo() { if (this->hThread != INVALID_HANDLE_VALUE) - CloseHandle(hThread); + CloseHandle(this->hThread); + } + + 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; } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.h b/GleeBug/Debugger.Thread.h index 1ea2ae9..a8e9b6d 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -1,7 +1,8 @@ -#ifndef _DEBUGGER_THREADS_H -#define _DEBUGGER_THREADS_H +#ifndef _DEBUGGER_THREAD_H +#define _DEBUGGER_THREAD_H #include "Debugger.Global.h" +#include "Debugger.Thread.Registers.h" namespace GleeBug { @@ -14,10 +15,40 @@ namespace GleeBug HANDLE hThread; ULONG_PTR lpThreadLocalBase; ULONG_PTR lpStartAddress; + RegistersInfo registers; + /** + \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, LPVOID lpThreadLocalBase, LPVOID lpStartAddress); + + /** + \brief Destructor. + */ ~ThreadInfo(); + + /** + \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(); + + private: + CONTEXT _oldContext; }; typedef std::map ThreadMap; diff --git a/GleeBug/Debugger.h b/GleeBug/Debugger.h index c8327ae..9038c47 100644 --- a/GleeBug/Debugger.h +++ b/GleeBug/Debugger.h @@ -113,6 +113,12 @@ namespace GleeBug */ virtual void cbSystemBreakpoint() {}; + /** + \brief Internal error callback. Provide an implementation to use this callback. + \param error The error message. + */ + virtual void cbInternalError(const std::string & error) {}; + protected: //core debug event handlers /** \brief Process creation debug event. Do not override this unless you know what you are doing! diff --git a/GleeBug/GleeBug.vcxproj b/GleeBug/GleeBug.vcxproj index ef28bcf..25d38a7 100644 --- a/GleeBug/GleeBug.vcxproj +++ b/GleeBug/GleeBug.vcxproj @@ -157,6 +157,7 @@ + @@ -164,6 +165,7 @@ + diff --git a/GleeBug/GleeBug.vcxproj.filters b/GleeBug/GleeBug.vcxproj.filters index 3c4e522..d02f2d2 100644 --- a/GleeBug/GleeBug.vcxproj.filters +++ b/GleeBug/GleeBug.vcxproj.filters @@ -48,6 +48,9 @@ Source Files + + Source Files + @@ -65,5 +68,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/MyDebugger/MyDebugger.h b/MyDebugger/MyDebugger.h index c49741f..7216b6f 100644 --- a/MyDebugger/MyDebugger.h +++ b/MyDebugger/MyDebugger.h @@ -55,7 +55,7 @@ protected: virtual void cbSystemBreakpoint() { - printf("System breakpoint reached!"); + printf("System breakpoint reached!\n"); } };