using System; using System.IO; namespace BurnOutSharp.Wrappers { public class LinearExecutable : WrapperBase { #region Pass-Through Properties #region MS-DOS Stub #region Standard Fields /// public string 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_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 #region Information Block /// public string Signature => _executable.InformationBlock.Signature; /// public Models.LinearExecutable.ByteOrder ByteOrder => _executable.InformationBlock.ByteOrder; /// public Models.LinearExecutable.WordOrder WordOrder => _executable.InformationBlock.WordOrder; /// public uint ExecutableFormatLevel => _executable.InformationBlock.ExecutableFormatLevel; /// public Models.LinearExecutable.CPUType CPUType => _executable.InformationBlock.CPUType; /// public Models.LinearExecutable.OperatingSystem ModuleOS => _executable.InformationBlock.ModuleOS; /// public uint ModuleVersion => _executable.InformationBlock.ModuleVersion; /// public Models.LinearExecutable.ModuleFlags ModuleTypeFlags => _executable.InformationBlock.ModuleTypeFlags; /// public uint ModuleNumberPages => _executable.InformationBlock.ModuleNumberPages; /// public uint InitialObjectCS => _executable.InformationBlock.InitialObjectCS; /// public uint InitialEIP => _executable.InformationBlock.InitialEIP; /// public uint InitialObjectSS => _executable.InformationBlock.InitialObjectSS; /// public uint InitialESP => _executable.InformationBlock.InitialESP; /// public uint MemoryPageSize => _executable.InformationBlock.MemoryPageSize; /// public uint BytesOnLastPage => _executable.InformationBlock.BytesOnLastPage; /// public uint FixupSectionSize => _executable.InformationBlock.FixupSectionSize; /// public uint FixupSectionChecksum => _executable.InformationBlock.FixupSectionChecksum; /// public uint LoaderSectionSize => _executable.InformationBlock.LoaderSectionSize; /// public uint LoaderSectionChecksum => _executable.InformationBlock.LoaderSectionChecksum; /// public uint ObjectTableOffset => _executable.InformationBlock.ObjectTableOffset; /// public uint ObjectTableCount => _executable.InformationBlock.ObjectTableCount; /// public uint ObjectPageMapOffset => _executable.InformationBlock.ObjectPageMapOffset; /// public uint ObjectIterateDataMapOffset => _executable.InformationBlock.ObjectIterateDataMapOffset; /// public uint ResourceTableOffset => _executable.InformationBlock.ResourceTableOffset; /// public uint ResourceTableCount => _executable.InformationBlock.ResourceTableCount; /// public uint ResidentNamesTableOffset => _executable.InformationBlock.ResidentNamesTableOffset; /// public uint EntryTableOffset => _executable.InformationBlock.EntryTableOffset; /// public uint ModuleDirectivesTableOffset => _executable.InformationBlock.ModuleDirectivesTableOffset; /// public uint ModuleDirectivesCount => _executable.InformationBlock.ModuleDirectivesCount; /// public uint FixupPageTableOffset => _executable.InformationBlock.FixupPageTableOffset; /// public uint FixupRecordTableOffset => _executable.InformationBlock.FixupRecordTableOffset; /// public uint ImportedModulesNameTableOffset => _executable.InformationBlock.ImportedModulesNameTableOffset; /// public uint ImportedModulesCount => _executable.InformationBlock.ImportedModulesCount; /// public uint ImportProcedureNameTableOffset => _executable.InformationBlock.ImportProcedureNameTableOffset; /// public uint PerPageChecksumTableOffset => _executable.InformationBlock.PerPageChecksumTableOffset; /// public uint DataPagesOffset => _executable.InformationBlock.DataPagesOffset; /// public uint PreloadPageCount => _executable.InformationBlock.PreloadPageCount; /// public uint NonResidentNamesTableOffset => _executable.InformationBlock.NonResidentNamesTableOffset; /// public uint NonResidentNamesTableLength => _executable.InformationBlock.NonResidentNamesTableLength; /// public uint NonResidentNamesTableChecksum => _executable.InformationBlock.NonResidentNamesTableChecksum; /// public uint AutomaticDataObject => _executable.InformationBlock.AutomaticDataObject; /// public uint DebugInformationOffset => _executable.InformationBlock.DebugInformationOffset; /// public uint DebugInformationLength => _executable.InformationBlock.DebugInformationLength; /// public uint PreloadInstancePagesNumber => _executable.InformationBlock.PreloadInstancePagesNumber; /// public uint DemandInstancePagesNumber => _executable.InformationBlock.DemandInstancePagesNumber; /// public uint ExtraHeapAllocation => _executable.InformationBlock.ExtraHeapAllocation; #endregion #region Tables /// public Models.LinearExecutable.ObjectTableEntry[] ObjectTable => _executable.ObjectTable; /// public Models.LinearExecutable.ObjectPageMapEntry[] ObjectPageMap => _executable.ObjectPageMap; /// public Models.LinearExecutable.ResourceTableEntry[] ResourceTable => _executable.ResourceTable; /// public Models.LinearExecutable.ResidentNamesTableEntry[] ResidentNamesTable => _executable.ResidentNamesTable; /// public Models.LinearExecutable.EntryTableBundle[] EntryTable => _executable.EntryTable; /// public Models.LinearExecutable.ModuleFormatDirectivesTableEntry[] ModuleFormatDirectivesTable => _executable.ModuleFormatDirectivesTable; /// public Models.LinearExecutable.VerifyRecordDirectiveTableEntry[] VerifyRecordDirectiveTable => _executable.VerifyRecordDirectiveTable; /// public Models.LinearExecutable.PerPageChecksumTableEntry[] PerPageChecksumTable => _executable.PerPageChecksumTable; /// public Models.LinearExecutable.FixupPageTableEntry[] FixupPageTable => _executable.FixupPageTable; /// public Models.LinearExecutable.FixupRecordTableEntry[] FixupRecordTable => _executable.FixupRecordTable; /// public Models.LinearExecutable.ImportModuleNameTableEntry[] ImportModuleNameTable => _executable.ImportModuleNameTable; /// public Models.LinearExecutable.ImportModuleProcedureNameTableEntry[] ImportModuleProcedureNameTable => _executable.ImportModuleProcedureNameTable; /// public Models.LinearExecutable.NonResidentNamesTableEntry[] NonResidentNamesTable => _executable.NonResidentNamesTable; #endregion #region Debug Information /// public string DI_Signature => _executable.DebugInformation?.Signature; /// public Models.LinearExecutable.DebugFormatType? DI_FormatType => _executable.DebugInformation?.FormatType; /// public byte[] DebuggerData => _executable.DebugInformation?.DebuggerData; #endregion #endregion #region Extension Properties // TODO: Determine what extension properties are needed #endregion #region Instance Variables /// /// Internal representation of the executable /// private Models.LinearExecutable.Executable _executable; #endregion #region Constructors /// /// Private constructor /// private LinearExecutable() { } /// /// Create an LE/LX executable from a byte array and offset /// /// Byte array representing the executable /// Offset within the array to parse /// An LE/LX executable wrapper on success, null on failure public static LinearExecutable Create(byte[] data, int offset) { // If the data is invalid if (data == null) return null; // If the offset is out of bounds if (offset < 0 || offset >= data.Length) return null; // Create a memory stream and use that MemoryStream dataStream = new MemoryStream(data, offset, data.Length - offset); return Create(dataStream); } /// /// Create an LE/LX executable from a Stream /// /// Stream representing the executable /// An LE/LX executable wrapper on success, null on failure public static LinearExecutable Create(Stream data) { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) return null; var executable = Builders.LinearExecutable.ParseExecutable(data); if (executable == null) return null; var wrapper = new LinearExecutable { _executable = executable, _dataSource = DataSource.Stream, _streamData = data, }; return wrapper; } #endregion #region Printing /// public override void Print() { Console.WriteLine("New Executable Information:"); Console.WriteLine("-------------------------"); Console.WriteLine(); // Stub PrintStubHeader(); PrintStubExtendedHeader(); // Information Block PrintInformationBlock(); // Tables PrintObjectTable(); PrintObjectPageMap(); PrintResourceTable(); PrintResidentNamesTable(); PrintEntryTable(); PrintModuleFormatDirectivesTable(); PrintVerifyRecordDirectiveTable(); PrintFixupPageTable(); PrintFixupRecordTable(); PrintImportModuleNameTable(); PrintImportModuleProcedureNameTable(); PrintPerPageChecksumTable(); PrintNonResidentNamesTable(); // Debug PrintDebugInformation(); } /// /// Print stub header information /// private void PrintStubHeader() { Console.WriteLine(" MS-DOS Stub Header Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Magic number: {Stub_Magic}"); Console.WriteLine($" Last page bytes: {Stub_LastPageBytes} (0x{Stub_LastPageBytes:X})"); Console.WriteLine($" Pages: {Stub_Pages} (0x{Stub_Pages:X})"); Console.WriteLine($" Relocation items: {Stub_RelocationItems} (0x{Stub_RelocationItems:X})"); Console.WriteLine($" Header paragraph size: {Stub_HeaderParagraphSize} (0x{Stub_HeaderParagraphSize:X})"); Console.WriteLine($" Minimum extra paragraphs: {Stub_MinimumExtraParagraphs} (0x{Stub_MinimumExtraParagraphs:X})"); Console.WriteLine($" Maximum extra paragraphs: {Stub_MaximumExtraParagraphs} (0x{Stub_MaximumExtraParagraphs:X})"); Console.WriteLine($" Initial SS value: {Stub_InitialSSValue} (0x{Stub_InitialSSValue:X})"); Console.WriteLine($" Initial SP value: {Stub_InitialSPValue} (0x{Stub_InitialSPValue:X})"); Console.WriteLine($" Checksum: {Stub_Checksum} (0x{Stub_Checksum:X})"); Console.WriteLine($" Initial IP value: {Stub_InitialIPValue} (0x{Stub_InitialIPValue:X})"); Console.WriteLine($" Initial CS value: {Stub_InitialCSValue} (0x{Stub_InitialCSValue:X})"); Console.WriteLine($" Relocation table address: {Stub_RelocationTableAddr} (0x{Stub_RelocationTableAddr:X})"); Console.WriteLine($" Overlay number: {Stub_OverlayNumber} (0x{Stub_OverlayNumber:X})"); Console.WriteLine(); } /// /// Print stub extended header information /// private void PrintStubExtendedHeader() { Console.WriteLine(" MS-DOS Stub Extended Header Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Reserved words: {string.Join(", ", Stub_Reserved1)}"); Console.WriteLine($" OEM identifier: {Stub_OEMIdentifier} (0x{Stub_OEMIdentifier:X})"); Console.WriteLine($" OEM information: {Stub_OEMInformation} (0x{Stub_OEMInformation:X})"); Console.WriteLine($" Reserved words: {string.Join(", ", Stub_Reserved2)}"); Console.WriteLine($" New EXE header address: {Stub_NewExeHeaderAddr} (0x{Stub_NewExeHeaderAddr:X})"); Console.WriteLine(); } /// /// Print information block information /// private void PrintInformationBlock() { Console.WriteLine(" Information Block Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Signature: {Signature}"); Console.WriteLine($" Byte order: {ByteOrder} (0x{ByteOrder:X})"); Console.WriteLine($" Word order: {WordOrder} (0x{WordOrder:X})"); Console.WriteLine($" Executable format level: {ExecutableFormatLevel} (0x{ExecutableFormatLevel:X})"); Console.WriteLine($" CPU type: {CPUType} (0x{CPUType:X})"); Console.WriteLine($" Module OS: {ModuleOS} (0x{ModuleOS:X})"); Console.WriteLine($" Module version: {ModuleVersion} (0x{ModuleVersion:X})"); Console.WriteLine($" Module type flags: {ModuleTypeFlags} (0x{ModuleTypeFlags:X})"); Console.WriteLine($" Module number pages: {ModuleNumberPages} (0x{ModuleNumberPages:X})"); Console.WriteLine($" Initial object CS: {InitialObjectCS} (0x{InitialObjectCS:X})"); Console.WriteLine($" Initial EIP: {InitialEIP} (0x{InitialEIP:X})"); Console.WriteLine($" Initial object SS: {InitialObjectSS} (0x{InitialObjectSS:X})"); Console.WriteLine($" Initial ESP: {InitialESP} (0x{InitialESP:X})"); Console.WriteLine($" Memory page size: {MemoryPageSize} (0x{MemoryPageSize:X})"); Console.WriteLine($" Bytes on last page: {BytesOnLastPage} (0x{BytesOnLastPage:X})"); Console.WriteLine($" Fix-up section size: {FixupSectionSize} (0x{FixupSectionSize:X})"); Console.WriteLine($" Fix-up section checksum: {FixupSectionChecksum} (0x{FixupSectionChecksum:X})"); Console.WriteLine($" Loader section size: {LoaderSectionSize} (0x{LoaderSectionSize:X})"); Console.WriteLine($" Loader section checksum: {LoaderSectionChecksum} (0x{LoaderSectionChecksum:X})"); Console.WriteLine($" Object table offset: {ObjectTableOffset} (0x{ObjectTableOffset:X})"); Console.WriteLine($" Object table count: {ObjectTableCount} (0x{ObjectTableCount:X})"); Console.WriteLine($" Object page map offset: {ObjectPageMapOffset} (0x{ObjectPageMapOffset:X})"); Console.WriteLine($" Object iterate data map offset: {ObjectIterateDataMapOffset} (0x{ObjectIterateDataMapOffset:X})"); Console.WriteLine($" Resource table offset: {ResourceTableOffset} (0x{ResourceTableOffset:X})"); Console.WriteLine($" Resource table count: {ResourceTableCount} (0x{ResourceTableCount:X})"); Console.WriteLine($" Resident names table offset: {ResidentNamesTableOffset} (0x{ResidentNamesTableOffset:X})"); Console.WriteLine($" Entry table offset: {EntryTableOffset} (0x{EntryTableOffset:X})"); Console.WriteLine($" Module directives table offset: {ModuleDirectivesTableOffset} (0x{ModuleDirectivesTableOffset:X})"); Console.WriteLine($" Module directives table count: {ModuleDirectivesCount} (0x{ModuleDirectivesCount:X})"); Console.WriteLine($" Fix-up page table offset: {FixupPageTableOffset} (0x{FixupPageTableOffset:X})"); Console.WriteLine($" Fix-up record table offset: {FixupRecordTableOffset} (0x{FixupRecordTableOffset:X})"); Console.WriteLine($" Imported modules name table offset: {ImportedModulesNameTableOffset} (0x{ImportedModulesNameTableOffset:X})"); Console.WriteLine($" Imported modules count: {ImportedModulesCount} (0x{ImportedModulesCount:X})"); Console.WriteLine($" Imported procedure name table count: {ImportProcedureNameTableOffset} (0x{ImportProcedureNameTableOffset:X})"); Console.WriteLine($" Per-page checksum table offset: {PerPageChecksumTableOffset} (0x{PerPageChecksumTableOffset:X})"); Console.WriteLine($" Data pages offset: {DataPagesOffset} (0x{DataPagesOffset:X})"); Console.WriteLine($" Preload page count: {PreloadPageCount} (0x{PreloadPageCount:X})"); Console.WriteLine($" Non-resident names table offset: {NonResidentNamesTableOffset} (0x{NonResidentNamesTableOffset:X})"); Console.WriteLine($" Non-resident names table length: {NonResidentNamesTableLength} (0x{NonResidentNamesTableLength:X})"); Console.WriteLine($" Non-resident names table checksum: {NonResidentNamesTableChecksum} (0x{NonResidentNamesTableChecksum:X})"); Console.WriteLine($" Automatic data object: {AutomaticDataObject} (0x{AutomaticDataObject:X})"); Console.WriteLine($" Debug information offset: {DebugInformationOffset} (0x{DebugInformationOffset:X})"); Console.WriteLine($" Debug information length: {DebugInformationLength} (0x{DebugInformationLength:X})"); Console.WriteLine($" Preload instance pages number: {PreloadInstancePagesNumber} (0x{PreloadInstancePagesNumber:X})"); Console.WriteLine($" Demand instance pages number: {DemandInstancePagesNumber} (0x{DemandInstancePagesNumber:X})"); Console.WriteLine($" Extra heap allocation: {ExtraHeapAllocation} (0x{ExtraHeapAllocation:X})"); Console.WriteLine(); } /// /// Print object table information /// private void PrintObjectTable() { Console.WriteLine(" Object Table Information:"); Console.WriteLine(" -------------------------"); if (ObjectTable == null || ObjectTable.Length == 0) { Console.WriteLine(" No object table entries"); } else { for (int i = 0; i < ObjectTable.Length; i++) { var entry = ObjectTable[i]; Console.WriteLine($" Object Table Entry {i}"); Console.WriteLine($" Virtual segment size: {entry.VirtualSegmentSize} (0x{entry.VirtualSegmentSize:X})"); Console.WriteLine($" Relocation base address: {entry.RelocationBaseAddress} (0x{entry.RelocationBaseAddress:X})"); Console.WriteLine($" Object flags: {entry.ObjectFlags} (0x{entry.ObjectFlags:X})"); Console.WriteLine($" Page table index: {entry.PageTableIndex} (0x{entry.PageTableIndex:X})"); Console.WriteLine($" Page table entries: {entry.PageTableEntries} (0x{entry.PageTableEntries:X})"); Console.WriteLine($" Reserved: {entry.Reserved} (0x{entry.Reserved:X})"); } } Console.WriteLine(); } /// /// Print object page map information /// private void PrintObjectPageMap() { Console.WriteLine(" Object Page Map Information:"); Console.WriteLine(" -------------------------"); if (ObjectPageMap == null || ObjectPageMap.Length == 0) { Console.WriteLine(" No object page map entries"); } else { for (int i = 0; i < ObjectPageMap.Length; i++) { var entry = ObjectPageMap[i]; Console.WriteLine($" Object Page Map Entry {i}"); Console.WriteLine($" Page data offset: {entry.PageDataOffset} (0x{entry.PageDataOffset:X})"); Console.WriteLine($" Data size: {entry.DataSize} (0x{entry.DataSize:X})"); Console.WriteLine($" Flags: {entry.Flags} (0x{entry.Flags:X})"); } } Console.WriteLine(); } /// /// Print resource table information /// private void PrintResourceTable() { Console.WriteLine(" Resource Table Information:"); Console.WriteLine(" -------------------------"); if (ResourceTable == null || ResourceTable.Length == 0) { Console.WriteLine(" No resource table entries"); } else { for (int i = 0; i < ResourceTable.Length; i++) { var entry = ResourceTable[i]; Console.WriteLine($" Resource Table Entry {i}"); Console.WriteLine($" Type ID: {entry.TypeID} (0x{entry.TypeID:X})"); Console.WriteLine($" Name ID: {entry.NameID} (0x{entry.NameID:X})"); Console.WriteLine($" Resource size: {entry.ResourceSize} (0x{entry.ResourceSize:X})"); Console.WriteLine($" Object number: {entry.ObjectNumber} (0x{entry.ObjectNumber:X})"); Console.WriteLine($" Offset: {entry.Offset} (0x{entry.Offset:X})"); } } Console.WriteLine(); } /// /// Print resident names table information /// private void PrintResidentNamesTable() { Console.WriteLine(" Resident Names Table Information:"); Console.WriteLine(" -------------------------"); if (ResidentNamesTable == null || ResidentNamesTable.Length == 0) { Console.WriteLine(" No resident names table entries"); } else { for (int i = 0; i < ResidentNamesTable.Length; i++) { var entry = ResidentNamesTable[i]; Console.WriteLine($" Resident Names Table Entry {i}"); Console.WriteLine($" Length: {entry.Length} (0x{entry.Length:X})"); Console.WriteLine($" Name: {entry.Name ?? "[NULL]"}"); Console.WriteLine($" Ordinal number: {entry.OrdinalNumber} (0x{entry.OrdinalNumber:X})"); } } Console.WriteLine(); } /// /// Print entry table information /// private void PrintEntryTable() { Console.WriteLine(" Entry Table Information:"); Console.WriteLine(" -------------------------"); if (EntryTable == null || EntryTable.Length == 0) { Console.WriteLine(" No entry table bundles"); } else { for (int i = 0; i < EntryTable.Length; i++) { var bundle = EntryTable[i]; Console.WriteLine($" Entry Table Bundle {i}"); Console.WriteLine($" Entries: {bundle.Entries} (0x{bundle.Entries:X})"); Console.WriteLine($" Bundle type: {bundle.BundleType} (0x{bundle.BundleType:X})"); if (bundle.TableEntries != null && bundle.TableEntries.Length != 0) { Console.WriteLine(); Console.WriteLine($" Entry Table Entries:"); Console.WriteLine(" -------------------------"); for (int j = 0; j < bundle.TableEntries.Length; j++) { var entry = bundle.TableEntries[j]; Console.WriteLine($" Entry Table Entry {j}"); switch (bundle.BundleType & ~Models.LinearExecutable.BundleType.ParameterTypingInformationPresent) { case Models.LinearExecutable.BundleType.UnusedEntry: Console.WriteLine($" Unused, empty entry"); break; case Models.LinearExecutable.BundleType.SixteenBitEntry: Console.WriteLine($" Object number: {entry.SixteenBitObjectNumber} (0x{entry.SixteenBitObjectNumber:X})"); Console.WriteLine($" Entry flags: {entry.SixteenBitEntryFlags} (0x{entry.SixteenBitEntryFlags:X})"); Console.WriteLine($" Offset: {entry.SixteenBitOffset} (0x{entry.SixteenBitOffset:X})"); break; case Models.LinearExecutable.BundleType.TwoEightySixCallGateEntry: Console.WriteLine($" Object number: {entry.TwoEightySixObjectNumber} (0x{entry.TwoEightySixObjectNumber:X})"); Console.WriteLine($" Entry flags: {entry.TwoEightySixEntryFlags} (0x{entry.TwoEightySixEntryFlags:X})"); Console.WriteLine($" Offset: {entry.TwoEightySixOffset} (0x{entry.TwoEightySixOffset:X})"); Console.WriteLine($" Callgate: {entry.TwoEightySixCallgate} (0x{entry.TwoEightySixCallgate:X})"); break; case Models.LinearExecutable.BundleType.ThirtyTwoBitEntry: Console.WriteLine($" Object number: {entry.ThirtyTwoBitObjectNumber} (0x{entry.ThirtyTwoBitObjectNumber:X})"); Console.WriteLine($" Entry flags: {entry.ThirtyTwoBitEntryFlags} (0x{entry.ThirtyTwoBitEntryFlags:X})"); Console.WriteLine($" Offset: {entry.ThirtyTwoBitOffset} (0x{entry.ThirtyTwoBitOffset:X})"); break; case Models.LinearExecutable.BundleType.ForwarderEntry: Console.WriteLine($" Reserved: {entry.ForwarderReserved} (0x{entry.ForwarderReserved:X})"); Console.WriteLine($" Forwarder flags: {entry.ForwarderFlags} (0x{entry.ForwarderFlags:X})"); Console.WriteLine($" Module ordinal number: {entry.ForwarderModuleOrdinalNumber} (0x{entry.ForwarderModuleOrdinalNumber:X})"); Console.WriteLine($" Procedure name offset: {entry.ProcedureNameOffset} (0x{entry.ProcedureNameOffset:X})"); Console.WriteLine($" Import ordinal number: {entry.ImportOrdinalNumber} (0x{entry.ImportOrdinalNumber:X})"); break; default: Console.WriteLine($" Unknown entry type {bundle.BundleType}"); break; } } } } } Console.WriteLine(); } /// /// Print module format directives table information /// private void PrintModuleFormatDirectivesTable() { Console.WriteLine(" Module Format Directives Table Information:"); Console.WriteLine(" -------------------------"); if (ModuleFormatDirectivesTable == null || ModuleFormatDirectivesTable.Length == 0) { Console.WriteLine(" No module format directives table entries"); } else { for (int i = 0; i < ModuleFormatDirectivesTable.Length; i++) { var entry = ModuleFormatDirectivesTable[i]; Console.WriteLine($" Moduile Format Directives Table Entry {i}"); Console.WriteLine($" Directive number: {entry.DirectiveNumber} (0x{entry.DirectiveNumber:X})"); Console.WriteLine($" Directive data length: {entry.DirectiveDataLength} (0x{entry.DirectiveDataLength:X})"); Console.WriteLine($" Directive data offset: {entry.DirectiveDataOffset} (0x{entry.DirectiveDataOffset:X})"); } } Console.WriteLine(); } /// /// Print verify record directive table information /// private void PrintVerifyRecordDirectiveTable() { Console.WriteLine(" Verify Record Directive Table Information:"); Console.WriteLine(" -------------------------"); if (VerifyRecordDirectiveTable == null || VerifyRecordDirectiveTable.Length == 0) { Console.WriteLine(" No verify record directive table entries"); } else { for (int i = 0; i < VerifyRecordDirectiveTable.Length; i++) { var entry = VerifyRecordDirectiveTable[i]; Console.WriteLine($" Verify Record Directive Table Entry {i}"); Console.WriteLine($" Entry count: {entry.EntryCount} (0x{entry.EntryCount:X})"); Console.WriteLine($" Ordinal index: {entry.OrdinalIndex} (0x{entry.OrdinalIndex:X})"); Console.WriteLine($" Version: {entry.Version} (0x{entry.Version:X})"); Console.WriteLine($" Object entries count: {entry.ObjectEntriesCount} (0x{entry.ObjectEntriesCount:X})"); Console.WriteLine($" Object number in module: {entry.ObjectNumberInModule} (0x{entry.ObjectNumberInModule:X})"); Console.WriteLine($" Object load base address: {entry.ObjectLoadBaseAddress} (0x{entry.ObjectLoadBaseAddress:X})"); Console.WriteLine($" Object virtual address size: {entry.ObjectVirtualAddressSize} (0x{entry.ObjectVirtualAddressSize:X})"); } } Console.WriteLine(); } /// /// Print fix-up page table information /// private void PrintFixupPageTable() { Console.WriteLine(" Fix-up Page Table Information:"); Console.WriteLine(" -------------------------"); if (FixupPageTable == null || FixupPageTable.Length == 0) { Console.WriteLine(" No fix-up page table entries"); } else { for (int i = 0; i < FixupPageTable.Length; i++) { var entry = FixupPageTable[i]; Console.WriteLine($" Fix-up Page Table Entry {i}"); Console.WriteLine($" Offset: {entry.Offset} (0x{entry.Offset:X})"); } } Console.WriteLine(); } /// /// Print fix-up record table information /// private void PrintFixupRecordTable() { Console.WriteLine(" Fix-up Record Table Information:"); Console.WriteLine(" -------------------------"); if (FixupRecordTable == null || FixupRecordTable.Length == 0) { Console.WriteLine(" No fix-up record table entries"); Console.WriteLine(); } else { for (int i = 0; i < FixupRecordTable.Length; i++) { var entry = FixupRecordTable[i]; Console.WriteLine($" Fix-up Record Table Entry {i}"); Console.WriteLine($" Source type: {entry.SourceType} (0x{entry.SourceType:X})"); Console.WriteLine($" Target flags: {entry.TargetFlags} (0x{entry.TargetFlags:X})"); // Source list flag if (entry.SourceType.HasFlag(Models.LinearExecutable.FixupRecordSourceType.SourceListFlag)) Console.WriteLine($" Source offset list count: {entry.SourceOffsetListCount} (0x{entry.SourceOffsetListCount:X})"); else Console.WriteLine($" Source offset: {entry.SourceOffset} (0x{entry.SourceOffset:X})"); // OBJECT / TRGOFF if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.InternalReference)) { // 16-bit Object Number/Module Ordinal Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag)) Console.WriteLine($" Target object number: {entry.TargetObjectNumberWORD} (0x{entry.TargetObjectNumberWORD:X})"); else Console.WriteLine($" Target object number: {entry.TargetObjectNumberByte} (0x{entry.TargetObjectNumberByte:X})"); // 16-bit Selector fixup if (!entry.SourceType.HasFlag(Models.LinearExecutable.FixupRecordSourceType.SixteenBitSelectorFixup)) { // 32-bit Target Offset Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag)) Console.WriteLine($" Target offset: {entry.TargetOffsetDWORD} (0x{entry.TargetOffsetDWORD:X})"); else Console.WriteLine($" Target offset: {entry.TargetOffsetWORD} (0x{entry.TargetOffsetWORD:X})"); } } // MOD ORD# / IMPORT ORD / ADDITIVE else if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.ImportedReferenceByOrdinal)) { // 16-bit Object Number/Module Ordinal Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag)) Console.WriteLine(value: $" Ordinal index import module name table: {entry.OrdinalIndexImportModuleNameTableWORD} (0x{entry.OrdinalIndexImportModuleNameTableWORD:X})"); else Console.WriteLine(value: $" Ordinal index import module name table: {entry.OrdinalIndexImportModuleNameTableByte} (0x{entry.OrdinalIndexImportModuleNameTableByte:X})"); // 8-bit Ordinal Flag & 32-bit Target Offset Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.EightBitOrdinalFlag)) Console.WriteLine(value: $" Imported ordinal number: {entry.ImportedOrdinalNumberByte} (0x{entry.ImportedOrdinalNumberByte:X})"); else if (entry.TargetFlags.HasFlag(flag: Models.LinearExecutable.FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag)) Console.WriteLine(value: $" Imported ordinal number: {entry.ImportedOrdinalNumberDWORD} (0x{entry.ImportedOrdinalNumberDWORD:X})"); else Console.WriteLine(value: $" Imported ordinal number: {entry.ImportedOrdinalNumberWORD} (0x{entry.ImportedOrdinalNumberWORD:X})"); // Additive Fixup Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.AdditiveFixupFlag)) { // 32-bit Additive Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag)) Console.WriteLine(value: $" Additive fixup value: {entry.AdditiveFixupValueDWORD} (0x{entry.AdditiveFixupValueDWORD:X})"); else Console.WriteLine(value: $" Additive fixup value: {entry.AdditiveFixupValueWORD} (0x{entry.AdditiveFixupValueWORD:X})"); } } // MOD ORD# / PROCEDURE NAME OFFSET / ADDITIVE else if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.ImportedReferenceByName)) { // 16-bit Object Number/Module Ordinal Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag)) Console.WriteLine(value: $" Ordinal index import module name table: {entry.OrdinalIndexImportModuleNameTableWORD} (0x{entry.OrdinalIndexImportModuleNameTableWORD:X})"); else Console.WriteLine(value: $" Ordinal index import module name table: {entry.OrdinalIndexImportModuleNameTableByte} (0x{entry.OrdinalIndexImportModuleNameTableByte:X})"); // 32-bit Target Offset Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag)) Console.WriteLine(value: $" Offset import procedure name table: {entry.OffsetImportProcedureNameTableDWORD} (0x{entry.OffsetImportProcedureNameTableDWORD:X})"); else Console.WriteLine(value: $" Offset import procedure name table: {entry.OffsetImportProcedureNameTableWORD} (0x{entry.OffsetImportProcedureNameTableWORD:X})"); // Additive Fixup Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.AdditiveFixupFlag)) { // 32-bit Additive Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag)) Console.WriteLine(value: $" Additive fixup value: {entry.AdditiveFixupValueDWORD} (0x{entry.AdditiveFixupValueDWORD:X})"); else Console.WriteLine(value: $" Additive fixup value: {entry.AdditiveFixupValueWORD} (0x{entry.AdditiveFixupValueWORD:X})"); } } // ORD # / ADDITIVE else if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.InternalReferenceViaEntryTable)) { // 16-bit Object Number/Module Ordinal Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag)) Console.WriteLine($" Target object number: {entry.TargetObjectNumberWORD} (0x{entry.TargetObjectNumberWORD:X})"); else Console.WriteLine($" Target object number: {entry.TargetObjectNumberByte} (0x{entry.TargetObjectNumberByte:X})"); // Additive Fixup Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.AdditiveFixupFlag)) { // 32-bit Additive Flag if (entry.TargetFlags.HasFlag(Models.LinearExecutable.FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag)) Console.WriteLine(value: $" Additive fixup value: {entry.AdditiveFixupValueDWORD} (0x{entry.AdditiveFixupValueDWORD:X})"); else Console.WriteLine(value: $" Additive fixup value: {entry.AdditiveFixupValueWORD} (0x{entry.AdditiveFixupValueWORD:X})"); } } // No other top-level flags recognized else { Console.WriteLine($" Unknown entry format"); } Console.WriteLine(); Console.WriteLine($" Source Offset List:"); Console.WriteLine(" -------------------------"); if (entry.SourceOffsetList == null || entry.SourceOffsetList.Length == 0) { Console.WriteLine($" No source offset list entries"); } else { for (int j = 0; j < entry.SourceOffsetList.Length; j++) { Console.WriteLine($" Source Offset List Entry {j}: {entry.SourceOffsetList[j]} (0x{entry.SourceOffsetList[j]:X})"); } } Console.WriteLine(); } } } /// /// Print import module name table information /// private void PrintImportModuleNameTable() { Console.WriteLine(" Import Module Name Table Information:"); Console.WriteLine(" -------------------------"); if (ImportModuleNameTable == null || ImportModuleNameTable.Length == 0) { Console.WriteLine(" No import module name table entries"); } else { for (int i = 0; i < ImportModuleNameTable.Length; i++) { var entry = ImportModuleNameTable[i]; Console.WriteLine($" Import Module Name Table Entry {i}"); Console.WriteLine($" Length: {entry.Length} (0x{entry.Length:X})"); Console.WriteLine($" Name: {entry.Name ?? "[NULL]"}"); } } Console.WriteLine(); } /// /// Print import module procedure name table information /// private void PrintImportModuleProcedureNameTable() { Console.WriteLine(" Import Module Procedure Name Table Information:"); Console.WriteLine(" -------------------------"); if (ImportModuleProcedureNameTable == null || ImportModuleProcedureNameTable.Length == 0) { Console.WriteLine(" No import module procedure name table entries"); } else { for (int i = 0; i < ImportModuleProcedureNameTable.Length; i++) { var entry = ImportModuleProcedureNameTable[i]; Console.WriteLine($" Import Module Procedure Name Table Entry {i}"); Console.WriteLine($" Length: {entry.Length} (0x{entry.Length:X})"); Console.WriteLine($" Name: {entry.Name ?? "[NULL]"}"); } } Console.WriteLine(); } /// /// Print per-page checksum table information /// private void PrintPerPageChecksumTable() { Console.WriteLine(" Per-Page Checksum Table Information:"); Console.WriteLine(" -------------------------"); if (PerPageChecksumTable == null || PerPageChecksumTable.Length == 0) { Console.WriteLine(" No per-page checksum table entries"); } else { for (int i = 0; i < PerPageChecksumTable.Length; i++) { var entry = PerPageChecksumTable[i]; Console.WriteLine($" Per-Page Checksum Table Entry {i}"); Console.WriteLine($" Checksum: {entry.Checksum} (0x{entry.Checksum:X})"); } } Console.WriteLine(); } /// /// Print non-resident names table information /// private void PrintNonResidentNamesTable() { Console.WriteLine(" Non-Resident Names Table Information:"); Console.WriteLine(" -------------------------"); if (NonResidentNamesTable == null || NonResidentNamesTable.Length == 0) { Console.WriteLine(" No non-resident names table entries"); } else { for (int i = 0; i < NonResidentNamesTable.Length; i++) { var entry = NonResidentNamesTable[i]; Console.WriteLine($" Non-Resident Names Table Entry {i}"); Console.WriteLine($" Length: {entry.Length} (0x{entry.Length:X})"); Console.WriteLine($" Name: {entry.Name ?? "[NULL]"}"); Console.WriteLine($" Ordinal number: {entry.OrdinalNumber} (0x{entry.OrdinalNumber:X})"); } } Console.WriteLine(); } /// /// Print debug information /// private void PrintDebugInformation() { Console.WriteLine(" Debug Information:"); Console.WriteLine(" -------------------------"); if (_executable.DebugInformation == null) { Console.WriteLine(" No debug information"); } else { Console.WriteLine($" Signature: {DI_Signature ?? "[NULL]"}"); Console.WriteLine($" Format type: {DI_FormatType} (0x{DI_FormatType:X})"); // Debugger data } Console.WriteLine(); } #if NET6_0_OR_GREATER /// public override string ExportJSON() => System.Text.Json.JsonSerializer.Serialize(_executable, _jsonSerializerOptions); #endif #endregion #region REMOVE -- DO NOT USE /// /// Read an arbitrary range from the source /// /// The start of where to read data from, -1 means start of source /// How many bytes to read, -1 means read until end /// Byte array representing the range, null on error [Obsolete] public byte[] ReadArbitraryRange(int rangeStart = -1, int length = -1) { // If we have an unset range start, read from the start of the source if (rangeStart == -1) rangeStart = 0; // If we have an unset length, read the whole source if (length == -1) { switch (_dataSource) { case DataSource.ByteArray: length = _byteArrayData.Length - _byteArrayOffset; break; case DataSource.Stream: length = (int)_streamData.Length; break; } } return ReadFromDataSource(rangeStart, length); } #endregion } }