diff --git a/BurnOutSharp.Builder/PortableExecutable.cs b/BurnOutSharp.Builder/PortableExecutable.cs
index 1fd94b81..c8061071 100644
--- a/BurnOutSharp.Builder/PortableExecutable.cs
+++ b/BurnOutSharp.Builder/PortableExecutable.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.IO;
using BurnOutSharp.Models.PortableExecutable;
@@ -115,7 +116,29 @@ namespace BurnOutSharp.Builder
#endregion
// TODO: COFFStringTable (Only if COFFSymbolTable?)
- // TODO: AttributeCertificateTable
+
+ #region Attribute Certificate Table
+
+ if (optionalHeader.CertificateTable != null && optionalHeader.CertificateTable.VirtualAddress != 0)
+ {
+ // If the offset for the COFF symbol table doesn't exist
+ int certificateTableAddress = initialOffset
+ + (int)optionalHeader.CertificateTable.VirtualAddress;
+ if (certificateTableAddress >= data.Length)
+ return executable;
+
+ // Try to parse the attribute certificate table
+ int endOffset = (int)(certificateTableAddress + optionalHeader.CertificateTable.Size);
+ var attributeCertificateTable = ParseAttributeCertificateTable(data, certificateTableAddress, endOffset);
+ if (attributeCertificateTable == null)
+ return null;
+
+ // Set the attribute certificate table
+ executable.AttributeCertificateTable = attributeCertificateTable;
+ }
+
+ #endregion
+
// TODO: DelayLoadDirectoryTable
#region Resource Directory Table
@@ -533,6 +556,33 @@ namespace BurnOutSharp.Builder
return coffSymbolTable;
}
+ ///
+ /// Parse a byte array into an attribute certificate table
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// First address not part of the attribute certificate table
+ /// Filled attribute certificate on success, null on error
+ private static AttributeCertificateTableEntry[] ParseAttributeCertificateTable(byte[] data, int offset, int endOffset)
+ {
+ var attributeCertificateTable = new List();
+
+ while (offset < endOffset)
+ {
+ var entry = new AttributeCertificateTableEntry();
+
+ entry.Length = data.ReadUInt32(ref offset);
+ entry.Revision = (WindowsCertificateRevision)data.ReadUInt16(ref offset);
+ entry.CertificateType = (WindowsCertificateType)data.ReadUInt16(ref offset);
+ if (entry.Length > 0)
+ entry.Certificate = data.ReadBytes(ref offset, (int)entry.Length);
+
+ attributeCertificateTable.Add(entry);
+ }
+
+ return attributeCertificateTable.ToArray();
+ }
+
///
/// Parse a byte array into a resource directory table
///
@@ -765,13 +815,13 @@ namespace BurnOutSharp.Builder
if (coffFileHeader.PointerToSymbolTable != 0)
{
// If the offset for the COFF symbol table doesn't exist
- int tableAddress = initialOffset
+ int symbolTableAddress = initialOffset
+ (int)coffFileHeader.PointerToSymbolTable.ConvertVirtualAddress(executable.SectionTable);
- if (tableAddress >= data.Length)
+ if (symbolTableAddress >= data.Length)
return executable;
// Try to parse the COFF symbol table
- data.Seek(tableAddress, SeekOrigin.Begin);
+ data.Seek(symbolTableAddress, SeekOrigin.Begin);
var coffSymbolTable = ParseCOFFSymbolTable(data, coffFileHeader.NumberOfSymbols);
if (coffSymbolTable == null)
return null;
@@ -783,22 +833,45 @@ namespace BurnOutSharp.Builder
#endregion
// TODO: COFFStringTable (Only if COFFSymbolTable?)
- // TODO: AttributeCertificateTable
+
+ #region Attribute Certificate Table
+
+ if (optionalHeader.CertificateTable != null && optionalHeader.CertificateTable.VirtualAddress != 0)
+ {
+ // If the offset for the attribute certificate table doesn't exist
+ int certificateTableAddress = initialOffset
+ + (int)optionalHeader.CertificateTable.VirtualAddress;
+ if (certificateTableAddress >= data.Length)
+ return executable;
+
+ // Try to parse the attribute certificate table
+ data.Seek(certificateTableAddress, SeekOrigin.Begin);
+ int endOffset = (int)(certificateTableAddress + optionalHeader.CertificateTable.Size);
+ var attributeCertificateTable = ParseAttributeCertificateTable(data, endOffset);
+ if (attributeCertificateTable == null)
+ return null;
+
+ // Set the attribute certificate table
+ executable.AttributeCertificateTable = attributeCertificateTable;
+ }
+
+ #endregion
+
// TODO: DelayLoadDirectoryTable
-
+
#region Resource Directory Table
// Should also be in the '.rsrc' section
if (optionalHeader.ResourceTable != null && optionalHeader.ResourceTable.VirtualAddress != 0)
{
// If the offset for the resource directory table doesn't exist
- int tableAddress = initialOffset
+ int resourceTableAddress = initialOffset
+ (int)optionalHeader.ResourceTable.VirtualAddress.ConvertVirtualAddress(executable.SectionTable);
- if (tableAddress >= data.Length)
+ if (resourceTableAddress >= data.Length)
return executable;
// Try to parse the resource directory table
- data.Seek(tableAddress, SeekOrigin.Begin);
+ data.Seek(resourceTableAddress, SeekOrigin.Begin);
var resourceDirectoryTable = ParseResourceDirectoryTable(data, data.Position, executable.SectionTable);
if (resourceDirectoryTable == null)
return null;
@@ -1198,6 +1271,32 @@ namespace BurnOutSharp.Builder
return coffSymbolTable;
}
+ ///
+ /// Parse a Stream into an attribute certificate table
+ ///
+ /// Stream to parse
+ /// First address not part of the attribute certificate table
+ /// Filled attribute certificate on success, null on error
+ private static AttributeCertificateTableEntry[] ParseAttributeCertificateTable(Stream data, int endOffset)
+ {
+ var attributeCertificateTable = new List();
+
+ while (data.Position < endOffset)
+ {
+ var entry = new AttributeCertificateTableEntry();
+
+ entry.Length = data.ReadUInt32();
+ entry.Revision = (WindowsCertificateRevision)data.ReadUInt16();
+ entry.CertificateType = (WindowsCertificateType)data.ReadUInt16();
+ if (entry.Length > 0)
+ entry.Certificate = data.ReadBytes((int)entry.Length);
+
+ attributeCertificateTable.Add(entry);
+ }
+
+ return attributeCertificateTable.ToArray();
+ }
+
///
/// Parse a Stream into a resource directory table
///