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

View File

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

View File

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

View File

@ -1,6 +1,9 @@
#include <GleeBug/Debugger.h>
#include <GleeBug/Static.Pe.h>
#include <GleeBug/Static.Bufferfile.h>
#include "TitanEngine.h"
#include "ntdll.h"
#include "FileMap.h"
using namespace GleeBug;
@ -54,7 +57,7 @@ public:
}
//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);
if (!process)
@ -72,6 +75,7 @@ public:
bool Fill(LPVOID MemoryStart, DWORD MemorySize, PBYTE FillByte)
{
//TODO: this is fucking inefficient
if (!mProcess)
return false;
for (DWORD i = 0; i < MemorySize; i++)
@ -177,25 +181,30 @@ public:
return PebAddress;
}
void* GetTEBLocation(HANDLE hThread)
static bool getThreadInfo(HANDLE hThread, THREAD_BASIC_INFORMATION & tbi)
{
ULONG RequiredLen = 0;
void* TebAddress = 0;
THREAD_BASIC_INFORMATION myThreadBasicInformation[5] = { 0 };
if(NtQueryInformationThread(hThread, ThreadBasicInformation, myThreadBasicInformation, sizeof(THREAD_BASIC_INFORMATION), &RequiredLen) == 0)
{
TebAddress = (void*)myThreadBasicInformation->TebBaseAddress;
tbi = myThreadBasicInformation[0];
return true;
}
else
{
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)
@ -232,11 +241,13 @@ public:
}
//Registers
ULONG_PTR GetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister) const
ULONG_PTR GetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister)
{
if(!hActiveThread)
return 0;
auto thread = threadFromHandle(hActiveThread);
if(!thread)
return 0;
__debugbreak(); //return 0;
if(mIsRunning)
thread->RegReadContext();
return thread->registers.Get(registerFromDword(IndexOfRegister));
@ -246,7 +257,7 @@ public:
{
auto thread = threadFromHandle(hActiveThread);
if (!thread)
return false;
__debugbreak(); //return false;
if(mIsRunning)
thread->RegReadContext();
thread->registers.Set(registerFromDword(IndexOfRegister), NewRegisterValue);
@ -255,11 +266,13 @@ public:
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);
if (!thread || !titcontext)
return false;
__debugbreak(); //return false;
if(mIsRunning)
thread->RegReadContext();
memset(titcontext, 0, sizeof(TITAN_ENGINE_CONTEXT_t));
@ -303,7 +316,7 @@ public:
{
auto thread = threadFromHandle(hActiveThread);
if (!thread || !titcontext)
return false;
__debugbreak(); //return false;
if(mIsRunning)
thread->RegReadContext();
thread->registers.Gax = titcontext->cax;
@ -357,77 +370,149 @@ public:
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
bool StaticFileLoadW(const wchar_t* szFileName, DWORD DesiredAccess, bool SimulateLoad, LPHANDLE FileHandle, LPDWORD LoadedSize, LPHANDLE FileMap, PULONG_PTR FileMapVA)
{
//TODO
return false;
auto file = new ::FileMap<unsigned char>;
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)
{
//TODO
return false;
auto found = mappedFiles.find(FileMapVA);
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)
{
//TODO
return 0;
auto found = mappedFiles.find(FileMapVA);
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)
{
//TODO
return 0;
auto found = mappedFiles.find(FileMapVA);
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)
{
//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)
{
case UE_PE_OFFSET:
break;
return headers.Offset();
case UE_IMPORTTABLEADDRESS:
break;
return headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
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:
break;
return headers->FileHeader.Characteristics;
case UE_DLLCHARACTERISTICS:
break;
return headers->OptionalHeader.DllCharacteristics;
case UE_OEP:
break;
return headers->OptionalHeader.AddressOfEntryPoint;
case UE_SECTIONNUMBER:
break;
return sections.size();
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
break;
return WhichSection < sections.size() ? sections[WhichSection].GetHeader().Misc.VirtualSize : 0;
case UE_SECTIONNAME:
break;
return WhichSection < sections.size() ? ULONG_PTR(&sections[WhichSection].GetHeader().Name[0]) : 0;
default:
__debugbreak();
}
return 0;
}
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)
{
case UE_CHARACTERISTICS:
return headers->FileHeader.Characteristics;
case UE_IMAGEBASE:
break;
return headers->OptionalHeader.ImageBase;
case UE_OEP:
break;
return headers->OptionalHeader.AddressOfEntryPoint;
default:
__debugbreak();
}
return 0;
}
bool IsFileDLLW(const wchar_t* szFileName, ULONG_PTR FileMapVA)
{
//TODO
return false;
return (GetPE32DataW(szFileName, NULL, UE_CHARACTERISTICS) & IMAGE_FILE_DLL) == IMAGE_FILE_DLL;
}
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)
return mThread;
//TODO: properly implement this
return mThread;
THREAD_BASIC_INFORMATION tbi;
if(!getThreadInfo(hThread, tbi))
return nullptr;
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)
return mProcess;
//TODO: properly implement this
return mProcess;
auto foundP = mProcesses.find(GetProcessId(hProcess));
if(foundP == mProcesses.end())
return nullptr;
return &foundP->second;
}
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);
}
__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)
{
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);
}
__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)
{
return emu.IsFileDLLW(szFileName, FileMapVA);

View File

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

View File

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