basic cached RegistersInfo

This commit is contained in:
Mr. eXoDia 2015-04-05 03:21:42 +02:00
parent c1bb981c16
commit 8e5f758c96
11 changed files with 215 additions and 80 deletions

View File

@ -8,8 +8,9 @@ namespace GleeBug
/** /**
\brief DLL information structure. \brief DLL information structure.
*/ */
struct DllInfo class DllInfo
{ {
public:
ULONG_PTR lpBaseOfDll; ULONG_PTR lpBaseOfDll;
DWORD sizeOfImage; DWORD sizeOfImage;
ULONG_PTR entryPoint; ULONG_PTR entryPoint;

View File

@ -6,12 +6,22 @@ namespace GleeBug
{ {
//process housekeeping //process housekeeping
ProcessInfo process(_debugEvent.dwProcessId, ProcessInfo process(_debugEvent.dwProcessId,
createProcess.hProcess,
_debugEvent.dwThreadId); _debugEvent.dwThreadId);
_processes.insert({ process.dwProcessId, process }); _processes.insert({ process.dwProcessId, process });
_curProcess = &_processes.find(process.dwProcessId)->second;
//set the current process and current thread //thread housekeeping (main thread is created implicitly)
_curProcess = &_processes[process.dwProcessId]; ThreadInfo thread(_debugEvent.dwThreadId,
_curProcess->curThread = &_curProcess->threads[process.dwMainThreadId]; 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 //call the debug event callback
cbCreateProcessEvent(createProcess, *_curProcess); cbCreateProcessEvent(createProcess, *_curProcess);

View File

@ -5,12 +5,13 @@ namespace GleeBug
void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread) void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread)
{ {
//thread housekeeping //thread housekeeping
ThreadInfo thread(_debugEvent.dwThreadId, createThread.lpThreadLocalBase, createThread.lpStartAddress); _curProcess->threads.insert({ _debugEvent.dwThreadId,
_curProcess->threads.insert({ thread.dwThreadId, thread }); ThreadInfo(_debugEvent.dwThreadId, createThread.hThread, createThread.lpThreadLocalBase, createThread.lpStartAddress) });
//set the current thread //set the current thread
_curProcess->curThread = &_curProcess->threads[thread.dwThreadId]; _curProcess->curThread = &_curProcess->threads.find(_debugEvent.dwThreadId)->second;
_curProcess->curThread->RegReadContext(); if (!_curProcess->curThread->RegReadContext())
cbInternalError("ThreadInfo::RegReadContext() failed!");
//call the debug event callback //call the debug event callback
cbCreateThreadEvent(createThread, *_curProcess->curThread); cbCreateThreadEvent(createThread, *_curProcess->curThread);

View File

@ -16,7 +16,7 @@ namespace GleeBug
_isRunning = false; _isRunning = false;
//set default continue status //set default continue status
_continueStatus = DBG_CONTINUE; _continueStatus = DBG_EXCEPTION_NOT_HANDLED;
//set the current process and thread //set the current process and thread
if (_processes.count(_debugEvent.dwProcessId)) if (_processes.count(_debugEvent.dwProcessId))
@ -25,7 +25,8 @@ namespace GleeBug
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(); if (!_curProcess->curThread->RegReadContext())
cbInternalError("ThreadInfo::RegReadContext() failed!");
} }
else else
_curProcess->curThread = nullptr; _curProcess->curThread = nullptr;
@ -66,8 +67,11 @@ namespace GleeBug
} }
//write the register context //write the register context
if (_curProcess->curThread) if (_curProcess && _curProcess->curThread)
_curProcess->curThread->RegWriteContext(); {
if (!_curProcess->curThread->RegWriteContext())
cbInternalError("ThreadInfo::RegWriteContext() failed!");
}
//continue the debug event //continue the debug event
if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus)) if (!ContinueDebugEvent(_debugEvent.dwProcessId, _debugEvent.dwThreadId, _continueStatus))

View File

@ -9,19 +9,12 @@ namespace GleeBug
this->hProcess = INVALID_HANDLE_VALUE; this->hProcess = INVALID_HANDLE_VALUE;
} }
ProcessInfo::ProcessInfo(DWORD dwProcessId, DWORD dwMainThreadId) ProcessInfo::ProcessInfo(DWORD dwProcessId, HANDLE hProcess, DWORD dwMainThreadId)
{ {
this->systemBreakpoint = false; this->systemBreakpoint = false;
this->hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); this->hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
this->dwProcessId = dwProcessId; this->dwProcessId = dwProcessId;
this->dwMainThreadId = dwMainThreadId; 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) bool ProcessInfo::MemRead(ULONG_PTR address, const size_t size, void* buffer)

View File

