some very amazing coding was done here (documentation + RegistersInfo with cache)

This commit is contained in:
Mr. eXoDia 2015-04-05 01:23:21 +02:00
parent aa38b3e721
commit c1bb981c16
12 changed files with 208 additions and 4 deletions

View File

@ -14,7 +14,17 @@ namespace GleeBug
DWORD sizeOfImage; DWORD sizeOfImage;
ULONG_PTR entryPoint; ULONG_PTR entryPoint;
/**
\brief Default constructor.
*/
DllInfo(); 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); DllInfo(LPVOID lpBaseOfDll, DWORD sizeOfImage, LPVOID entryPoint);
}; };

View File

@ -10,6 +10,7 @@ namespace GleeBug
//set the current thread //set the current thread
_curProcess->curThread = &_curProcess->threads[thread.dwThreadId]; _curProcess->curThread = &_curProcess->threads[thread.dwThreadId];
_curProcess->curThread->RegReadContext();
//call the debug event callback //call the debug event callback
cbCreateThreadEvent(createThread, *_curProcess->curThread); cbCreateThreadEvent(createThread, *_curProcess->curThread);

View File

@ -23,7 +23,10 @@ namespace GleeBug
{ {
_curProcess = &_processes[_debugEvent.dwProcessId]; _curProcess = &_processes[_debugEvent.dwProcessId];
if (_curProcess->threads.count(_debugEvent.dwThreadId)) if (_curProcess->threads.count(_debugEvent.dwThreadId))
{
_curProcess->curThread = &_curProcess->threads[_debugEvent.dwThreadId]; _curProcess->curThread = &_curProcess->threads[_debugEvent.dwThreadId];
_curProcess->curThread->RegReadContext();
}
else else
_curProcess->curThread = nullptr; _curProcess->curThread = nullptr;
} }
@ -62,6 +65,10 @@ namespace GleeBug
break; break;
} }
//write the register context
if (_curProcess->curThread)
_curProcess->curThread->RegWriteContext();
//continue the debug event //continue the debug event
if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus)) if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus))
break; break;

View File

@ -22,10 +22,39 @@ namespace GleeBug
ThreadMap threads; ThreadMap threads;
DllMap dlls; DllMap dlls;
/**
\brief Default constructor.
*/
ProcessInfo(); ProcessInfo();
/**
\brief Constructor.
\param dwProcessId Identifier for the process.
\param dwMainThreadId Identifier for the main thread.
*/
ProcessInfo(DWORD dwProcessId, DWORD dwMainThreadId); ProcessInfo(DWORD dwProcessId, DWORD dwMainThreadId);
/**
\brief Destructor.
*/
~ProcessInfo(); ~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); 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); bool MemWrite(ULONG_PTR address, const size_t size, const void* buffer);
}; };

View File

@ -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;
}
};

View File

@ -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

View File

@ -18,6 +18,33 @@ namespace GleeBug
ThreadInfo::~ThreadInfo() ThreadInfo::~ThreadInfo()
{ {
if (this->hThread != INVALID_HANDLE_VALUE) 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;
} }
}; };

View File

@ -1,7 +1,8 @@
#ifndef _DEBUGGER_THREADS_H #ifndef _DEBUGGER_THREAD_H
#define _DEBUGGER_THREADS_H #define _DEBUGGER_THREAD_H
#include "Debugger.Global.h" #include "Debugger.Global.h"
#include "Debugger.Thread.Registers.h"
namespace GleeBug namespace GleeBug
{ {
@ -14,10 +15,40 @@ namespace GleeBug
HANDLE hThread; HANDLE hThread;
ULONG_PTR lpThreadLocalBase; ULONG_PTR lpThreadLocalBase;
ULONG_PTR lpStartAddress; ULONG_PTR lpStartAddress;
RegistersInfo registers;
/**
\brief Default constructor.
*/
ThreadInfo(); 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); ThreadInfo(DWORD dwThreadId, LPVOID lpThreadLocalBase, LPVOID lpStartAddress);
/**
\brief Destructor.
*/
~ThreadInfo(); ~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<DWORD, ThreadInfo> ThreadMap; typedef std::map<DWORD, ThreadInfo> ThreadMap;

View File

@ -113,6 +113,12 @@ namespace GleeBug
*/ */
virtual void cbSystemBreakpoint() {}; 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 protected: //core debug event handlers
/** /**
\brief Process creation debug event. Do not override this unless you know what you are doing! \brief Process creation debug event. Do not override this unless you know what you are doing!

View File

@ -157,6 +157,7 @@
<ClCompile Include="Debugger.Loop.Thread.cpp" /> <ClCompile Include="Debugger.Loop.Thread.cpp" />
<ClCompile Include="Debugger.Process.cpp" /> <ClCompile Include="Debugger.Process.cpp" />
<ClCompile Include="Debugger.Thread.cpp" /> <ClCompile Include="Debugger.Thread.cpp" />
<ClCompile Include="Debugger.Thread.Registers.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Debugger.Dll.h" /> <ClInclude Include="Debugger.Dll.h" />
@ -164,6 +165,7 @@
<ClInclude Include="Debugger.h" /> <ClInclude Include="Debugger.h" />
<ClInclude Include="Debugger.Thread.h" /> <ClInclude Include="Debugger.Thread.h" />
<ClInclude Include="Debugger.Global.h" /> <ClInclude Include="Debugger.Global.h" />
<ClInclude Include="Debugger.Thread.Registers.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -48,6 +48,9 @@
<ClCompile Include="Debugger.Loop.Rip.cpp"> <ClCompile Include="Debugger.Loop.Rip.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Debugger.Thread.Registers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Debugger.h"> <ClInclude Include="Debugger.h">
@ -65,5 +68,8 @@
<ClInclude Include="Debugger.Global.h"> <ClInclude Include="Debugger.Global.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Debugger.Thread.Registers.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -55,7 +55,7 @@ protected:
virtual void cbSystemBreakpoint() virtual void cbSystemBreakpoint()
{ {
printf("System breakpoint reached!"); printf("System breakpoint reached!\n");
} }
}; };