initial GleeBug implementation ready

This commit is contained in:
mrexodia 2017-05-23 23:02:04 +02:00
parent ebe1973c26
commit b0b4f5ded3
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
9 changed files with 200 additions and 108 deletions

View File

@ -1,41 +0,0 @@
#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

@ -70,11 +70,6 @@ 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

@ -167,7 +167,6 @@
<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,9 +83,6 @@
<ClCompile Include="Static.Pattern.cpp"> <ClCompile Include="Static.Pattern.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="GleeBug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="zyan-disassembler-engine\src\Decoder.c"> <ClCompile Include="zyan-disassembler-engine\src\Decoder.c">
<Filter>Source Files\Zydis</Filter> <Filter>Source Files\Zydis</Filter>
</ClCompile> </ClCompile>

View File

@ -1,6 +1,9 @@
#include <GleeBug/Debugger.h> #include <GleeBug/Debugger.h>
#include <GleeBug/Static.Pe.h>
#include <GleeBug/Static.Bufferfile.h>
#include "TitanEngine.h" #include "TitanEngine.h"
#include "ntdll.h" #include "ntdll.h"
#include "FileMap.h"
using namespace GleeBug; using namespace GleeBug;
@ -54,7 +57,7 @@ public:
} }
//Memory //Memory
bool MemoryReadSafe(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) const bool MemoryReadSafe(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead)
{ {
auto process = processFromHandle(hProcess); auto process = processFromHandle(hProcess);
if (!process) if (!process)
@ -72,6 +75,7 @@ public:
bool Fill(LPVOID MemoryStart, DWORD MemorySize, PBYTE FillByte) bool Fill(LPVOID MemoryStart, DWORD MemorySize, PBYTE FillByte)
{ {
//TODO: this is fucking inefficient
if (!mProcess) if (!mProcess)
return false; return false;
for (DWORD i = 0; i < MemorySize; i++) for (DWORD i = 0; i < MemorySize; i++)
@ -177,25 +181,30 @@ public:
return PebAddress; return PebAddress;
} }
void* GetTEBLocation(HANDLE hThread) static bool getThreadInfo(HANDLE hThread, THREAD_BASIC_INFORMATION & tbi)
{ {
ULONG RequiredLen = 0; ULONG RequiredLen = 0;
void* TebAddress = 0;
THREAD_BASIC_INFORMATION myThreadBasicInformation[5] = { 0 }; THREAD_BASIC_INFORMATION myThreadBasicInformation[5] = { 0 };
if(NtQueryInformationThread(hThread, ThreadBasicInformation, myThreadBasicInformation, sizeof(THREAD_BASIC_INFORMATION), &RequiredLen) == 0) if(NtQueryInformationThread(hThread, ThreadBasicInformation, myThreadBasicInformation, sizeof(THREAD_BASIC_INFORMATION), &RequiredLen) == 0)
{ {
TebAddress = (void*)myThreadBasicInformation->TebBaseAddress; tbi = myThreadBasicInformation[0];
return true;
} }
else else
{ {
if(NtQueryInformationThread(hThread, ThreadBasicInformation, myThreadBasicInformation, RequiredLen, &RequiredLen) == 0) if(NtQueryInformationThread(hThread, ThreadBasicInformation, myThreadBasicInformation, RequiredLen, &RequiredLen) == 0)
{ {
TebAddress = (void*)myThreadBasicInformation->TebBaseAddress; tbi = myThreadBasicInformation[0];
return true;
} }
} }
return false;
}
return TebAddress; void* GetTEBLocation(HANDLE hThread)
{
THREAD_BASIC_INFORMATION tbi;
return getThreadInfo(hThread, tbi) ? tbi.TebBaseAddress : nullptr;
} }
bool HideDebugger(HANDLE hProcess, DWORD PatchAPILevel) bool HideDebugger(HANDLE hProcess, DWORD PatchAPILevel)
@ -232,11 +241,13 @@ public:
} }
//Registers //Registers
ULONG_PTR GetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister) const ULONG_PTR GetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister)
{ {
if(!hActiveThread)
return 0;
auto thread = threadFromHandle(hActiveThread); auto thread = threadFromHandle(hActiveThread);
if(!thread) if(!thread)
return 0; __debugbreak(); //return 0;
if(mIsRunning) if(mIsRunning)
thread->RegReadContext(); thread->RegReadContext();
return thread->registers.Get(registerFromDword(IndexOfRegister)); return thread->registers.Get(registerFromDword(IndexOfRegister));
@ -246,7 +257,7 @@ public:
{ {
auto thread = threadFromHandle(hActiveThread); auto thread = threadFromHandle(hActiveThread);
if (!thread) if (!thread)
return false; __debugbreak(); //return false;
if(mIsRunning) if(mIsRunning)
thread->RegReadContext(); thread->RegReadContext();
thread->registers.Set(registerFromDword(IndexOfRegister), NewRegisterValue); thread->registers.Set(registerFromDword(IndexOfRegister), NewRegisterValue);
@ -255,11 +266,13 @@ public:
return true; return true;
} }
bool GetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext) const bool GetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext)
{ {
if(!hActiveThread)
return false;
auto thread = threadFromHandle(hActiveThread); auto thread = threadFromHandle(hActiveThread);
if (!thread || !titcontext) if (!thread || !titcontext)
return false; __debugbreak(); //return false;
if(mIsRunning) if(mIsRunning)
thread->RegReadContext(); thread->RegReadContext();
memset(titcontext, 0, sizeof(TITAN_ENGINE_CONTEXT_t)); memset(titcontext, 0, sizeof(TITAN_ENGINE_CONTEXT_t));
@ -303,7 +316,7 @@ public:
{ {
auto thread = threadFromHandle(hActiveThread); auto thread = threadFromHandle(hActiveThread);
if (!thread || !titcontext) if (!thread || !titcontext)
return false; __debugbreak(); //return false;
if(mIsRunning) if(mIsRunning)
thread->RegReadContext(); thread->RegReadContext();
thread->registers.Gax = titcontext->cax; thread->registers.Gax = titcontext->cax;
@ -357,77 +370,149 @@ public:
memset(x87FPURegisters, 0, sizeof(x87FPURegister_t) * 8); memset(x87FPURegisters, 0, sizeof(x87FPURegister_t) * 8);
} }
struct MappedPe
{
FileMap<unsigned char>* file;
BufferFile* buffer;
Pe* pe;
};
std::unordered_map<ULONG_PTR, MappedPe> mappedFiles;
//PE //PE
bool StaticFileLoadW(const wchar_t* szFileName, DWORD DesiredAccess, bool SimulateLoad, LPHANDLE FileHandle, LPDWORD LoadedSize, LPHANDLE FileMap, PULONG_PTR FileMapVA) bool StaticFileLoadW(const wchar_t* szFileName, DWORD DesiredAccess, bool SimulateLoad, LPHANDLE FileHandle, LPDWORD LoadedSize, LPHANDLE FileMap, PULONG_PTR FileMapVA)
{ {
//TODO auto file = new ::FileMap<unsigned char>;
return false; if(!file->Map(szFileName, DesiredAccess == UE_ACCESS_ALL))
__debugbreak(); //return false;
*FileHandle = file->hFile;
*LoadedSize = file->size;
*FileMap = file->hMap;
*FileMapVA = ULONG_PTR(file->data);
MappedPe mappedPe;
mappedPe.file = std::move(file);
mappedPe.buffer = new BufferFile(mappedPe.file->data, mappedPe.file->size);
mappedPe.pe = new Pe(*mappedPe.buffer);
if(mappedPe.pe->Parse(true) != Pe::ErrorOk)
__debugbreak();
mappedFiles.insert({ *FileMapVA, mappedPe });
return true;
} }
bool StaticFileUnloadW(const wchar_t* szFileName, bool CommitChanges, HANDLE FileHandle, DWORD LoadedSize, HANDLE FileMap, ULONG_PTR FileMapVA) bool StaticFileUnloadW(const wchar_t* szFileName, bool CommitChanges, HANDLE FileHandle, DWORD LoadedSize, HANDLE FileMap, ULONG_PTR FileMapVA)
{ {
//TODO auto found = mappedFiles.find(FileMapVA);
return false; if(found == mappedFiles.end())
__debugbreak(); //return false;
delete found->second.pe;
delete found->second.buffer;
delete found->second.file;
mappedFiles.erase(found);
return true;
} }
ULONG_PTR ConvertFileOffsetToVA(ULONG_PTR FileMapVA, ULONG_PTR AddressToConvert, bool ReturnType) ULONG_PTR ConvertFileOffsetToVA(ULONG_PTR FileMapVA, ULONG_PTR AddressToConvert, bool ReturnType)
{ {
//TODO auto found = mappedFiles.find(FileMapVA);
return 0; if(found == mappedFiles.end())
__debugbreak(); //return 0;
if(!found->second.pe->IsValidPe())
__debugbreak(); //return 0;
return found->second.pe->ConvertOffsetToRva(uint32(AddressToConvert));
} }
ULONG_PTR ConvertVAtoFileOffsetEx(ULONG_PTR FileMapVA, DWORD FileSize, ULONG_PTR ImageBase, ULONG_PTR AddressToConvert, bool AddressIsRVA, bool ReturnType) ULONG_PTR ConvertVAtoFileOffsetEx(ULONG_PTR FileMapVA, DWORD FileSize, ULONG_PTR ImageBase, ULONG_PTR AddressToConvert, bool AddressIsRVA, bool ReturnType)
{ {
//TODO auto found = mappedFiles.find(FileMapVA);
return 0; if(found == mappedFiles.end())
__debugbreak(); //return 0;
if(!found->second.pe->IsValidPe())
__debugbreak(); //return 0;
return found->second.pe->ConvertRvaToOffset(uint32(AddressToConvert));
} }
ULONG_PTR GetPE32DataFromMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData) ULONG_PTR GetPE32DataFromMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData)
{ {
//TODO auto found = mappedFiles.find(FileMapVA);
if(found == mappedFiles.end())
__debugbreak(); //return 0;
if(!found->second.pe->IsValidPe())
__debugbreak(); //return 0;
#ifdef _WIN64
if(!found->second.pe->IsPe64()) __debugbreak(); //return 0;
auto headers = found->second.pe->GetNtHeaders64();
#else
if(found->second.pe->IsPe64()) __debugbreak(); //return 0;
auto headers = found->second.pe->GetNtHeaders32();
#endif //_WIN64
const auto & sections = found->second.pe->GetSections();
switch(WhichData) switch(WhichData)
{ {
case UE_PE_OFFSET: case UE_PE_OFFSET:
break; return headers.Offset();
case UE_IMPORTTABLEADDRESS: case UE_IMPORTTABLEADDRESS:
break; return headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
case UE_IMPORTTABLESIZE: case UE_IMPORTTABLESIZE:
break; return headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
case UE_EXPORTTABLEADDRESS:
return headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
case UE_EXPORTTABLESIZE:
return headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
case UE_CHARACTERISTICS: case UE_CHARACTERISTICS:
break; return headers->FileHeader.Characteristics;
case UE_DLLCHARACTERISTICS: case UE_DLLCHARACTERISTICS:
break; return headers->OptionalHeader.DllCharacteristics;
case UE_OEP: case UE_OEP:
break; return headers->OptionalHeader.AddressOfEntryPoint;
case UE_SECTIONNUMBER: case UE_SECTIONNUMBER:
break; return sections.size();
case UE_SECTIONVIRTUALOFFSET: //WhichSection: IMAGE_DIRECTORY_ENTRY_EXCEPTION case UE_SECTIONVIRTUALOFFSET: //WhichSection: IMAGE_DIRECTORY_ENTRY_EXCEPTION
break; return WhichSection < sections.size() ? sections[WhichSection].GetHeader().VirtualAddress : 0;
case UE_SECTIONVIRTUALSIZE: //WhichSection: IMAGE_DIRECTORY_ENTRY_EXCEPTION case UE_SECTIONVIRTUALSIZE: //WhichSection: IMAGE_DIRECTORY_ENTRY_EXCEPTION
break; return WhichSection < sections.size() ? sections[WhichSection].GetHeader().Misc.VirtualSize : 0;
case UE_SECTIONNAME: case UE_SECTIONNAME:
break; return WhichSection < sections.size() ? ULONG_PTR(&sections[WhichSection].GetHeader().Name[0]) : 0;
default:
__debugbreak();
} }
return 0; return 0;
} }
ULONG_PTR GetPE32DataW(const wchar_t* szFileName, DWORD WhichSection, DWORD WhichData) ULONG_PTR GetPE32DataW(const wchar_t* szFileName, DWORD WhichSection, DWORD WhichData)
{ {
//TODO FileMap<unsigned char> file;
if(!file.Map(szFileName))
__debugbreak(); //return 0;
BufferFile buf(file.data, file.size);
Pe pe(buf);
if(pe.Parse(true) != Pe::ErrorOk)
__debugbreak(); //return 0;
if(!pe.IsValidPe())
__debugbreak(); //return 0;
#ifdef _WIN64
if(!pe.IsPe64()) __debugbreak(); //return 0;
auto headers = pe.GetNtHeaders64().Data();
#else
if(pe.IsPe64()) __debugbreak(); //return 0;
auto headers = pe.GetNtHeaders32().Data();
#endif //_WIN64
switch(WhichData) switch(WhichData)
{ {
case UE_CHARACTERISTICS:
return headers->FileHeader.Characteristics;
case UE_IMAGEBASE: case UE_IMAGEBASE:
break; return headers->OptionalHeader.ImageBase;
case UE_OEP: case UE_OEP:
break; return headers->OptionalHeader.AddressOfEntryPoint;
default:
__debugbreak();
} }
return 0; return 0;
} }
bool IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA) bool IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA)
{ {
//TODO return (GetPE32DataW(szFileName, NULL, UE_CHARACTERISTICS) & IMAGE_FILE_DLL) == IMAGE_FILE_DLL;
return false;
} }
bool TLSGrabCallBackDataW(const wchar_t* szFileName, LPVOID ArrayOfCallBacks, LPDWORD NumberOfCallBacks) bool TLSGrabCallBackDataW(const wchar_t* szFileName, LPVOID ArrayOfCallBacks, LPDWORD NumberOfCallBacks)
@ -663,20 +748,26 @@ private: //functions
} }
} }
Thread* threadFromHandle(HANDLE hThread) const Thread* threadFromHandle(HANDLE hThread)
{ {
if(!hThread) THREAD_BASIC_INFORMATION tbi;
return mThread; if(!getThreadInfo(hThread, tbi))
//TODO: properly implement this return nullptr;
return mThread; auto foundP = mProcesses.find(uint32(tbi.ClientId.UniqueProcess));
if(foundP == mProcesses.end())
return nullptr;
auto foundT = foundP->second.threads.find(uint32(tbi.ClientId.UniqueThread));
if(foundT == foundP->second.threads.end())
return nullptr;
return &foundT->second;
} }
Process* processFromHandle(HANDLE hProcess) const Process* processFromHandle(HANDLE hProcess)
{ {
if(!hProcess) auto foundP = mProcesses.find(GetProcessId(hProcess));
return mProcess; if(foundP == mProcesses.end())
//TODO: properly implement this return nullptr;
return mProcess; return &foundP->second;
} }
static HardwareType hwtypeFromTitan(DWORD type) static HardwareType hwtypeFromTitan(DWORD type)