@ -10,8 +10,9 @@ namespace GleeBug
/** /**
\brief Process information structure. \brief Process information structure.
*/ */
struct ProcessInfo class ProcessInfo
{ {
public:
HANDLE hProcess; HANDLE hProcess;
DWORD dwProcessId; DWORD dwProcessId;
DWORD dwMainThreadId; DWORD dwMainThreadId;
@ -32,12 +33,7 @@ namespace GleeBug
\param dwProcessId Identifier for the process. \param dwProcessId Identifier for the process.
\param dwMainThreadId Identifier for the main thread. \param dwMainThreadId Identifier for the main thread.
*/ */
ProcessInfo(DWORD dwProcessId, DWORD dwMainThreadId); ProcessInfo(DWORD dwProcessId, HANDLE hProcess, DWORD dwMainThreadId);
/**
\brief Destructor.
*/
~ProcessInfo();
/** /**
\brief Read memory from the process. \brief Read memory from the process.

View File

@ -9,11 +9,99 @@ namespace GleeBug
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;
#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; 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;
#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; 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;
}
}; };

View File

@ -7,38 +7,41 @@ namespace GleeBug
{ {
CONTEXT; CONTEXT;
/** /**
\brief Thread register context. #lovethetrash \brief Thread register context.
*/ */
struct RegistersInfo class RegistersInfo
{ {
public:
#ifdef _WIN64 #ifdef _WIN64
ULONG_PTR & Rax = _context.Rax; DWORD64 Rax;
ULONG_PTR & Rbx = _context.Rbx; DWORD64 Rbx;
ULONG_PTR & Rcx = _context.Rcx; DWORD64 Rcx;
ULONG_PTR & Rdx = _context.Rdx; DWORD64 Rdx;
ULONG_PTR & Rsi = _context.Rsi; DWORD64 Rsi;
ULONG_PTR & Rdi = _context.Rdi; DWORD64 Rdi;
ULONG_PTR & Rbp = _context.Rbp; DWORD64 Rbp;
ULONG_PTR & Rsp = _context.Rsp; DWORD64 Rsp;
ULONG_PTR & Rip = _context.Rip; DWORD64 Rip;
ULONG_PTR & R8 = _context.R8; DWORD64 R8;
ULONG_PTR & R9 = _context.R9; DWORD64 R9;
ULONG_PTR & R10 = _context.R10; DWORD64 R10;
ULONG_PTR & R11 = _context.R11; DWORD64 R11;
ULONG_PTR & R12 = _context.R12; DWORD64 R12;
ULONG_PTR & R13 = _context.R13; DWORD64 R13;
ULONG_PTR & R14 = _context.R14; DWORD64 R14;
ULONG_PTR & R15 = _context.R15; DWORD64 R15;
DWORD EFlags;
#else //x86 #else //x86
ULONG_PTR & Eax = _context.Eax; DWORD Eax;
ULONG_PTR & Ebx = _context.Ebx; DWORD Ebx;
ULONG_PTR & Ecx = _context.Ecx; DWORD Ecx;
ULONG_PTR & Edx = _context.Edx; DWORD Edx;
ULONG_PTR & Esi = _context.Esi; DWORD Esi;
ULONG_PTR & Edi = _context.Edi; DWORD Edi;
ULONG_PTR & Ebp = _context.Ebp; DWORD Ebp;
ULONG_PTR & Esp = _context.Esp; DWORD Esp;
ULONG_PTR & Eip = _context.Eip; DWORD Eip;
DWORD EFlags;
#endif //_WIN64 #endif //_WIN64
/** /**
@ -58,8 +61,34 @@ namespace GleeBug
*/ */
void SetContext(const CONTEXT & context); 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: private:
CONTEXT _context; CONTEXT _context;
const int TRAP_FLAG = 0x100;
const int RESUME_FLAG = 0x10000;
}; };
}; };

View File

@ -7,20 +7,14 @@ namespace GleeBug
this->hThread = INVALID_HANDLE_VALUE; 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->dwThreadId = dwThreadId;
this->hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId); this->hThread = hThread;
this->lpThreadLocalBase = (ULONG_PTR)lpThreadLocalBase; this->lpThreadLocalBase = (ULONG_PTR)lpThreadLocalBase;
this->lpStartAddress = (ULONG_PTR)lpStartAddress; this->lpStartAddress = (ULONG_PTR)lpStartAddress;
} }
ThreadInfo::~ThreadInfo()
{
if (this->hThread != INVALID_HANDLE_VALUE)
CloseHandle(this->hThread);
}
bool ThreadInfo::RegReadContext() bool ThreadInfo::RegReadContext()
{ {
SuspendThread(this->hThread); SuspendThread(this->hThread);

View File

@ -9,8 +9,9 @@ namespace GleeBug
/** /**
\brief Thread information structure. \brief Thread information structure.
*/ */
struct ThreadInfo class ThreadInfo
{ {
public:
DWORD dwThreadId; DWORD dwThreadId;
HANDLE hThread; HANDLE hThread;
ULONG_PTR lpThreadLocalBase; ULONG_PTR lpThreadLocalBase;
@ -28,12 +29,7 @@ namespace GleeBug
\param lpThreadLocalBase The thread local base. \param lpThreadLocalBase The thread local base.
\param lpStartAddress The start address. \param lpStartAddress The start address.
*/ */
ThreadInfo(DWORD dwThreadId, LPVOID lpThreadLocalBase, LPVOID lpStartAddress); ThreadInfo(DWORD dwThreadId, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress);
/**
\brief Destructor.
*/
~ThreadInfo();
/** /**
\brief Read the register context from the thread. This fills the RegistersInfo member. \brief Read the register context from the thread. This fills the RegistersInfo member.

View File

@ -10,52 +10,75 @@ class MyDebugger : public Debugger
protected: protected:
virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) 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) 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) 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) 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) 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) 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) 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) 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) 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() 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());
} }
}; };