From 9411f5044a66b0373db23e03137fa4dae6caf1ba Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 5 Dec 2022 13:52:15 -0800 Subject: [PATCH] Fix import table parsing --- BurnOutSharp.Builder/PortableExecutable.cs | 121 +++++++++++++----- .../ImportAddressTableEntry.cs | 20 ++- BurnOutSharp.Wrappers/PortableExecutable.cs | 9 +- 3 files changed, 109 insertions(+), 41 deletions(-) diff --git a/BurnOutSharp.Builder/PortableExecutable.cs b/BurnOutSharp.Builder/PortableExecutable.cs index b8b28179..8e4e0d3c 100644 --- a/BurnOutSharp.Builder/PortableExecutable.cs +++ b/BurnOutSharp.Builder/PortableExecutable.cs @@ -1067,46 +1067,73 @@ namespace BurnOutSharp.Builder continue; int tableAddress = (int)importDirectoryTableEntry.ImportAddressTableRVA.ConvertVirtualAddress(sections); - var entryAddressTable = new List(); + var addressLookupTable = new List(); while (true) { - var entryLookupTableEntry = new ImportAddressTableEntry(); + var addressLookupTableEntry = new ImportAddressTableEntry(); if (magic == OptionalHeaderMagicNumber.PE32) { uint entryValue = data.ReadUInt32(ref tableAddress); - entryLookupTableEntry.Address_PE32 = entryValue; + addressLookupTableEntry.OrdinalNameFlag = (entryValue & 0x80000000) != 0; + if (addressLookupTableEntry.OrdinalNameFlag) + addressLookupTableEntry.OrdinalNumber = (ushort)(entryValue & ~0x80000000); + else + addressLookupTableEntry.HintNameTableRVA = (uint)(entryValue & ~0x80000000); } else if (magic == OptionalHeaderMagicNumber.PE32Plus) { ulong entryValue = data.ReadUInt64(ref tableAddress); - entryLookupTableEntry.Address_PE32Plus = entryValue; + addressLookupTableEntry.OrdinalNameFlag = (entryValue & 0x8000000000000000) != 0; + if (addressLookupTableEntry.OrdinalNameFlag) + addressLookupTableEntry.OrdinalNumber = (ushort)(entryValue & ~0x8000000000000000); + else + addressLookupTableEntry.HintNameTableRVA = (uint)(entryValue & ~0x8000000000000000); } - entryAddressTable.Add(entryLookupTableEntry); + addressLookupTable.Add(addressLookupTableEntry); // All zero values means the last entry - if (entryLookupTableEntry.Address_PE32 == 0 - && entryLookupTableEntry.Address_PE32Plus == 0) + if (addressLookupTableEntry.OrdinalNameFlag == false + && addressLookupTableEntry.OrdinalNumber == 0 + && addressLookupTableEntry.HintNameTableRVA == 0) break; } - importAddressTables[i] = entryAddressTable.ToArray(); + importAddressTables[i] = addressLookupTable.ToArray(); } importTable.ImportAddressTables = importAddressTables; // Hint/Name table + var importHintNameTable = new List(); + if (importTable.ImportLookupTables != null && importTable.ImportLookupTables.Count > 0) { - var importHintNameTable = new List(); - // Get the addresses of the hint/name table entries - List hintNameTableEntryAddresses = importTable.ImportLookupTables - .SelectMany(kvp => kvp.Value) - .Select(ilte => (int)ilte.HintNameTableRVA.ConvertVirtualAddress(sections)) - .Where(addr => addr != 0) + List hintNameTableEntryAddresses = new List(); + + // If we have import lookup tables + if (importTable.ImportLookupTables != null && importLookupTables.Count > 0) + { + var addresses = importTable.ImportLookupTables + .SelectMany(kvp => kvp.Value) + .Select(ilte => (int)ilte.HintNameTableRVA.ConvertVirtualAddress(sections)); + hintNameTableEntryAddresses.AddRange(addresses); + } + + // If we have import address tables + if (importTable.ImportAddressTables != null && importTable.ImportAddressTables.Count > 0) + { + var addresses = importTable.ImportAddressTables + .SelectMany(kvp => kvp.Value) + .Select(iate => (int)iate.HintNameTableRVA.ConvertVirtualAddress(sections)); + hintNameTableEntryAddresses.AddRange(addresses); + } + + // Sanitize the addresses + hintNameTableEntryAddresses = hintNameTableEntryAddresses.Where(addr => addr != 0) .Distinct() .OrderBy(a => a) .ToList(); @@ -1125,10 +1152,10 @@ namespace BurnOutSharp.Builder importHintNameTable.Add(hintNameTableEntry); } } - - importTable.HintNameTable = importHintNameTable.ToArray(); } + importTable.HintNameTable = importHintNameTable.ToArray(); + return importTable; } @@ -2295,46 +2322,74 @@ namespace BurnOutSharp.Builder uint tableAddress = importDirectoryTableEntry.ImportAddressTableRVA.ConvertVirtualAddress(sections); data.Seek(tableAddress, SeekOrigin.Begin); - var entryAddressTable = new List(); + var addressLookupTable = new List(); while (true) { - var entryLookupTableEntry = new ImportAddressTableEntry(); + var addressLookupTableEntry = new ImportAddressTableEntry(); if (magic == OptionalHeaderMagicNumber.PE32) { uint entryValue = data.ReadUInt32(); - entryLookupTableEntry.Address_PE32 = entryValue; + addressLookupTableEntry.OrdinalNameFlag = (entryValue & 0x80000000) != 0; + if (addressLookupTableEntry.OrdinalNameFlag) + addressLookupTableEntry.OrdinalNumber = (ushort)(entryValue & ~0x80000000); + else + addressLookupTableEntry.HintNameTableRVA = (uint)(entryValue & ~0x80000000); } else if (magic == OptionalHeaderMagicNumber.PE32Plus) { ulong entryValue = data.ReadUInt64(); - entryLookupTableEntry.Address_PE32Plus = entryValue; + addressLookupTableEntry.OrdinalNameFlag = (entryValue & 0x8000000000000000) != 0; + if (addressLookupTableEntry.OrdinalNameFlag) + addressLookupTableEntry.OrdinalNumber = (ushort)(entryValue & ~0x8000000000000000); + else + addressLookupTableEntry.HintNameTableRVA = (uint)(entryValue & ~0x8000000000000000); } - entryAddressTable.Add(entryLookupTableEntry); + addressLookupTable.Add(addressLookupTableEntry); // All zero values means the last entry - if (entryLookupTableEntry.Address_PE32 == 0 - && entryLookupTableEntry.Address_PE32Plus == 0) + if (addressLookupTableEntry.OrdinalNameFlag == false + && addressLookupTableEntry.OrdinalNumber == 0 + && addressLookupTableEntry.HintNameTableRVA == 0) break; } - importAddressTables[i] = entryAddressTable.ToArray(); + importAddressTables[i] = addressLookupTable.ToArray(); } importTable.ImportAddressTables = importAddressTables; // Hint/Name table - if (importTable.ImportLookupTables != null && importTable.ImportLookupTables.Count > 0) - { - var importHintNameTable = new List(); + var importHintNameTable = new List(); + if ((importTable.ImportLookupTables != null && importTable.ImportLookupTables.Count > 0) + || importTable.ImportAddressTables != null && importTable.ImportAddressTables.Count > 0) + { // Get the addresses of the hint/name table entries - List hintNameTableEntryAddresses = importTable.ImportLookupTables - .SelectMany(kvp => kvp.Value) - .Select(ilte => (int)ilte.HintNameTableRVA.ConvertVirtualAddress(sections)) - .Where(addr => addr != 0) + List hintNameTableEntryAddresses = new List(); + + // If we have import lookup tables + if (importTable.ImportLookupTables != null && importLookupTables.Count > 0) + { + var addresses = importTable.ImportLookupTables + .SelectMany(kvp => kvp.Value) + .Select(ilte => (int)ilte.HintNameTableRVA.ConvertVirtualAddress(sections)); + hintNameTableEntryAddresses.AddRange(addresses); + } + + // If we have import address tables + if (importTable.ImportAddressTables != null && importTable.ImportAddressTables.Count > 0) + { + var addresses = importTable.ImportAddressTables + .SelectMany(kvp => kvp.Value) + .Select(iate => (int)iate.HintNameTableRVA.ConvertVirtualAddress(sections)); + hintNameTableEntryAddresses.AddRange(addresses); + } + + // Sanitize the addresses + hintNameTableEntryAddresses = hintNameTableEntryAddresses.Where(addr => addr != 0) .Distinct() .OrderBy(a => a) .ToList(); @@ -2355,10 +2410,10 @@ namespace BurnOutSharp.Builder importHintNameTable.Add(hintNameTableEntry); } } - - importTable.HintNameTable = importHintNameTable.ToArray(); } + importTable.HintNameTable = importHintNameTable.ToArray(); + return importTable; } diff --git a/BurnOutSharp.Models/PortableExecutable/ImportAddressTableEntry.cs b/BurnOutSharp.Models/PortableExecutable/ImportAddressTableEntry.cs index 007fd8de..334fa668 100644 --- a/BurnOutSharp.Models/PortableExecutable/ImportAddressTableEntry.cs +++ b/BurnOutSharp.Models/PortableExecutable/ImportAddressTableEntry.cs @@ -12,13 +12,25 @@ public class ImportAddressTableEntry { /// - /// 32-bit address of the symbol being imported + /// If this bit is set, import by ordinal. Otherwise, import by name. Bit is + /// masked as 0x80000000 for PE32, 0x8000000000000000 for PE32+. /// - public uint Address_PE32; + /// Bit 31/63 + public bool OrdinalNameFlag; /// - /// 64-bit address of the symbol being imported + /// A 16-bit ordinal number. This field is used only if the Ordinal/Name Flag + /// bit field is 1 (import by ordinal). Bits 30-15 or 62-15 must be 0. /// - public ulong Address_PE32Plus; + /// Bits 15-0 + public ushort OrdinalNumber; + + /// + /// A 31-bit RVA of a hint/name table entry. This field is used only if the + /// Ordinal/Name Flag bit field is 0 (import by name). For PE32+ bits 62-31 + /// must be zero. + /// + /// Bits 30-0 + public uint HintNameTableRVA; } } diff --git a/BurnOutSharp.Wrappers/PortableExecutable.cs b/BurnOutSharp.Wrappers/PortableExecutable.cs index ac647628..8141fa3b 100644 --- a/BurnOutSharp.Wrappers/PortableExecutable.cs +++ b/BurnOutSharp.Wrappers/PortableExecutable.cs @@ -1579,12 +1579,13 @@ namespace BurnOutSharp.Wrappers { for (int i = 0; i < importAddressTable.Length; i++) { - var importLookupTableEntry = importAddressTable[i]; + var importAddressTableEntry = importAddressTable[i]; Console.WriteLine($" Import Address Table {index} Entry {i}"); - if (OH_Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32) - Console.WriteLine($" Address: {importLookupTableEntry.Address_PE32}"); + Console.WriteLine($" Ordinal/Name flag: {importAddressTableEntry.OrdinalNameFlag}"); + if (importAddressTableEntry.OrdinalNameFlag) + Console.WriteLine($" Ordinal number: {importAddressTableEntry.OrdinalNumber}"); else - Console.WriteLine($" Address: {importLookupTableEntry.Address_PE32Plus}"); + Console.WriteLine($" Hint/Name table RVA: {importAddressTableEntry.HintNameTableRVA}"); } } }