From e690c6d0ffc27bc3ecfb5d25c1eb312beb0bf5ed Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 9 Nov 2022 22:23:40 -0800 Subject: [PATCH] Add PE .edata components (not hooked up) This also does a pretty major cleanup of TODOs --- BurnOutSharp.Builder/Extensions.cs | 2 - .../PortableExecutable/Executable.cs | 16 +++---- .../ExportNamePointerTable.cs | 18 ++++++++ .../PortableExecutable/ExportNameTable.cs | 27 ++++++++++++ .../PortableExecutable/ExportOrdinalTable.cs | 42 +++++++++++++++++++ 5 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 BurnOutSharp.Models/PortableExecutable/ExportNamePointerTable.cs create mode 100644 BurnOutSharp.Models/PortableExecutable/ExportNameTable.cs create mode 100644 BurnOutSharp.Models/PortableExecutable/ExportOrdinalTable.cs diff --git a/BurnOutSharp.Builder/Extensions.cs b/BurnOutSharp.Builder/Extensions.cs index 3ad2a3eb..768fa31d 100644 --- a/BurnOutSharp.Builder/Extensions.cs +++ b/BurnOutSharp.Builder/Extensions.cs @@ -665,7 +665,6 @@ namespace BurnOutSharp.Builder stringData.Value = entry.Data.ReadString(ref offset, Encoding.Unicode); - // TODO: Is this necessary? while ((offset % 4) != 0) _ = entry.Data.ReadUInt16(ref offset); @@ -780,7 +779,6 @@ namespace BurnOutSharp.Builder stringData.Value = entry.Data.ReadString(ref offset, Encoding.Unicode); - // TODO: Is this necessary? while ((offset % 4) != 0) _ = entry.Data.ReadUInt16(ref offset); diff --git a/BurnOutSharp.Models/PortableExecutable/Executable.cs b/BurnOutSharp.Models/PortableExecutable/Executable.cs index 9e5cde81..77899a6e 100644 --- a/BurnOutSharp.Models/PortableExecutable/Executable.cs +++ b/BurnOutSharp.Models/PortableExecutable/Executable.cs @@ -72,28 +72,24 @@ namespace BurnOutSharp.Models.PortableExecutable #endregion // TODO: Implement and/or document the following non-modeled parts: - // - Certificate Data // - Delay Import Address Table // - Delay Import Name Table // - Delay Bound Import Address Table // - Delay Unload Import Address Table // - The .debug Section - // - IMAGE_DEBUG_TYPE_FPO - // - .debug$F (Object Only) - // - .debug$S (Object Only) - // - .debug$P (Object Only) - // - .debug$T (Object Only) + // - .debug$F (Object Only) / IMAGE_DEBUG_TYPE_FPO // - The .drectve Section (Object Only) // - The .edata Section (Image Only) - // - Export Name Pointer Table - // - Export Ordinal Table - // - Export Name Table + // - [Export directory table] + // - [Export address table] + // - [Export Name Pointer Table] + // - [Export Ordinal Table] + // - [Export Name Table] // - The .idata Section // - Import Lookup Table [has model, but bit-based] // - Import Address Table // - The .pdata Section [Multiple formats per entry] // - TLS Callback Functions - // - The .rsrc Section // - The .cormeta Section (Object Only) // - The .sxdata Section diff --git a/BurnOutSharp.Models/PortableExecutable/ExportNamePointerTable.cs b/BurnOutSharp.Models/PortableExecutable/ExportNamePointerTable.cs new file mode 100644 index 00000000..723cf5ad --- /dev/null +++ b/BurnOutSharp.Models/PortableExecutable/ExportNamePointerTable.cs @@ -0,0 +1,18 @@ +namespace BurnOutSharp.Models.PortableExecutable +{ + /// + /// The export name pointer table is an array of addresses (RVAs) into the export name table. + /// The pointers are 32 bits each and are relative to the image base. The pointers are ordered + /// lexically to allow binary searches. + /// + /// An export name is defined only if the export name pointer table contains a pointer to it. + /// + /// + public class ExportNamePointerTable + { + /// + /// The pointers are 32 bits each and are relative to the image base. + /// + public uint[] Pointers; + } +} diff --git a/BurnOutSharp.Models/PortableExecutable/ExportNameTable.cs b/BurnOutSharp.Models/PortableExecutable/ExportNameTable.cs new file mode 100644 index 00000000..671f8a54 --- /dev/null +++ b/BurnOutSharp.Models/PortableExecutable/ExportNameTable.cs @@ -0,0 +1,27 @@ +namespace BurnOutSharp.Models.PortableExecutable +{ + /// + /// The export name table contains the actual string data that was pointed to by the export + /// name pointer table. The strings in this table are public names that other images can use + /// to import the symbols. These public export names are not necessarily the same as the + /// private symbol names that the symbols have in their own image file and source code, + /// although they can be. + /// + /// Every exported symbol has an ordinal value, which is just the index into the export + /// address table. Use of export names, however, is optional. Some, all, or none of the + /// exported symbols can have export names. For exported symbols that do have export names, + /// corresponding entries in the export name pointer table and export ordinal table work + /// together to associate each name with an ordinal. + /// + /// The structure of the export name table is a series of null-terminated ASCII strings + /// of variable length. + /// + /// + public class ExportNameTable + { + /// + /// A series of null-terminated ASCII strings of variable length. + /// + public string[] Indexes; + } +} diff --git a/BurnOutSharp.Models/PortableExecutable/ExportOrdinalTable.cs b/BurnOutSharp.Models/PortableExecutable/ExportOrdinalTable.cs new file mode 100644 index 00000000..a4a686a5 --- /dev/null +++ b/BurnOutSharp.Models/PortableExecutable/ExportOrdinalTable.cs @@ -0,0 +1,42 @@ +namespace BurnOutSharp.Models.PortableExecutable +{ + /// + /// The export ordinal table is an array of 16-bit unbiased indexes into the export address table. + /// Ordinals are biased by the Ordinal Base field of the export directory table. In other words, + /// the ordinal base must be subtracted from the ordinals to obtain true indexes into the export + /// address table. + /// + /// The export name pointer table and the export ordinal table form two parallel arrays that are + /// separated to allow natural field alignment. These two tables, in effect, operate as one table, + /// in which the Export Name Pointer column points to a public (exported) name and the Export + /// Ordinal column gives the corresponding ordinal for that public name. A member of the export + /// name pointer table and a member of the export ordinal table are associated by having the same + /// position (index) in their respective arrays. + /// + /// Thus, when the export name pointer table is searched and a matching string is found at position + /// i, the algorithm for finding the symbol's RVA and biased ordinal is: + /// + /// i = Search_ExportNamePointerTable(name); + /// ordinal = ExportOrdinalTable[i]; + /// + /// rva = ExportAddressTable[ordinal]; + /// biased_ordinal = ordinal + OrdinalBase; + /// + /// When searching for a symbol by(biased) ordinal, the algorithm for finding the symbol's RVA + /// and name is: + /// + /// ordinal = biased_ordinal - OrdinalBase; + /// i = Search_ExportOrdinalTable(ordinal); + /// + /// rva = ExportAddressTable[ordinal]; + /// name = ExportNameTable[i]; + /// + /// + public class ExportOrdinalTable + { + /// + /// An array of 16-bit unbiased indexes into the export address table + /// + public ushort[] Indexes; + } +}