Fix PE delay-load directory

This commit is contained in:
Matt Nadareski
2022-11-09 22:02:38 -08:00
parent 95b5f12226
commit 0c6bf406c1
4 changed files with 35 additions and 58 deletions

View File

@@ -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
/// </summary>
/// <param name="data">Byte array to parse</param>
/// <param name="offset">Offset into the byte array</param>
/// <param name="endOffset">First address not part of the delay-load directory table</param>
/// <returns>Filled delay-load directory table on success, null on error</returns>
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<DelayLoadDirectoryTableEntry>();
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;
}
/// <summary>
@@ -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
/// </summary>
/// <param name="data">Stream to parse</param>
/// <param name="endOffset">First address not part of the delay-load directory table</param>
/// <returns>Filled delay-load directory table on success, null on error</returns>
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<DelayLoadDirectoryTableEntry>();
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;
}
/// <summary>

View File

@@ -9,7 +9,7 @@ namespace BurnOutSharp.Models.PortableExecutable
/// </summary>
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
[StructLayout(LayoutKind.Sequential)]
public class DelayLoadDirectoryTableEntry
public class DelayLoadDirectoryTable
{
/// <summary>
/// Must be zero.

View File

@@ -60,7 +60,7 @@ namespace BurnOutSharp.Models.PortableExecutable
/// <summary>
/// Delay-load directory table
/// </summary>
public DelayLoadDirectoryTableEntry[] DelayLoadDirectoryTable { get; set; }
public DelayLoadDirectoryTable DelayLoadDirectoryTable { get; set; }
#region Named Sections

View File

@@ -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();