View File

@ -0,0 +1,57 @@
#pragma once
#include <windows.h>
template<typename T>
struct FileMap
{
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hMap = nullptr;
T* data = nullptr;
unsigned int size = 0;
FileMap() { }
~FileMap()
{
Unmap();
}
FileMap(const FileMap<T> &) = delete;
FileMap(FileMap<T> && other)
{
other.hFile = hFile;
other.hMap = hMap;
other.data = data;
other.size = size;
}
bool Map(const wchar_t* szFileName, bool write = false)
{
hFile = CreateFileW(szFileName, GENERIC_READ | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if(hFile != INVALID_HANDLE_VALUE)
{
size = GetFileSize(hFile, nullptr);
hMap = CreateFileMappingW(hFile, nullptr, write ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
if(hMap)
data = (T*)MapViewOfFile(hMap, write ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, 0);
}
return data != nullptr;
}
void Unmap()
{
if(data)
UnmapViewOfFile(data);
if(hMap)
CloseHandle(hMap);
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
hMap = nullptr;
data = nullptr;
size = 0;
}
};

View File

@ -159,11 +159,6 @@ __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);
@ -194,11 +189,6 @@ __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);

View File

@ -154,6 +154,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Emulator.h" /> <ClInclude Include="Emulator.h" />
<ClInclude Include="FileMap.h" />
<ClInclude Include="TitanEngine.h" /> <ClInclude Include="TitanEngine.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -22,5 +22,8 @@
<ClInclude Include="Emulator.h"> <ClInclude Include="Emulator.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="FileMap.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>