mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-27 23:37:04 -05:00
patterns: Added enhancements for PE pattern (#41)
The current pattern file for the PE format doesn't have a lot of the format's quirks, so I decided to code them in after I noticed that it doesn't cover the structure known as Rich Header. (Forgive the garbage code for its ProductType enum, it was the only way I found to make the values appear.) Here are my sources for the improvements included here: How the MZ header works and some of its variables' names: [How to determine the size of an PE executable file from headers and or footers](https://stackoverflow.com/questions/34684660/how-to-determine-the-size-of-an-pe-executable-file-from-headers-and-or-footers) The function of some of the MZ header variables: [https://github.com/corkami/pics/blob/master/binary/pe102.png](PE102 by Corkami) The existence of sections: [https://github.com/corkami/pics/blob/master/binary/pe101/pe101.png](PE101 by Corkami) The Machine values for LoongArch processors, the architecture enum and how it's used in the Optional Header, Subsystem types, DLL & Section characteristics, how sections, their line numbers and relocations work: [PE Format](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-rsrc-section) The Machine values for DECAlphaAXP and i860: [Peering Inside the PE: A Tour of the Win32 Portable Executable File Format](https://docs.microsoft.com/en-us/previous-versions/ms809762(v=msdn.10)#the-pe-header) How the Rich Header works: [https://www.virusbulletin.com/virusbulletin/2020/01/vb2019-paper-rich-headers-leveraging-mysterious-artifact-pe-format/](VB2019 paper: Rich Headers: leveraging this mysterious artifact of the PE format) Values of products in the Rich Header: [https://securelist.com/the-devils-in-the-rich-header/84348/](The devil’s in the Rich header) Every other value not found in the above source: Ghidra
This commit is contained in:
@@ -1,4 +1,10 @@
|
||||
#pragma MIME application/x-dosexec
|
||||
#pragma MIME application/x-msdownload
|
||||
#pragma pattern_limit 100000
|
||||
#pragma array_limit 10000
|
||||
#include <std/mem.pat>
|
||||
#include <std/string.pat>
|
||||
#include <std/ctype.pat>
|
||||
#include <std/io.pat>
|
||||
|
||||
enum MachineType : u16 {
|
||||
Unknown = 0x00,
|
||||
@@ -7,9 +13,13 @@ enum MachineType : u16 {
|
||||
ARM = 0x1C0,
|
||||
ARM64 = 0xAA64,
|
||||
ARMNT = 0x1C4,
|
||||
DECAlphaAXP = 0x183,
|
||||
EBC = 0xEBC,
|
||||
I386 = 0x14C,
|
||||
I860 = 0x14D,
|
||||
IA64 = 0x200,
|
||||
LOONGARCH32 = 0x6232,
|
||||
LOONGARCH64 = 0x6264,
|
||||
M32R = 0x9041,
|
||||
MIPS16 = 0x266,
|
||||
MIPSFPU = 0x366,
|
||||
@@ -28,32 +38,99 @@ enum MachineType : u16 {
|
||||
WCEMIPSV2 = 0x169
|
||||
};
|
||||
|
||||
enum PEFormat : u16 {
|
||||
PE32 = 0x10B,
|
||||
PE32Plus = 0x20B
|
||||
};
|
||||
|
||||
enum SubsystemType : u16 {
|
||||
Unknown = 0x00,
|
||||
Native = 0x01,
|
||||
WindowsGUI = 0x02,
|
||||
WindowsCUI = 0x03,
|
||||
OS2CUI = 0x05,
|
||||
POSIXCUI = 0x07,
|
||||
Windows9xNative = 0x08,
|
||||
WindowsCEGUI = 0x09,
|
||||
EFIApplication = 0x0A,
|
||||
EFIBootServiceDriver = 0x0B,
|
||||
EFIRuntimeDriver = 0x0C,
|
||||
EFIROM = 0x0D,
|
||||
Xbox = 0x0E,
|
||||
WindowsBootApplication = 0x10
|
||||
};
|
||||
|
||||
bitfield Characteristics {
|
||||
stripped : 1;
|
||||
relocationsStripped : 1;
|
||||
executableImage : 1;
|
||||
lineNumsStripped : 1;
|
||||
localSymsStripped : 1;
|
||||
lineNumbersStripped : 1;
|
||||
localSymbolsStripped : 1;
|
||||
aggressiveWsTrim : 1;
|
||||
largeAddressAware : 1;
|
||||
reserved : 1;
|
||||
bytesReversedLo : 1;
|
||||
is32BitMachine : 1;
|
||||
debugStripped : 1;
|
||||
debugInfoStripped : 1;
|
||||
removableRunFromSwap : 1;
|
||||
netRunFromSwap : 1;
|
||||
system : 1;
|
||||
dll : 1;
|
||||
upSystemOnly : 1;
|
||||
uniprocessorMachineOnly : 1;
|
||||
bytesReversedHi : 1;
|
||||
};
|
||||
} [[right_to_left]];
|
||||
|
||||
bitfield DLLCharacteristics {
|
||||
reserved : 4;
|
||||
padding : 1;
|
||||
highEntropyVA : 1;
|
||||
dynamicBase : 1;
|
||||
forceIntegrity : 1;
|
||||
nxCompatible : 1;
|
||||
noIsolation : 1;
|
||||
noSEH : 1;
|
||||
doNotBind : 1;
|
||||
appContainer : 1;
|
||||
wdmDriver : 1;
|
||||
cfGuard : 1;
|
||||
terminalServerAware : 1;
|
||||
} [[right_to_left]];
|
||||
|
||||
bitfield SectionFlags {
|
||||
reserved : 3;
|
||||
doNotPad : 1;
|
||||
reserved : 1;
|
||||
containsCode : 1;
|
||||
containsInitializedData : 1;
|
||||
containsUninitializedData : 1;
|
||||
linkOther : 1;
|
||||
comments : 1;
|
||||
reserved : 1;
|
||||
remove : 1;
|
||||
comdat : 1;
|
||||
padding : 2;
|
||||
globalPointerRelocation : 1;
|
||||
purgeable : 1;
|
||||
is16Bit : 1;
|
||||
locked : 1;
|
||||
preloaded : 1;
|
||||
dataAlignment : 4;
|
||||
extendedRelocations : 1;
|
||||
discardable : 1;
|
||||
notCacheable : 1;
|
||||
notPageable : 1;
|
||||
shared : 1;
|
||||
executed : 1;
|
||||
read : 1;
|
||||
writtenTo : 1;
|
||||
} [[right_to_left]];
|
||||
|
||||
struct DataDirectory {
|
||||
u32 virtualAddress;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct OptionalHeader32 {
|
||||
u16 magic;
|
||||
struct OptionalHeader {
|
||||
PEFormat magic;
|
||||
u8 majorLinkerVersion;
|
||||
u8 minorLinkerVersion;
|
||||
u32 sizeOfCode;
|
||||
@@ -61,8 +138,13 @@ struct OptionalHeader32 {
|
||||
u32 sizeOfUninitializedData;
|
||||
u32 addressOfEntryPoint;
|
||||
u32 baseOfCode;
|
||||
u32 baseOfData;
|
||||
u32 imageBase;
|
||||
if (magic == PEFormat::PE32) {
|
||||
u32 baseOfData;
|
||||
u32 imageBase;
|
||||
}
|
||||
else if (magic == PEFormat::PE32Plus) {
|
||||
u64 imageBase;
|
||||
}
|
||||
u32 sectionAlignment;
|
||||
u32 fileAlignment;
|
||||
u16 majorOperatingSystemVersion;
|
||||
@@ -75,87 +157,90 @@ struct OptionalHeader32 {
|
||||
u32 sizeOfImage;
|
||||
u32 sizeOfHeaders;
|
||||
u32 checksum;
|
||||
u16 subsystem;
|
||||
u16 dllCharacteristics;
|
||||
u32 sizeOfStackReserve;
|
||||
u32 sizeOfStackCommit;
|
||||
u32 sizeOfHeapReserve;
|
||||
u32 sizeOfHeapCommit;
|
||||
SubsystemType subsystem;
|
||||
DLLCharacteristics dllCharacteristics;
|
||||
if (magic == PEFormat::PE32) {
|
||||
u32 sizeOfStackReserve;
|
||||
u32 sizeOfStackCommit;
|
||||
u32 sizeOfHeapReserve;
|
||||
u32 sizeOfHeapCommit;
|
||||
}
|
||||
else if (magic == PEFormat::PE32Plus) {
|
||||
u64 sizeOfStackReserve;
|
||||
u64 sizeOfStackCommit;
|
||||
u64 sizeOfHeapReserve;
|
||||
u64 sizeOfHeapCommit;
|
||||
}
|
||||
u32 loaderFlags;
|
||||
u32 numberOfRvaAndSizes;
|
||||
DataDirectory directories[numberOfRvaAndSizes];
|
||||
u32 numberOfRVAsAndSizes;
|
||||
DataDirectory directories[numberOfRVAsAndSizes];
|
||||
};
|
||||
|
||||
struct OptionalHeader64 {
|
||||
u16 magic;
|
||||
u8 majorLinkerVersion;
|
||||
u8 minorLinkerVersion;
|
||||
u32 sizeOfCode;
|
||||
u32 sizeOfInitializedData;
|
||||
u32 sizeOfUninitializedData;
|
||||
u32 addressOfEntryPoint;
|
||||
u32 baseOfCode;
|
||||
u64 imageBase;
|
||||
u32 sectionAlignment;
|
||||
u32 fileAlignment;
|
||||
u16 majorOperatingSystemVersion;
|
||||
u16 minorOperatingSystemVersion;
|
||||
u16 majorImageVersion;
|
||||
u16 minorImageVersion;
|
||||
u16 majorSubsystemVersion;
|
||||
u16 minorSubSystemVersion;
|
||||
u32 win32VersionValue;
|
||||
u32 sizeOfImage;
|
||||
u32 sizeOfHeaders;
|
||||
u32 checksum;
|
||||
u16 subsystem;
|
||||
u16 dllCharacteristics;
|
||||
u64 sizeOfStackReserve;
|
||||
u64 sizeOfStackCommit;
|
||||
u64 sizeOfHeapReserve;
|
||||
u64 sizeOfHeapCommit;
|
||||
u32 loaderFlags;
|
||||
u32 numberOfRvaAndSizes;
|
||||
DataDirectory directories[numberOfRvaAndSizes];
|
||||
};
|
||||
|
||||
struct COFFHeader {
|
||||
u32 signature;
|
||||
struct COFFHeader {
|
||||
char signature[4];
|
||||
MachineType machine;
|
||||
u16 numberOfSections;
|
||||
u32 timeDateStamp;
|
||||
u32 pointerToSymbolTable;
|
||||
u32 numberOfSymbolTable;
|
||||
u32 numberOfSymbols;
|
||||
u16 sizeOfOptionalHeader;
|
||||
Characteristics characteristics;
|
||||
|
||||
if (machine == MachineType::AMD64) {
|
||||
OptionalHeader64 optionalHeader;
|
||||
} else {
|
||||
OptionalHeader32 optionalHeader;
|
||||
|
||||
if (sizeOfOptionalHeader > 0x00) {
|
||||
OptionalHeader optionalHeader;
|
||||
}
|
||||
};
|
||||
|
||||
struct DOSHeader {
|
||||
u16 signature;
|
||||
u8 header[0x3A];
|
||||
COFFHeader *coffHeaderPointer : u32;
|
||||
char signature[2];
|
||||
u16 lastPageSize;
|
||||
u16 numberOfPages;
|
||||
u16 relocations;
|
||||
u16 headerSizeInParagraphs;
|
||||
u16 minimumAllocatedParagraphs;
|
||||
u16 maximumAllocatedParagraphs;
|
||||
u16 initialSSValue;
|
||||
u16 initialRelativeSPValue;
|
||||
u16 checksum;
|
||||
u16 initialRelativeIPValue;
|
||||
u16 initialCSValue;
|
||||
u16 relocationsTablePointer;
|
||||
u16 overlayNumber;
|
||||
u16 reservedWords[4];
|
||||
u16 oemIdentifier;
|
||||
u16 oemInformation;
|
||||
u16 reservedWords[10];
|
||||
u32 coffHeaderPointer;
|
||||
};
|
||||
|
||||
fn isdosmessage(char c) {
|
||||
return std::ctype::isalnum(c) || c == '.' || c == ' ';
|
||||
};
|
||||
|
||||
struct DOSStub {
|
||||
u8 code[14];
|
||||
s8 message[0x27];
|
||||
u8 data[11];
|
||||
u8 code[while(std::mem::read_string($, 4) != "This")];
|
||||
char message[while(isdosmessage(std::mem::read_unsigned($, 1)))];
|
||||
char data[while(std::mem::read_unsigned($, 1) != 0x00)];
|
||||
};
|
||||
|
||||
union SectionMisc {
|
||||
u32 physicalAddress;
|
||||
u32 virtualSize;
|
||||
struct PEHeader {
|
||||
DOSHeader dosHeader;
|
||||
if (dosHeader.headerSizeInParagraphs * 16 < std::mem::size()) {
|
||||
DOSStub dosStub @ dosHeader.headerSizeInParagraphs * 16;
|
||||
}
|
||||
};
|
||||
|
||||
struct Section {
|
||||
PEHeader peHeader @ 0x00;
|
||||
|
||||
COFFHeader coffHeader @ peHeader.dosHeader.coffHeaderPointer;
|
||||
|
||||
struct SectionHeader {
|
||||
char name[8];
|
||||
SectionMisc misc;
|
||||
if (coffHeader.characteristics.executableImage) {
|
||||
u32 virtualSize;
|
||||
} else {
|
||||
u32 physicalAddress;
|
||||
}
|
||||
u32 virtualAddress;
|
||||
u32 sizeOfRawData;
|
||||
u32 ptrRawData;
|
||||
@@ -163,15 +248,436 @@ struct Section {
|
||||
u32 ptrLineNumbers;
|
||||
u16 numberOfRelocations;
|
||||
u16 numberOfLineNumbers;
|
||||
SectionFlags characteristics;
|
||||
};
|
||||
|
||||
SectionHeader sectionTable[coffHeader.numberOfSections] @ (addressof(coffHeader.characteristics) + 2) + coffHeader.sizeOfOptionalHeader;
|
||||
|
||||
u16 currentSectionIndex;
|
||||
fn updateSectionIndex() {
|
||||
currentSectionIndex = currentSectionIndex + 1;
|
||||
};
|
||||
|
||||
struct NullTerminatedString {
|
||||
char string[while(std::mem::read_unsigned($, 1) != 0x00)];
|
||||
padding[1];
|
||||
} [[inline]];
|
||||
|
||||
// Declarations of sections and variables used by it
|
||||
// Imports + Readonly Data Section
|
||||
struct DirectoryTable {
|
||||
u32 lookupTableRVA;
|
||||
u32 timeDateStamp;
|
||||
u32 forwarderChain;
|
||||
u32 dllNameRVA;
|
||||
u32 addressTableRVA;
|
||||
};
|
||||
|
||||
struct ImportsSection {
|
||||
DirectoryTable directoryTables[while(std::mem::read_unsigned($, 16) != 0x00)];
|
||||
DirectoryTable nullDirectoryTable;
|
||||
};
|
||||
|
||||
struct ReadonlyDataSection {
|
||||
u8 readonlyDataStart[while($ < coffHeader.optionalHeader.directories[1].virtualAddress - (sectionTable[currentSectionIndex].virtualAddress - sectionTable[currentSectionIndex].ptrRawData))];
|
||||
ImportsSection importsSection;
|
||||
u8 readonlyDataEnd[while($ < sectionTable[currentSectionIndex+1].ptrRawData)];
|
||||
};
|
||||
|
||||
// Resource Section
|
||||
struct ResourceDirectoryTable {
|
||||
u32 characteristics;
|
||||
u32 timeDateStamp;
|
||||
u16 majorVersion;
|
||||
u16 minorVersion;
|
||||
u16 nameEntriesAmount;
|
||||
u16 idEntriesAmount;
|
||||
};
|
||||
|
||||
enum ResourceID : u32 {
|
||||
Bitmap = 0x02,
|
||||
Icon = 0x03,
|
||||
Menu = 0x04,
|
||||
Dialog = 0x05,
|
||||
String = 0x06,
|
||||
GroupIcon = 0x0D,
|
||||
Version = 0x10,
|
||||
Manifest = 0x18
|
||||
};
|
||||
|
||||
struct IdDirectoryEntry {
|
||||
ResourceID id;
|
||||
u32 relativeOffsetToData;
|
||||
};
|
||||
|
||||
struct ResourceDirectory {
|
||||
ResourceDirectoryTable resourceDirectoryTable;
|
||||
IdDirectoryEntry idEntries[resourceDirectoryTable.idEntriesAmount];
|
||||
};
|
||||
|
||||
struct ResourceSection {
|
||||
ResourceDirectory rootDirectory;
|
||||
};
|
||||
|
||||
// Exports Section
|
||||
struct ExportDirectoryTable {
|
||||
u32 exportFlags;
|
||||
u32 timeDateStamp;
|
||||
u16 majorVersion;
|
||||
u16 minorVersion;
|
||||
u32 nameRVA;
|
||||
u32 ordinalBase;
|
||||
u32 addressTableEntries;
|
||||
u32 numberOfNamePointers;
|
||||
u32 exportAddressTableRVA;
|
||||
u32 namePointerRVA;
|
||||
u32 ordinalTableRVA;
|
||||
};
|
||||
|
||||
struct ExportAddress {
|
||||
if (std::mem::read_unsigned($, 4) > sectionTable[currentSectionIndex].sizeOfRawData && std::mem::read_unsigned($, 4) < sectionTable[currentSectionIndex].ptrRawData) {
|
||||
u32 exportRVA;
|
||||
}
|
||||
else {
|
||||
u32 forwarderRVA;
|
||||
}
|
||||
};
|
||||
|
||||
struct ExportsSection {
|
||||
ExportDirectoryTable exportDirectoryTable;
|
||||
ExportAddress exportAddressTable[exportDirectoryTable.addressTableEntries];
|
||||
u32 exportNamePointerTable[exportDirectoryTable.numberOfNamePointers];
|
||||
};
|
||||
|
||||
// Exception Section
|
||||
bitfield ExceptionSectionBits {
|
||||
functionLength : 22;
|
||||
instructions32Bit : 1;
|
||||
exceptionHandler : 1;
|
||||
} [[right_to_left]];
|
||||
|
||||
struct FunctionTableEntry {
|
||||
if (coffHeader.machine == MachineType::MIPSFPU) {
|
||||
u32 beginVA;
|
||||
u32 endVA;
|
||||
u32 exceptionHandlerPointer;
|
||||
u32 handlerDataPointer;
|
||||
u32 prologEndVA;
|
||||
} else if (coffHeader.machine == MachineType::ARM || MachineType::ARM64 || MachineType::ARMNT || MachineType::POWERPC || MachineType::POWERPCFP || MachineType::SH3 || MachineType::SH4) {
|
||||
u32 beginVA;
|
||||
u8 prologLength;
|
||||
ExceptionSectionBits miscellaneousBits;
|
||||
} else if (coffHeader.machine == MachineType::AMD64 || MachineType::IA64) {
|
||||
u32 beginRVA;
|
||||
u32 endRVA;
|
||||
u32 unwindInformationRVA;
|
||||
}
|
||||
};
|
||||
|
||||
struct ExceptionSection {
|
||||
FunctionTableEntry functionTableEntries[while($ < sectionTable[currentSectionIndex].ptrRawData + sectionTable[currentSectionIndex].sizeOfRawData)];
|
||||
};
|
||||
|
||||
// TLS Section
|
||||
struct TLSSection {
|
||||
if (coffHeader.optionalHeader.magic == PEFormat::PE32) {
|
||||
u32 rawDataStartVA;
|
||||
u32 rawDataEndVA;
|
||||
u32 indexAddress;
|
||||
u32 callbacksAddress;
|
||||
}
|
||||
else if (coffHeader.optionalHeader.magic == PEFormat::PE32Plus) {
|
||||
u64 rawDataStartVA;
|
||||
u64 rawDataEndVA;
|
||||
u64 indexAddress;
|
||||
u64 callbacksAddress;
|
||||
}
|
||||
u32 zeroFillSize;
|
||||
u32 characteristics;
|
||||
};
|
||||
|
||||
struct PEHeader {
|
||||
DOSHeader dosHeader;
|
||||
DOSStub dosStub;
|
||||
// Relocations Section
|
||||
bitfield RelocationWord {
|
||||
type : 4;
|
||||
offset : 12;
|
||||
};
|
||||
|
||||
PEHeader peHeader @ 0x00;
|
||||
struct BaseRelocationBlock {
|
||||
u32 pageRVA;
|
||||
u32 blockSize;
|
||||
RelocationWord word;
|
||||
};
|
||||
|
||||
Section sectionsTable[peHeader.dosHeader.coffHeaderPointer.numberOfSections]
|
||||
@ addressof(peHeader.dosHeader.coffHeaderPointer) + sizeof(peHeader.dosHeader.coffHeaderPointer);
|
||||
struct BaseRelocationTable {
|
||||
BaseRelocationBlock baseRelocationBlocks[while(std::mem::read_unsigned($, 8) != 0x00)];
|
||||
};
|
||||
|
||||
// General Section things
|
||||
enum I386Relocations : u16 {
|
||||
Absolute = 0x00,
|
||||
Dir16 = 0x01,
|
||||
Rel16 = 0x02,
|
||||
Dir32 = 0x06
|
||||
};
|
||||
|
||||
struct Relocation {
|
||||
u32 virtualAddress;
|
||||
u32 symbolTableIndex;
|
||||
if (coffHeader.machine == MachineType::I386) {
|
||||
I386Relocations type;
|
||||
}
|
||||
else {
|
||||
u16 type;
|
||||
}
|
||||
};
|
||||
|
||||
struct LineNumber {
|
||||
u32 lineNumber @ $ + 4;
|
||||
if (lineNumber > 0x00) {
|
||||
u32 virtualAddress @ $ - 8;
|
||||
} else {
|
||||
u32 symbolTableIndex @ $ - 8;
|
||||
}
|
||||
$ += 8;
|
||||
};
|
||||
|
||||
fn importsSectionExists() {
|
||||
bool returnedValue = false;
|
||||
std::print("Checking which section is .idata for read-only data section");
|
||||
for (u16 i = 0, i < coffHeader.numberOfSections, i = i + 1) {
|
||||
std::print("Checking section " + std::string::to_string(i));
|
||||
if (sectionTable[i].name == ".idata") {
|
||||
std::print("Check successful. Section " + std::string::to_string(i) + " is .idata, so the read-only data section won't have an imports section in it");
|
||||
returnedValue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!returnedValue) {
|
||||
std::print("Check failed! This means there is no separate imports section");
|
||||
}
|
||||
return returnedValue;
|
||||
};
|
||||
|
||||
struct Section {
|
||||
if (std::string::starts_with(sectionTable[currentSectionIndex].name, ".pdata")) { // Exception section
|
||||
ExceptionSection exceptionSection;
|
||||
}
|
||||
else if (std::string::starts_with(sectionTable[currentSectionIndex].name, ".rdata")) {// Read-only data section
|
||||
if (importsSectionExists() || coffHeader.optionalHeader.directories[1].size == 0) {
|
||||
u8 readonlyDataSection[sectionTable[currentSectionIndex].sizeOfRawData];
|
||||
}
|
||||
else {
|
||||
ReadonlyDataSection readonlyDataSection;
|
||||
}
|
||||
}
|
||||
else if (std::string::starts_with(sectionTable[currentSectionIndex].name, ".idata")) {// Imports section
|
||||
ImportsSection importsSection;
|
||||
}
|
||||
else if (std::string::starts_with(sectionTable[currentSectionIndex].name, ".edata")) {// Exports section
|
||||
ExportsSection exportsSection;
|
||||
}
|
||||
else if (std::string::starts_with(sectionTable[currentSectionIndex].name, ".rsrc")) { // Resource section
|
||||
ResourceSection resourceSection;
|
||||
}
|
||||
else if (std::string::starts_with(sectionTable[currentSectionIndex].name, ".tls")) { // Thread-local storage section
|
||||
TLSSection tlsSection;
|
||||
}
|
||||
else if (std::string::starts_with(sectionTable[currentSectionIndex].name, ".reloc")) {// Thread-local storage section
|
||||
BaseRelocationTable relocationsSection;
|
||||
}
|
||||
else {
|
||||
u8 freeformSection[sectionTable[currentSectionIndex].sizeOfRawData]; // Freeform data section
|
||||
}
|
||||
|
||||
// Additional things
|
||||
//Relocation relocations[sectionTable[currentSectionIndex].numberOfRelocations] @ sectionTable[currentSectionIndex].ptrRelocations;
|
||||
LineNumber lineNumbers[sectionTable[currentSectionIndex].numberOfLineNumbers] @ sectionTable[currentSectionIndex].ptrLineNumbers;
|
||||
|
||||
// Next section
|
||||
if (currentSectionIndex < coffHeader.numberOfSections-1) { // If it's not the last section (to avoid problems this code would have with it)
|
||||
updateSectionIndex(); // Make the current section index the next section's index
|
||||
if (sectionTable[currentSectionIndex].sizeOfRawData > 0) { // If the size of this section is bigger than 0
|
||||
$ = sectionTable[currentSectionIndex].ptrRawData; // Put the current offset at the start of the next section
|
||||
}
|
||||
}
|
||||
} [[inline]];
|
||||
|
||||
Section sections[coffHeader.numberOfSections] @ sectionTable[0].ptrRawData;
|
||||
|
||||
// Symbol & String Tables
|
||||
enum SectionNumberType : s16 {
|
||||
Undefined = 0,
|
||||
Absolute = -1,
|
||||
Debug = -2
|
||||
};
|
||||
|
||||
enum SymbolTypeMSB : u8 {
|
||||
Null = 0x00,
|
||||
Pointer = 0x10,
|
||||
Function = 0x20,
|
||||
Array = 0x30
|
||||
};
|
||||
|
||||
enum SymbolTypeLSB : u8 {
|
||||
Null = 0x00,
|
||||
Void = 0x01,
|
||||
Char = 0x02,
|
||||
Short = 0x03,
|
||||
Integer = 0x04,
|
||||
Long = 0x05,
|
||||
Float = 0x06,
|
||||
Double = 0x07,
|
||||
Struct = 0x08,
|
||||
Union = 0x09,
|
||||
Enum = 0x0A,
|
||||
MemberOfEnum = 0x0B,
|
||||
Byte = 0x0C,
|
||||
Word = 0x0D,
|
||||
UInt = 0x0E,
|
||||
DWord = 0x0F
|
||||
};
|
||||
|
||||
enum StorageClassType : s8 {
|
||||
EndOfFunction = -1,
|
||||
Null = 0,
|
||||
Automatic = 1,
|
||||
External = 2,
|
||||
Static = 3,
|
||||
Register = 4,
|
||||
DefinedExternally = 5,
|
||||
Label = 6,
|
||||
UndefinedLabel = 7,
|
||||
MemberOfStruct = 8,
|
||||
Argument = 9,
|
||||
StructTag = 10,
|
||||
MemberOfUnion = 11,
|
||||
UnionTag = 12,
|
||||
TypeDefinition = 13,
|
||||
UndefinedStatic = 14,
|
||||
EnumTag = 15,
|
||||
MemberOfEnum = 16,
|
||||
RegisterParameter = 17,
|
||||
Bitfield = 18,
|
||||
Block = 100,
|
||||
BlockFunction = 101,
|
||||
EndOfStruct = 102,
|
||||
File = 103,
|
||||
Section = 104,
|
||||
WeakExternal = 105,
|
||||
CLRToken = 107
|
||||
};
|
||||
|
||||
struct SymbolNameAddress {
|
||||
u32 zeroes;
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
struct SymbolName {
|
||||
if (std::mem::read_unsigned($, 4) == 0) {
|
||||
SymbolNameAddress nameAddress;
|
||||
}
|
||||
else {
|
||||
char shortName[8];
|
||||
}
|
||||
};
|
||||
|
||||
struct SymbolType {
|
||||
SymbolTypeMSB msb;
|
||||
SymbolTypeLSB lsb;
|
||||
};
|
||||
|
||||
struct Symbol {
|
||||
SymbolName name;
|
||||
u32 value;
|
||||
SectionNumberType sectionNumber;
|
||||
SymbolType type;
|
||||
StorageClassType storageClass;
|
||||
u8 numberOfAuxSymbols;
|
||||
};
|
||||
|
||||
Symbol symbolTable[coffHeader.numberOfSymbols] @ coffHeader.pointerToSymbolTable;
|
||||
|
||||
struct StringTable {
|
||||
u32 size;
|
||||
NullTerminatedString strings[while($ < addressof(this) + size)];
|
||||
} [[inline]];
|
||||
|
||||
StringTable stringTable[coffHeader.numberOfSymbols > 0] @ addressof(symbolTable) + sizeof(symbolTable);
|
||||
|
||||
// Rich Header
|
||||
enum ProductType : u16 {
|
||||
Unmarked = 0x00 ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
Imports = 0x01 ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
STDLIBDLL = 0x04 ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC6CVTRes = 0x06 ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC6CCompiler = 0x0A ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC6CPPCompiler = 0x0B ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
OldNames = 0x0C ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
MASM613 = 0x0E ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC2003Assembler = 0x0F ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC2002Linker = 0x19 ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC2002CCompiler = 0x1C ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC2002CPPCompiler = 0x1D ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC2003SDKIMP = 0x5D ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC2003CPPCompiler = 0x60 ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC2008SDKIMP = 0x93 ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
Linker12 = 0x9D ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
MASM10 = 0x9E ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC2010CCompiler = 0xAA ^ richHeaderEnd[0].mask.maskArray[1],
|
||||
VC2010CPPCompiler = 0xAB ^ richHeaderEnd[0].mask.maskArray[1]
|
||||
};
|
||||
|
||||
union RichHeaderMask {
|
||||
u32 maskVariable;
|
||||
u16 maskArray[2];
|
||||
};
|
||||
|
||||
struct RichHeaderEnd {
|
||||
char signature[4];
|
||||
RichHeaderMask mask;
|
||||
} [[inline]];
|
||||
|
||||
u8 richHeaderAmount;
|
||||
u8 richHeaderEndPosition;
|
||||
u8 richHeaderCorpusPosition;
|
||||
fn initializeRichHeader() {
|
||||
$ = sizeof(peHeader);
|
||||
while ($ < peHeader.dosHeader.coffHeaderPointer) {
|
||||
if (std::mem::read_string($, 4) == "Rich") {
|
||||
richHeaderAmount = 1;
|
||||
richHeaderEndPosition = $;
|
||||
break;
|
||||
}
|
||||
$ += 1;
|
||||
}
|
||||
};
|
||||
initializeRichHeader();
|
||||
|
||||
RichHeaderEnd richHeaderEnd[richHeaderAmount] @ richHeaderEndPosition;
|
||||
|
||||
struct Product {
|
||||
u16 buildNumber;
|
||||
ProductType productID;
|
||||
u32 objectCount;
|
||||
};
|
||||
|
||||
struct RichHeaderCorpus {
|
||||
char maskedSignature[4];
|
||||
u32 nullPadding[3];
|
||||
Product products[while($ != richHeaderEndPosition)];
|
||||
} [[inline]];
|
||||
|
||||
fn setupRichHeader() {
|
||||
if (richHeaderAmount > 0) {
|
||||
//0x20 is the size of a Rich Header with one product
|
||||
for (u8 richCursor = $ - 0x20, richCursor > sizeof(peHeader), richCursor = richCursor - 0x01) {
|
||||
if (str(std::mem::read_unsigned(richCursor, 4) ^ richHeaderEnd[0].mask.maskVariable) == "DanS") {
|
||||
richHeaderCorpusPosition = richCursor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
setupRichHeader();
|
||||
|
||||
RichHeaderCorpus richHeaderCorpus[richHeaderAmount] @ richHeaderCorpusPosition;
|
||||
|
||||
Reference in New Issue
Block a user