mirror of https://github.com/x64dbg/GleeBug
Static.Pe is now working with corkami's mini.exe and reports specific error messages.
This commit is contained in:
parent
0b527f1985
commit
c56f2daebd
|
|
@ -20,7 +20,7 @@ namespace GleeBug
|
||||||
_sectionHeaders = Region<IMAGE_SECTION_HEADER>();
|
_sectionHeaders = Region<IMAGE_SECTION_HEADER>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Pe::ParseHeaders()
|
Pe::Error Pe::ParseHeaders()
|
||||||
{
|
{
|
||||||
//clear all current data
|
//clear all current data
|
||||||
Clear();
|
Clear();
|
||||||
|
|
@ -28,58 +28,89 @@ namespace GleeBug
|
||||||
//read the DOS header
|
//read the DOS header
|
||||||
_dosHeader = readRegion<IMAGE_DOS_HEADER>();
|
_dosHeader = readRegion<IMAGE_DOS_HEADER>();
|
||||||
if (!_dosHeader)
|
if (!_dosHeader)
|
||||||
return false;
|
return ErrorDosHeaderRead;
|
||||||
|
|
||||||
//verify the DOS header
|
//verify the DOS header
|
||||||
if (_dosHeader()->e_magic != IMAGE_DOS_SIGNATURE)
|
if (_dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||||
return false;
|
return ErrorDosHeaderMagic;
|
||||||
|
|
||||||
//get the NT headers offset
|
//get the NT headers offset
|
||||||
auto newOffset = uint32(_dosHeader()->e_lfanew);
|
auto newOffset = uint32(_dosHeader->e_lfanew);
|
||||||
|
|
||||||
//verify the new offset
|
//verify the new offset
|
||||||
if (newOffset < 0 || newOffset < _offset || newOffset >= _file.GetSize())
|
if (newOffset < 0 || newOffset < _offset || newOffset >= _file.GetSize())
|
||||||
return false;
|
return ErrorDosHeaderNtHeaderOffset;
|
||||||
|
|
||||||
//read the data between the DOS header and the NT headers
|
//read & verify the data between the DOS header and the NT headers
|
||||||
auto offsetDiff = newOffset - _offset;
|
auto afterDosCount = newOffset - _offset;
|
||||||
_afterDosData = readRegion<uint8>(offsetDiff);
|
_afterDosData = readRegion<uint8>(afterDosCount);
|
||||||
|
if (!_afterDosData)
|
||||||
|
return ErrorAfterDosHeaderData;
|
||||||
|
|
||||||
//read & verify the signature
|
//read & verify the signature
|
||||||
auto signature = readRegion<DWORD>();
|
auto signature = readRegion<DWORD>();
|
||||||
if (!signature || *(signature()) != IMAGE_NT_SIGNATURE)
|
if (!signature)
|
||||||
return false;
|
return ErrorNtSignatureRead;
|
||||||
|
if (*(signature()) != IMAGE_NT_SIGNATURE)
|
||||||
|
return ErrorNtSignatureMagic;
|
||||||
|
|
||||||
//read the file header
|
//read the file header
|
||||||
auto ifh = readRegion<IMAGE_FILE_HEADER>();
|
auto ifh = readRegion<IMAGE_FILE_HEADER>();
|
||||||
if (!ifh)
|
if (!ifh)
|
||||||
return false;
|
return ErrorNtFileHeaderRead;
|
||||||
switch (ifh()->Machine)
|
|
||||||
|
//read the optional header
|
||||||
|
uint32 realSizeOfIoh;
|
||||||
|
switch (ifh->Machine)
|
||||||
{
|
{
|
||||||
case IMAGE_FILE_MACHINE_I386:
|
case IMAGE_FILE_MACHINE_I386:
|
||||||
_ntHeaders32 = Region<IMAGE_NT_HEADERS32>(&_data, signature.Offset()); //this region is not valid at this point
|
{
|
||||||
if (!readRegion<IMAGE_OPTIONAL_HEADER32>()) //read the optional header data
|
//read & verify the optional header
|
||||||
return false;
|
realSizeOfIoh = uint32(sizeof(IMAGE_OPTIONAL_HEADER32));
|
||||||
if (!_ntHeaders32) //validate we read the entire NT headers region
|
auto ioh = readRegion<IMAGE_OPTIONAL_HEADER32>();
|
||||||
return false;
|
if (!ioh)
|
||||||
break;
|
return ErrorNtOptionalHeaderRead;
|
||||||
|
if (ioh->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||||
|
return ErrorNtOptionalHeaderMagic;
|
||||||
|
|
||||||
|
//construct & verify the NT headers region
|
||||||
|
_ntHeaders32 = Region<IMAGE_NT_HEADERS32>(&_data, signature.Offset());
|
||||||
|
if (!_ntHeaders32)
|
||||||
|
return ErrorNtHeadersRegionSize;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case IMAGE_FILE_MACHINE_AMD64:
|
case IMAGE_FILE_MACHINE_AMD64:
|
||||||
_ntHeaders64 = Region<IMAGE_NT_HEADERS64>(&_data, signature.Offset()); //this region is not valid at this point
|
{
|
||||||
if (!readRegion<IMAGE_OPTIONAL_HEADER64>()) //read the optional header data
|
//read & verify the optional header
|
||||||
return false;
|
realSizeOfIoh = uint32(sizeof(IMAGE_OPTIONAL_HEADER64));
|
||||||
if (!_ntHeaders64) //validate we read the entire NT headers region
|
auto ioh = readRegion<IMAGE_OPTIONAL_HEADER64>();
|
||||||
return false;
|
if (!ioh)
|
||||||
break;
|
return ErrorNtOptionalHeaderRead;
|
||||||
|
if (ioh->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||||
|
return ErrorNtOptionalHeaderMagic;
|
||||||
|
|
||||||
|
//construct & verify the NT headers region
|
||||||
|
_ntHeaders64 = Region<IMAGE_NT_HEADERS64>(&_data, signature.Offset());
|
||||||
|
if (!_ntHeaders64)
|
||||||
|
return ErrorNtHeadersRegionSize;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default: //unsupported machine
|
default: //unsupported machine
|
||||||
return false;
|
return ErrorNtFileHeaderUnsupportedMachine;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IMAGE_FIRST_SECTION123( ntheader ) ((PIMAGE_SECTION_HEADER) \
|
//read data after the optional header
|
||||||
((ULONG_PTR)(ntheader) + \
|
auto sizeOfIoh = ifh->SizeOfOptionalHeader; //this field can be zero
|
||||||
FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \
|
uint32 afterOptionalCount = sizeOfIoh > realSizeOfIoh ? sizeOfIoh - realSizeOfIoh : 0;
|
||||||
((ntheader))->FileHeader.SizeOfOptionalHeader \
|
_afterOptionalData = readRegion<uint8>(afterOptionalCount);
|
||||||
))
|
|
||||||
return true;
|
//read the section headers
|
||||||
|
auto sectionCount = ifh->NumberOfSections;
|
||||||
|
_sectionHeaders = readRegion<IMAGE_SECTION_HEADER>(sectionCount);
|
||||||
|
|
||||||
|
return ErrorOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Pe::readData(uint32 size)
|
uint32 Pe::readData(uint32 size)
|
||||||
|
|
@ -97,11 +128,11 @@ namespace GleeBug
|
||||||
|
|
||||||
bool Pe::IsValidPe() const
|
bool Pe::IsValidPe() const
|
||||||
{
|
{
|
||||||
return false;
|
return _sectionHeaders.Valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Pe::IsPe64() const
|
bool Pe::IsPe64() const
|
||||||
{
|
{
|
||||||
return false;
|
return IsValidPe() ? _ntHeaders64.Valid() : false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -9,10 +9,26 @@ namespace GleeBug
|
||||||
class Pe
|
class Pe
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum Error
|
||||||
|
{
|
||||||
|
ErrorOk,
|
||||||
|
ErrorDosHeaderRead,
|
||||||
|
ErrorDosHeaderMagic,
|
||||||
|
ErrorDosHeaderNtHeaderOffset,
|
||||||
|
ErrorAfterDosHeaderData,
|
||||||
|
ErrorNtSignatureRead,
|
||||||
|
ErrorNtSignatureMagic,
|
||||||
|
ErrorNtFileHeaderRead,
|
||||||
|
ErrorNtFileHeaderUnsupportedMachine,
|
||||||
|
ErrorNtOptionalHeaderRead,
|
||||||
|
ErrorNtOptionalHeaderMagic,
|
||||||
|
ErrorNtHeadersRegionSize
|
||||||
|
};
|
||||||
|
|
||||||
explicit Pe(File & file);
|
explicit Pe(File & file);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
bool ParseHeaders();
|
Error ParseHeaders();
|
||||||
bool IsValidPe() const;
|
bool IsValidPe() const;
|
||||||
bool IsPe64() const;
|
bool IsPe64() const;
|
||||||
|
|
||||||
|
|
@ -20,6 +36,7 @@ namespace GleeBug
|
||||||
const Region<uint8> & GetAfterDosData() const { return _afterDosData; }
|
const Region<uint8> & GetAfterDosData() const { return _afterDosData; }
|
||||||
const Region<IMAGE_NT_HEADERS32> & GetNtHeaders32() const { return _ntHeaders32; }
|
const Region<IMAGE_NT_HEADERS32> & GetNtHeaders32() const { return _ntHeaders32; }
|
||||||
const Region<IMAGE_NT_HEADERS64> & GetNtHeaders64() const { return _ntHeaders64; }
|
const Region<IMAGE_NT_HEADERS64> & GetNtHeaders64() const { return _ntHeaders64; }
|
||||||
|
const Region<uint8> & GetAfterOptionalData() const { return _afterOptionalData; }
|
||||||
const Region<IMAGE_SECTION_HEADER> & GetSectionHeaders() const { return _sectionHeaders; }
|
const Region<IMAGE_SECTION_HEADER> & GetSectionHeaders() const { return _sectionHeaders; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -40,6 +57,7 @@ namespace GleeBug
|
||||||
Region<uint8> _afterDosData;
|
Region<uint8> _afterDosData;
|
||||||
Region<IMAGE_NT_HEADERS32> _ntHeaders32;
|
Region<IMAGE_NT_HEADERS32> _ntHeaders32;
|
||||||
Region<IMAGE_NT_HEADERS64> _ntHeaders64;
|
Region<IMAGE_NT_HEADERS64> _ntHeaders64;
|
||||||
|
Region<uint8> _afterOptionalData;
|
||||||
Region<IMAGE_SECTION_HEADER> _sectionHeaders;
|
Region<IMAGE_SECTION_HEADER> _sectionHeaders;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,14 @@ namespace GleeBug
|
||||||
_offset + _count * sizeof(T) <= _data->size();
|
_offset + _count * sizeof(T) <= _data->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Returns if this region is empty (has no data).
|
||||||
|
*/
|
||||||
|
bool Empty() const
|
||||||
|
{
|
||||||
|
return Size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Returns Valid().
|
\brief Returns Valid().
|
||||||
*/
|
*/
|
||||||
|
|
@ -96,6 +104,11 @@ namespace GleeBug
|
||||||
return Data();
|
return Data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T* operator ->() const
|
||||||
|
{
|
||||||
|
return Data();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<uint8>* _data;
|
std::vector<uint8>* _data;
|
||||||
uint32 _offset;
|
uint32 _offset;
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,13 @@
|
||||||
#include "GleeBug/Static.File.h"
|
#include "GleeBug/Static.File.h"
|
||||||
#include "GleeBug/Static.Pe.h"
|
#include "GleeBug/Static.Pe.h"
|
||||||
|
|
||||||
#ifdef _WIN64
|
|
||||||
wchar_t szFilePath[256] = L"c:\\test64.exe";
|
|
||||||
#else //x86
|
|
||||||
wchar_t szFilePath[256] = L"c:\\test32.exe";
|
|
||||||
#endif //_WIN64
|
|
||||||
|
|
||||||
static void testDebugger()
|
static void testDebugger()
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN64
|
||||||
|
wchar_t szFilePath[256] = L"c:\\test64.exe";
|
||||||
|
#else //x86
|
||||||
|
wchar_t szFilePath[256] = L"c:\\test32.exe";
|
||||||
|
#endif //_WIN64
|
||||||
wchar_t szCommandLine[256] = L"";
|
wchar_t szCommandLine[256] = L"";
|
||||||
wchar_t szCurrentDir[256] = L"c:\\";
|
wchar_t szCurrentDir[256] = L"c:\\";
|
||||||
MyDebugger dbg;
|
MyDebugger dbg;
|
||||||
|
|
@ -26,36 +25,79 @@ static void testDebugger()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static void printRegion(const char* str, Region<T> region)
|
||||||
|
{
|
||||||
|
printf("\n%s (offset: 0x%X, size: 0x%X, v: %s, e: %s)\n",
|
||||||
|
str,
|
||||||
|
region.Offset(),
|
||||||
|
region.Size(),
|
||||||
|
region.Valid() ? "true" : "false",
|
||||||
|
region.Empty() ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
static void testStatic()
|
static void testStatic()
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN64
|
||||||
|
wchar_t szFilePath[256] = L"c:\\test64.exe";
|
||||||
|
#else //x86
|
||||||
|
wchar_t szFilePath[256] = L"c:\\!exclude\\pe\\mini.exe";
|
||||||
|
#endif //_WIN64
|
||||||
using namespace GleeBug;
|
using namespace GleeBug;
|
||||||
File file(szFilePath, File::ReadOnly);
|
File file(szFilePath, File::ReadOnly);
|
||||||
if (file.Open())
|
if (file.Open())
|
||||||
{
|
{
|
||||||
Pe pe(file);
|
Pe pe(file);
|
||||||
if (pe.ParseHeaders())
|
if (pe.ParseHeaders() == Pe::ErrorOk)
|
||||||
{
|
{
|
||||||
PIMAGE_DOS_HEADER idh = pe.GetDosHeader().Data();
|
auto idh = pe.GetDosHeader();
|
||||||
puts("DOS Header:");
|
printRegion("DOS Header:", idh);
|
||||||
printf(" e_magic: %02X\n", idh->e_magic);
|
printf(" e_magic: %02X\n", idh->e_magic);
|
||||||
printf(" e_lfanew: %08X\n", idh->e_lfanew);
|
printf(" e_lfanew: %08X\n", idh->e_lfanew);
|
||||||
|
|
||||||
|
auto afterDosData = pe.GetAfterDosData();
|
||||||
|
printRegion("After DOS Data", afterDosData);
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
PIMAGE_NT_HEADERS64 inth = pe.GetNtHeaders64().Data();
|
auto inth = pe.GetNtHeaders64();
|
||||||
#else //x32
|
#else //x32
|
||||||
PIMAGE_NT_HEADERS32 inth = pe.GetNtHeaders32().Data();
|
auto inth = pe.GetNtHeaders32();
|
||||||
#endif //_WIN64
|
#endif //_WIN64
|
||||||
puts("\nNT Headers:");
|
printRegion("NT Headers:", inth);
|
||||||
printf(" Signature: %08X\n", inth->Signature);
|
printf(" Signature: %08X\n", inth->Signature);
|
||||||
|
|
||||||
PIMAGE_FILE_HEADER ifh = &inth->FileHeader;
|
PIMAGE_FILE_HEADER ifh = &inth->FileHeader;
|
||||||
puts("\n File Header:");
|
puts("\n File Header:");
|
||||||
printf(" Machine : %02X\n", ifh->Machine);
|
printf(" Machine : %04X\n", ifh->Machine);
|
||||||
printf(" TimeDateStamp: %08X\n", ifh->TimeDateStamp);
|
printf(" NumberOfSections: %04X\n", ifh->NumberOfSections);
|
||||||
|
printf(" TimeDateStamp : %08X\n", ifh->TimeDateStamp);
|
||||||
|
|
||||||
PIMAGE_OPTIONAL_HEADER ioh = &inth->OptionalHeader;
|
PIMAGE_OPTIONAL_HEADER ioh = &inth->OptionalHeader;
|
||||||
puts("\n Optional Header:");
|
puts("\n Optional Header:");
|
||||||
printf(" Magic : %04X\n", ioh->Magic);
|
printf(" Magic : %04X\n", ioh->Magic);
|
||||||
printf(" ImageBase: %p\n", ioh->ImageBase);
|
printf(" EntryPoint: %08X\n", ioh->AddressOfEntryPoint);
|
||||||
printf(" Subsystem: %04X\n", ioh->Subsystem);
|
printf(" ImageBase : %p\n", ioh->ImageBase);
|
||||||
puts("\n Section Headers:");
|
printf(" Subsystem : %04X\n", ioh->Subsystem);
|
||||||
|
|
||||||
|
auto afterOptionalData = pe.GetAfterOptionalData();
|
||||||
|
printRegion("After Optional Data", afterOptionalData);
|
||||||
|
|
||||||
|
auto ish = pe.GetSectionHeaders();
|
||||||
|
printRegion("Section Headers:", ish);
|
||||||
|
for (auto i = 0; i < ifh->NumberOfSections; i++)
|
||||||
|
{
|
||||||
|
if (i)
|
||||||
|
puts("");
|
||||||
|
auto cur = ish.Data() + i;
|
||||||
|
printf(" Section %d:\n", i + 1);
|
||||||
|
char name[9] = "";
|
||||||
|
memcpy(name, cur->Name, sizeof(cur->Name));
|
||||||
|
printf(" Name : %s\n", name);
|
||||||
|
printf(" VSize: %08X\n", cur->Misc.VirtualSize);
|
||||||
|
printf(" VAddr: %08X\n", cur->VirtualAddress);
|
||||||
|
printf(" RSize: %08X\n", cur->SizeOfRawData);
|
||||||
|
printf(" RAddr: %08X\n", cur->PointerToRawData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
puts("Pe::ParseHeaders failed!");
|
puts("Pe::ParseHeaders failed!");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue