diff --git a/GleeBug/Static.Pe.cpp b/GleeBug/Static.Pe.cpp index d440666..321136d 100644 --- a/GleeBug/Static.Pe.cpp +++ b/GleeBug/Static.Pe.cpp @@ -6,6 +6,7 @@ namespace GleeBug : _file(file) { Clear(); + setupErrorMap(); } void Pe::Clear() @@ -35,12 +36,16 @@ namespace GleeBug return ErrorDosHeaderMagic; //get the NT headers offset - auto newOffset = uint32(_dosHeader->e_lfanew); + auto newOffset = _dosHeader->e_lfanew; //verify the new offset - if (newOffset < 0 || newOffset < _offset || newOffset >= _file.GetSize()) + if (newOffset < 0 || uint32(newOffset) >= _file.GetSize()) return ErrorDosHeaderNtHeaderOffset; + //TODO: special case where DOS and PE header overlap (tinygui.exe) + if (uint32(newOffset) < _offset) + return ErrorDosHeaderNtHeaderOffsetOverlap; + //read & verify the data between the DOS header and the NT headers auto afterDosCount = newOffset - _offset; _afterDosData = readRegion(afterDosCount); @@ -51,7 +56,7 @@ namespace GleeBug auto signature = readRegion(); if (!signature) return ErrorNtSignatureRead; - if (*(signature()) != IMAGE_NT_SIGNATURE) + if (*signature() != IMAGE_NT_SIGNATURE) return ErrorNtSignatureMagic; //read the file header @@ -98,11 +103,26 @@ namespace GleeBug break; default: //unsupported machine + { + //try the best possible effort (corkami's d_resource.dll) + auto ioh = readRegion(ifh->SizeOfOptionalHeader); + if (!ioh) + return ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead; + + _ntHeaders32 = Region(&_data, signature.Offset()); + if (!_ntHeaders32) + return ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize; + return ErrorNtFileHeaderUnsupportedMachine; } + } - //read data after the optional header - auto sizeOfIoh = ifh->SizeOfOptionalHeader; //this field can be zero + //check the SizeOfOptionalHeader field + auto sizeOfIoh = ifh->SizeOfOptionalHeader; + if (ifh->NumberOfSections && sizeOfIoh < realSizeOfIoh) //TODO: this can be valid in certain circumstances (nullSOH-XP) + return ErrorNtFileHeaderSizeOfOptionalHeaderOverlap; + + //read data after the optional header (TODO: check if this is even possible) uint32 afterOptionalCount = sizeOfIoh > realSizeOfIoh ? sizeOfIoh - realSizeOfIoh : 0; _afterOptionalData = readRegion(afterOptionalCount); @@ -113,6 +133,16 @@ namespace GleeBug return ErrorOk; } + bool Pe::IsValidPe() const + { + return _sectionHeaders.Valid(); + } + + bool Pe::IsPe64() const + { + return IsValidPe() ? _ntHeaders64.Valid() : false; + } + uint32 Pe::readData(uint32 size) { std::vector temp(size); @@ -126,13 +156,23 @@ namespace GleeBug return result; } - bool Pe::IsValidPe() const + void Pe::setupErrorMap() { - return _sectionHeaders.Valid(); - } - - bool Pe::IsPe64() const - { - return IsValidPe() ? _ntHeaders64.Valid() : false; + _errorMap.insert({ ErrorOk, "ErrorOk" }); + _errorMap.insert({ ErrorDosHeaderRead, "ErrorDosHeaderRead" }); + _errorMap.insert({ ErrorDosHeaderMagic, "ErrorDosHeaderMagic" }); + _errorMap.insert({ ErrorDosHeaderNtHeaderOffset, "ErrorDosHeaderNtHeaderOffset" }); + _errorMap.insert({ ErrorDosHeaderNtHeaderOffsetOverlap, "ErrorDosHeaderNtHeaderOffsetOverlap" }); + _errorMap.insert({ ErrorAfterDosHeaderData, "ErrorAfterDosHeaderData" }); + _errorMap.insert({ ErrorNtSignatureRead, "ErrorNtSignatureRead" }); + _errorMap.insert({ ErrorNtSignatureMagic, "ErrorNtSignatureMagic" }); + _errorMap.insert({ ErrorNtFileHeaderRead, "ErrorNtFileHeaderRead" }); + _errorMap.insert({ ErrorNtFileHeaderSizeOfOptionalHeaderOverlap, "ErrorNtFileHeaderSizeOfOptionalHeaderOverlap" }); + _errorMap.insert({ ErrorNtFileHeaderUnsupportedMachine, "ErrorNtFileHeaderUnsupportedMachine" }); + _errorMap.insert({ ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead, "ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead" }); + _errorMap.insert({ ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize, "ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize" }); + _errorMap.insert({ ErrorNtOptionalHeaderRead, "ErrorNtOptionalHeaderRead" }); + _errorMap.insert({ ErrorNtOptionalHeaderMagic, "ErrorNtOptionalHeaderMagic" }); + _errorMap.insert({ ErrorNtHeadersRegionSize, "ErrorNtHeadersRegionSize" }); } }; \ No newline at end of file diff --git a/GleeBug/Static.Pe.h b/GleeBug/Static.Pe.h index 028e413..dc84b70 100644 --- a/GleeBug/Static.Pe.h +++ b/GleeBug/Static.Pe.h @@ -11,18 +11,22 @@ namespace GleeBug public: enum Error { - ErrorOk, - ErrorDosHeaderRead, - ErrorDosHeaderMagic, - ErrorDosHeaderNtHeaderOffset, - ErrorAfterDosHeaderData, - ErrorNtSignatureRead, - ErrorNtSignatureMagic, - ErrorNtFileHeaderRead, - ErrorNtFileHeaderUnsupportedMachine, - ErrorNtOptionalHeaderRead, - ErrorNtOptionalHeaderMagic, - ErrorNtHeadersRegionSize + ErrorOk = 0, + ErrorDosHeaderRead = 1, + ErrorDosHeaderMagic = 2, + ErrorDosHeaderNtHeaderOffset = 3, + ErrorDosHeaderNtHeaderOffsetOverlap = 4, + ErrorAfterDosHeaderData = 5, + ErrorNtSignatureRead = 6, + ErrorNtSignatureMagic = 7, + ErrorNtFileHeaderRead = 8, + ErrorNtFileHeaderSizeOfOptionalHeaderOverlap = 9, + ErrorNtFileHeaderUnsupportedMachine = 10, + ErrorNtFileHeaderUnsupportedMachineOptionalHeaderRead = 11, + ErrorNtFileHeaderUnsupportedMachineNtHeadersRegionSize = 12, + ErrorNtOptionalHeaderRead = 13, + ErrorNtOptionalHeaderMagic = 14, + ErrorNtHeadersRegionSize = 15, }; explicit Pe(File & file); @@ -41,6 +45,7 @@ namespace GleeBug private: uint32 readData(uint32 size); + void setupErrorMap(); template inline Region readRegion(uint32 count = 1) @@ -48,6 +53,7 @@ namespace GleeBug return Region(&_data, readData(sizeof(T) * count), count); } + std::unordered_map _errorMap; File & _file; uint32 _fileSize; std::vector _data; diff --git a/MyDebugger/MyDebugger.vcxproj b/MyDebugger/MyDebugger.vcxproj index 31c5fb9..dffba95 100644 --- a/MyDebugger/MyDebugger.vcxproj +++ b/MyDebugger/MyDebugger.vcxproj @@ -142,6 +142,7 @@ + diff --git a/MyDebugger/MyDebugger.vcxproj.filters b/MyDebugger/MyDebugger.vcxproj.filters index f1b353c..bec50a8 100644 --- a/MyDebugger/MyDebugger.vcxproj.filters +++ b/MyDebugger/MyDebugger.vcxproj.filters @@ -23,5 +23,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/MyDebugger/PeTests.h b/MyDebugger/PeTests.h new file mode 100644 index 0000000..2d04f60 --- /dev/null +++ b/MyDebugger/PeTests.h @@ -0,0 +1,231 @@ +const wchar_t* peTestFiles[] = +{ + L"65535sects.exe", + L"96emptysections.exe", + L"96workingsections.exe", + L"appendeddata.exe", + L"appendedhdr.exe", + L"appendedsecttbl.exe", + L"apphdrW7.exe", + L"appsectableW7.exe", + L"aslr-ld.exe", + L"aslr.dll", + L"bigalign.exe", + L"bigib.exe", + L"bigsec.exe", + L"bigSoRD.exe", + L"bottomsecttbl.exe", + L"cfgbogus.exe", + L"compiled.exe", + L"copyright.exe", + L"ctxt-ld.exe", + L"ctxt.dll", + L"debug.exe", + L"delaycorrupt.exe", + L"delayfake.exe", + L"delayimports.exe", + L"dep.exe", + L"dll-dynld.exe", + L"dll-dynunicld.exe", + L"dll-ld.exe", + L"dll-webdavld.exe", + L"dll.dll", + L"dllbound-ld.exe", + L"dllbound-redirld.exe", + L"dllbound-redirldXP.exe", + L"dllbound.dll", + L"dllbound2.dll", + L"dllcfgdup-dynld.exe", + L"dllcfgdup.dll", + L"dllemptyexp-ld.exe", + L"dllemptyexp.dll", + L"dllextep-ld.exe", + L"dllextep.dll", + L"dllfakess-dynld.exe", + L"dllfakess-ld.exe", + L"dllfakess.dll", + L"dllfw-ld.exe", + L"dllfw.dll", + L"dllfwloop-ld.exe", + L"dllfwloop.dll", + L"dllmaxvals-dynld.exe", + L"dllmaxvals-ld.exe", + L"dllmaxvals.dll", + L"dllnegep-ld.exe", + L"dllnegep.dll", + L"dllnoexp-dynld.exe", + L"dllnoexp.dll", + L"dllnomain-ld.exe", + L"dllnomain.dll", + L"dllnomain2-dynld.exe", + L"dllnomain2.dll", + L"dllnoreloc-ld.exe", + L"dllnoreloc.dll", + L"dllnullep-dynld.exe", + L"dllnullep-ld.exe", + L"dllnullep.dll", + L"dllord-ld.exe", + L"dllord.dll", + L"dllweirdexp-ld.exe", + L"dllweirdexp.dll", + L"dosZMXP.exe", + L"dotnet20.exe", + L"driver.sys", + L"dump_imports.exe", + L"duphead.exe", + L"dupsec.exe", + L"d_nonnull-ld.exe", + L"d_nonnull.dll", + L"d_resource-ld.exe", + L"d_resource.dll", + L"d_tiny-ld.exe", + L"d_tiny.dll", + L"exceptions.exe", + L"exe2pe.exe", + L"exportobf.exe", + L"exportsdata.exe", + L"exports_doc.exe", + L"exports_order.exe", + L"fakenet.exe", + L"fakeregs.exe", + L"fakeregslib.dll", + L"fakerelocs.exe", + L"foldedhdr.exe", + L"foldedhdrW7.exe", + L"footer.exe", + L"gui.exe", + L"hard_imports.exe", + L"hdrcode.exe", + L"hdrdata.exe", + L"hiddenappdata1.exe", + L"hiddenappdata2.exe", + L"ibkernel.exe", + L"ibkmanual.exe", + L"ibknoreloc64.exe", + L"ibnullXP.exe", + L"ibreloc.exe", + L"ibrelocW7.exe", + L"impbyord.exe", + L"imports.exe", + L"importsdotXP.exe", + L"importshint.exe", + L"imports_apimsW7.exe", + L"imports_badterm.exe", + L"imports_bogusIAT.exe", + L"imports_corruptedIAT.exe", + L"imports_iatindesc.exe", + L"imports_mixed.exe", + L"imports_multidesc.exe", + L"imports_nnIAT.exe", + L"imports_noext.exe", + L"imports_noint.exe", + L"imports_nothunk.exe", + L"imports_relocW7.exe", + L"imports_tinyW7.exe", + L"imports_tinyXP.exe", + L"imports_virtdesc.exe", + L"imports_vterm.exe", + L"ldrsnaps.exe", + L"ldrsnaps64.exe", + L"lfanew_relocW7.exe", + L"lfanew_relocXP.exe", + L"lowsubsys.exe", + L"manifest.exe", + L"manifest_broken.exe", + L"manifest_bsod.exe", + L"manyimportsW7.exe", + L"maxsecW7.exe", + L"maxsecXP.exe", + L"maxsec_lowaligW7.exe", + L"maxvals.exe", + L"memshared-ld.exe", + L"memshared.dll", + L"mini.exe", + L"mscoree.exe", + L"multiss.exe", + L"multiss_con.exe", + L"multiss_drv.sys", + L"multiss_gui.exe", + L"mz.exe", + L"namedresource.exe", + L"no0code.exe", + L"normal.exe", + L"normal64.exe", + L"nosectionW7.exe", + L"nosectionXP.exe", + L"nothing-ld.exe", + L"nothing.dll", + L"no_dd.exe", + L"no_dd64.exe", + L"no_dep.exe", + L"no_seh.exe", + L"nullEP.exe", + L"nullSOH-XP.exe", + L"nullvirt.exe", + L"ownexports.exe", + L"ownexports2.exe", + L"ownexportsdot.exe", + L"pdf.exe", + L"pdf_zip_pe.exe", + L"quine.exe", + L"reloc4.exe", + L"reloc9.exe", + L"reloccrypt.exe", + L"reloccryptW8.exe", + L"reloccryptXP.exe", + L"relocsstripped.exe", + L"relocsstripped64.exe", + L"reshdr.exe", + L"resource.exe", + L"resource2.exe", + L"resourceloop.exe", + L"resource_icon.exe", + L"resource_string.exe", + L"safeseh.exe", + L"safeseh_fly.exe", + L"sc.exe", + L"secinsec.exe", + L"seh_change64.exe", + L"shuffledsect.exe", + L"signature.exe", + L"skippeddynbase.exe", + L"slackspace.exe", + L"ss63.exe", + L"ss63nocookie.exe", + L"standard.exe", + L"tiny.exe", + L"tinydll-ld.exe", + L"tinydll.dll", + L"tinydllXP-ld.exe", + L"tinydllXP.dll", + L"tinydrivXP.sys", + L"tinygui.exe", + L"tinynet.exe", + L"tinyW7.exe", + L"tinyW7x64.exe", + L"tinyW7_3264.exe", + L"tinyXP.exe", + L"tls.exe", + L"tls64.exe", + L"tls_aoi.exe", + L"tls_aoiOSDET.exe", + L"tls_exiting.exe", + L"tls_import.exe", + L"tls_k32.exe", + L"tls_noEP.exe", + L"tls_obfuscation.exe", + L"tls_onthefly.exe", + L"tls_reloc.exe", + L"tls_virtEP.exe", + L"truncatedlast.exe", + L"truncsectbl.exe", + L"version_cust.exe", + L"version_mini.exe", + L"version_std.exe", + L"virtEP.exe", + L"virtgap.exe", + L"virtrelocXP.exe", + L"virtsectblXP.exe", + L"weirdsord.exe", + L"winver.exe" +}; \ No newline at end of file diff --git a/MyDebugger/main.cpp b/MyDebugger/main.cpp index f4d60ab..bd0c436 100644 --- a/MyDebugger/main.cpp +++ b/MyDebugger/main.cpp @@ -37,15 +37,11 @@ static void printRegion(const char* str, Region region) region.Empty() ? "true" : "false"); } -static void testStatic() +static bool testPeFile(const wchar_t* szFileName, bool dumpData = true) { -#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; - File diskFile(szFilePath, File::ReadOnly); + auto result = false; + File diskFile(szFileName, File::ReadOnly); if (diskFile.Open()) { auto diskSize = diskFile.GetSize(); @@ -57,6 +53,9 @@ static void testStatic() auto parseError = pe.ParseHeaders(); if (parseError == Pe::ErrorOk) { + result = true; + if (!dumpData) + return result; auto idh = pe.GetDosHeader(); printRegion("DOS Header:", idh); printf(" e_magic: %02X\n", idh->e_magic); @@ -75,9 +74,10 @@ static void testStatic() PIMAGE_FILE_HEADER ifh = &inth->FileHeader; puts("\n File Header:"); - printf(" Machine : %04X\n", ifh->Machine); - printf(" NumberOfSections: %04X\n", ifh->NumberOfSections); - printf(" TimeDateStamp : %08X\n", ifh->TimeDateStamp); + printf(" Machine : %04X\n", ifh->Machine); + printf(" NumberOfSections : %04X\n", ifh->NumberOfSections); + printf(" TimeDateStamp : %08X\n", ifh->TimeDateStamp); + printf(" SizeOfOptionalHeader: %04X\n", ifh->SizeOfOptionalHeader); PIMAGE_OPTIONAL_HEADER ioh = &inth->OptionalHeader; puts("\n Optional Header:"); @@ -114,11 +114,31 @@ static void testStatic() } else puts("File::Open failed!"); + return result; +} + +static void testCorkami() +{ +#include "PeTests.h" + wchar_t szBasePath[MAX_PATH] = L"c:\\!exclude\\pe\\bin\\"; + int okCount = 0; + for (auto i = 0; i < _countof(peTestFiles); i++) + { + std::wstring fileName(szBasePath); + fileName += peTestFiles[i]; + if (testPeFile(fileName.c_str(), false)) + okCount++; + else + { + printf("file: %ws\n\n", fileName.c_str()); + } + } + printf("\n%d/%d parsed OK!\n", okCount, _countof(peTestFiles)); } int main() { - testStatic(); + testCorkami(); puts(""); system("pause"); return 0;