//------------------------------------------------ //--- 010 Editor v4.0.3 Binary Template // // File: EXE.bt // Authors: xSpy, Peter Kankowski, SweetScape Software, mirar // E-mail: cdutboy@gmail.com (xSpy) // Website: http://smallcode.weblogs.us (Peter Kankowski) // Version: 0.7.6 // Purpose: Parse Windows executable exe, dll, and sys files. // Supports 32 and 64 bit. // Category: Executable // File Mask: *.exe,*.dll,*.sys // ID Bytes: 4D 5A //MZ // History: // 0.7.6 2021-07-25 ts: Tiny change to parse timestamp in IMAGE_DEBUG_DIRECTORY // 0.7.5 2021-07-13 zhentar: Added debug directory parsing // 0.7.4 2021-06-18 ts: Updated IMAGE_MACHINE enum (added ARM64 among others) // 0.7.3 2021-02-11 Gon Rappaport: Fixed and improved base relocation parsing // 0.7.2 2019-09-16 gf: CommentBaseRelocBlock detects more cases. // 0.7.1 2019-09-02 mirar: Added mapping of Rich id and version on comp.id // 0.7 2019-07-10 mirar: Added Rich header parsing // 0.6 2019-03-18 Sen Jiang: Allow NT header to be overlapping with DOS header // 0.5 2018-04-21 Joshua Dugie: Added resource section parsing, cleaned up formatting and order, // also added Resource Directory String parsing // 0.4 2018-03-08 Rafal Cyran: Fixed size of IMAGE_EXPORT_DIRECTORY // 0.3 2016-03-31 T Strazzere: Fixed issue with IMAGE_IMPORT_DESCRIPTOR // 0.2 2016-03-10 Yann Le Brech: Added LittleEndian(); // 0.1 2016-02-15 SweetScape Software: Merged changes from PETemplate.bt and EXETemplate2.bt // and renamed to this file. Added some coloring and rearranged // for readability. Update header for repository submission. // 0.0.0.2 2013-01-06 xSpy: Add Parse Reloc. // 0.0.0.1 2013-01-01 xSpy: Public release. // // Recommended reading: // 1. Bernd Luevelsmeyer. The PE file format // http://webster.cs.ucr.edu/Page_TechDocs/pe.txt // 2. DJ Delorie. MS DOS EXE format // http://www.delorie.com/djgpp/doc/exe/ // 3. Iczelion. PE tutorial // http://spiff.tripnet.se/~iczelion/tutorials.html // 4. The Undocumented Microsoft "Rich" Header // http://bytepointer.com/articles/the_microsoft_rich_header.htm //------------------------------------------------ typedef QWORD ULONGLONG; //fix ULONGLONG /**** DOS AND NT HEADER STRUCTURES ****/ typedef struct { WORD MZSignature ; WORD UsedBytesInTheLastPage ; WORD FileSizeInPages ; WORD NumberOfRelocationItems ; WORD HeaderSizeInParagraphs ; WORD MinimumExtraParagraphs ; WORD MaximumExtraParagraphs ; WORD InitialRelativeSS ; WORD InitialSP ; WORD Checksum ; WORD InitialIP ; WORD InitialRelativeCS ; WORD AddressOfRelocationTable ; WORD OverlayNumber ; WORD Reserved[4] ; WORD OEMid ; WORD OEMinfo ; WORD Reserved2[10] ; LONG AddressOfNewExeHeader ; } IMAGE_DOS_HEADER; typedef struct (int Entries) { DWORD StartMarker ; DWORD Padding[3] ; struct RICH_HEADER_ENTRY { DWORD IdVersion ; DWORD Count ; } Entry[Entries] ; DWORD EndMarker ; DWORD XorKey ; } RICH_HEADER; typedef struct { local ULONG RichEnd = 0; local ULONG ea; local DWORD dw; for ( ea = FTell(); ea < DosHeader.AddressOfNewExeHeader; ea += 4 ) { dw = ReadUInt64(ea); if(dw == 0x68636952u) // Rich end marker "Rich" { RichEnd = ea; break; } } if (RichEnd != 0) { local DWORD XorKey; local DWORD Decoded; local DWORD RichStart; local int Entries; XorKey = ReadUInt64(RichEnd + 4); for (ea = ea - 4; ea >= FTell(); ea -= 4) { Decoded = ReadUInt64(ea); Decoded ^= XorKey; if (Decoded == 0x536E6144) // Rich start marker "DanS" { RichStart = ea; break; } } UCHAR Data[RichStart - sizeof(IMAGE_DOS_HEADER)] ; Entries = (RichEnd - RichStart - 16) / 8; RICH_HEADER RichHeader(Entries); } else if (DosHeader.AddressOfNewExeHeader > sizeof(IMAGE_DOS_HEADER)) { UCHAR Data[DosHeader.AddressOfNewExeHeader - sizeof(IMAGE_DOS_HEADER)] ; } Printf("Space between DOS header and NT header is %d bytes\n", DosHeader.AddressOfNewExeHeader - sizeof(IMAGE_DOS_HEADER)); } IMAGE_DOS_STUB; typedef enum { IMAGE_MACHINE_UNKNOWN = 0, I386 = 0x014c, // Intel 386 or later processors and compatible processors R3000 = 0x0162, // MIPS little-endian, 0x160 big-endian R4000 = 0x0166, // MIPS little-endian R10000 = 0x0168, // MIPS little-endian WCEMIPSV2 = 0x0169, // MIPS little-endian WCE v2 ALPHA = 0x0184, // Alpha_AXP SH3 = 0x01a2, // Hitachi SH3 SH3DSP = 0x01a3, // Hitachi SH3 DSP SH3E = 0x01a4, // Hitachi SH3E little-endian SH4 = 0x01a6, // Hitachi SH4 SH5 = 0x01a8, // Hitachi SH5 ARM = 0x01c0, // ARM little-endian THUMB = 0x01c2, // Thumb ARMNT = 0x01c4, // Arm Thumb-2 little-endian AM33 = 0x01d3, // Matsushita AM33 POWERPC = 0x01f0, // Power PC little endian POWERPCFP = 0x01f1, // Power PC with floating point support IA64 = 0x0200, // Intel Itanium processor family MIPS16 = 0x0266, // MIPS16 ALPHA64 = 0x0284, // ALPHA64 MIPSFPU = 0x0366, // MIPS with FPU MIPSFPU16 = 0x0466, // MIPS16 with FPU TRICORE = 0x0520, // Infineon CEF = 0x0CEF, EBC = 0x0EBC, // EFI Byte Code RISCV32 = 0x5032, // RISC-V 32-bit address space RISCV64 = 0x5064, // RISC-V 64-bit address space RISCV128 = 0x5128, // RISC-V 128-bit address space AMD64 = 0x8664, // x64 M32R = 0x9041, // Mitsubishi M32R little-endian ARM64 = 0xAA64, // ARM64 little-endian CEE = 0xC0EE } IMAGE_MACHINE ; // Characteristics typedef struct { WORD IMAGE_FILE_RELOCS_STRIPPED:1 ; WORD IMAGE_FILE_EXECUTABLE_IMAGE:1 ; WORD IMAGE_FILE_LINE_NUMS_STRIPPED:1 ; WORD IMAGE_FILE_LOCAL_SYMS_STRIPPED:1 ; WORD IMAGE_FILE_AGGRESIVE_WS_TRIM:1 ; WORD IMAGE_FILE_LARGE_ADDRESS_AWARE:1 2gb addresses">; WORD :1 ; WORD IMAGE_FILE_BYTES_REVERSED_LO:1 ; WORD IMAGE_FILE_32BIT_MACHINE:1 ; WORD IMAGE_FILE_DEBUG_STRIPPED:1 ; WORD IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP:1 ; WORD IMAGE_FILE_NET_RUN_FROM_SWAP:1 ; WORD IMAGE_FILE_SYSTEM:1 ; WORD IMAGE_FILE_DLL:1 ; WORD IMAGE_FILE_UP_SYSTEM_ONLY:1 ; WORD IMAGE_FILE_BYTES_REVERSED_HI:1 ; } FILE_CHARACTERISTICS ; typedef struct { IMAGE_MACHINE Machine ; WORD NumberOfSections ; time_t TimeDateStamp ; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; FILE_CHARACTERISTICS Characteristics ; } IMAGE_FILE_HEADER; typedef struct { DWORD VirtualAddress ; DWORD Size; } IMAGE_DATA_DIRECTORY; typedef struct { local int len = NtHeader.OptionalHeader.NumberOfRvaAndSizes; if (len > 16) { len = 16; } if (len > 0) IMAGE_DATA_DIRECTORY Export ; if (len > 1) IMAGE_DATA_DIRECTORY Import ; if (len > 2) IMAGE_DATA_DIRECTORY Resource ; if (len > 3) IMAGE_DATA_DIRECTORY Exception ; if (len > 4) IMAGE_DATA_DIRECTORY Security ; if (len > 5) IMAGE_DATA_DIRECTORY BaseRelocationTable ; if (len > 6) IMAGE_DATA_DIRECTORY DebugDirectory ; if (len > 7) IMAGE_DATA_DIRECTORY CopyrightOrArchitectureSpecificData ; if (len > 8) IMAGE_DATA_DIRECTORY GlobalPtr ; if (len > 9) IMAGE_DATA_DIRECTORY TLSDirectory ; if (len > 10) IMAGE_DATA_DIRECTORY LoadConfigurationDirectory ; if (len > 11) IMAGE_DATA_DIRECTORY BoundImportDirectory ; if (len > 12) IMAGE_DATA_DIRECTORY ImportAddressTable ; if (len > 13) IMAGE_DATA_DIRECTORY DelayLoadImportDescriptors ; if (len > 14) IMAGE_DATA_DIRECTORY COMRuntimedescriptor ; if (len > 15) IMAGE_DATA_DIRECTORY Reserved ; } IMAGE_DATA_DIRECTORY_ARRAY; typedef enum { IMAGE_SUBSYSTEM_UNKNOWN = 0, // Unknown subsystem NATIVE = 1, // Image doesn't require a subsystem WINDOWS_GUI = 2, // Image runs in the Windows GUI subsystem WINDOWS_CUI = 3, // Image runs in the Windows character subsystem OS2_CUI = 5, // image runs in the OS/2 character subsystem POSIX_CUI = 7, // image runs in the Posix character subsystem NATIVE_WINDOWS = 8, // image is a native Win9x driver WINDOWS_CE_GUI = 9, // Image runs in the Windows CE subsystem EFI_APPLICATION = 10, EFI_BOOT_SERVICE_DRIVER = 11, EFI_RUNTIME_DRIVER = 12, EFI_ROM = 13, XBOX = 14, WINDOWS_BOOT_APPLICATION = 16 } IMAGE_SUBSYSTEM ; typedef struct { WORD IMAGE_LIBRARY_PROCESS_INIT :1 ; WORD IMAGE_LIBRARY_PROCESS_TERM :1 ; WORD IMAGE_LIBRARY_THREAD_INIT :1 ; WORD IMAGE_LIBRARY_THREAD_TERM :1 ; WORD :2 ; WORD IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE :1 ; WORD IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY :1 ; WORD IMAGE_DLLCHARACTERISTICS_NX_COMPAT :1 ; WORD IMAGE_DLLCHARACTERISTICS_NO_ISOLATION :1 ; WORD IMAGE_DLLCHARACTERISTICS_NO_SEH :1 ; WORD IMAGE_DLLCHARACTERISTICS_NO_BIND :1 ; WORD :1 ; WORD IMAGE_DLLCHARACTERISTICS_WDM_DRIVER :1 ; WORD :1 ; WORD IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE :1 ; } DLL_CHARACTERISTICS ; typedef enum { PE32 = 0x10b, PE64 = 0x20b, ROM = 0x107 } OPTIONAL_MAGIC ; typedef struct { OPTIONAL_MAGIC Magic ; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode ; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint ; DWORD BaseOfCode ; DWORD BaseOfData ; DWORD ImageBase ; DWORD SectionAlignment ; DWORD FileAlignment ; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage ; DWORD SizeOfHeaders ; DWORD CheckSum ; IMAGE_SUBSYSTEM Subsystem; DLL_CHARACTERISTICS DllCharacteristics; DWORD SizeOfStackReserve ; DWORD SizeOfStackCommit ; DWORD SizeOfHeapReserve ; DWORD SizeOfHeapCommit ; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY_ARRAY DataDirArray; } IMAGE_OPTIONAL_HEADER32; typedef struct { OPTIONAL_MAGIC Magic ; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint ; DWORD BaseOfCode ; ULONGLONG ImageBase ; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage ; DWORD SizeOfHeaders; DWORD CheckSum; IMAGE_SUBSYSTEM Subsystem; DLL_CHARACTERISTICS DllCharacteristics; ULONGLONG SizeOfStackReserve ; ULONGLONG SizeOfStackCommit ; ULONGLONG SizeOfHeapReserve ; ULONGLONG SizeOfHeapCommit ; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY_ARRAY DataDirArray; } IMAGE_OPTIONAL_HEADER64; typedef struct { DWORD Signature ; IMAGE_FILE_HEADER FileHeader; local WORD OptionalHeaderMagic = ReadShort(FTell()); if (0x10b == OptionalHeaderMagic) { IMAGE_OPTIONAL_HEADER32 OptionalHeader; } else if (0x20b == OptionalHeaderMagic) { IMAGE_OPTIONAL_HEADER64 OptionalHeader; } else { Printf("Invalid Optional header magic %x.\n", OptionalHeaderMagic); return 1; } } IMAGE_NT_HEADERS ; /**** GENERIC SECTION HEADERS ****/ typedef struct { ULONG IMAGE_SCN_TYPE_DSECT:1 ; ULONG IMAGE_SCN_TYPE_NOLOAD:1 ; ULONG IMAGE_SCN_TYPE_GROUP:1 ; ULONG IMAGE_SCN_TYPE_NO_PAD:1 ; ULONG IMAGE_SCN_TYPE_COPY:1 ; ULONG IMAGE_SCN_CNT_CODE:1 ; ULONG IMAGE_SCN_CNT_INITIALIZED_DATA:1 ; ULONG IMAGE_SCN_CNT_UNINITIALIZED_DATA:1 ; ULONG IMAGE_SCN_LNK_OTHER:1 ; ULONG IMAGE_SCN_LNK_INFO:1 ; ULONG IMAGE_SCN_TYPE_OVER:1 ; ULONG IMAGE_SCN_LNK_REMOVE:1 ; ULONG IMAGE_SCN_LNK_COMDAT:1 ; ULONG :1 ; ULONG IMAGE_SCN_NO_DEFER_SPEC_EXC:1 ; ULONG IMAGE_SCN_GPREL:1 ; ULONG IMAGE_SCN_MEM_SYSHEAP:1 ; ULONG IMAGE_SCN_MEM_16BIT:1 ; ULONG IMAGE_SCN_MEM_LOCKED:1 ; ULONG IMAGE_SCN_MEM_PRELOAD:1 ; ULONG IMAGE_SCN_ALIGN_1BYTES:1 ; ULONG IMAGE_SCN_ALIGN_2BYTES:1 ; ULONG IMAGE_SCN_ALIGN_8BYTES:1 ; ULONG IMAGE_SCN_ALIGN_128BYTES:1 ; ULONG IMAGE_SCN_LNK_NRELOC_OVFL:1 ; ULONG IMAGE_SCN_MEM_DISCARDABLE:1 ; ULONG IMAGE_SCN_MEM_NOT_CACHED:1 ; ULONG IMAGE_SCN_MEM_NOT_PAGED:1 ; ULONG IMAGE_SCN_MEM_SHARED:1 ; ULONG IMAGE_SCN_MEM_EXECUTE:1 ; ULONG IMAGE_SCN_MEM_READ:1 ; ULONG IMAGE_SCN_MEM_WRITE:1 ; } SECTION_CHARACTERISTICS; typedef struct { BYTE Name[8] ; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress ; DWORD SizeOfRawData ; DWORD PointerToRawData ; DWORD PointerToRelocations ; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; SECTION_CHARACTERISTICS Characteristics ; } IMAGE_SECTION_HEADER ; typedef struct (IMAGE_SECTION_HEADER& SecHeader) { local string sSecName = SecHeader.Name; UCHAR Data[SecHeader.SizeOfRawData]; } IMAGE_SECTION_DATA ; /**** SECTION-SPECIFIC STRUCTURES ****/ typedef struct (int nNameLen) { WORD Hint; BYTE Name[nNameLen]; } IMAGE_IMPORT_BY_NAME ; typedef struct { local int nNameIndex=0; local ULONG ulThrunk=0; local int nNameLen=0; local string sDllName=""; local ULONG ulOriginalFirstThunkFOA=0; union { ULONG Characteristics; ULONG OriginalFirstThunk ; } DUMMYUNIONNAME; ULONG TimeDateStamp ; ULONG ForwarderChain ; ULONG Name ; ULONG FirstThunk ; ulOriginalFirstThunkFOA = RVA2FOA(DUMMYUNIONNAME.OriginalFirstThunk); if (!(0x20b == NtHeader.OptionalHeader.Magic)) { nNameIndex =0; local long og_position = 0; while (1) { ulThrunk = ReadUInt(ulOriginalFirstThunkFOA + 4 * nNameIndex); if (0 == ulThrunk) { break; } if (!(ulThrunk & 0x80000000)) { nNameLen = Strlen(ReadString(RVA2FOA(ulThrunk) + sizeof(WORD))); if (0 != nNameLen) { // This appears to not be continuous, so we need to ensure that we // fall back to the original position otherwise the structs will // not finish being created og_position = FTell(); FSeek(RVA2FOA(ulThrunk)); IMAGE_IMPORT_BY_NAME ImportByName(nNameLen + 1); FSeek(og_position); } } nNameIndex++; } } } IMAGE_IMPORT_DESCRIPTOR ; typedef struct (string sExportFuncName, ULONG ulDestRVA, string sJmpName) { local ULONG ulLocalDestRVA = ulDestRVA; local string sLocalJmpName = sJmpName; char Function[Strlen(sExportFuncName) + 1]; } IMAGE_EXPORT_BY_NAME ; typedef struct { DWORD Characteristics; time_t TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name ; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions ; // RVA from base of image DWORD AddressOfNames ; // RVA from base of image DWORD AddressOfNameOrdinals ; // RVA from base of image local int nIndex = 0; local ULONG NameArrayFOA = 0; local ULONG OrdinalArrayFOA = 0; local ULONG FuncArrayFOA = 0; local ULONG ulNameRVA = 0; local ULONG ulNameFOA = 0; local ULONG ulFuncRVA = 0; local WORD wOrdinal = 0; local string sExportName = ""; local string sJmpName = ""; local ULONG ulCurPos = FTell(); local ULONG ulEndPos = ulCurPos; // List Export names. NameArrayFOA = RVA2FOA(ExportDir.AddressOfNames); OrdinalArrayFOA = RVA2FOA(ExportDir.AddressOfNameOrdinals); FuncArrayFOA = RVA2FOA(ExportDir.AddressOfFunctions); for (nIndex = 0; nIndex < ExportDir.NumberOfNames; nIndex++) { ulNameRVA = ReadUInt(NameArrayFOA + nIndex*sizeof(ULONG)); ulNameFOA = RVA2FOA(ulNameRVA); sExportName = ReadString(ulNameFOA); if (0 != Strlen(sExportName)) { wOrdinal = ReadUShort(OrdinalArrayFOA + nIndex*sizeof(USHORT)); ulFuncRVA = ReadUInt(FuncArrayFOA + wOrdinal* sizeof(ULONG) ); //GetRVA if ((ulFuncRVA > NtHeader.OptionalHeader.DataDirArray.Export.VirtualAddress) && \ (ulFuncRVA < NtHeader.OptionalHeader.DataDirArray.Export.VirtualAddress + NtHeader.OptionalHeader.DataDirArray.Export.Size)) { // is a jmp sJmpName = ReadString( RVA2FOA(ulFuncRVA) ); FSeek(ulNameFOA); IMAGE_EXPORT_BY_NAME ExportByName(sExportName,ulFuncRVA,sJmpName); } else { // normal sJmpName = ""; FSeek(ulNameFOA); IMAGE_EXPORT_BY_NAME ExportByName(sExportName,ulFuncRVA,sJmpName); } } ulCurPos = FTell(); if (ulEndPos < ulCurPos) { ulEndPos = ulCurPos; } } FSeek(ulEndPos); } IMAGE_EXPORT_DIRECTORY ; typedef struct { WORD Length; if (Length > 0) { BYTE String[Length*2]; } } pascal_wstring_t ; typedef pascal_wstring_t RESOURCE_DIRECTORY_STRING; typedef struct { RESOURCE_DIRECTORY_STRING Strings[16] ; } RESOURCE_DIRECTORY_STRINGS ; typedef struct { local int originalPos; DWORD DataRVA ; DWORD DataSize; DWORD CodePage; DWORD Reserved; originalPos = FTell(); FSeek(RVA2FOA(DataRVA)); if (!IsResourceDirectoryString(this)) { UCHAR Data[DataSize]; } else { RESOURCE_DIRECTORY_STRINGS ResourceDirectoryStrings; } FSeek(originalPos); } RESOURCE_DATA_ENTRY ; typedef struct (int isNameEntry, DWORD level) { local int IsNameEntry = 0; local int originalPos; local DWORD Level; Level = level; IsNameEntry = isNameEntry; if (IsNameEntry > 0) { DWORD NameOffset ; } else { DWORD IntegerID ; } local DWORD NextDWORD = ReadInt(); if (NextDWORD & 0x80000000) { DWORD SubdirectoryOffset ; local DWORD dwMaskedOffset; dwMaskedOffset = SubdirectoryOffset & 0x7fffffff; originalPos = FTell(); FSeek(RVA2FOA(NtHeader.OptionalHeader.DataDirArray.Resource.VirtualAddress + dwMaskedOffset)); struct RESOURCE_DIRECTORY_TABLE RsourceDirectoryTable(Level+1); FSeek(originalPos); } else { DWORD DataEntryOffset ; originalPos = FTell(); FSeek(RVA2FOA(NtHeader.OptionalHeader.DataDirArray.Resource.VirtualAddress + DataEntryOffset)); RESOURCE_DATA_ENTRY ResourceDataEntry; FSeek(originalPos); } } RESOURCE_DIRECTORY_ENTRY ; typedef struct (DWORD level) { local DWORD Level; DWORD Characteristics ; time_t TimeDateStamp; WORD MajorVersion ; WORD MinorVersion ; WORD NumberOfNameEntries ; WORD NumberOfIDEntries ; Level = level; if (NumberOfNameEntries > 0) { RESOURCE_DIRECTORY_ENTRY NameEntries(1, Level)[NumberOfNameEntries] ; } if (NumberOfIDEntries > 0) { RESOURCE_DIRECTORY_ENTRY IDEntries(0, Level)[NumberOfIDEntries] ; } } RESOURCE_DIRECTORY_TABLE ; typedef enum { IMAGE_REL_BASED_ABSOLUTE = 0, IMAGE_REL_BASED_HIGH, IMAGE_REL_BASED_LOW, IMAGE_REL_BASED_HIGHLOW, IMAGE_REL_BASED_HIGHADJ, IMAGE_REL_BASED_MACHINE_SPECIFIC_5, IMAGE_REL_BASED_RESERVED, IMAGE_REL_BASED_MACHINE_SPECIFIC_7, IMAGE_REL_BASED_MACHINE_SPECIFIC_8, IMAGE_REL_BASED_MACHINE_SPECIFIC_9, IMAGE_REL_BASED_DIR64 } BASE_RELOCATION_TYPE; typedef struct { WORD Offset : 12; BASE_RELOCATION_TYPE Type : 4; } BASE_RELOCATION_BLOCK; typedef struct { DWORD VirtualAddress ; DWORD SizeOfBlock; // WORD TypeOffset[1]; local ULONG ulBlockNum=0; ulBlockNum = (SizeOfBlock - 8)/2; BASE_RELOCATION_BLOCK Block[ulBlockNum] ; } IMAGE_BASE_RELOCATION ; typedef struct (DWORD cbRelocDirectory) { local ULONG ulRelocNum=0; while ((FTell() - startof(this)) < cbRelocDirectory) { IMAGE_BASE_RELOCATION BaseReloc; ulRelocNum++; } } BASE_RELOCATION_TABLE ; typedef struct { DWORD DataType; DWORD Length; DWORD Reserved; string DbgFileName; } IMAGE_DEBUG_MISC; typedef enum { COFF = 1, CODEVIEW = 2, FPO = 3, MISC = 4, EXCEPTION, FIXUP, OMAP_TO_SRC, OMAP_FROM_SRC, BORLAND, RESERVED10, CLSID, VC_FEATURE, POGO, ILTCG, MPX, REPRO } IMAGE_DEBUG_TYPE; typedef struct { BYTE CvSignature[4]; if(CvSignature == "RSDS") { GUID RsDsSignature; DWORD Age; } else if (CvSignature == "NB10") { DWORD Offset; //not actually used DWORD Nb10Signature ; DWORD Age; } } CV_INFO; typedef struct { DWORD Characteristics; time_t TimeDateStamp ; WORD MajorVersion ; WORD MinorVersion ; IMAGE_DEBUG_TYPE Type; DWORD SizeOfData; DWORD AddressOfRawData ; DWORD PointerToRawData ; FSeek(PointerToRawData); switch(Type) { case 2: CV_INFO CodeViewInfo; break; case 4: IMAGE_DEBUG_MISC DebugMisc; break; } } IMAGE_DEBUG_DIRECTORY ; /**** PARSING UTILITY FUNCTIONS ****/ // IMAGE_DIRECTORY_ENTRY_EXPORT 0 void ParseEAT(void) { if ( (NtHeader.OptionalHeader.DataDirArray.Export.VirtualAddress != 0) && (NtHeader.OptionalHeader.DataDirArray.Export.Size != 0) ) { local ULONG ulExportFOA= RVA2FOA(NtHeader.OptionalHeader.DataDirArray.Export.VirtualAddress); FSeek(ulExportFOA); IMAGE_EXPORT_DIRECTORY ExportDir; } } // IMAGE_DIRECTORY_ENTRY_IMPORT 1 void ParseIAT() { if ( (NtHeader.OptionalHeader.DataDirArray.Import.VirtualAddress != 0) && (NtHeader.OptionalHeader.DataDirArray.Import.Size != 0) ) { local ULONG ulImportFOA = RVA2FOA(NtHeader.OptionalHeader.DataDirArray.Import.VirtualAddress); //Import local ULONG ulOriginalFirstThunk=0; local ULONG ulOriginalFirstThunkFOA=0; local int nImportIndex=0; FSeek(ulImportFOA); while (1) { ulOriginalFirstThunk = ReadUInt(ulImportFOA + 0x14*nImportIndex ); if (0 == ulOriginalFirstThunk) { break; } FSeek(ulImportFOA + 0x14*nImportIndex); IMAGE_IMPORT_DESCRIPTOR ImportDescriptor; nImportIndex++; } } } // IMAGE_DIRECTORY_ENTRY_RESOURCE void ParseResource() { if ( (NtHeader.OptionalHeader.DataDirArray.Resource.VirtualAddress == 0) || (NtHeader.OptionalHeader.DataDirArray.Resource.Size == 0) ) { return; } FSeek(RVA2FOA(NtHeader.OptionalHeader.DataDirArray.Resource.VirtualAddress)); RESOURCE_DIRECTORY_TABLE ResourceDirectoryTable(1); } // IMAGE_DIRECTORY_ENTRY_EXCEPTION void ParseException() { if ( (NtHeader.OptionalHeader.DataDirArray.Exception.VirtualAddress == 0) || (NtHeader.OptionalHeader.DataDirArray.Exception.Size == 0) ) { return; } //FixMe } // IMAGE_DIRECTORY_ENTRY_SECURITY void ParseSecurity() { if ( (NtHeader.OptionalHeader.DataDirArray.Security.VirtualAddress == 0) || (NtHeader.OptionalHeader.DataDirArray.Security.Size == 0) ) { return; } //FixMe } // IMAGE_DIRECTORY_ENTRY_BASERELOC void ParseBaseReloc() { if ( (NtHeader.OptionalHeader.DataDirArray.BaseRelocationTable.VirtualAddress == 0) || (NtHeader.OptionalHeader.DataDirArray.BaseRelocationTable.Size == 0) ) { return; } FSeek( RVA2FOA(NtHeader.OptionalHeader.DataDirArray.BaseRelocationTable.VirtualAddress) ); BASE_RELOCATION_TABLE RelocTable(NtHeader.OptionalHeader.DataDirArray.BaseRelocationTable.Size); } // IMAGE_DIRECTORY_ENTRY_DEBUG void ParseDebug() { if ( (NtHeader.OptionalHeader.DataDirArray.DebugDirectory.VirtualAddress == 0) || (NtHeader.OptionalHeader.DataDirArray.DebugDirectory.Size == 0) ) { return; } FSeek( RVA2FOA(NtHeader.OptionalHeader.DataDirArray.DebugDirectory.VirtualAddress) ); local ULONG ulDirCount=0; ulDirCount = NtHeader.OptionalHeader.DataDirArray.DebugDirectory.Size / 0x1C; // sizeof(IMAGE_DEBUG_DIRECTORY) IMAGE_DEBUG_DIRECTORY DebugDirectory[ulDirCount] ; } // IMAGE_DIRECTORY_ENTRY_TLS void ParseTLS() { if ( (NtHeader.OptionalHeader.DataDirArray.TLSDirectory.VirtualAddress == 0) || (NtHeader.OptionalHeader.DataDirArray.TLSDirectory.Size == 0) ) { return; } //FixMe } // IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT void ParseBoundImport() { if ( (NtHeader.OptionalHeader.DataDirArray.BoundImportDirectory.VirtualAddress == 0) || (NtHeader.OptionalHeader.DataDirArray.BoundImportDirectory.Size == 0) ) { return; } //FixMe } // IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT void ParseDelayImport() { if ( (NtHeader.OptionalHeader.DataDirArray.DelayLoadImportDescriptors.VirtualAddress == 0) || (NtHeader.OptionalHeader.DataDirArray.DelayLoadImportDescriptors.Size == 0) ) { return; } //FixMe } ULONG RVA2FOA(ULONG ulRVA) { local int i=0; for (i = 0; i < NtHeader.FileHeader.NumberOfSections; i++) { if ( (ulRVA >= SectionHeaders[i].VirtualAddress) && (ulRVA <= SectionHeaders[i].VirtualAddress + SectionHeaders[i].SizeOfRawData) ) { return SectionHeaders[i].PointerToRawData + (ulRVA - SectionHeaders[i].VirtualAddress); } } return 0; } int CalcImageNtHeadersSize(IMAGE_NT_HEADERS& stNtHeader) { local WORD OptionalHeaderMagic = ReadShort(startof(stNtHeader) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) ); if (0x10B == OptionalHeaderMagic) { Printf("PE32\n"); return 0xF8; //sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER32); } else if (0x20B == OptionalHeaderMagic) { Printf("PE64\n"); return 0x108; //sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER64); } else { return sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + 0; } return 0; } /**** READ AND WRITE UTILITY FUNCTIONS ****/ string ReadImageSectionHeader(IMAGE_SECTION_HEADER& h) { return h.Name; } string ReadSectionData(IMAGE_SECTION_DATA& SecData) { return SecData.sSecName; } string ReadImageImportDescriptor(IMAGE_IMPORT_DESCRIPTOR& ImportDescriptor) { return ReadString( RVA2FOA(ImportDescriptor.Name)); } string ReadExportByName(IMAGE_EXPORT_BY_NAME& ExportByName) { return ExportByName.Function; } string GetRichIdVersionString(DWORD& idVersion) { // from https://github.com/dishather/richprint/blob/master/comp_id.txt local string sIdVersion; if (idVersion == 0x00010000) SPrintf(sIdVersion, "[---] Unmarked objects"); else if (idVersion == 0x00000000) SPrintf(sIdVersion, "[---] Unmarked objects (old)"); else if (idVersion == 0x01046b74) SPrintf(sIdVersion, "[ C ] VS2019 v16.0.0 build 27508"); else if (idVersion == 0x01036b74) SPrintf(sIdVersion, "[ASM] VS2019 v16.0.0 build 27508"); else if (idVersion == 0x01056b74) SPrintf(sIdVersion, "[C++] VS2019 v16.0.0 build 27508"); else if (idVersion == 0x00ff6b74) SPrintf(sIdVersion, "[RES] VS2019 v16.0.0 build 27508"); else if (idVersion == 0x01026b74) SPrintf(sIdVersion, "[LNK] VS2019 v16.0.0 build 27508"); else if (idVersion == 0x01006b74) SPrintf(sIdVersion, "[EXP] VS2019 v16.0.0 build 27508"); else if (idVersion == 0x01016b74) SPrintf(sIdVersion, "[IMP] VS2019 v16.0.0 build 27508"); else if (idVersion == 0x010464ea) SPrintf(sIdVersion, "[ C ] VS2017 v15.5.4 build 25834"); else if (idVersion == 0x010364ea) SPrintf(sIdVersion, "[ASM] VS2017 v15.5.4 build 25834"); else if (idVersion == 0x010564ea) SPrintf(sIdVersion, "[C++] VS2017 v15.5.4 build 25834"); else if (idVersion == 0x00ff64ea) SPrintf(sIdVersion, "[RES] VS2017 v15.5.4 build 25834"); else if (idVersion == 0x010264ea) SPrintf(sIdVersion, "[LNK] VS2017 v15.5.4 build 25834"); else if (idVersion == 0x010064ea) SPrintf(sIdVersion, "[EXP] VS2017 v15.5.4 build 25834"); else if (idVersion == 0x010164ea) SPrintf(sIdVersion, "[IMP] VS2017 v15.5.4 build 25834"); else if (idVersion == 0x01045e97) SPrintf(sIdVersion, "[ C ] VS2015 UPD3.1 build 24215"); else if (idVersion == 0x01055e97) SPrintf(sIdVersion, "[C++] VS2015 UPD3.1 build 24215"); else if (idVersion == 0x01025e97) SPrintf(sIdVersion, "[LNK] VS2015 UPD3.1 build 24215"); else if (idVersion == 0x01005e97) SPrintf(sIdVersion, "[EXP] VS2015 UPD3.1 build 24215"); else if (idVersion == 0x01015e97) SPrintf(sIdVersion, "[IMP] VS2015 UPD3.1 build 24215"); else if (idVersion == 0x01045e95) SPrintf(sIdVersion, "[ C ] VS2015 UPD3 build 24213"); else if (idVersion == 0x01035e92) SPrintf(sIdVersion, "[ASM] VS2015 UPD3 build 24210"); else if (idVersion == 0x01055e95) SPrintf(sIdVersion, "[C++] VS2015 UPD3 build 24213"); else if (idVersion == 0x00ff5e92) SPrintf(sIdVersion, "[RES] VS2015 UPD3 build 24210"); else if (idVersion == 0x01025e95) SPrintf(sIdVersion, "[LNK] VS2015 UPD3 build 24213"); else if (idVersion == 0x01005e95) SPrintf(sIdVersion, "[EXP] VS2015 UPD3 build 24213"); else if (idVersion == 0x01015e95) SPrintf(sIdVersion, "[IMP] VS2015 UPD3 build 24213"); else if (idVersion == 0x01045d6e) SPrintf(sIdVersion, "[ C ] VS2015 UPD2 build 23918"); else if (idVersion == 0x01035d6e) SPrintf(sIdVersion, "[ASM] VS2015 UPD2 build 23918"); else if (idVersion == 0x01055d6e) SPrintf(sIdVersion, "[C++] VS2015 UPD2 build 23918"); else if (idVersion == 0x00ff5d6e) SPrintf(sIdVersion, "[RES] VS2015 UPD2 build 23918"); else if (idVersion == 0x01025d6e) SPrintf(sIdVersion, "[LNK] VS2015 UPD2 build 23918"); else if (idVersion == 0x01005d6e) SPrintf(sIdVersion, "[EXP] VS2015 UPD2 build 23918"); else if (idVersion == 0x01015d6e) SPrintf(sIdVersion, "[IMP] VS2015 UPD2 build 23918"); else if (idVersion == 0x01045bd2) SPrintf(sIdVersion, "[ C ] VS2015 UPD1 build 23506"); else if (idVersion == 0x01035bd2) SPrintf(sIdVersion, "[ASM] VS2015 UPD1 build 23506"); else if (idVersion == 0x01055bd2) SPrintf(sIdVersion, "[C++] VS2015 UPD1 build 23506"); else if (idVersion == 0x00ff5bd2) SPrintf(sIdVersion, "[RES] VS2015 UPD1 build 23506"); else if (idVersion == 0x01025bd2) SPrintf(sIdVersion, "[LNK] VS2015 UPD1 build 23506"); else if (idVersion == 0x01005bd2) SPrintf(sIdVersion, "[EXP] VS2015 UPD1 build 23506"); else if (idVersion == 0x01015bd2) SPrintf(sIdVersion, "[IMP] VS2015 UPD1 build 23506"); else if (idVersion == 0x010459f2) SPrintf(sIdVersion, "[ C ] VS2015 build 23026"); else if (idVersion == 0x010359f2) SPrintf(sIdVersion, "[ASM] VS2015 build 23026"); else if (idVersion == 0x010559f2) SPrintf(sIdVersion, "[C++] VS2015 build 23026"); else if (idVersion == 0x00ff59f2) SPrintf(sIdVersion, "[RES] VS2015 build 23026"); else if (idVersion == 0x010259f2) SPrintf(sIdVersion, "[LNK] VS2015 build 23026"); else if (idVersion == 0x010059f2) SPrintf(sIdVersion, "[EXP] VS2015 build 23026"); else if (idVersion == 0x010159f2) SPrintf(sIdVersion, "[IMP] VS2015 build 23026"); else if (idVersion == 0x00e09eb5) SPrintf(sIdVersion, "[ C ] VS2013 UPD5 build 40629"); else if (idVersion == 0x00e19eb5) SPrintf(sIdVersion, "[C++] VS2013 UPD5 build 40629"); else if (idVersion == 0x00de9eb5) SPrintf(sIdVersion, "[LNK] VS2013 UPD5 build 40629"); else if (idVersion == 0x00dc9eb5) SPrintf(sIdVersion, "[EXP] VS2013 UPD5 build 40629"); else if (idVersion == 0x00dd9eb5) SPrintf(sIdVersion, "[IMP] VS2013 UPD5 build 40629"); else if (idVersion == 0x00df9eb5) SPrintf(sIdVersion, "[ASM] VS2013 UPD5 build 40629"); else if (idVersion == 0x00e0797d) SPrintf(sIdVersion, "[ C ] VS2013 UPD4 build 31101"); else if (idVersion == 0x00e1797d) SPrintf(sIdVersion, "[C++] VS2013 UPD4 build 31101"); else if (idVersion == 0x00de797d) SPrintf(sIdVersion, "[LNK] VS2013 UPD4 build 31101"); else if (idVersion == 0x00dc797d) SPrintf(sIdVersion, "[EXP] VS2013 UPD4 build 31101"); else if (idVersion == 0x00dd797d) SPrintf(sIdVersion, "[IMP] VS2013 UPD4 build 31101"); else if (idVersion == 0x00df797d) SPrintf(sIdVersion, "[ASM] VS2013 UPD4 build 31101"); else if (idVersion == 0x00e07803) SPrintf(sIdVersion, "[ C ] VS2013 UPD3 build 30723"); else if (idVersion == 0x00e17803) SPrintf(sIdVersion, "[C++] VS2013 UPD3 build 30723"); else if (idVersion == 0x00de7803) SPrintf(sIdVersion, "[LNK] VS2013 UPD3 build 30723"); else if (idVersion == 0x00dc7803) SPrintf(sIdVersion, "[EXP] VS2013 UPD3 build 30723"); else if (idVersion == 0x00dd7803) SPrintf(sIdVersion, "[IMP] VS2013 UPD3 build 30723"); else if (idVersion == 0x00df7803) SPrintf(sIdVersion, "[ASM] VS2013 UPD3 build 30723"); else if (idVersion == 0x00e07725) SPrintf(sIdVersion, "[ C ] VS2013 UPD2 build 30501"); else if (idVersion == 0x00e17725) SPrintf(sIdVersion, "[C++] VS2013 UPD2 build 30501"); else if (idVersion == 0x00de7725) SPrintf(sIdVersion, "[LNK] VS2013 UPD2 build 30501"); else if (idVersion == 0x00dc7725) SPrintf(sIdVersion, "[EXP] VS2013 UPD2 build 30501"); else if (idVersion == 0x00dd7725) SPrintf(sIdVersion, "[IMP] VS2013 UPD2 build 30501"); else if (idVersion == 0x00df7725) SPrintf(sIdVersion, "[ASM] VS2013 UPD2 build 30501"); else if (idVersion == 0x00e0520d) SPrintf(sIdVersion, "[ C ] VS2013 build 21005"); else if (idVersion == 0x00e1520d) SPrintf(sIdVersion, "[C++] VS2013 build 21005"); else if (idVersion == 0x00db520d) SPrintf(sIdVersion, "[RES] VS2013 build 21005"); else if (idVersion == 0x00de520d) SPrintf(sIdVersion, "[LNK] VS2013 build 21005"); else if (idVersion == 0x00dc520d) SPrintf(sIdVersion, "[EXP] VS2013 build 21005"); else if (idVersion == 0x00dd520d) SPrintf(sIdVersion, "[IMP] VS2013 build 21005"); else if (idVersion == 0x00df520d) SPrintf(sIdVersion, "[ASM] VS2013 build 21005"); else if (idVersion == 0x00ceee66) SPrintf(sIdVersion, "[ C ] VS2012 UPD4 build 61030"); else if (idVersion == 0x00cfee66) SPrintf(sIdVersion, "[C++] VS2012 UPD4 build 61030"); else if (idVersion == 0x00cdee66) SPrintf(sIdVersion, "[ASM] VS2012 UPD4 build 61030"); else if (idVersion == 0x00c9ee66) SPrintf(sIdVersion, "[RES] VS2012 UPD4 build 61030"); else if (idVersion == 0x00ccee66) SPrintf(sIdVersion, "[LNK] VS2012 UPD4 build 61030"); else if (idVersion == 0x00caee66) SPrintf(sIdVersion, "[EXP] VS2012 UPD4 build 61030"); else if (idVersion == 0x00cbee66) SPrintf(sIdVersion, "[IMP] VS2012 UPD4 build 61030"); else if (idVersion == 0x00ceecc2) SPrintf(sIdVersion, "[ C ] VS2012 UPD3 build 60610"); else if (idVersion == 0x00cfecc2) SPrintf(sIdVersion, "[C++] VS2012 UPD3 build 60610"); else if (idVersion == 0x00cdecc2) SPrintf(sIdVersion, "[ASM] VS2012 UPD3 build 60610"); else if (idVersion == 0x00c9ecc2) SPrintf(sIdVersion, "[RES] VS2012 UPD3 build 60610"); else if (idVersion == 0x00ccecc2) SPrintf(sIdVersion, "[LNK] VS2012 UPD3 build 60610"); else if (idVersion == 0x00caecc2) SPrintf(sIdVersion, "[EXP] VS2012 UPD3 build 60610"); else if (idVersion == 0x00cbecc2) SPrintf(sIdVersion, "[IMP] VS2012 UPD3 build 60610"); else if (idVersion == 0x00ceeb9b) SPrintf(sIdVersion, "[ C ] VS2012 UPD2 build 60315"); else if (idVersion == 0x00cfeb9b) SPrintf(sIdVersion, "[C++] VS2012 UPD2 build 60315"); else if (idVersion == 0x00cdeb9b) SPrintf(sIdVersion, "[ASM] VS2012 UPD2 build 60315"); else if (idVersion == 0x00c9eb9b) SPrintf(sIdVersion, "[RES] VS2012 UPD2 build 60315"); else if (idVersion == 0x00cceb9b) SPrintf(sIdVersion, "[LNK] VS2012 UPD2 build 60315"); else if (idVersion == 0x00caeb9b) SPrintf(sIdVersion, "[EXP] VS2012 UPD2 build 60315"); else if (idVersion == 0x00cbeb9b) SPrintf(sIdVersion, "[IMP] VS2012 UPD2 build 60315"); else if (idVersion == 0x00cec7a2) SPrintf(sIdVersion, "[ C ] VS2012 UPD1 build 51106"); else if (idVersion == 0x00cfc7a2) SPrintf(sIdVersion, "[C++] VS2012 UPD1 build 51106"); else if (idVersion == 0x00cdc7a2) SPrintf(sIdVersion, "[ASM] VS2012 UPD1 build 51106"); else if (idVersion == 0x00c9c7a2) SPrintf(sIdVersion, "[RES] VS2012 UPD1 build 51106"); else if (idVersion == 0x00ccc7a2) SPrintf(sIdVersion, "[LNK] VS2012 UPD1 build 51106"); else if (idVersion == 0x00cac7a2) SPrintf(sIdVersion, "[EXP] VS2012 UPD1 build 51106"); else if (idVersion == 0x00cbc7a2) SPrintf(sIdVersion, "[IMP] VS2012 UPD1 build 51106"); else if (idVersion == 0x00cec627) SPrintf(sIdVersion, "[ C ] VS2012 build 50727"); else if (idVersion == 0x00cfc627) SPrintf(sIdVersion, "[C++] VS2012 build 50727"); else if (idVersion == 0x00c9c627) SPrintf(sIdVersion, "[RES] VS2012 build 50727"); else if (idVersion == 0x00cdc627) SPrintf(sIdVersion, "[ASM] VS2012 build 50727"); else if (idVersion == 0x00cac627) SPrintf(sIdVersion, "[EXP] VS2012 build 50727"); else if (idVersion == 0x00cbc627) SPrintf(sIdVersion, "[IMP] VS2012 build 50727"); else if (idVersion == 0x00ccc627) SPrintf(sIdVersion, "[LNK] VS2012 build 50727"); else if (idVersion == 0x00aa9d1b) SPrintf(sIdVersion, "[ C ] VS2010 SP1 build 40219"); else if (idVersion == 0x00ab9d1b) SPrintf(sIdVersion, "[C++] VS2010 SP1 build 40219"); else if (idVersion == 0x009d9d1b) SPrintf(sIdVersion, "[LNK] VS2010 SP1 build 40219"); else if (idVersion == 0x009a9d1b) SPrintf(sIdVersion, "[RES] VS2010 SP1 build 40219"); else if (idVersion == 0x009b9d1b) SPrintf(sIdVersion, "[EXP] VS2010 SP1 build 40219"); else if (idVersion == 0x009c9d1b) SPrintf(sIdVersion, "[IMP] VS2010 SP1 build 40219"); else if (idVersion == 0x009e9d1b) SPrintf(sIdVersion, "[ASM] VS2010 SP1 build 40219"); else if (idVersion == 0x00aa766f) SPrintf(sIdVersion, "[ C ] VS2010 build 30319"); else if (idVersion == 0x00ab766f) SPrintf(sIdVersion, "[C++] VS2010 build 30319"); else if (idVersion == 0x009d766f) SPrintf(sIdVersion, "[LNK] VS2010 build 30319"); else if (idVersion == 0x009a766f) SPrintf(sIdVersion, "[RES] VS2010 build 30319"); else if (idVersion == 0x009b766f) SPrintf(sIdVersion, "[EXP] VS2010 build 30319"); else if (idVersion == 0x009c766f) SPrintf(sIdVersion, "[IMP] VS2010 build 30319"); else if (idVersion == 0x009e766f) SPrintf(sIdVersion, "[ASM] VS2010 build 30319"); else if (idVersion == 0x00837809) SPrintf(sIdVersion, "[ C ] VS2008 SP1 build 30729"); else if (idVersion == 0x00847809) SPrintf(sIdVersion, "[C++] VS2008 SP1 build 30729"); else if (idVersion == 0x00957809) SPrintf(sIdVersion, "[ASM] VS2008 SP1 build 30729"); else if (idVersion == 0x00927809) SPrintf(sIdVersion, "[EXP] VS2008 SP1 build 30729"); else if (idVersion == 0x00937809) SPrintf(sIdVersion, "[IMP] VS2008 SP1 build 30729"); else if (idVersion == 0x00917809) SPrintf(sIdVersion, "[LNK] VS2008 SP1 build 30729"); else if (idVersion == 0x0083521e) SPrintf(sIdVersion, "[ C ] VS2008 build 21022"); else if (idVersion == 0x0084521e) SPrintf(sIdVersion, "[C++] VS2008 build 21022"); else if (idVersion == 0x0091521e) SPrintf(sIdVersion, "[LNK] VS2008 build 21022"); else if (idVersion == 0x0094521e) SPrintf(sIdVersion, "[RES] VS2008 build 21022"); else if (idVersion == 0x0092521e) SPrintf(sIdVersion, "[EXP] VS2008 build 21022"); else if (idVersion == 0x0093521e) SPrintf(sIdVersion, "[IMP] VS2008 build 21022"); else if (idVersion == 0x0095521e) SPrintf(sIdVersion, "[ASM] VS2008 build 21022"); else if (idVersion == 0x006dc627) SPrintf(sIdVersion, "[ C ] VS2005 build 50727"); else if (idVersion == 0x006ec627) SPrintf(sIdVersion, "[C++] VS2005 build 50727"); else if (idVersion == 0x0078c627) SPrintf(sIdVersion, "[LNK] VS2005 build 50727"); else if (idVersion == 0x007cc627) SPrintf(sIdVersion, "[RES] VS2005 build 50727"); else if (idVersion == 0x007ac627) SPrintf(sIdVersion, "[EXP] VS2005 build 50727"); else if (idVersion == 0x007bc627) SPrintf(sIdVersion, "[IMP] VS2005 build 50727"); else if (idVersion == 0x007dc627) SPrintf(sIdVersion, "[ASM] VS2005 build 50727"); else if (idVersion == 0x005f178e) SPrintf(sIdVersion, "[ C ] VS2003 (.NET) SP1 build 6030"); else if (idVersion == 0x0060178e) SPrintf(sIdVersion, "[C++] VS2003 (.NET) SP1 build 6030"); else if (idVersion == 0x005a178e) SPrintf(sIdVersion, "[LNK] VS2003 (.NET) SP1 build 6030"); else if (idVersion == 0x000f178e) SPrintf(sIdVersion, "[ASM] VS2003 (.NET) SP1 build 6030"); else if (idVersion == 0x005c178e) SPrintf(sIdVersion, "[EXP] VS2003 (.NET) SP1 build 6030"); else if (idVersion == 0x005d178e) SPrintf(sIdVersion, "[IMP] VS2003 (.NET) SP1 build 6030"); else if (idVersion == 0x005f0c05) SPrintf(sIdVersion, "[ C ] VS2003 (.NET) build 3077"); else if (idVersion == 0x00600c05) SPrintf(sIdVersion, "[C++] VS2003 (.NET) build 3077"); else if (idVersion == 0x000f0c05) SPrintf(sIdVersion, "[ASM] VS2003 (.NET) build 3077"); else if (idVersion == 0x005e0bec) SPrintf(sIdVersion, "[RES] VS2003 (.NET) build 3052"); else if (idVersion == 0x005c0c05) SPrintf(sIdVersion, "[EXP] VS2003 (.NET) build 3077"); else if (idVersion == 0x005d0c05) SPrintf(sIdVersion, "[IMP] VS2003 (.NET) build 3077"); else if (idVersion == 0x005a0c05) SPrintf(sIdVersion, "[LNK] VS2003 (.NET) build 3077"); else if (idVersion == 0x001c24fa) SPrintf(sIdVersion, "[ C ] VS2002 (.NET) build 9466"); else if (idVersion == 0x001d24fa) SPrintf(sIdVersion, "[C++] VS2002 (.NET) build 9466"); else if (idVersion == 0x004024fa) SPrintf(sIdVersion, "[ASM] VS2002 (.NET) build 9466"); else if (idVersion == 0x003d24fa) SPrintf(sIdVersion, "[LNK] VS2002 (.NET) build 9466"); else if (idVersion == 0x004524fa) SPrintf(sIdVersion, "[RES] VS2002 (.NET) build 9466"); else if (idVersion == 0x003f24fa) SPrintf(sIdVersion, "[EXP] VS2002 (.NET) build 9466"); else if (idVersion == 0x001924fa) SPrintf(sIdVersion, "[IMP] VS2002 (.NET) build 9466"); else if (idVersion == 0x000a2636) SPrintf(sIdVersion, "[ C ] VS98 (6.0) SP6 build 8804"); else if (idVersion == 0x000b2636) SPrintf(sIdVersion, "[C++] VS98 (6.0) SP6 build 8804"); else if (idVersion == 0x00152306) SPrintf(sIdVersion, "[ C ] VC++ 6.0 SP5 build 8804"); else if (idVersion == 0x00162306) SPrintf(sIdVersion, "[C++] VC++ 6.0 SP5 build 8804"); else if (idVersion == 0x000420ff) SPrintf(sIdVersion, "[LNK] VC++ 6.0 SP5 imp/exp build 8447"); else if (idVersion == 0x000606c7) SPrintf(sIdVersion, "[RES] VS98 (6.0) SP6 cvtres build 1736"); else if (idVersion == 0x000a1fe8) SPrintf(sIdVersion, "[ C ] VS98 (6.0) build 8168"); else if (idVersion == 0x000b1fe8) SPrintf(sIdVersion, "[C++] VS98 (6.0) build 8168"); else if (idVersion == 0x000606b8) SPrintf(sIdVersion, "[RES] VS98 (6.0) cvtres build 1720"); else if (idVersion == 0x00041fe8) SPrintf(sIdVersion, "[LNK] VS98 (6.0) imp/exp build 8168"); else if (idVersion == 0x00060684) SPrintf(sIdVersion, "[RES] VS97 (5.0) SP3 cvtres 5.00.1668"); else if (idVersion == 0x00021c87) SPrintf(sIdVersion, "[IMP] VS97 (5.0) SP3 link 5.10.7303"); else { local WORD id = idVersion >> 0x10; local WORD version = idVersion & 0xffff; SPrintf(sIdVersion, "id: %d version: %d", id, version); } return sIdVersion; } string ReadRichEntryIdVersion(DWORD& idVersionEncoded) { local DWORD idVersion = idVersionEncoded ^ DosStub.RichHeader.XorKey; local string sIdVersion = GetRichIdVersionString(idVersion); return sIdVersion; } string ReadRichEntryCount(DWORD& count) { local DWORD v = count ^ DosStub.RichHeader.XorKey; local string s; SPrintf(s, "count: %d", v); return s; } /**** COMMMENT UTILITY FUNCTIONS ****/ string LocationRVA(ULONG ulRVA) { local int i=0; for (i = 0; i < NtHeader.FileHeader.NumberOfSections; i++) { if ( (ulRVA >= SectionHeaders[i].VirtualAddress) && (ulRVA <= SectionHeaders[i].VirtualAddress + SectionHeaders[i].SizeOfRawData) ) { return SectionHeaders[i].Name; } } return ""; } string CommentRVA2FOA(DWORD dwRVA) { local string sComment = ""; if (0 != dwRVA) { SPrintf(sComment, "%s FOA = 0x%X \n", LocationRVA(dwRVA), RVA2FOA(dwRVA)); } return sComment; } string CommentRVAString(DWORD dwRVA) { local string sComment = ""; if (0 != dwRVA) { SPrintf(sComment, "%s FOA = 0x%X -> %s", LocationRVA(dwRVA), RVA2FOA(dwRVA), ReadString(RVA2FOA(dwRVA)) ); } return sComment; } string CommentImageImportByName(IMAGE_IMPORT_BY_NAME& ImportByName) { return ImportByName.Name; } string CommentExportByName(IMAGE_EXPORT_BY_NAME& ExportByName) { local string sComment = ""; if (0 == Strlen(ExportByName.sLocalJmpName)) { SPrintf(sComment, "0x%X", ExportByName.ulLocalDestRVA); } else { SPrintf(sComment, "%s", ExportByName.sLocalJmpName); } return sComment; } string CommentExportDirectory(IMAGE_EXPORT_DIRECTORY& ExportDir) { return ReadString(RVA2FOA(ExportDir.Name)); } string CommentBaseRelocBlock(BASE_RELOCATION_BLOCK& Block) { switch (Block.Type) { case IMAGE_REL_BASED_ABSOLUTE: return "ABSOLUTE"; case IMAGE_REL_BASED_HIGH: return "HIGH"; case IMAGE_REL_BASED_LOW: return "LOW"; case IMAGE_REL_BASED_HIGHLOW: return "HIGHLOW"; case IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ"; case IMAGE_REL_BASED_RESERVED: return "RESERVED"; case IMAGE_REL_BASED_DIR64: return "DIR64"; default: return "UNKNOWN"; } } string CommentImageBaseRelocation(IMAGE_BASE_RELOCATION& BaseReloc) { local string sComment = ""; SPrintf(sComment, "%d", BaseReloc.ulBlockNum); return sComment; } string CommentResourceNameOffset(DWORD& NameOffset) { local DWORD dwMaskedOffset = (NameOffset & 0x7fffffff); local wstring wsComment = L""; local string sComment = ""; local DWORD loc = RVA2FOA(NtHeader.OptionalHeader.DataDirArray.Resource.VirtualAddress) + dwMaskedOffset; local WORD actualLength = ReadUShort(loc); wsComment = ReadWString(loc + sizeof(WORD)); wsComment = WSubStr(wsComment, 0, actualLength); sComment = WStringToString(wsComment); return sComment; } short GetNameEntries(RESOURCE_DIRECTORY_TABLE& ResourceDirectoryTable) { return ResourceDirectoryTable.NumberOfNameEntries; } int GetLevel(RESOURCE_DIRECTORY_ENTRY& ResourceDirectoryEntry) { return ResourceDirectoryEntry.Level; } string GetType(DWORD& IntegerID) { local string sComment = ""; if (IntegerID == 0 || IntegerID > 255) SPrintf(sComment, "%d: Unknown", IntegerID); else if (IntegerID == 1) SPrintf(sComment, "%d: RT_CURSOR", IntegerID); else if (IntegerID == 2) SPrintf(sComment, "%d: RT_BITMAP", IntegerID); else if (IntegerID == 3) SPrintf(sComment, "%d: RT_ICON", IntegerID); else if (IntegerID == 4) SPrintf(sComment, "%d: RT_MENU", IntegerID); else if (IntegerID == 5) SPrintf(sComment, "%d: RT_DIALOG", IntegerID); else if (IntegerID == 6) SPrintf(sComment, "%d: RT_STRING", IntegerID); else if (IntegerID == 7) SPrintf(sComment, "%d: RT_FONTDIR", IntegerID); else if (IntegerID == 8) SPrintf(sComment, "%d: RT_FONT", IntegerID); else if (IntegerID == 9) SPrintf(sComment, "%d: RT_ACCELERATOR", IntegerID); else if (IntegerID == 10) SPrintf(sComment, "%d: RT_RCDATA", IntegerID); else if (IntegerID == 11) SPrintf(sComment, "%d: RT_MESSAGETABLE", IntegerID); else if (IntegerID == 12) SPrintf(sComment, "%d: RT_GROUP_CURSOR", IntegerID); else if (IntegerID == 13) SPrintf(sComment, "%d: Reserved", IntegerID); else if (IntegerID == 14) SPrintf(sComment, "%d: RT_GROUP_ICON", IntegerID); else if (IntegerID == 15) SPrintf(sComment, "%d: Reserved", IntegerID); else if (IntegerID == 16) SPrintf(sComment, "%d: RT_VERSION", IntegerID); else if (IntegerID == 17) SPrintf(sComment, "%d: RT_DLGINCLUDE", IntegerID); else if (IntegerID == 18) SPrintf(sComment, "%d: Reserved", IntegerID); else if (IntegerID == 19) SPrintf(sComment, "%d: RT_PLUGPLAY", IntegerID); else if (IntegerID == 20) SPrintf(sComment, "%d: RT_VXD", IntegerID); else if (IntegerID == 21) SPrintf(sComment, "%d: RT_ANICURSOR", IntegerID); else if (IntegerID == 22) SPrintf(sComment, "%d: RT_ANIICON", IntegerID); else if (IntegerID == 23) SPrintf(sComment, "%d: RT_HTML", IntegerID); else if (IntegerID == 24) SPrintf(sComment, "%d: RT_MANIFEST", IntegerID); else if (IntegerID < 256) SPrintf(sComment, "%d: Reserved", IntegerID); return sComment; } string CommentIntegerID(DWORD& IntegerID) { local string sComment = ""; local int level = GetLevel( parentof(IntegerID) ); switch(level) { case 1: sComment = "Type (" + GetType(IntegerID) + ")"; break; case 2: sComment = ""; break; case 3: sComment = "Language"; break; default: break; } return sComment; } string CommentResourceDirectoryString(RESOURCE_DIRECTORY_STRING& str) { local string sComment = ""; local DWORD loc = startof(str); local WORD actualLength = ReadShort(loc); local DWORD BlockNumber = GetEntryIntegerID( parentof(parentof(parentof(parentof(parentof(str))))) ); local int myIndex = 0; local DWORD blockStart = startof(parentof(str)); local DWORD curLoc = blockStart; while(curLoc != loc) { myIndex++; curLoc += 2*ReadUShort(curLoc)+sizeof(WORD); } local DWORD myStringID = (BlockNumber-1)*16+myIndex; if (actualLength > 0) { local wstring wsComment = ReadWString(startof(str) + sizeof(WORD)); wsComment = WSubStr(wsComment, 0, actualLength); SPrintf(sComment, "String ID #%d: %s", myStringID, WStringToString(wsComment)); } else { SPrintf(sComment, "String ID #%d: ", myStringID); } return sComment; } string CommentResourceDirectoryTable(RESOURCE_DIRECTORY_TABLE& ResourceDirectoryTable) { local string sComment = ""; local DWORD totalEntries = ResourceDirectoryTable.NumberOfNameEntries + ResourceDirectoryTable.NumberOfIDEntries; if (totalEntries == 1) { SPrintf(sComment, "Level %d, %d entry", ResourceDirectoryTable.Level, totalEntries); } else { SPrintf(sComment, "Level %d, %d entries", ResourceDirectoryTable.Level, totalEntries); } return sComment; } int GetEntryIntegerID(RESOURCE_DIRECTORY_ENTRY& ResourceDirectoryEntry) { return ResourceDirectoryEntry.IntegerID; } int GetEntryIsNameEntry(RESOURCE_DIRECTORY_ENTRY& ResourceDirectoryEntry) { return ResourceDirectoryEntry.IsNameEntry; } int GetParentTableLevel(RESOURCE_DIRECTORY_TABLE& ResourceDirectoryTable) { return ResourceDirectoryTable.Level; } int IsResourceDirectoryString(RESOURCE_DATA_ENTRY& ResourceDataEntry) { local int ParentTableLevel = GetParentTableLevel( parentof(parentof(ResourceDataEntry)) ); if (ParentTableLevel == 3) { local int BaseEntryIsNameEntry = GetEntryIsNameEntry( parentof(parentof(parentof(parentof(parentof(ResourceDataEntry)))))); if (BaseEntryIsNameEntry == 0) { local int BaseEntryIntegerID = GetEntryIntegerID( parentof(parentof(parentof(parentof(parentof(ResourceDataEntry)))))); if (BaseEntryIntegerID == 6) { return 1; } } } return 0; } string CommentBaseRelocationTable(BASE_RELOCATION_TABLE& RelocTable) { local string sComment = ""; SPrintf(sComment,"%d",RelocTable.ulRelocNum); return sComment; } /**** PARSING CODE ****/ LittleEndian(); Printf("EXE.bt Begin\n"); IMAGE_DOS_HEADER DosHeader ; if (DosHeader.MZSignature != 0x5A4D) { Printf("Invalid DOS Magic.\n"); return 1; } if (0 == DosHeader.AddressOfNewExeHeader ) { Warning("Invalid AddressOfNewExeHeader = 0x%X",DosHeader.AddressOfNewExeHeader); return 2; } IMAGE_DOS_STUB DosStub; FSeek(DosHeader.AddressOfNewExeHeader); IMAGE_NT_HEADERS NtHeader ; if (0x00004550 != NtHeader.Signature) { Printf("Invalid NT Signature 0x%x\n",NtHeader.Signature); return 3; } IMAGE_SECTION_HEADER SectionHeaders[NtHeader.FileHeader.NumberOfSections] ; // Unpadded header size local ULONG ulRawHeaderSize = DosHeader.AddressOfNewExeHeader + sizeof(NtHeader) + NtHeader.FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER); if (NtHeader.OptionalHeader.SizeOfHeaders - ulRawHeaderSize > 0) { UCHAR Space2[NtHeader.OptionalHeader.SizeOfHeaders - ulRawHeaderSize] ; } Printf("Space between headers and first sections is %d bytes\n", sizeof(Space2)); FSeek(NtHeader.OptionalHeader.SizeOfHeaders); local ULONG ulIndex=0; for (ulIndex=0; ulIndex < NtHeader.FileHeader.NumberOfSections; ulIndex++) { if ( 0 == SectionHeaders[ulIndex].PointerToRawData ) { continue; } if ( 0 == SectionHeaders[ulIndex].SizeOfRawData ) { continue; } IMAGE_SECTION_DATA Section(SectionHeaders[ulIndex]); } FSeek(NtHeader.OptionalHeader.SizeOfHeaders); // Parse IMAGE_DIRECTORY_ENTRIES ParseEAT(); ParseIAT(); ParseResource(); ParseException(); ParseSecurity(); ParseBaseReloc(); ParseDebug(); ParseTLS(); ParseBoundImport(); ParseDelayImport(); Printf("EXE.bt finished\n");