diff --git a/BurnOutSharp.Builder/PortableExecutable.cs b/BurnOutSharp.Builder/PortableExecutable.cs
index e81e11ba..6f97ca5c 100644
--- a/BurnOutSharp.Builder/PortableExecutable.cs
+++ b/BurnOutSharp.Builder/PortableExecutable.cs
@@ -70,7 +70,7 @@ namespace BurnOutSharp.Builder
#region Optional Header
// Try to parse the optional header
- var optionalHeader = ParseOptionalHeader(data, offset, coffFileHeader.SizeOfOptionalHeader);
+ var optionalHeader = ParseOptionalHeader(data, ref offset, coffFileHeader.SizeOfOptionalHeader);
if (optionalHeader == null)
return null;
@@ -79,6 +79,18 @@ namespace BurnOutSharp.Builder
#endregion
+ #region Section Table
+
+ // Try to parse the section table
+ var sectionTable = ParseSectionTable(data, offset, coffFileHeader.NumberOfSections);
+ if (sectionTable == null)
+ return null;
+
+ // Set the section table
+ executable.SectionTable = sectionTable;
+
+ #endregion
+
// TODO: Finish implementing PE parsing
return executable;
}
@@ -112,7 +124,7 @@ namespace BurnOutSharp.Builder
/// Offset into the byte array
/// Size of the optional header
/// Filled optional header on success, null on error
- private static OptionalHeader ParseOptionalHeader(byte[] data, int offset, int optionalSize)
+ private static OptionalHeader ParseOptionalHeader(byte[] data, ref int offset, int optionalSize)
{
int initialOffset = offset;
@@ -141,6 +153,7 @@ namespace BurnOutSharp.Builder
optionalHeader.ImageBase_PE32 = data.ReadUInt32(ref offset);
else if (optionalHeader.Magic == OptionalHeaderMagicNumber.PE32Plus)
optionalHeader.ImageBase_PE32Plus = data.ReadUInt64(ref offset);
+ optionalHeader.SectionAlignment = data.ReadUInt32(ref offset);
optionalHeader.FileAlignment = data.ReadUInt32(ref offset);
optionalHeader.MajorOperatingSystemVersion = data.ReadUInt16(ref offset);
optionalHeader.MinorOperatingSystemVersion = data.ReadUInt16(ref offset);
@@ -275,6 +288,47 @@ namespace BurnOutSharp.Builder
return optionalHeader;
}
+ ///
+ /// Parse a byte array into a section table
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// Number of section table entries to read
+ /// Filled section table on success, null on error
+ private static SectionHeader[] ParseSectionTable(byte[] data, int offset, int count)
+ {
+ // TODO: Use marshalling here instead of building
+ var sectionTable = new SectionHeader[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ var entry = new SectionHeader();
+ entry.Name = data.ReadBytes(ref offset, 8);
+ entry.VirtualSize = data.ReadUInt32(ref offset);
+ entry.VirtualAddress = data.ReadUInt32(ref offset);
+ entry.SizeOfRawData = data.ReadUInt32(ref offset);
+ entry.PointerToRawData = data.ReadUInt32(ref offset);
+ entry.PointerToRelocations = data.ReadUInt32(ref offset);
+ entry.PointerToLinenumbers = data.ReadUInt32(ref offset);
+ entry.NumberOfRelocations = data.ReadUInt16(ref offset);
+ entry.NumberOfLinenumbers = data.ReadUInt16(ref offset);
+ entry.Characteristics = (SectionFlags)data.ReadUInt32(ref offset);
+ entry.COFFRelocations = new COFFRelocation[entry.NumberOfRelocations];
+ for (int j = 0; i < entry.NumberOfRelocations; j++)
+ {
+ // TODO: Seek to correct location and read data
+ }
+ entry.COFFLineNumbers = new COFFLineNumber[entry.NumberOfRelocations];
+ for (int j = 0; i < entry.NumberOfRelocations; j++)
+ {
+ // TODO: Seek to correct location and read data
+ }
+ sectionTable[i] = entry;
+ }
+
+ return sectionTable;
+ }
+
#endregion
#region Stream Data
@@ -349,6 +403,18 @@ namespace BurnOutSharp.Builder
#endregion
+ #region Section Table
+
+ // Try to parse the section table
+ var sectionTable = ParseSectionTable(data, coffFileHeader.NumberOfSections);
+ if (sectionTable == null)
+ return null;
+
+ // Set the section table
+ executable.SectionTable = sectionTable;
+
+ #endregion
+
// TODO: Finish implementing PE parsing
return executable;
}
@@ -409,6 +475,7 @@ namespace BurnOutSharp.Builder
optionalHeader.ImageBase_PE32 = data.ReadUInt32();
else if (optionalHeader.Magic == OptionalHeaderMagicNumber.PE32Plus)
optionalHeader.ImageBase_PE32Plus = data.ReadUInt64();
+ optionalHeader.SectionAlignment = data.ReadUInt32();
optionalHeader.FileAlignment = data.ReadUInt32();
optionalHeader.MajorOperatingSystemVersion = data.ReadUInt16();
optionalHeader.MinorOperatingSystemVersion = data.ReadUInt16();
@@ -543,6 +610,46 @@ namespace BurnOutSharp.Builder
return optionalHeader;
}
+ ///
+ /// Parse a Stream into a section table
+ ///
+ /// Stream to parse
+ /// Number of section table entries to read
+ /// Filled section table on success, null on error
+ private static SectionHeader[] ParseSectionTable(Stream data, int count)
+ {
+ // TODO: Use marshalling here instead of building
+ var sectionTable = new SectionHeader[count];
+
+ for (int i = 0; i < count; i++)
+ {
+ var entry = new SectionHeader();
+ entry.Name = data.ReadBytes(8);
+ entry.VirtualSize = data.ReadUInt32();
+ entry.VirtualAddress = data.ReadUInt32();
+ entry.SizeOfRawData = data.ReadUInt32();
+ entry.PointerToRawData = data.ReadUInt32();
+ entry.PointerToRelocations = data.ReadUInt32();
+ entry.PointerToLinenumbers = data.ReadUInt32();
+ entry.NumberOfRelocations = data.ReadUInt16();
+ entry.NumberOfLinenumbers = data.ReadUInt16();
+ entry.Characteristics = (SectionFlags)data.ReadUInt32();
+ entry.COFFRelocations = new COFFRelocation[entry.NumberOfRelocations];
+ for (int j = 0; j < entry.NumberOfRelocations; j++)
+ {
+ // TODO: Seek to correct location and read data
+ }
+ entry.COFFLineNumbers = new COFFLineNumber[entry.NumberOfLinenumbers];
+ for (int j = 0; j < entry.NumberOfLinenumbers; j++)
+ {
+ // TODO: Seek to correct location and read data
+ }
+ sectionTable[i] = entry;
+ }
+
+ return sectionTable;
+ }
+
#endregion
}
}
\ No newline at end of file
diff --git a/ExecutableTest/Program.cs b/ExecutableTest/Program.cs
index feba089a..bff03479 100644
--- a/ExecutableTest/Program.cs
+++ b/ExecutableTest/Program.cs
@@ -485,99 +485,127 @@ namespace ExecutableTest
if (executable.OptionalHeader.ExportTable != null)
{
- Console.WriteLine(" Export Table (1)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.ExportTable.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.ExportTable.Size}");
+ Console.WriteLine(" Export Table (1)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.ExportTable.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.ExportTable.Size}");
}
if (executable.OptionalHeader.ImportTable != null)
{
- Console.WriteLine(" Import Table (2)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.ImportTable.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.ImportTable.Size}");
+ Console.WriteLine(" Import Table (2)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.ImportTable.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.ImportTable.Size}");
}
if (executable.OptionalHeader.ResourceTable != null)
{
- Console.WriteLine(" Resource Table (3)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.ResourceTable.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.ResourceTable.Size}");
+ Console.WriteLine(" Resource Table (3)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.ResourceTable.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.ResourceTable.Size}");
}
if (executable.OptionalHeader.ExceptionTable != null)
{
- Console.WriteLine(" Exception Table (4)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.ExceptionTable.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.ExceptionTable.Size}");
+ Console.WriteLine(" Exception Table (4)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.ExceptionTable.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.ExceptionTable.Size}");
}
if (executable.OptionalHeader.CertificateTable != null)
{
- Console.WriteLine(" Certificate Table (5)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.CertificateTable.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.CertificateTable.Size}");
+ Console.WriteLine(" Certificate Table (5)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.CertificateTable.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.CertificateTable.Size}");
}
if (executable.OptionalHeader.BaseRelocationTable != null)
{
- Console.WriteLine(" Base Relocation Table (6)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.BaseRelocationTable.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.BaseRelocationTable.Size}");
+ Console.WriteLine(" Base Relocation Table (6)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.BaseRelocationTable.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.BaseRelocationTable.Size}");
}
if (executable.OptionalHeader.Debug != null)
{
- Console.WriteLine(" Debug Table (7)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.Debug.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.Debug.Size}");
+ Console.WriteLine(" Debug Table (7)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.Debug.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.Debug.Size}");
}
if (executable.OptionalHeader.NumberOfRvaAndSizes >= 8)
{
- Console.WriteLine(" Architecture Table (8)");
- Console.WriteLine($" Virtual address: 0");
- Console.WriteLine($" Size: 0");
+ Console.WriteLine(" Architecture Table (8)");
+ Console.WriteLine($" Virtual address: 0");
+ Console.WriteLine($" Size: 0");
}
if (executable.OptionalHeader.GlobalPtr != null)
{
- Console.WriteLine(" Global Pointer Register (9)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.GlobalPtr.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.GlobalPtr.Size}");
+ Console.WriteLine(" Global Pointer Register (9)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.GlobalPtr.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.GlobalPtr.Size}");
}
if (executable.OptionalHeader.ThreadLocalStorageTable != null)
{
- Console.WriteLine(" Thread Local Storage (TLS) Table (10)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.ThreadLocalStorageTable.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.ThreadLocalStorageTable.Size}");
+ Console.WriteLine(" Thread Local Storage (TLS) Table (10)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.ThreadLocalStorageTable.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.ThreadLocalStorageTable.Size}");
}
if (executable.OptionalHeader.LoadConfigTable != null)
{
- Console.WriteLine(" Load Config Table (11)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.LoadConfigTable.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.LoadConfigTable.Size}");
+ Console.WriteLine(" Load Config Table (11)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.LoadConfigTable.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.LoadConfigTable.Size}");
}
if (executable.OptionalHeader.BoundImport != null)
{
- Console.WriteLine(" Bound Import Table (12)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.BoundImport.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.BoundImport.Size}");
+ Console.WriteLine(" Bound Import Table (12)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.BoundImport.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.BoundImport.Size}");
}
if (executable.OptionalHeader.ImportAddressTable != null)
{
- Console.WriteLine(" Import Address Table (13)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.ImportAddressTable.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.ImportAddressTable.Size}");
+ Console.WriteLine(" Import Address Table (13)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.ImportAddressTable.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.ImportAddressTable.Size}");
}
if (executable.OptionalHeader.DelayImportDescriptor != null)
{
- Console.WriteLine(" Delay Import Descriptior (14)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.DelayImportDescriptor.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.DelayImportDescriptor.Size}");
+ Console.WriteLine(" Delay Import Descriptior (14)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.DelayImportDescriptor.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.DelayImportDescriptor.Size}");
}
if (executable.OptionalHeader.CLRRuntimeHeader != null)
{
- Console.WriteLine(" CLR Runtime Header (15)");
- Console.WriteLine($" Virtual address: {executable.OptionalHeader.CLRRuntimeHeader.VirtualAddress}");
- Console.WriteLine($" Size: {executable.OptionalHeader.CLRRuntimeHeader.Size}");
+ Console.WriteLine(" CLR Runtime Header (15)");
+ Console.WriteLine($" Virtual address: {executable.OptionalHeader.CLRRuntimeHeader.VirtualAddress}");
+ Console.WriteLine($" Size: {executable.OptionalHeader.CLRRuntimeHeader.Size}");
}
if (executable.OptionalHeader.NumberOfRvaAndSizes >= 16)
{
- Console.WriteLine(" Reserved (16)");
- Console.WriteLine($" Virtual address: 0");
- Console.WriteLine($" Size: 0");
+ Console.WriteLine(" Reserved (16)");
+ Console.WriteLine($" Virtual address: 0");
+ Console.WriteLine($" Size: 0");
+ }
+ }
+ Console.WriteLine();
+
+ Console.WriteLine(" Section Table Information:");
+ Console.WriteLine(" -------------------------");
+ if (executable.COFFFileHeader.NumberOfSections == 0 || executable.SectionTable.Length == 0)
+ {
+ Console.WriteLine(" No section table items");
+ }
+ else
+ {
+ for (int i = 0; i < executable.SectionTable.Length; i++)
+ {
+ var entry = executable.SectionTable[i];
+ Console.WriteLine($" Segment Table Entry {i}");
+ Console.WriteLine($" Name = {Encoding.UTF8.GetString(entry.Name)}");
+ Console.WriteLine($" Virtual size = {entry.VirtualSize}");
+ Console.WriteLine($" Virtual address = {entry.VirtualAddress}");
+ Console.WriteLine($" Size of raw data = {entry.SizeOfRawData}");
+ Console.WriteLine($" Pointer to raw data = {entry.PointerToRawData}");
+ Console.WriteLine($" Pointer to relocations = {entry.PointerToRelocations}");
+ Console.WriteLine($" Pointer to linenumbers = {entry.PointerToLinenumbers}");
+ Console.WriteLine($" Number of relocations = {entry.NumberOfRelocations}");
+ Console.WriteLine($" Number of linenumbers = {entry.NumberOfLinenumbers}");
+ Console.WriteLine($" Characteristics = {entry.Characteristics}");
+ // TODO: Add COFFRelocations
+ // TODO: Add COFFLineNumbers
}
}
Console.WriteLine();