using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using SabreTools.Data.Extensions;
using SabreTools.Data.Models.COFF;
using SabreTools.Data.Models.COFF.SymbolTableEntries;
using SabreTools.Data.Models.PortableExecutable;
using SabreTools.Data.Models.PortableExecutable.Resource.Entries;
using SabreTools.IO.Extensions;
using SabreTools.Matching;
using SabreTools.Numerics.Extensions;
using SabreTools.Text.Extensions;
namespace SabreTools.Wrappers
{
public partial class PortableExecutable : IPrintable
{
#if NETCOREAPP
///
public string ExportJSON() => System.Text.Json.JsonSerializer.Serialize(Model, _jsonSerializerOptions);
#endif
///
public void PrintInformation(StringBuilder builder)
{
builder.AppendLine("Portable Executable Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
// Stub
Print(builder, Model.Stub.Header);
// Header
Print(builder, Model.Signature, Model.FileHeader);
Print(builder, Model.OptionalHeader, Model.SectionTable);
// COFF Tables
Print(builder, Model.SectionTable);
Print(builder, Model.SymbolTable);
Print(builder, Model.StringTable);
// Export Table
Print(builder, Model.ExportDirectoryTable, Model.SectionTable);
Print(builder, Model.ExportAddressTable, Model.SectionTable);
Print(builder, Model.NamePointerTable);
Print(builder, Model.OrdinalTable);
Print(builder, Model.ExportNameTable);
// Import Table
Print(builder, Model.ImportDirectoryTable, Model.SectionTable);
Print(builder, Model.ImportLookupTables, Model.SectionTable);
Print(builder, Model.ImportAddressTables, Model.SectionTable);
Print(builder, Model.HintNameTable);
// Resource Table
Print(builder, Model.ResourceDirectoryTable, Model.SectionTable);
Print(builder, Model.AttributeCertificateTable);
Print(builder, Model.DelayLoadDirectoryTable, Model.SectionTable);
// Named Sections
Print(builder, Model.BaseRelocationTable, Model.SectionTable);
Print(builder, Model.DebugTable);
}
private static void Print(StringBuilder builder, Data.Models.MSDOS.ExecutableHeader header)
{
builder.AppendLine(" MS-DOS Stub Header Information:");
builder.AppendLine(" -------------------------");
builder.AppendLine(header.Magic, " Magic number");
builder.AppendLine(header.LastPageBytes, " Last page bytes");
builder.AppendLine(header.Pages, " Pages");
builder.AppendLine(header.RelocationItems, " Relocation items");
builder.AppendLine(header.HeaderParagraphSize, " Header paragraph size");
builder.AppendLine(header.MinimumExtraParagraphs, " Minimum extra paragraphs");
builder.AppendLine(header.MaximumExtraParagraphs, " Maximum extra paragraphs");
builder.AppendLine(header.InitialSSValue, " Initial SS value");
builder.AppendLine(header.InitialSPValue, " Initial SP value");
builder.AppendLine(header.Checksum, " Checksum");
builder.AppendLine(header.InitialIPValue, " Initial IP value");
builder.AppendLine(header.InitialCSValue, " Initial CS value");
builder.AppendLine(header.RelocationTableAddr, " Relocation table address");
builder.AppendLine(header.OverlayNumber, " Overlay number");
builder.AppendLine();
builder.AppendLine(" MS-DOS Stub Extended Header Information:");
builder.AppendLine(" -------------------------");
builder.AppendLine(header.Reserved1, " Reserved words");
builder.AppendLine(header.OEMIdentifier, " OEM identifier");
builder.AppendLine(header.OEMInformation, " OEM information");
builder.AppendLine(header.Reserved2, " Reserved words");
builder.AppendLine(header.NewExeHeaderAddr, " New EXE header address");
builder.AppendLine();
}
private static void Print(StringBuilder builder, string? signature, FileHeader header)
{
builder.AppendLine(" File Header Information:");
builder.AppendLine(" -------------------------");
builder.AppendLine(signature, " Signature");
builder.AppendLine($" Machine: {header.Machine} (0x{header.Machine:X})");
builder.AppendLine(header.NumberOfSections, " Number of sections");
builder.AppendLine(header.TimeDateStamp, " Time/Date stamp");
builder.AppendLine(header.PointerToSymbolTable, " Pointer to symbol table");
builder.AppendLine(header.NumberOfSymbols, " Number of symbols");
builder.AppendLine(header.SizeOfOptionalHeader, " Size of optional header");
builder.AppendLine($" Characteristics: {header.Characteristics} (0x{header.Characteristics:X})");
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.OptionalHeader header, SectionHeader[] table)
{
builder.AppendLine(" Optional Header Information:");
builder.AppendLine(" -------------------------");
builder.AppendLine($" Magic: {header.Magic} (0x{header.Magic:X})");
builder.AppendLine(header.MajorLinkerVersion, " Major linker version");
builder.AppendLine(header.MinorLinkerVersion, " Minor linker version");
builder.AppendLine(header.SizeOfCode, " Size of code section");
builder.AppendLine(header.SizeOfInitializedData, " Size of initialized data");
builder.AppendLine(header.SizeOfUninitializedData, " Size of uninitialized data");
builder.AppendLine(header.AddressOfEntryPoint, " Address of entry point");
builder.AppendLine(header.BaseOfCode, " Base of code");
if (header.Magic == OptionalHeaderMagicNumber.PE32)
builder.AppendLine(header.BaseOfData, " Base of data");
builder.AppendLine(header.ImageBase, " Image base");
builder.AppendLine(header.SectionAlignment, " Section alignment");
builder.AppendLine(header.FileAlignment, " File alignment");
builder.AppendLine(header.MajorOperatingSystemVersion, " Major operating system version");
builder.AppendLine(header.MinorOperatingSystemVersion, " Minor operating system version");
builder.AppendLine(header.MajorImageVersion, " Major image version");
builder.AppendLine(header.MinorImageVersion, " Minor image version");
builder.AppendLine(header.MajorSubsystemVersion, " Major subsystem version");
builder.AppendLine(header.MinorSubsystemVersion, " Minor subsystem version");
builder.AppendLine(header.Win32VersionValue, " Win32 version value");
builder.AppendLine(header.SizeOfImage, " Size of image");
builder.AppendLine(header.SizeOfHeaders, " Size of headers");
builder.AppendLine(header.CheckSum, " Checksum");
builder.AppendLine($" Subsystem: {header.Subsystem} (0x{header.Subsystem:X})");
builder.AppendLine($" DLL characteristics: {header.DllCharacteristics} (0x{header.DllCharacteristics:X})");
builder.AppendLine(header.SizeOfStackReserve, " Size of stack reserve");
builder.AppendLine(header.SizeOfStackCommit, " Size of stack commit");
builder.AppendLine(header.SizeOfHeapReserve, " Size of heap reserve");
builder.AppendLine(header.SizeOfHeapCommit, " Size of heap commit");
builder.AppendLine(header.LoaderFlags, " Loader flags");
builder.AppendLine(header.NumberOfRvaAndSizes, " Number of data-directory entries");
if (header.ExportTable is not null)
{
builder.AppendLine(" Export Table (1)");
builder.AppendLine(header.ExportTable.VirtualAddress, " Virtual address");
builder.AppendLine(header.ExportTable.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.ExportTable.Size, " Size");
}
if (header.ImportTable is not null)
{
builder.AppendLine(" Import Table (2)");
builder.AppendLine(header.ImportTable.VirtualAddress, " Virtual address");
builder.AppendLine(header.ImportTable.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.ImportTable.Size, " Size");
}
if (header.ResourceTable is not null)
{
builder.AppendLine(" Resource Table (3)");
builder.AppendLine(header.ResourceTable.VirtualAddress, " Virtual address");
builder.AppendLine(header.ResourceTable.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.ResourceTable.Size, " Size");
}
if (header.ExceptionTable is not null)
{
builder.AppendLine(" Exception Table (4)");
builder.AppendLine(header.ExceptionTable.VirtualAddress, " Virtual address");
builder.AppendLine(header.ExceptionTable.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.ExceptionTable.Size, " Size");
}
if (header.CertificateTable is not null)
{
builder.AppendLine(" Certificate Table (5)");
builder.AppendLine(" Virtual address: N/A");
builder.AppendLine(header.CertificateTable.VirtualAddress, " Physical address");
builder.AppendLine(header.CertificateTable.Size, " Size");
}
if (header.BaseRelocationTable is not null)
{
builder.AppendLine(" Base Relocation Table (6)");
builder.AppendLine(header.BaseRelocationTable.VirtualAddress, " Virtual address");
builder.AppendLine(header.BaseRelocationTable.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.BaseRelocationTable.Size, " Size");
}
if (header.Debug is not null)
{
builder.AppendLine(" Debug Table (7)");
builder.AppendLine(header.Debug.VirtualAddress, " Virtual address");
builder.AppendLine(header.Debug.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.Debug.Size, " Size");
}
if (header.NumberOfRvaAndSizes >= 8)
{
builder.AppendLine(" Architecture Table (8)");
builder.AppendLine(" Virtual address: 0 (0x00000000)");
builder.AppendLine(" Physical address: 0 (0x00000000)");
builder.AppendLine(" Size: 0 (0x00000000)");
}
if (header.GlobalPtr is not null)
{
builder.AppendLine(" Global Pointer Register (9)");
builder.AppendLine(header.GlobalPtr.VirtualAddress, " Virtual address");
builder.AppendLine(header.GlobalPtr.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.GlobalPtr.Size, " Size");
}
if (header.ThreadLocalStorageTable is not null)
{
builder.AppendLine(" Thread Local Storage (TLS) Table (10)");
builder.AppendLine(header.ThreadLocalStorageTable.VirtualAddress, " Virtual address");
builder.AppendLine(header.ThreadLocalStorageTable.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.ThreadLocalStorageTable.Size, " Size");
}
if (header.LoadConfigTable is not null)
{
builder.AppendLine(" Load Config Table (11)");
builder.AppendLine(header.LoadConfigTable.VirtualAddress, " Virtual address");
builder.AppendLine(header.LoadConfigTable.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.LoadConfigTable.Size, " Size");
}
if (header.BoundImport is not null)
{
builder.AppendLine(" Bound Import Table (12)");
builder.AppendLine(header.BoundImport.VirtualAddress, " Virtual address");
builder.AppendLine(header.BoundImport.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.BoundImport.Size, " Size");
}
if (header.ImportAddressTable is not null)
{
builder.AppendLine(" Import Address Table (13)");
builder.AppendLine(header.ImportAddressTable.VirtualAddress, " Virtual address");
builder.AppendLine(header.ImportAddressTable.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.ImportAddressTable.Size, " Size");
}
if (header.DelayImportDescriptor is not null)
{
builder.AppendLine(" Delay Import Descriptor (14)");
builder.AppendLine(header.DelayImportDescriptor.VirtualAddress, " Virtual address");
builder.AppendLine(header.DelayImportDescriptor.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.DelayImportDescriptor.Size, " Size");
}
if (header.CLRRuntimeHeader is not null)
{
builder.AppendLine(" CLR Runtime Header (15)");
builder.AppendLine(header.CLRRuntimeHeader.VirtualAddress, " Virtual address");
builder.AppendLine(header.CLRRuntimeHeader.VirtualAddress.ConvertVirtualAddress(table), " Physical address");
builder.AppendLine(header.CLRRuntimeHeader.Size, " Size");
}
if (header.NumberOfRvaAndSizes >= 16)
{
builder.AppendLine(" Reserved (16)");
builder.AppendLine(" Virtual address: 0 (0x00000000)");
builder.AppendLine(" Physical address: 0 (0x00000000)");
builder.AppendLine(" Size: 0 (0x00000000)");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, SectionHeader[] entries)
{
builder.AppendLine(" Section Table Information:");
builder.AppendLine(" -------------------------");
if (entries is null || entries.Length == 0)
{
builder.AppendLine(" No section table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries!.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Section Table Entry {i}");
builder.AppendLine(entry.Name, " Name", Encoding.ASCII);
builder.AppendLine(entry.VirtualSize, " Virtual size");
builder.AppendLine(entry.VirtualAddress, " Virtual address");
builder.AppendLine(entry.VirtualAddress.ConvertVirtualAddress(entries), " Physical address");
builder.AppendLine(entry.SizeOfRawData, " Size of raw data");
builder.AppendLine(entry.PointerToRawData, " Pointer to raw data");
builder.AppendLine(entry.PointerToRelocations, " Pointer to relocations");
builder.AppendLine(entry.PointerToLinenumbers, " Pointer to linenumbers");
builder.AppendLine(entry.NumberOfRelocations, " Number of relocations");
builder.AppendLine(entry.NumberOfLinenumbers, " Number of linenumbers");
builder.AppendLine($" Characteristics: {entry.Characteristics} (0x{entry.Characteristics:X})");
// TODO: Add COFFRelocations
// TODO: Add COFFLineNumbers
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, BaseEntry[]? entries)
{
builder.AppendLine(" Symbol Table Information:");
builder.AppendLine(" -------------------------");
if (entries is null || entries.Length == 0)
{
builder.AppendLine(" No symbol table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
switch (entry)
{
case StandardRecord item: Print(builder, item, i); break;
case FunctionDefinition item: Print(builder, item, i); break;
case Descriptor item: Print(builder, item, i); break;
case WeakExternal item: Print(builder, item, i); break;
case FileRecord item: Print(builder, item, i); break;
case SectionDefinition item: Print(builder, item, i); break;
case CLRTokenDefinition item: Print(builder, item, i); break;
default: break;
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, StandardRecord entry, int i)
{
builder.AppendLine($" Symbol Table Entry {i} (Standard Record)");
if (entry.ShortName is not null)
{
builder.AppendLine(entry.ShortName, " Short name", Encoding.ASCII);
}
else
{
builder.AppendLine(entry.Zeroes, " Zeroes");
builder.AppendLine(entry.Offset, " Offset");
}
builder.AppendLine(entry.Value, " Value");
builder.AppendLine($" Section number: {entry.SectionNumber} (0x{entry.SectionNumber:X})");
builder.AppendLine($" Symbol type: {entry.SymbolType} (0x{entry.SymbolType:X})");
builder.AppendLine($" Storage class: {entry.StorageClass} (0x{entry.StorageClass:X})");
builder.AppendLine(entry.NumberOfAuxSymbols, " Number of aux symbols");
}
private static void Print(StringBuilder builder, FunctionDefinition entry, int i)
{
builder.AppendLine($" Symbol Table Entry {i} (Function Definition)");
builder.AppendLine(entry.TagIndex, " Tag index");
builder.AppendLine(entry.TotalSize, " Total size");
builder.AppendLine(entry.PointerToLinenumber, " Pointer to linenumber");
builder.AppendLine(entry.PointerToNextFunction, " Pointer to next function");
builder.AppendLine(entry.Unused, " Unused");
}
private static void Print(StringBuilder builder, Descriptor entry, int i)
{
builder.AppendLine($" Symbol Table Entry {i} (.bf and .ef Symbol)");
builder.AppendLine(entry.Unused1, " Unused");
builder.AppendLine(entry.Linenumber, " Linenumber");
builder.AppendLine(entry.Unused2, " Unused");
builder.AppendLine(entry.PointerToNextFunction, " Pointer to next function");
builder.AppendLine(entry.Unused3, " Unused");
}
private static void Print(StringBuilder builder, WeakExternal entry, int i)
{
builder.AppendLine($" Symbol Table Entry {i} (Weak External)");
builder.AppendLine(entry.TagIndex, " Tag index");
builder.AppendLine(entry.Characteristics, " Characteristics");
builder.AppendLine(entry.Unused, " Unused");
}
private static void Print(StringBuilder builder, FileRecord entry, int i)
{
builder.AppendLine($" Symbol Table Entry {i} (File)");
builder.AppendLine(entry.FileName, " File name", Encoding.ASCII);
}
private static void Print(StringBuilder builder, SectionDefinition entry, int i)
{
builder.AppendLine($" Symbol Table Entry {i} (Section Defintion)");
builder.AppendLine(entry.Length, " Length");
builder.AppendLine(entry.NumberOfRelocations, " Number of relocations");
builder.AppendLine(entry.NumberOfLinenumbers, " Number of linenumbers");
builder.AppendLine(entry.CheckSum, " Checksum");
builder.AppendLine(entry.Number, " Number");
builder.AppendLine(entry.Selection, " Selection");
builder.AppendLine(entry.Unused, " Unused");
}
private static void Print(StringBuilder builder, CLRTokenDefinition entry, int i)
{
builder.AppendLine($" Symbol Table Entry {i} (CLR Token Defintion)");
builder.AppendLine(entry.AuxType, " Aux type");
builder.AppendLine(entry.Reserved1, " Reserved");
builder.AppendLine(entry.SymbolTableIndex, " Symbol table index");
builder.AppendLine(entry.Reserved2, " Reserved");
}
private static void Print(StringBuilder builder, Data.Models.COFF.StringTable? stringTable)
{
builder.AppendLine(" String Table Information:");
builder.AppendLine(" -------------------------");
if (stringTable?.Strings is null || stringTable.Strings.Length == 0)
{
builder.AppendLine(" No string table items");
builder.AppendLine();
return;
}
builder.AppendLine(stringTable.TotalSize, " Total size");
for (int i = 0; i < stringTable.Strings.Length; i++)
{
string? entry = stringTable.Strings[i];
builder.AppendLine($" String Table Entry {i})");
builder.AppendLine(entry, " Value");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.AttributeCertificate.Entry[]? entries)
{
builder.AppendLine(" Attribute Certificate Table Information:");
builder.AppendLine(" -------------------------");
if (entries is null || entries.Length == 0)
{
builder.AppendLine(" No attribute certificate table items");
builder.AppendLine();
return;
}
// Create the deserializer
var deserializer = new Serialization.Readers.AbstractSyntaxNotationOne();
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Attribute Certificate Table Entry {i}");
builder.AppendLine(entry.Length, " Length");
builder.AppendLine($" Revision: {entry.Revision} (0x{entry.Revision:X})");
builder.AppendLine($" Certificate type: {entry.CertificateType} (0x{entry.CertificateType:X})");
builder.AppendLine();
if (entry.CertificateType == WindowsCertificateType.WIN_CERT_TYPE_PKCS_SIGNED_DATA)
{
builder.AppendLine(" Certificate Data [Formatted]");
builder.AppendLine(" -------------------------");
if (entry.Certificate is null)
{
builder.AppendLine(" INVALID DATA FOUND");
}
else
{
var topLevelValues = deserializer.Deserialize(entry.Certificate, 0);
if (topLevelValues is null)
{
builder.AppendLine(" INVALID DATA FOUND");
builder.AppendLine(entry.Certificate, " Raw data");
}
else
{
foreach (Data.Models.ASN1.TypeLengthValue tlv in topLevelValues)
{
string tlvString = tlv.Format(paddingLevel: 4);
builder.AppendLine(tlvString);
}
}
}
}
else
{
builder.AppendLine(" Certificate Data [Binary]");
builder.AppendLine(" -------------------------");
try
{
builder.AppendLine(entry.Certificate, " Raw data");
}
catch
{
builder.AppendLine(" [DATA TOO LARGE TO FORMAT]");
}
}
builder.AppendLine();
}
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.DelayLoad.DirectoryTable? table, SectionHeader[] sections)
{
builder.AppendLine(" Delay-Load Directory Table Information:");
builder.AppendLine(" -------------------------");
if (table is null)
{
builder.AppendLine(" No delay-load directory table items");
builder.AppendLine();
return;
}
builder.AppendLine(table.Attributes, " Attributes");
builder.AppendLine(table.NameRVA, " Name RVA");
builder.AppendLine(table.NameRVA.ConvertVirtualAddress(sections), " Name physical address");
builder.AppendLine(table.ModuleHandle, " Module handle");
builder.AppendLine(table.DelayImportAddressTable, " Delay import address table RVA");
builder.AppendLine(table.DelayImportAddressTable.ConvertVirtualAddress(sections), " Delay import address table physical address");
builder.AppendLine(table.DelayImportNameTable, " Delay import name table RVA");
builder.AppendLine(table.DelayImportNameTable.ConvertVirtualAddress(sections), " Delay import name table physical address");
builder.AppendLine(table.BoundDelayImportTable, " Bound delay import table RVA");
builder.AppendLine(table.BoundDelayImportTable.ConvertVirtualAddress(sections), " Bound delay import table physical address");
builder.AppendLine(table.UnloadDelayImportTable, " Unload delay import table RVA");
builder.AppendLine(table.UnloadDelayImportTable.ConvertVirtualAddress(sections), " Unload delay import table physical address");
builder.AppendLine(table.TimeStamp, " Timestamp");
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.BaseRelocation.Block[]? entries, SectionHeader[] sections)
{
builder.AppendLine(" Base Relocation Table Information:");
builder.AppendLine(" -------------------------");
if (entries is null || entries.Length == 0)
{
builder.AppendLine(" No base relocation table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var baseRelocationTableEntry = entries[i];
builder.AppendLine($" Base Relocation Table Entry {i}");
builder.AppendLine(baseRelocationTableEntry.PageRVA, " Page RVA");
builder.AppendLine(baseRelocationTableEntry.PageRVA.ConvertVirtualAddress(sections), " Page physical address");
builder.AppendLine(baseRelocationTableEntry.BlockSize, " Block size");
builder.AppendLine();
builder.AppendLine($" Base Relocation Table {i} Type and Offset Information:");
builder.AppendLine(" -------------------------");
if (baseRelocationTableEntry.TypeOffsetFieldEntries.Length == 0)
{
builder.AppendLine(" No base relocation table type and offset entries");
builder.AppendLine();
continue;
}
for (int j = 0; j < baseRelocationTableEntry.TypeOffsetFieldEntries.Length; j++)
{
var typeOffsetFieldEntry = baseRelocationTableEntry.TypeOffsetFieldEntries[j];
builder.AppendLine($" Type and Offset Entry {j}");
builder.AppendLine($" Type: {typeOffsetFieldEntry.BaseRelocationType} (0x{typeOffsetFieldEntry.BaseRelocationType:X})");
builder.AppendLine(typeOffsetFieldEntry.Offset, " Offset");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.DebugData.Table? table)
{
builder.AppendLine(" Debug Table Information:");
builder.AppendLine(" -------------------------");
if (table?.DebugDirectoryTable is null || table.DebugDirectoryTable.Length == 0)
{
builder.AppendLine(" No debug table items");
builder.AppendLine();
return;
}
for (int i = 0; i < table.DebugDirectoryTable.Length; i++)
{
var entry = table.DebugDirectoryTable[i];
builder.AppendLine($" Debug Directory Table Entry {i}");
builder.AppendLine(entry.Characteristics, " Characteristics");
builder.AppendLine(entry.TimeDateStamp, " Time/Date stamp");
builder.AppendLine(entry.MajorVersion, " Major version");
builder.AppendLine(entry.MinorVersion, " Minor version");
builder.AppendLine($" Debug type: {entry.DebugType} (0x{entry.DebugType:X})");
builder.AppendLine(entry.SizeOfData, " Size of data");
builder.AppendLine(entry.AddressOfRawData, " Address of raw data");
builder.AppendLine(entry.PointerToRawData, " Pointer to raw data");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.Export.DirectoryTable? table, SectionHeader[] sections)
{
builder.AppendLine(value: " Export Directory Table Information:");
builder.AppendLine(" -------------------------");
if (table is null)
{
builder.AppendLine(" No export directory table");
}
else
{
builder.AppendLine(table.ExportFlags, " Export flags");
builder.AppendLine(table.TimeDateStamp, " Time/Date stamp");
builder.AppendLine(table.MajorVersion, " Major version");
builder.AppendLine(table.MinorVersion, " Minor version");
builder.AppendLine(table.NameRVA, " Name RVA");
builder.AppendLine(table.NameRVA.ConvertVirtualAddress(sections), " Name physical address");
builder.AppendLine(table.Name, " Name");
builder.AppendLine(table.OrdinalBase, " Ordinal base");
builder.AppendLine(table.AddressTableEntries, " Address table entries");
builder.AppendLine(table.NumberOfNamePointers, " Number of name pointers");
builder.AppendLine(table.ExportAddressTableRVA, " Export address table RVA");
builder.AppendLine(table.ExportAddressTableRVA.ConvertVirtualAddress(sections), " Export address table physical address");
builder.AppendLine(table.NamePointerRVA, " Name pointer table RVA");
builder.AppendLine(table.NamePointerRVA.ConvertVirtualAddress(sections), " Name pointer table physical address");
builder.AppendLine(table.OrdinalTableRVA, " Ordinal table RVA");
builder.AppendLine(table.OrdinalTableRVA.ConvertVirtualAddress(sections), " Ordinal table physical address");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.Export.AddressTableEntry[]? table, SectionHeader[] sections)
{
builder.AppendLine(" Export Address Table Information:");
builder.AppendLine(" -------------------------");
if (table is null || table.Length == 0)
{
builder.AppendLine(" No export address table items");
}
else
{
for (int i = 0; i < table.Length; i++)
{
var entry = table[i];
builder.AppendLine($" Export Address Table Entry {i}");
builder.AppendLine(entry.ExportRVA, " Export / Forwarder RVA");
builder.AppendLine(entry.ExportRVA.ConvertVirtualAddress(sections), " Export / Forwarder physical address");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.Export.NamePointerTable? table)
{
builder.AppendLine(" Export Name Pointer Table Information:");
builder.AppendLine(" -------------------------");
if (table?.Pointers is null || table.Pointers.Length == 0)
{
builder.AppendLine(" No export name pointer table items");
}
else
{
for (int i = 0; i < table.Pointers.Length; i++)
{
var entry = table.Pointers[i];
builder.AppendLine($" Export Name Pointer Table Entry {i}");
builder.AppendLine(entry, " Pointer");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.Export.OrdinalTable? table)
{
builder.AppendLine(" Export Ordinal Table Information:");
builder.AppendLine(" -------------------------");
if (table?.Indexes is null || table.Indexes.Length == 0)
{
builder.AppendLine(" No export ordinal table items");
}
else
{
for (int i = 0; i < table.Indexes.Length; i++)
{
var entry = table.Indexes[i];
builder.AppendLine($" Export Ordinal Table Entry {i}");
builder.AppendLine(entry, " Index");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.Export.NameTable? table)
{
builder.AppendLine(" Export Name Table Information:");
builder.AppendLine(" -------------------------");
if (table?.Strings is null || table.Strings.Length == 0)
{
builder.AppendLine(" No export name table items");
}
else
{
for (int i = 0; i < table.Strings.Length; i++)
{
var entry = table.Strings[i];
builder.AppendLine($" Export Name Table Entry {i}");
builder.AppendLine(entry, " String");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.Import.DirectoryTableEntry[]? table, SectionHeader[] sections)
{
builder.AppendLine(" Import Directory Table Information:");
builder.AppendLine(" -------------------------");
if (table is null || table.Length == 0)
{
builder.AppendLine(" No import directory table items");
}
else
{
for (int i = 0; i < table.Length; i++)
{
var entry = table[i];
builder.AppendLine($" Import Directory Table Entry {i}");
builder.AppendLine(entry.ImportLookupTableRVA, " Import lookup table RVA");
builder.AppendLine(entry.ImportLookupTableRVA.ConvertVirtualAddress(sections), " Import lookup table physical address");
builder.AppendLine(entry.TimeDateStamp, " Time/Date stamp");
builder.AppendLine(entry.ForwarderChain, " Forwarder chain");
builder.AppendLine(entry.NameRVA, " Name RVA");
builder.AppendLine(entry.NameRVA.ConvertVirtualAddress(sections), " Name physical address");
builder.AppendLine(entry.Name, " Name");
builder.AppendLine(entry.ImportAddressTableRVA, " Import address table RVA");
builder.AppendLine(entry.ImportAddressTableRVA.ConvertVirtualAddress(sections), " Import address table physical address");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Dictionary? tables, SectionHeader[] sections)
{
builder.AppendLine(" Import Lookup Tables Information:");
builder.AppendLine(" -------------------------");
if (tables is null || tables.Count == 0)
{
builder.AppendLine(" No import lookup tables");
}
else
{
foreach (var kvp in tables)
{
int index = kvp.Key;
var importLookupTable = kvp.Value;
builder.AppendLine();
builder.AppendLine($" Import Lookup Table {index} Information:");
builder.AppendLine(" -------------------------");
if (importLookupTable is null || importLookupTable.Length == 0)
{
builder.AppendLine(" No import lookup table items");
continue;
}
for (int i = 0; i < importLookupTable.Length; i++)
{
var entry = importLookupTable[i];
builder.AppendLine($" Import Lookup Table {index} Entry {i}");
builder.AppendLine(entry.OrdinalNameFlag, " Ordinal/Name flag");
if (entry.OrdinalNameFlag)
{
builder.AppendLine(entry.OrdinalNumber, " Ordinal number");
}
else
{
builder.AppendLine(entry.HintNameTableRVA, " Hint/Name table RVA");
builder.AppendLine(entry.HintNameTableRVA.ConvertVirtualAddress(sections), " Hint/Name table physical address");
}
}
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Dictionary? tables, SectionHeader[] sections)
{
builder.AppendLine(" Import Address Tables Information:");
builder.AppendLine(" -------------------------");
if (tables is null || tables.Count == 0)
{
builder.AppendLine(" No import address tables");
}
else
{
foreach (var kvp in tables)
{
int index = kvp.Key;
var importAddressTable = kvp.Value;
builder.AppendLine();
builder.AppendLine($" Import Address Table {index} Information:");
builder.AppendLine(" -------------------------");
if (importAddressTable is null || importAddressTable.Length == 0)
{
builder.AppendLine(" No import address table items");
continue;
}
for (int i = 0; i < importAddressTable.Length; i++)
{
var entry = importAddressTable[i];
builder.AppendLine($" Import Address Table {index} Entry {i}");
builder.AppendLine(entry.OrdinalNameFlag, " Ordinal/Name flag");
if (entry.OrdinalNameFlag)
{
builder.AppendLine(entry.OrdinalNumber, " Ordinal number");
}
else
{
builder.AppendLine(entry.HintNameTableRVA, " Hint/Name table RVA");
builder.AppendLine(entry.HintNameTableRVA.ConvertVirtualAddress(sections), " Hint/Name table physical address");
}
}
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.Import.HintNameTableEntry[]? table)
{
builder.AppendLine(" Import Hint/Name Table Information:");
builder.AppendLine(" -------------------------");
if (table is null || table.Length == 0)
{
builder.AppendLine(" No import hint/name table items");
}
else
{
for (int i = 0; i < table.Length; i++)
{
var entry = table[i];
builder.AppendLine($" Hint/Name Table Entry {i}");
builder.AppendLine(entry.Hint, " Hint");
builder.AppendLine(entry.Name, " Name");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.Resource.DirectoryTable? table, SectionHeader[] sections)
{
builder.AppendLine(" Resource Directory Table Information:");
builder.AppendLine(" -------------------------");
if (table is null)
{
builder.AppendLine(" No resource directory table items");
builder.AppendLine();
return;
}
Print(builder, table, level: 0, types: [], sections);
builder.AppendLine();
}
private static void Print(StringBuilder builder, Data.Models.PortableExecutable.Resource.DirectoryTable table, int level, List