using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using static BurnOutSharp.Builder.Extensions;
namespace BurnOutSharp.Wrappers
{
public class PortableExecutable : WrapperBase
{
#region Pass-Through Properties
#region MS-DOS Stub
#region Standard Fields
///
public byte[] Stub_Magic => _executable.Stub.Header.Magic;
///
public ushort Stub_LastPageBytes => _executable.Stub.Header.LastPageBytes;
///
public ushort Stub_Pages => _executable.Stub.Header.Pages;
///
public ushort Stub_RelocationItems => _executable.Stub.Header.RelocationItems;
///
public ushort Stub_HeaderParagraphSize => _executable.Stub.Header.HeaderParagraphSize;
///
public ushort Stub_MinimumExtraParagraphs => _executable.Stub.Header.MinimumExtraParagraphs;
///
public ushort Stub_MaximumExtraParagraphs => _executable.Stub.Header.MaximumExtraParagraphs;
///
public ushort Stub_InitialSSValue => _executable.Stub.Header.InitialSSValue;
///
public ushort Stub_Stub_InitialSPValue => _executable.Stub.Header.InitialSPValue;
///
public ushort Stub_Checksum => _executable.Stub.Header.Checksum;
///
public ushort Stub_InitialIPValue => _executable.Stub.Header.InitialIPValue;
///
public ushort Stub_InitialCSValue => _executable.Stub.Header.InitialCSValue;
///
public ushort Stub_RelocationTableAddr => _executable.Stub.Header.RelocationTableAddr;
///
public ushort Stub_OverlayNumber => _executable.Stub.Header.OverlayNumber;
#endregion
#region PE Extensions
///
public ushort[] Stub_Reserved1 => _executable.Stub.Header.Reserved1;
///
public ushort Stub_OEMIdentifier => _executable.Stub.Header.OEMIdentifier;
///
public ushort Stub_OEMInformation => _executable.Stub.Header.OEMInformation;
///
public ushort[] Stub_Reserved2 => _executable.Stub.Header.Reserved2;
///
public uint Stub_NewExeHeaderAddr => _executable.Stub.Header.NewExeHeaderAddr;
#endregion
#endregion
///
public byte[] Signature => _executable.Signature;
#region COFF File Header
///
public Models.PortableExecutable.MachineType Machine => _executable.COFFFileHeader.Machine;
///
public ushort NumberOfSections => _executable.COFFFileHeader.NumberOfSections;
///
public uint TimeDateStamp => _executable.COFFFileHeader.TimeDateStamp;
///
public uint PointerToSymbolTable => _executable.COFFFileHeader.PointerToSymbolTable;
///
public uint NumberOfSymbols => _executable.COFFFileHeader.NumberOfSymbols;
///
public uint SizeOfOptionalHeader => _executable.COFFFileHeader.SizeOfOptionalHeader;
///
public Models.PortableExecutable.Characteristics Characteristics => _executable.COFFFileHeader.Characteristics;
#endregion
#region Optional Header
#region Standard Fields
///
public Models.PortableExecutable.OptionalHeaderMagicNumber OH_Magic => _executable.OptionalHeader.Magic;
///
public byte OH_MajorLinkerVersion => _executable.OptionalHeader.MajorLinkerVersion;
///
public byte OH_MinorLinkerVersion => _executable.OptionalHeader.MinorLinkerVersion;
///
public uint OH_SizeOfCode => _executable.OptionalHeader.SizeOfCode;
///
public uint OH_SizeOfInitializedData => _executable.OptionalHeader.SizeOfInitializedData;
///
public uint OH_SizeOfUninitializedData => _executable.OptionalHeader.SizeOfUninitializedData;
///
public uint OH_AddressOfEntryPoint => _executable.OptionalHeader.AddressOfEntryPoint;
///
public uint OH_BaseOfCode => _executable.OptionalHeader.BaseOfCode;
///
public uint? OH_BaseOfData => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32
? (uint?)_executable.OptionalHeader.BaseOfData
: null;
#endregion
#region Windows-Specific Fields
///
public ulong OH_ImageBase => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32
? _executable.OptionalHeader.ImageBase_PE32
: _executable.OptionalHeader.ImageBase_PE32Plus;
///
public uint OH_SectionAlignment => _executable.OptionalHeader.SectionAlignment;
///
public uint OH_FileAlignment => _executable.OptionalHeader.FileAlignment;
///
public ushort OH_MajorOperatingSystemVersion => _executable.OptionalHeader.MajorOperatingSystemVersion;
///
public ushort OH_MinorOperatingSystemVersion => _executable.OptionalHeader.MinorOperatingSystemVersion;
///
public ushort OH_MajorImageVersion => _executable.OptionalHeader.MajorImageVersion;
///
public ushort OH_MinorImageVersion => _executable.OptionalHeader.MinorImageVersion;
///
public ushort OH_MajorSubsystemVersion => _executable.OptionalHeader.MajorSubsystemVersion;
///
public ushort OH_MinorSubsystemVersion => _executable.OptionalHeader.MinorSubsystemVersion;
///
public uint OH_Win32VersionValue => _executable.OptionalHeader.Win32VersionValue;
///
public uint OH_SizeOfImage => _executable.OptionalHeader.SizeOfImage;
///
public uint OH_SizeOfHeaders => _executable.OptionalHeader.SizeOfHeaders;
///
public uint OH_CheckSum => _executable.OptionalHeader.CheckSum;
///
public Models.PortableExecutable.WindowsSubsystem OH_Subsystem => _executable.OptionalHeader.Subsystem;
///
public Models.PortableExecutable.DllCharacteristics OH_DllCharacteristics => _executable.OptionalHeader.DllCharacteristics;
///
public ulong OH_SizeOfStackReserve => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32
? _executable.OptionalHeader.SizeOfStackReserve_PE32
: _executable.OptionalHeader.SizeOfStackReserve_PE32Plus;
///
public ulong OH_SizeOfStackCommit => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32
? _executable.OptionalHeader.SizeOfStackCommit_PE32
: _executable.OptionalHeader.SizeOfStackCommit_PE32Plus;
///
public ulong OH_SizeOfHeapReserve => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32
? _executable.OptionalHeader.SizeOfHeapReserve_PE32
: _executable.OptionalHeader.SizeOfHeapReserve_PE32Plus;
///
public ulong OH_SizeOfHeapCommit => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32
? _executable.OptionalHeader.SizeOfHeapCommit_PE32
: _executable.OptionalHeader.SizeOfHeapCommit_PE32Plus;
///
public uint OH_LoaderFlags => _executable.OptionalHeader.LoaderFlags;
///
public uint OH_NumberOfRvaAndSizes => _executable.OptionalHeader.NumberOfRvaAndSizes;
#endregion
#region Data Directories
///
public Models.PortableExecutable.DataDirectory OH_ExportTable => _executable.OptionalHeader.ExportTable;
///
public Models.PortableExecutable.DataDirectory OH_ImportTable => _executable.OptionalHeader.ImportTable;
///
public Models.PortableExecutable.DataDirectory OH_ResourceTable => _executable.OptionalHeader.ResourceTable;
///
public Models.PortableExecutable.DataDirectory OH_ExceptionTable => _executable.OptionalHeader.ExceptionTable;
///
public Models.PortableExecutable.DataDirectory OH_CertificateTable => _executable.OptionalHeader.CertificateTable;
///
public Models.PortableExecutable.DataDirectory OH_BaseRelocationTable => _executable.OptionalHeader.BaseRelocationTable;
///
public Models.PortableExecutable.DataDirectory OH_Debug => _executable.OptionalHeader.Debug;
///
public ulong OH_Architecture => _executable.OptionalHeader.Architecture;
///
public Models.PortableExecutable.DataDirectory OH_GlobalPtr => _executable.OptionalHeader.GlobalPtr;
///
public Models.PortableExecutable.DataDirectory OH_ThreadLocalStorageTable => _executable.OptionalHeader.ThreadLocalStorageTable;
///
public Models.PortableExecutable.DataDirectory OH_LoadConfigTable => _executable.OptionalHeader.LoadConfigTable;
///
public Models.PortableExecutable.DataDirectory OH_BoundImport => _executable.OptionalHeader.BoundImport;
///
public Models.PortableExecutable.DataDirectory OH_ImportAddressTable => _executable.OptionalHeader.ImportAddressTable;
///
public Models.PortableExecutable.DataDirectory OH_DelayImportDescriptor => _executable.OptionalHeader.DelayImportDescriptor;
///
public Models.PortableExecutable.DataDirectory OH_CLRRuntimeHeader => _executable.OptionalHeader.CLRRuntimeHeader;
///
public ulong OH_Reserved => _executable.OptionalHeader.Reserved;
#endregion
#endregion
#region Tables
///
public Models.PortableExecutable.SectionHeader[] SectionTable => _executable.SectionTable;
///
public Models.PortableExecutable.COFFSymbolTableEntry[] COFFSymbolTable => _executable.COFFSymbolTable;
///
public Models.PortableExecutable.COFFStringTable COFFStringTable => _executable.COFFStringTable;
///
public Models.PortableExecutable.AttributeCertificateTableEntry[] AttributeCertificateTable => _executable.AttributeCertificateTable;
///
public Models.PortableExecutable.DelayLoadDirectoryTable DelayLoadDirectoryTable => _executable.DelayLoadDirectoryTable;
#endregion
#region Sections
///
public Models.PortableExecutable.DebugTable DebugTable => _executable.DebugTable;
///
public Models.PortableExecutable.ExportTable ExportTable => _executable.ExportTable;
///
public string[] ExportNameTable => _executable.ExportTable?.ExportNameTable?.Strings;
///
public Models.PortableExecutable.ImportTable ImportTable => _executable.ImportTable;
///
public string[] ImportHintNameTable => _executable.ImportTable?.HintNameTable != null
? _executable.ImportTable.HintNameTable.Select(entry => entry.Name).ToArray()
: null;
///
public Models.PortableExecutable.ResourceDirectoryTable ResourceDirectoryTable => _executable.ResourceDirectoryTable;
#endregion
#endregion
#region Extension Properties
///
/// Overlay data, if it exists
///
public byte[] Overlay
{
get
{
lock (_overlayDataLock)
{
// Use the cached data if possible
if (_overlayData != null)
return _overlayData;
// TODO: Implement from https://www.autoitscript.com/forum/topic/153277-pe-file-overlay-extraction/
return null;
}
}
}
///
/// Array of sanitized section names
///
public string[] SectionNames
{
get
{
lock (_sectionNamesLock)
{
// Use the cached data if possible
if (_sectionNames != null)
return _sectionNames;
// Otherwise, build and return the cached array
_sectionNames = new string[_executable.SectionTable.Length];
for (int i = 0; i < _sectionNames.Length; i++)
{
var section = _executable.SectionTable[i];
// TODO: Handle long section names with leading `/`
byte[] sectionNameBytes = section.Name;
string sectionNameString = Encoding.UTF8.GetString(sectionNameBytes).TrimEnd('\0');
_sectionNames[i] = sectionNameString;
}
return _sectionNames;
}
}
}
///
/// Dictionary of resource data
///
public Dictionary ResourceData
{
get
{
lock (_resourceDataLock)
{
// Use the cached data if possible
if (_resourceData != null)
return _resourceData;
// If we have no resource table, just return
if (_executable.OptionalHeader?.ResourceTable == null
|| _executable.OptionalHeader.ResourceTable.VirtualAddress == 0
|| _executable.ResourceDirectoryTable == null)
return null;
// Otherwise, build and return the cached dictionary
ParseResourceDirectoryTable(_executable.ResourceDirectoryTable, types: new List