Merge branch 'master' into membp

# Conflicts:
#	GleeBug/Debugger.Loop.Exception.cpp
This commit is contained in:
mrexodia 2017-01-04 03:11:50 +01:00
commit c40e9e68ce
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
15 changed files with 183 additions and 18 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ Release/
*.orig *.orig
*.vcxproj.user *.vcxproj.user
docs/ docs/
.vs/

View File

@ -29,6 +29,10 @@ namespace GleeBug
mProcess->permanentDep = true; mProcess->permanentDep = true;
#endif //_WIN64 #endif //_WIN64
//call the attach callback if appropriate
if(mAttachedToProcess && mProcess->dwProcessId == mMainProcess.dwProcessId)
cbAttachBreakpoint();
//call the callback //call the callback
cbSystemBreakpoint(); cbSystemBreakpoint();
} }

View File

@ -4,6 +4,15 @@ namespace GleeBug
{ {
void Debugger::createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess) void Debugger::createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess)
{ {
//initial attach housekeeping
if(mAttachedToProcess && !mMainProcess.dwProcessId)
{
mMainProcess.hProcess = createProcess.hProcess;
mMainProcess.hThread = createProcess.hThread;
mMainProcess.dwProcessId = mDebugEvent.dwProcessId;
mMainProcess.dwThreadId = mDebugEvent.dwThreadId;
}
//process housekeeping //process housekeeping
mProcesses.insert({ mDebugEvent.dwProcessId, mProcesses.insert({ mDebugEvent.dwProcessId,
Process(createProcess.hProcess, Process(createProcess.hProcess,

View File

@ -113,7 +113,7 @@ namespace GleeBug
break; break;
} }
//clear trap flag when set by GleeBug (to prevent an EXCEPTION_SINGLE_STEP after detach //clear trap flag when set by GleeBug (to prevent an EXCEPTION_SINGLE_STEP after detach)
if (mDetach && mThread) if (mDetach && mThread)
{ {
if (mThread->isInternalStepping || mThread->isSingleStepping) if (mThread->isInternalStepping || mThread->isSingleStepping)

View File

@ -42,17 +42,14 @@ namespace GleeBug
bool Thread::RegReadContext() bool Thread::RegReadContext()
{ {
SuspendThread(this->hThread);
memset(&this->mOldContext, 0, sizeof(CONTEXT)); memset(&this->mOldContext, 0, sizeof(CONTEXT));
this->mOldContext.ContextFlags = CONTEXT_ALL; this->mOldContext.ContextFlags = CONTEXT_ALL; //TODO: granular control over what's required
bool bReturn = false;
if (GetThreadContext(this->hThread, &this->mOldContext)) if (GetThreadContext(this->hThread, &this->mOldContext))
{ {
this->registers.SetContext(this->mOldContext); this->registers.SetContext(this->mOldContext);
bReturn = true; return true;
} }
ResumeThread(this->hThread); return false;
return bReturn;
} }
bool Thread::RegWriteContext() const bool Thread::RegWriteContext() const
@ -61,10 +58,7 @@ namespace GleeBug
if (memcmp(&this->mOldContext, this->registers.GetContext(), sizeof(CONTEXT)) == 0) if (memcmp(&this->mOldContext, this->registers.GetContext(), sizeof(CONTEXT)) == 0)
return true; return true;
//update the context //update the context
SuspendThread(this->hThread); return !!SetThreadContext(this->hThread, this->registers.GetContext());
bool bReturn = !!SetThreadContext(this->hThread, this->registers.GetContext());
ResumeThread(this->hThread);
return bReturn;
} }
void Thread::StepInto() void Thread::StepInto()

View File

@ -15,8 +15,8 @@ namespace GleeBug
const wchar_t* szCommandLine, const wchar_t* szCommandLine,
const wchar_t* szCurrentDirectory) const wchar_t* szCurrentDirectory)
{ {
STARTUPINFOW si; memset(&mMainStartupInfo, 0, sizeof(mMainStartupInfo));
memset(&si, 0, sizeof(si)); memset(&mMainProcess, 0, sizeof(mMainProcess));
const wchar_t* szFileNameCreateProcess; const wchar_t* szFileNameCreateProcess;
wchar_t* szCommandLineCreateProcess; wchar_t* szCommandLineCreateProcess;
wchar_t* szCreateWithCmdLine = nullptr; wchar_t* szCreateWithCmdLine = nullptr;
@ -42,14 +42,28 @@ namespace GleeBug
DEBUG_PROCESS | CREATE_NEW_CONSOLE, DEBUG_PROCESS | CREATE_NEW_CONSOLE,
nullptr, nullptr,
szCurrentDirectory, szCurrentDirectory,
&si, &mMainStartupInfo,
&mMainProcess); &mMainProcess);
delete[] szCreateWithCmdLine; delete[] szCreateWithCmdLine;
mAttachedToProcess = false;
return result; return result;
} }
bool Debugger::Attach(DWORD processId)
{
//don't allow attaching when still debugging
if(mIsDebugging)
return false;
if(!DebugActiveProcess(processId))
return false;
mAttachedToProcess = true;
memset(&mMainStartupInfo, 0, sizeof(mMainStartupInfo));
memset(&mMainProcess, 0, sizeof(mMainProcess));
return true;
}
bool Debugger::Stop() const bool Debugger::Stop() const
{ {
return !!TerminateProcess(mMainProcess.hProcess, 0); return !!TerminateProcess(mMainProcess.hProcess, 0);

View File

@ -35,6 +35,13 @@ namespace GleeBug
const wchar_t* szCommandLine, const wchar_t* szCommandLine,
const wchar_t* szCurrentDirectory); const wchar_t* szCurrentDirectory);
/**
\brief Attach to a debuggee.
\param processId Process to attach to.
\return true if the debuggee was attached to successfully, false otherwise.
*/
bool Attach(DWORD processId);
/** /**
\brief Stops the debuggee (terminate the process) \brief Stops the debuggee (terminate the process)
\return true if the debuggee was stopped correctly, false otherwise. \return true if the debuggee was stopped correctly, false otherwise.
@ -161,6 +168,11 @@ namespace GleeBug
*/ */
virtual void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) {}; virtual void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) {};
/**
\brief Attach breakpoint callback. Called just before cbSystemBreakpoint, only for the process that was attached to. Provide an implementation to use this callback.
*/
virtual void cbAttachBreakpoint() {};
/** /**
\brief System breakpoint callback. Called after the event is internally processed. Provide an implementation to use this callback. \brief System breakpoint callback. Called after the event is internally processed. Provide an implementation to use this callback.
*/ */
@ -264,6 +276,7 @@ namespace GleeBug
virtual void exceptionAccessViolation(const EXCEPTION_RECORD & exceptionRecord, bool firstChance); virtual void exceptionAccessViolation(const EXCEPTION_RECORD & exceptionRecord, bool firstChance);
protected: //variables protected: //variables
STARTUPINFOW mMainStartupInfo;
PROCESS_INFORMATION mMainProcess; PROCESS_INFORMATION mMainProcess;
uint32 mContinueStatus = DBG_EXCEPTION_NOT_HANDLED; uint32 mContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
bool mBreakDebugger = false; bool mBreakDebugger = false;
@ -273,6 +286,7 @@ namespace GleeBug
bool mIsDebugging = false; bool mIsDebugging = false;
bool mDetach = false; bool mDetach = false;
bool mDetachAndBreak = false; bool mDetachAndBreak = false;
bool mAttachedToProcess = false;
Capstone mCapstone; Capstone mCapstone;
/** /**

41
GleeBug/GleeBug.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "GleeBug.h"
namespace GleeBug
{
//Conversion functions taken from: http://www.nubaria.com/en/blog/?p=289
std::string Utf16ToUtf8(const std::wstring & wstr)
{
std::string convertedString;
auto requiredSize = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
if(requiredSize > 0)
{
std::vector<char> buffer(requiredSize);
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &buffer[0], requiredSize, nullptr, nullptr);
convertedString.assign(buffer.begin(), buffer.end() - 1);
}
return convertedString;
}
std::string Utf16ToUtf8(const wchar_t* wstr)
{
return Utf16ToUtf8(wstr ? std::wstring(wstr) : std::wstring());
}
std::wstring Utf8ToUtf16(const std::string & str)
{
std::wstring convertedString;
int requiredSize = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
if(requiredSize > 0)
{
std::vector<wchar_t> buffer(requiredSize);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &buffer[0], requiredSize);
convertedString.assign(buffer.begin(), buffer.end() - 1);
}
return convertedString;
}
std::wstring Utf8ToUtf16(const char* str)
{
return Utf8ToUtf16(str ? std::string(str) : std::string());
}
};

View File

@ -53,6 +53,11 @@ namespace GleeBug
return a.second < b.first; return a.second < b.first;
} }
}; };
std::string Utf16ToUtf8(const std::wstring & wstr);
std::string Utf16ToUtf8(const wchar_t* wstr);
std::wstring Utf8ToUtf16(const std::string & str);
std::wstring Utf8ToUtf16(const char* str);
} }
#endif //GLEEBUG_H #endif //GLEEBUG_H

View File

@ -168,6 +168,7 @@
<ClCompile Include="Debugger.Thread.HardwareBreakpoint.cpp" /> <ClCompile Include="Debugger.Thread.HardwareBreakpoint.cpp" />
<ClCompile Include="Debugger.Thread.Registers.cpp" /> <ClCompile Include="Debugger.Thread.Registers.cpp" />
<ClCompile Include="Debugger.Thread.Registers.GetSet.cpp" /> <ClCompile Include="Debugger.Thread.Registers.GetSet.cpp" />
<ClCompile Include="GleeBug.cpp" />
<ClCompile Include="Static.BufferFile.cpp" /> <ClCompile Include="Static.BufferFile.cpp" />
<ClCompile Include="Static.File.cpp" /> <ClCompile Include="Static.File.cpp" />
<ClCompile Include="Static.Pattern.cpp" /> <ClCompile Include="Static.Pattern.cpp" />

View File

@ -83,6 +83,9 @@
<ClCompile Include="..\capstone_wrapper\capstone_wrapper.cpp"> <ClCompile Include="..\capstone_wrapper\capstone_wrapper.cpp">
<Filter>Source Files\capstone_wrapper</Filter> <Filter>Source Files\capstone_wrapper</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="GleeBug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Debugger.h"> <ClInclude Include="Debugger.h">

View File

@ -153,6 +153,12 @@ protected:
rip.dwError); rip.dwError);
} }
void cbAttachBreakpoint() override
{
printf("Attach breakpoint reached, GIP: 0x%p\n",
mRegisters->Gip());
}
void cbSystemBreakpoint() override void cbSystemBreakpoint() override
{ {
printf("System breakpoint reached, GIP: 0x%p\n", printf("System breakpoint reached, GIP: 0x%p\n",

View File

@ -9,6 +9,7 @@ public:
//Debugger //Debugger
PROCESS_INFORMATION* InitDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder) PROCESS_INFORMATION* InitDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder)
{ {
mCbATTACHBREAKPOINT = nullptr;
if (!Init(szFileName, szCommandLine, szCurrentFolder)) if (!Init(szFileName, szCommandLine, szCurrentFolder))
return nullptr; return nullptr;
return &mMainProcess; return &mMainProcess;
@ -27,13 +28,16 @@ public:
bool AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack) bool AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack)
{ {
//TODO if(!Attach(ProcessId))
return false; return false;
mCbATTACHBREAKPOINT = STEPCALLBACK(CallBack);
mAttachProcessInfo = (PROCESS_INFORMATION*)DebugInfo;
DebugLoop();
return true;
} }
bool DetachDebuggerEx(DWORD ProcessId) bool DetachDebuggerEx(DWORD ProcessId)
{ {
//TODO
Detach(); Detach();
return true; return true;
} }
@ -141,6 +145,16 @@ public:
mSetDebugPrivilege = VariableSet; mSetDebugPrivilege = VariableSet;
} }
PROCESS_INFORMATION* TitanGetProcessInformation()
{
return &mMainProcess;
}
STARTUPINFOW* TitanGetStartupInformation()
{
return &mMainStartupInfo;
}
//Misc //Misc
bool IsJumpGoingToExecuteEx(HANDLE hProcess, HANDLE hThread, ULONG_PTR InstructionAddress, ULONG_PTR RegFlags) bool IsJumpGoingToExecuteEx(HANDLE hProcess, HANDLE hThread, ULONG_PTR InstructionAddress, ULONG_PTR RegFlags)
{ {
@ -475,6 +489,13 @@ public:
return false; return false;
} }
//Threader
ULONG_PTR ThreaderCreateRemoteThread(ULONG_PTR ThreadStartAddress, bool AutoCloseTheHandle, LPVOID ThreadPassParameter, LPDWORD ThreadId)
{
//TODO
return 0;
}
protected: protected:
void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const Process & process) override void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const Process & process) override
{ {
@ -530,6 +551,16 @@ protected:
mCbDEBUGEVENT(&debugEvent); mCbDEBUGEVENT(&debugEvent);
} }
void cbAttachBreakpoint() override
{
if(mCbATTACHBREAKPOINT)
{
if(mAttachProcessInfo)
*mAttachProcessInfo = mMainProcess;
mCbATTACHBREAKPOINT();
}
}
void cbSystemBreakpoint() override void cbSystemBreakpoint() override
{ {
if (mCbSYSTEMBREAKPOINT) if (mCbSYSTEMBREAKPOINT)
@ -586,12 +617,16 @@ private: //functions
Thread* threadFromHandle(HANDLE hThread) const Thread* threadFromHandle(HANDLE hThread) const
{ {
if(!hThread)
return mThread;
//TODO: properly implement this //TODO: properly implement this
return mThread; return mThread;
} }
Process* processFromHandle(HANDLE hProcess) const Process* processFromHandle(HANDLE hProcess) const
{ {
if(!hProcess)
return mProcess;
//TODO: properly implement this //TODO: properly implement this
return mProcess; return mProcess;
} }
@ -664,4 +699,6 @@ private: //variables
CUSTOMHANDLER mCbOUTPUTDEBUGSTRING = nullptr; CUSTOMHANDLER mCbOUTPUTDEBUGSTRING = nullptr;
CUSTOMHANDLER mCbUNHANDLEDEXCEPTION = nullptr; CUSTOMHANDLER mCbUNHANDLEDEXCEPTION = nullptr;
CUSTOMHANDLER mCbDEBUGEVENT = nullptr; CUSTOMHANDLER mCbDEBUGEVENT = nullptr;
STEPCALLBACK mCbATTACHBREAKPOINT = nullptr;
PROCESS_INFORMATION* mAttachProcessInfo = nullptr;
}; };

View File

@ -81,6 +81,16 @@ __declspec(dllexport) void TITCALL SetEngineVariable(DWORD VariableId, bool Vari
emu.SetEngineVariable(VariableId, VariableSet); emu.SetEngineVariable(VariableId, VariableSet);
} }
__declspec(dllexport) PROCESS_INFORMATION* TITCALL TitanGetProcessInformation()
{
return emu.TitanGetProcessInformation();
}
__declspec(dllexport) STARTUPINFOW* TITCALL TitanGetStartupInformation()
{
return emu.TitanGetStartupInformation();
}
//Misc //Misc
__declspec(dllexport) bool TITCALL IsJumpGoingToExecuteEx(HANDLE hProcess, HANDLE hThread, ULONG_PTR InstructionAddress, ULONG_PTR RegFlags) __declspec(dllexport) bool TITCALL IsJumpGoingToExecuteEx(HANDLE hProcess, HANDLE hThread, ULONG_PTR InstructionAddress, ULONG_PTR RegFlags)
{ {
@ -118,6 +128,11 @@ __declspec(dllexport) ULONG_PTR TITCALL GetContextDataEx(HANDLE hActiveThread, D
return emu.GetContextDataEx(hActiveThread, IndexOfRegister); return emu.GetContextDataEx(hActiveThread, IndexOfRegister);
} }
__declspec(dllexport) ULONG_PTR TITCALL GetContextData(DWORD IndexOfRegister)
{
return GetContextDataEx(nullptr, IndexOfRegister);
}
__declspec(dllexport) bool TITCALL SetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister, ULONG_PTR NewRegisterValue) __declspec(dllexport) bool TITCALL SetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister, ULONG_PTR NewRegisterValue)
{ {
return emu.SetContextDataEx(hActiveThread, IndexOfRegister, NewRegisterValue); return emu.SetContextDataEx(hActiveThread, IndexOfRegister, NewRegisterValue);
@ -149,6 +164,11 @@ __declspec(dllexport) bool TITCALL StaticFileLoadW(const wchar_t* szFileName, DW
return emu.StaticFileLoadW(szFileName, DesiredAccess, SimulateLoad, FileHandle, LoadedSize, FileMap, FileMapVA); return emu.StaticFileLoadW(szFileName, DesiredAccess, SimulateLoad, FileHandle, LoadedSize, FileMap, FileMapVA);
} }
__declspec(dllexport) bool TITCALL StaticFileLoad(const char* szFileName, DWORD DesiredAccess, bool SimulateLoad, LPHANDLE FileHandle, LPDWORD LoadedSize, LPHANDLE FileMap, PULONG_PTR FileMapVA)
{
return StaticFileLoadW(Utf8ToUtf16(szFileName).c_str(), DesiredAccess, SimulateLoad, FileHandle, LoadedSize, FileMap, FileMapVA);
}
__declspec(dllexport) bool TITCALL StaticFileUnloadW(const wchar_t* szFileName, bool CommitChanges, HANDLE FileHandle, DWORD LoadedSize, HANDLE FileMap, ULONG_PTR FileMapVA) __declspec(dllexport) bool TITCALL StaticFileUnloadW(const wchar_t* szFileName, bool CommitChanges, HANDLE FileHandle, DWORD LoadedSize, HANDLE FileMap, ULONG_PTR FileMapVA)
{ {
return emu.StaticFileUnloadW(szFileName, CommitChanges, FileHandle, LoadedSize, FileMap, FileMapVA); return emu.StaticFileUnloadW(szFileName, CommitChanges, FileHandle, LoadedSize, FileMap, FileMapVA);
@ -164,6 +184,11 @@ __declspec(dllexport) ULONG_PTR TITCALL ConvertVAtoFileOffsetEx(ULONG_PTR FileMa
return emu.ConvertVAtoFileOffsetEx(FileMapVA, FileSize, ImageBase, AddressToConvert, AddressIsRVA, ReturnType); return emu.ConvertVAtoFileOffsetEx(FileMapVA, FileSize, ImageBase, AddressToConvert, AddressIsRVA, ReturnType);
} }
__declspec(dllexport) ULONG_PTR TITCALL ConvertVAtoFileOffset(ULONG_PTR FileMapVA, ULONG_PTR AddressToConvert, bool ReturnType)
{
return ConvertVAtoFileOffsetEx(FileMapVA, 0, 0, AddressToConvert, false, ReturnType);
}
__declspec(dllexport) ULONG_PTR TITCALL GetPE32DataFromMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData) __declspec(dllexport) ULONG_PTR TITCALL GetPE32DataFromMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData)
{ {
return emu.GetPE32DataFromMappedFile(FileMapVA, WhichSection, WhichData); return emu.GetPE32DataFromMappedFile(FileMapVA, WhichSection, WhichData);
@ -174,6 +199,11 @@ __declspec(dllexport) ULONG_PTR TITCALL GetPE32DataW(const wchar_t* szFileName,
return emu.GetPE32DataW(szFileName, WhichSection, WhichData); return emu.GetPE32DataW(szFileName, WhichSection, WhichData);
} }
__declspec(dllexport) ULONG_PTR TITCALL GetPE32Data(const char* szFileName, DWORD WhichSection, DWORD WhichData)
{
return GetPE32DataW(Utf8ToUtf16(szFileName).c_str(), WhichSection, WhichData);
}
__declspec(dllexport) bool TITCALL IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA) __declspec(dllexport) bool TITCALL IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA)
{ {
return emu.IsFileDLLW(szFileName, FileMapVA); return emu.IsFileDLLW(szFileName, FileMapVA);
@ -269,3 +299,9 @@ __declspec(dllexport) void TITCALL StepInto(LPVOID traceCallBack)
{ {
emu.StepInto(traceCallBack); emu.StepInto(traceCallBack);
} }
//Threader
__declspec(dllexport) ULONG_PTR TITCALL ThreaderCreateRemoteThread(ULONG_PTR ThreadStartAddress, bool AutoCloseTheHandle, LPVOID ThreadPassParameter, LPDWORD ThreadId)
{
return emu.ThreaderCreateRemoteThread(ThreadStartAddress, AutoCloseTheHandle, ThreadPassParameter, ThreadId);
}

@ -1 +1 @@
Subproject commit 7fbeb7edaad3ffda7a7f37bd31086662e56f7a42 Subproject commit 619f5e0a0c43b19ca9dabf34da4ddd19cb84a704