From aa38b3e7212a66be3d36ddac61ba4996b32f20ed Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sat, 4 Apr 2015 23:59:38 +0200 Subject: [PATCH 1/7] read/write memory done (LOL) --- GleeBug/Debugger.Process.cpp | 10 ++++++++++ GleeBug/Debugger.Process.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/GleeBug/Debugger.Process.cpp b/GleeBug/Debugger.Process.cpp index 7a126a3..99e99be 100644 --- a/GleeBug/Debugger.Process.cpp +++ b/GleeBug/Debugger.Process.cpp @@ -23,4 +23,14 @@ namespace GleeBug if (this->hProcess != INVALID_HANDLE_VALUE) CloseHandle(hProcess); } + + bool ProcessInfo::MemRead(ULONG_PTR address, const size_t size, void* buffer) + { + return !!ReadProcessMemory(this->hProcess, (const void*)address, buffer, size, NULL); + } + + bool ProcessInfo::MemWrite(ULONG_PTR address, const size_t size, const void* buffer) + { + return !!WriteProcessMemory(this->hProcess, (void*)address, buffer, size, NULL); + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index 0343da7..902ad1f 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -25,6 +25,8 @@ namespace GleeBug ProcessInfo(); ProcessInfo(DWORD dwProcessId, DWORD dwMainThreadId); ~ProcessInfo(); + bool MemRead(ULONG_PTR address, const size_t size, void* buffer); + bool MemWrite(ULONG_PTR address, const size_t size, const void* buffer); }; typedef std::map ProcessMap; From c1bb981c16046fcc8849eff2ee6965d20b44f521 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sun, 5 Apr 2015 01:23:21 +0200 Subject: [PATCH 2/7] 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"); } }; From 8e5f758c96230b09073a99ac2c18e0b4e86302e9 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sun, 5 Apr 2015 03:21:42 +0200 Subject: [PATCH 3/7] basic cached RegistersInfo --- GleeBug/Debugger.Dll.h | 3 +- GleeBug/Debugger.Loop.Process.cpp | 16 ++++- GleeBug/Debugger.Loop.Thread.cpp | 9 +-- GleeBug/Debugger.Loop.cpp | 12 ++-- GleeBug/Debugger.Process.cpp | 9 +-- GleeBug/Debugger.Process.h | 10 +-- GleeBug/Debugger.Thread.Registers.cpp | 88 +++++++++++++++++++++++++++ GleeBug/Debugger.Thread.Registers.h | 85 +++++++++++++++++--------- GleeBug/Debugger.Thread.cpp | 10 +-- GleeBug/Debugger.Thread.h | 10 +-- MyDebugger/MyDebugger.h | 43 ++++++++++--- 11 files changed, 215 insertions(+), 80 deletions(-) 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()); } }; From 25b4dd40deb99d2c150c200a184b70aaff6ae0d7 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sun, 5 Apr 2015 03:45:00 +0200 Subject: [PATCH 4/7] some forward declarations and typedefs in one place --- GleeBug/Debugger.Dll.h | 2 -- GleeBug/Debugger.Global.h | 17 +++++++++++++++++ GleeBug/Debugger.Process.h | 2 -- GleeBug/Debugger.Thread.h | 2 -- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/GleeBug/Debugger.Dll.h b/GleeBug/Debugger.Dll.h index 413c070..6782df4 100644 --- a/GleeBug/Debugger.Dll.h +++ b/GleeBug/Debugger.Dll.h @@ -28,8 +28,6 @@ namespace GleeBug */ DllInfo(LPVOID lpBaseOfDll, DWORD sizeOfImage, LPVOID 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 index 8aaa312..28f80e9 100644 --- a/GleeBug/Debugger.Global.h +++ b/GleeBug/Debugger.Global.h @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include @@ -21,6 +23,21 @@ namespace GleeBug return a.second < b.first; } }; + + //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; + }; #endif //_DEBUGGER_GLOBAL_H \ No newline at end of file diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index 402d239..ba9d690 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -53,8 +53,6 @@ namespace GleeBug */ bool MemWrite(ULONG_PTR address, const size_t size, const void* buffer); }; - - typedef std::map ProcessMap; }; #endif //_DEBUGGER_PROCESS_H \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.h b/GleeBug/Debugger.Thread.h index 46684d0..4c33f41 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -46,8 +46,6 @@ namespace GleeBug private: CONTEXT _oldContext; }; - - typedef std::map ThreadMap; }; #endif //_DEBUGGER_THREADS_H \ No newline at end of file From 1a072a78c5ba25822b521387a77610f031e65240 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sun, 5 Apr 2015 05:11:51 +0200 Subject: [PATCH 5/7] working single step with callbacks --- GleeBug/Debugger.Global.h | 9 +++++++-- GleeBug/Debugger.Loop.Dll.cpp | 12 ++++++------ GleeBug/Debugger.Loop.Exception.cpp | 19 +++++++++++++++++-- GleeBug/Debugger.Loop.Process.cpp | 14 +++++++------- GleeBug/Debugger.Loop.Thread.cpp | 14 +++++++------- GleeBug/Debugger.Loop.cpp | 18 +++++++++--------- GleeBug/Debugger.Process.cpp | 2 +- GleeBug/Debugger.Process.h | 2 +- GleeBug/Debugger.Thread.cpp | 12 ++++++++++++ GleeBug/Debugger.Thread.h | 7 +++++++ GleeBug/Debugger.h | 22 ++++++++++++++++++---- MyDebugger/MyDebugger.h | 9 ++++++++- 12 files changed, 100 insertions(+), 40 deletions(-) diff --git a/GleeBug/Debugger.Global.h b/GleeBug/Debugger.Global.h index 28f80e9..db8e746 100644 --- a/GleeBug/Debugger.Global.h +++ b/GleeBug/Debugger.Global.h @@ -36,8 +36,13 @@ namespace GleeBug typedef std::map ThreadMap; //callback function typedefs - typedef std::function StepCallback; - + typedef std::function StepCallback; + + //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.Dll.cpp b/GleeBug/Debugger.Loop.Dll.cpp index ee0ddcc..1cc7397 100644 --- a/GleeBug/Debugger.Loop.Dll.cpp +++ b/GleeBug/Debugger.Loop.Dll.cpp @@ -7,12 +7,12 @@ namespace GleeBug //DLL housekeeping MODULEINFO modinfo; memset(&modinfo, 0, sizeof(MODULEINFO)); - GetModuleInformation(_curProcess->hProcess, + GetModuleInformation(_process->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 }); + _process->dlls.insert({ Range(dll.lpBaseOfDll, dll.lpBaseOfDll + dll.sizeOfImage - 1), dll }); //call the debug event callback cbLoadDllEvent(loadDll, dll); @@ -25,14 +25,14 @@ namespace GleeBug { //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()) + 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)); //DLL housekeeping - if (dll != _curProcess->dlls.end()) - _curProcess->dlls.erase(dll); + 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 9be1187..ca6feea 100644 --- a/GleeBug/Debugger.Loop.Exception.cpp +++ b/GleeBug/Debugger.Loop.Exception.cpp @@ -4,9 +4,9 @@ namespace GleeBug { void Debugger::exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) { - if (!_curProcess->systemBreakpoint) //handle system breakpoint + if (!_process->systemBreakpoint) //handle system breakpoint { - _curProcess->systemBreakpoint = true; + _process->systemBreakpoint = true; _continueStatus = DBG_CONTINUE; //call the callback @@ -19,6 +19,21 @@ namespace GleeBug 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 + { + } } void Debugger::exceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) diff --git a/GleeBug/Debugger.Loop.Process.cpp b/GleeBug/Debugger.Loop.Process.cpp index aeb9951..a86675f 100644 --- a/GleeBug/Debugger.Loop.Process.cpp +++ b/GleeBug/Debugger.Loop.Process.cpp @@ -9,22 +9,22 @@ namespace GleeBug createProcess.hProcess, _debugEvent.dwThreadId); _processes.insert({ process.dwProcessId, process }); - _curProcess = &_processes.find(process.dwProcessId)->second; + _process = &_processes.find(process.dwProcessId)->second; //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; + _process->threads.insert({ thread.dwThreadId, thread }); + _thread = _process->thread = &_process->threads.find(thread.dwThreadId)->second; //read thread context from main thread - if (!_curProcess->curThread->RegReadContext()) + if (!_thread->RegReadContext()) cbInternalError("ThreadInfo::RegReadContext() failed!"); //call the debug event callback - cbCreateProcessEvent(createProcess, *_curProcess); + cbCreateProcessEvent(createProcess, *_process); //close the file handle CloseHandle(createProcess.hFile); @@ -37,12 +37,12 @@ namespace GleeBug _breakDebugger = true; //call the debug event callback - cbExitProcessEvent(exitProcess, *_curProcess); + cbExitProcessEvent(exitProcess, *_process); //process housekeeping _processes.erase(_debugEvent.dwProcessId); //set the current process - _curProcess = nullptr; + _process = nullptr; } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Loop.Thread.cpp b/GleeBug/Debugger.Loop.Thread.cpp index fcb92be..df09de3 100644 --- a/GleeBug/Debugger.Loop.Thread.cpp +++ b/GleeBug/Debugger.Loop.Thread.cpp @@ -5,27 +5,27 @@ namespace GleeBug void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread) { //thread housekeeping - _curProcess->threads.insert({ _debugEvent.dwThreadId, + _process->threads.insert({ _debugEvent.dwThreadId, ThreadInfo(_debugEvent.dwThreadId, createThread.hThread, createThread.lpThreadLocalBase, createThread.lpStartAddress) }); //set the current thread - _curProcess->curThread = &_curProcess->threads.find(_debugEvent.dwThreadId)->second; - if (!_curProcess->curThread->RegReadContext()) + _thread = _process->thread = &_process->threads.find(_debugEvent.dwThreadId)->second; + if (!_thread->RegReadContext()) cbInternalError("ThreadInfo::RegReadContext() failed!"); //call the debug event callback - cbCreateThreadEvent(createThread, *_curProcess->curThread); + cbCreateThreadEvent(createThread, *_thread); } void Debugger::exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread) { //call the debug event callback - cbExitThreadEvent(exitThread, *_curProcess->curThread); + cbExitThreadEvent(exitThread, *_thread); //thread housekeeping - _curProcess->threads.erase(_debugEvent.dwThreadId); + _process->threads.erase(_debugEvent.dwThreadId); //set the current thread - _curProcess->curThread = nullptr; + _thread = _process->thread = nullptr; } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Loop.cpp b/GleeBug/Debugger.Loop.cpp index 6fa63ce..2c33b68 100644 --- a/GleeBug/Debugger.Loop.cpp +++ b/GleeBug/Debugger.Loop.cpp @@ -21,18 +21,18 @@ namespace GleeBug //set the current process and thread if (_processes.count(_debugEvent.dwProcessId)) { - _curProcess = &_processes[_debugEvent.dwProcessId]; - if (_curProcess->threads.count(_debugEvent.dwThreadId)) + _process = &_processes[_debugEvent.dwProcessId]; + if (_process->threads.count(_debugEvent.dwThreadId)) { - _curProcess->curThread = &_curProcess->threads[_debugEvent.dwThreadId]; - if (!_curProcess->curThread->RegReadContext()) + _thread = _process->thread = &_process->threads[_debugEvent.dwThreadId]; + if (!_thread->RegReadContext()) cbInternalError("ThreadInfo::RegReadContext() failed!"); } else - _curProcess->curThread = nullptr; + _thread = _process->thread = nullptr; } else - _curProcess = nullptr; + _process = nullptr; //dispatch the debug event switch (_debugEvent.dwDebugEventCode) @@ -67,9 +67,9 @@ namespace GleeBug } //write the register context - if (_curProcess && _curProcess->curThread) + if (_thread) { - if (!_curProcess->curThread->RegWriteContext()) + if (!_thread->RegWriteContext()) cbInternalError("ThreadInfo::RegWriteContext() failed!"); } @@ -80,6 +80,6 @@ namespace GleeBug //cleanup _processes.clear(); - _curProcess = nullptr; + _process = nullptr; } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Process.cpp b/GleeBug/Debugger.Process.cpp index 7c96cce..3e9f772 100644 --- a/GleeBug/Debugger.Process.cpp +++ b/GleeBug/Debugger.Process.cpp @@ -4,7 +4,7 @@ namespace GleeBug { ProcessInfo::ProcessInfo() { - this->curThread = nullptr; + this->thread = nullptr; this->systemBreakpoint = false; this->hProcess = INVALID_HANDLE_VALUE; } diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index ba9d690..c1bb2a2 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -17,7 +17,7 @@ namespace GleeBug DWORD dwProcessId; DWORD dwMainThreadId; - ThreadInfo* curThread; + ThreadInfo* thread; bool systemBreakpoint; ThreadMap threads; diff --git a/GleeBug/Debugger.Thread.cpp b/GleeBug/Debugger.Thread.cpp index 1272e8e..8877b08 100644 --- a/GleeBug/Debugger.Thread.cpp +++ b/GleeBug/Debugger.Thread.cpp @@ -41,4 +41,16 @@ namespace GleeBug ResumeThread(this->hThread); return bReturn; } + + void ThreadInfo::StepInto(StepCallback cbStep) + { + StepInto(); + stepCallbacks.push_back(cbStep); + } + + 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 4c33f41..cfc6a76 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -16,7 +16,10 @@ namespace GleeBug HANDLE hThread; ULONG_PTR lpThreadLocalBase; ULONG_PTR lpStartAddress; + RegistersInfo registers; + StepCallbackVector stepCallbacks; + bool isSingleStepping; /** \brief Default constructor. @@ -43,6 +46,10 @@ namespace GleeBug */ bool RegWriteContext(); + void StepInto(StepCallback cbStep); + + void StepInto(); + private: CONTEXT _oldContext; }; diff --git a/GleeBug/Debugger.h b/GleeBug/Debugger.h index 9038c47..30647d5 100644 --- a/GleeBug/Debugger.h +++ b/GleeBug/Debugger.h @@ -101,6 +101,12 @@ namespace GleeBug virtual void cbRipEvent(const RIP_INFO & rip) {}; 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 Unhandled exception callback. Provide an implementation to use this callback. \param exceptionRecord The exception record. @@ -114,10 +120,9 @@ namespace GleeBug virtual void cbSystemBreakpoint() {}; /** - \brief Internal error callback. Provide an implementation to use this callback. - \param error The error message. + \brief Step callback. Provide an implementation to use this callback. */ - virtual void cbInternalError(const std::string & error) {}; + virtual void cbStep() {}; protected: //core debug event handlers /** @@ -195,8 +200,17 @@ namespace GleeBug bool _breakDebugger; DEBUG_EVENT _debugEvent; ProcessMap _processes; - ProcessInfo* _curProcess; bool _isRunning; + + /** + \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; }; }; diff --git a/MyDebugger/MyDebugger.h b/MyDebugger/MyDebugger.h index 9c1a54b..8486087 100644 --- a/MyDebugger/MyDebugger.h +++ b/MyDebugger/MyDebugger.h @@ -69,10 +69,17 @@ protected: rip.dwError); }; + void boobs() + { + printf("(.)Y(.) 0x%p\n", + _thread->registers.Rip); + } + virtual void cbSystemBreakpoint() { printf("System breakpoint reached, CIP: 0x%p\n", - _curProcess->curThread->registers.Rip); + _thread->registers.Rip); + _thread->StepInto(BIND(this, MyDebugger::boobs)); } virtual void cbInternalError(const std::string & error) From f0ef6ed929e3a3e4a75639796dfb79d88956702f Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sun, 5 Apr 2015 05:32:26 +0200 Subject: [PATCH 6/7] template function for simpler callbacks --- GleeBug/Debugger.Thread.h | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/GleeBug/Debugger.Thread.h b/GleeBug/Debugger.Thread.h index cfc6a76..7243595 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -46,9 +46,32 @@ namespace GleeBug */ bool RegWriteContext(); + /** + \brief Step into. + */ + void StepInto(); + + /** + \brief Step into. + \param cbStep StepCallback. Can be written using BIND(this, MyDebugger::cb). + */ void StepInto(StepCallback cbStep); - void StepInto(); + /** + \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([](void (T::*callback)(), T* debugger) + { + (debugger->*callback)(); + }, callback, debugger)); + } private: CONTEXT _oldContext; From 0a030f8b2681fed098886eaeb8b6e7254c925ef0 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sun, 5 Apr 2015 05:33:50 +0200 Subject: [PATCH 7/7] fix --- GleeBug/Debugger.Thread.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/GleeBug/Debugger.Thread.h b/GleeBug/Debugger.Thread.h index 7243595..57c71c6 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -67,10 +67,7 @@ namespace GleeBug void StepInto(T* debugger, void(T::*callback)()) { static_cast(static_cast(debugger)); - StepInto(std::bind([](void (T::*callback)(), T* debugger) - { - (debugger->*callback)(); - }, callback, debugger)); + StepInto(std::bind(callback, debugger)); } private: