From 0c6bf406c179aa36063c265be863a655a3926eef Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 9 Nov 2022 22:02:38 -0800 Subject: [PATCH] Fix PE delay-load directory --- BurnOutSharp.Builder/PortableExecutable.cs | 66 +++++++------------ ...bleEntry.cs => DelayLoadDirectoryTable.cs} | 2 +- .../PortableExecutable/Executable.cs | 2 +- ExecutableTest/Program.cs | 23 +++---- 4 files changed, 35 insertions(+), 58 deletions(-) rename BurnOutSharp.Models/PortableExecutable/{DelayLoadDirectoryTableEntry.cs => DelayLoadDirectoryTable.cs} (99%) diff --git a/BurnOutSharp.Builder/PortableExecutable.cs b/BurnOutSharp.Builder/PortableExecutable.cs index 37da7031..92319770 100644 --- a/BurnOutSharp.Builder/PortableExecutable.cs +++ b/BurnOutSharp.Builder/PortableExecutable.cs @@ -163,8 +163,7 @@ namespace BurnOutSharp.Builder return executable; // Try to parse the delay-load directory table - int endOffset = (int)(delayLoadDirectoryTableAddress + optionalHeader.DelayImportDescriptor.Size); - var delayLoadDirectoryTable = ParseDelayLoadDirectoryTable(data, delayLoadDirectoryTableAddress, endOffset); + var delayLoadDirectoryTable = ParseDelayLoadDirectoryTable(data, delayLoadDirectoryTableAddress); if (delayLoadDirectoryTable == null) return null; @@ -652,30 +651,22 @@ namespace BurnOutSharp.Builder /// /// Byte array to parse /// Offset into the byte array - /// First address not part of the delay-load directory table /// Filled delay-load directory table on success, null on error - private static DelayLoadDirectoryTableEntry[] ParseDelayLoadDirectoryTable(byte[] data, int offset, int endOffset) + private static DelayLoadDirectoryTable ParseDelayLoadDirectoryTable(byte[] data, int offset) { // TODO: Use marshalling here instead of building - var delayLoadDirectoryTable = new List(); + var delayLoadDirectoryTable = new DelayLoadDirectoryTable(); - while (offset < endOffset) - { - var entry = new DelayLoadDirectoryTableEntry(); + delayLoadDirectoryTable.Attributes = data.ReadUInt32(ref offset); + delayLoadDirectoryTable.Name = data.ReadUInt32(ref offset); + delayLoadDirectoryTable.ModuleHandle = data.ReadUInt32(ref offset); + delayLoadDirectoryTable.DelayImportAddressTable = data.ReadUInt32(ref offset); + delayLoadDirectoryTable.DelayImportNameTable = data.ReadUInt32(ref offset); + delayLoadDirectoryTable.BoundDelayImportTable = data.ReadUInt32(ref offset); + delayLoadDirectoryTable.UnloadDelayImportTable = data.ReadUInt32(ref offset); + delayLoadDirectoryTable.TimeStamp = data.ReadUInt32(ref offset); - entry.Attributes = data.ReadUInt32(ref offset); - entry.Name = data.ReadUInt32(ref offset); - entry.ModuleHandle = data.ReadUInt32(ref offset); - entry.DelayImportAddressTable = data.ReadUInt32(ref offset); - entry.DelayImportNameTable = data.ReadUInt32(ref offset); - entry.BoundDelayImportTable = data.ReadUInt32(ref offset); - entry.UnloadDelayImportTable = data.ReadUInt32(ref offset); - entry.TimeStamp = data.ReadUInt32(ref offset); - - delayLoadDirectoryTable.Add(entry); - } - - return delayLoadDirectoryTable.ToArray(); + return delayLoadDirectoryTable; } /// @@ -970,8 +961,7 @@ namespace BurnOutSharp.Builder // Try to parse the delay-load directory table data.Seek(delayLoadDirectoryTableAddress, SeekOrigin.Begin); - int endOffset = (int)(delayLoadDirectoryTableAddress + optionalHeader.DelayImportDescriptor.Size); - var delayLoadDirectoryTable = ParseDelayLoadDirectoryTable(data, endOffset); + var delayLoadDirectoryTable = ParseDelayLoadDirectoryTable(data); if (delayLoadDirectoryTable == null) return null; @@ -1453,30 +1443,22 @@ namespace BurnOutSharp.Builder /// Parse a byte array into a delay-load directory table /// /// Stream to parse - /// First address not part of the delay-load directory table /// Filled delay-load directory table on success, null on error - private static DelayLoadDirectoryTableEntry[] ParseDelayLoadDirectoryTable(Stream data, int endOffset) + private static DelayLoadDirectoryTable ParseDelayLoadDirectoryTable(Stream data) { // TODO: Use marshalling here instead of building - var delayLoadDirectoryTable = new List(); + var delayLoadDirectoryTable = new DelayLoadDirectoryTable(); - while (data.Position < endOffset) - { - var entry = new DelayLoadDirectoryTableEntry(); + delayLoadDirectoryTable.Attributes = data.ReadUInt32(); + delayLoadDirectoryTable.Name = data.ReadUInt32(); + delayLoadDirectoryTable.ModuleHandle = data.ReadUInt32(); + delayLoadDirectoryTable.DelayImportAddressTable = data.ReadUInt32(); + delayLoadDirectoryTable.DelayImportNameTable = data.ReadUInt32(); + delayLoadDirectoryTable.BoundDelayImportTable = data.ReadUInt32(); + delayLoadDirectoryTable.UnloadDelayImportTable = data.ReadUInt32(); + delayLoadDirectoryTable.TimeStamp = data.ReadUInt32(); - entry.Attributes = data.ReadUInt32(); - entry.Name = data.ReadUInt32(); - entry.ModuleHandle = data.ReadUInt32(); - entry.DelayImportAddressTable = data.ReadUInt32(); - entry.DelayImportNameTable = data.ReadUInt32(); - entry.BoundDelayImportTable = data.ReadUInt32(); - entry.UnloadDelayImportTable = data.ReadUInt32(); - entry.TimeStamp = data.ReadUInt32(); - - delayLoadDirectoryTable.Add(entry); - } - - return delayLoadDirectoryTable.ToArray(); + return delayLoadDirectoryTable; } /// diff --git a/BurnOutSharp.Models/PortableExecutable/DelayLoadDirectoryTableEntry.cs b/BurnOutSharp.Models/PortableExecutable/DelayLoadDirectoryTable.cs similarity index 99% rename from BurnOutSharp.Models/PortableExecutable/DelayLoadDirectoryTableEntry.cs rename to BurnOutSharp.Models/PortableExecutable/DelayLoadDirectoryTable.cs index 3fea2757..d551b2a6 100644 --- a/BurnOutSharp.Models/PortableExecutable/DelayLoadDirectoryTableEntry.cs +++ b/BurnOutSharp.Models/PortableExecutable/DelayLoadDirectoryTable.cs @@ -9,7 +9,7 @@ namespace BurnOutSharp.Models.PortableExecutable /// /// [StructLayout(LayoutKind.Sequential)] - public class DelayLoadDirectoryTableEntry + public class DelayLoadDirectoryTable { /// /// Must be zero. diff --git a/BurnOutSharp.Models/PortableExecutable/Executable.cs b/BurnOutSharp.Models/PortableExecutable/Executable.cs index 4f698c56..9e5cde81 100644 --- a/BurnOutSharp.Models/PortableExecutable/Executable.cs +++ b/BurnOutSharp.Models/PortableExecutable/Executable.cs @@ -60,7 +60,7 @@ namespace BurnOutSharp.Models.PortableExecutable /// /// Delay-load directory table /// - public DelayLoadDirectoryTableEntry[] DelayLoadDirectoryTable { get; set; } + public DelayLoadDirectoryTable DelayLoadDirectoryTable { get; set; } #region Named Sections diff --git a/ExecutableTest/Program.cs b/ExecutableTest/Program.cs index 5db75d2a..ee79bd6f 100644 --- a/ExecutableTest/Program.cs +++ b/ExecutableTest/Program.cs @@ -790,25 +790,20 @@ namespace ExecutableTest Console.WriteLine(" -------------------------"); if (executable.OptionalHeader?.DelayImportDescriptor == null || executable.OptionalHeader.DelayImportDescriptor.VirtualAddress == 0 - || executable.DelayLoadDirectoryTable.Length == 0) + || executable.DelayLoadDirectoryTable == null) { Console.WriteLine(" No delay-load directory table items"); } else { - for (int i = 0; i < executable.DelayLoadDirectoryTable.Length; i++) - { - var entry = executable.DelayLoadDirectoryTable[i]; - Console.WriteLine($" Delay-Load Directory Table Entry {i}"); - Console.WriteLine($" Attributes = {entry.Attributes}"); - Console.WriteLine($" Name RVA = {entry.Name}"); - Console.WriteLine($" Module handle = {entry.ModuleHandle}"); - Console.WriteLine($" Delay import address table RVA = {entry.DelayImportAddressTable}"); - Console.WriteLine($" Delay import name table RVA = {entry.DelayImportNameTable}"); - Console.WriteLine($" Bound delay import table RVA = {entry.BoundDelayImportTable}"); - Console.WriteLine($" Unload delay import table RVA = {entry.UnloadDelayImportTable}"); - Console.WriteLine($" Timestamp = {entry.TimeStamp}"); - } + Console.WriteLine($" Attributes = {executable.DelayLoadDirectoryTable.Attributes}"); + Console.WriteLine($" Name RVA = {executable.DelayLoadDirectoryTable.Name}"); + Console.WriteLine($" Module handle = {executable.DelayLoadDirectoryTable.ModuleHandle}"); + Console.WriteLine($" Delay import address table RVA = {executable.DelayLoadDirectoryTable.DelayImportAddressTable}"); + Console.WriteLine($" Delay import name table RVA = {executable.DelayLoadDirectoryTable.DelayImportNameTable}"); + Console.WriteLine($" Bound delay import table RVA = {executable.DelayLoadDirectoryTable.BoundDelayImportTable}"); + Console.WriteLine($" Unload delay import table RVA = {executable.DelayLoadDirectoryTable.UnloadDelayImportTable}"); + Console.WriteLine($" Timestamp = {executable.DelayLoadDirectoryTable.TimeStamp}"); } Console.WriteLine();