diff --git a/BurnOutSharp.Builder/PortableExecutable.cs b/BurnOutSharp.Builder/PortableExecutable.cs index c8061071..c78d1f9c 100644 --- a/BurnOutSharp.Builder/PortableExecutable.cs +++ b/BurnOutSharp.Builder/PortableExecutable.cs @@ -109,14 +109,27 @@ namespace BurnOutSharp.Builder if (coffSymbolTable == null) return null; + // If the offset for the COFF string table doesn't exist + tableAddress = initialOffset + + (int)coffFileHeader.PointerToSymbolTable.ConvertVirtualAddress(executable.SectionTable) + + (coffSymbolTable.Length * 18 /* sizeof(COFFSymbolTableEntry) */); + if (tableAddress >= data.Length) + return executable; + // Set the COFF symbol table executable.COFFSymbolTable = coffSymbolTable; + + // Try to parse the COFF string table + var coffStringTable = ParseCOFFStringTable(data, tableAddress); + if (coffStringTable == null) + return null; + + // Set the COFF string table + executable.COFFStringTable = coffStringTable; } #endregion - // TODO: COFFStringTable (Only if COFFSymbolTable?) - #region Attribute Certificate Table if (optionalHeader.CertificateTable != null && optionalHeader.CertificateTable.VirtualAddress != 0) @@ -583,6 +596,37 @@ namespace BurnOutSharp.Builder return attributeCertificateTable.ToArray(); } + /// + /// Parse a Stream into a COFF string table + /// + /// Byte array to parse + /// Offset into the byte array + /// Filled COFF string table on success, null on error + private static COFFStringTable ParseCOFFStringTable(byte[] data, int offset) + { + // TODO: Use marshalling here instead of building + var coffStringTable = new COFFStringTable(); + + coffStringTable.TotalSize = data.ReadUInt32(ref offset); + + var strings = new List(); + if (coffStringTable.TotalSize > 4) + { + uint totalSize = coffStringTable.TotalSize; + while (totalSize > 0) + { + int initialPosition = offset; + string str = data.ReadString(ref offset); + strings.Add(str); + totalSize -= (uint)(offset - initialPosition); + } + } + + coffStringTable.Strings = strings.ToArray(); + + return coffStringTable; + } + /// /// Parse a byte array into a resource directory table /// @@ -828,12 +872,18 @@ namespace BurnOutSharp.Builder // Set the COFF symbol table executable.COFFSymbolTable = coffSymbolTable; + + // Try to parse the COFF string table + var coffStringTable = ParseCOFFStringTable(data); + if (coffStringTable == null) + return null; + + // Set the COFF string table + executable.COFFStringTable = coffStringTable; } #endregion - // TODO: COFFStringTable (Only if COFFSymbolTable?) - #region Attribute Certificate Table if (optionalHeader.CertificateTable != null && optionalHeader.CertificateTable.VirtualAddress != 0) @@ -1271,6 +1321,36 @@ namespace BurnOutSharp.Builder return coffSymbolTable; } + /// + /// Parse a Stream into a COFF string table + /// + /// Stream to parse + /// Filled COFF string table on success, null on error + private static COFFStringTable ParseCOFFStringTable(Stream data) + { + // TODO: Use marshalling here instead of building + var coffStringTable = new COFFStringTable(); + + coffStringTable.TotalSize = data.ReadUInt32(); + + var strings = new List(); + if (coffStringTable.TotalSize > 4) + { + uint totalSize = coffStringTable.TotalSize; + while (totalSize > 0) + { + long initialPosition = data.Position; + string str = data.ReadString(); + strings.Add(str); + totalSize -= (uint)(data.Position - initialPosition); + } + } + + coffStringTable.Strings = strings.ToArray(); + + return coffStringTable; + } + /// /// Parse a Stream into an attribute certificate table /// diff --git a/BurnOutSharp.Models/PortableExecutable/COFFSymbolTableEntry.cs b/BurnOutSharp.Models/PortableExecutable/COFFSymbolTableEntry.cs index de1a61c1..0ee83017 100644 --- a/BurnOutSharp.Models/PortableExecutable/COFFSymbolTableEntry.cs +++ b/BurnOutSharp.Models/PortableExecutable/COFFSymbolTableEntry.cs @@ -1,7 +1,4 @@ -using System.Diagnostics; -using System; -using System.Drawing; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; namespace BurnOutSharp.Models.PortableExecutable {