diff --git a/BurnOutSharp.Wrappers/LinearExecutable.cs b/BurnOutSharp.Wrappers/LinearExecutable.cs index afdeeab5..6449afa4 100644 --- a/BurnOutSharp.Wrappers/LinearExecutable.cs +++ b/BurnOutSharp.Wrappers/LinearExecutable.cs @@ -286,6 +286,8 @@ namespace BurnOutSharp.Wrappers #endregion + #region Constructors + /// /// Private constructor /// @@ -333,11 +335,11 @@ namespace BurnOutSharp.Wrappers return wrapper; } + #endregion + #region Printing - /// - /// Pretty print the Linear Executable information - /// + /// public override void Print() { // TODO: Implement printing diff --git a/BurnOutSharp.Wrappers/MSDOS.cs b/BurnOutSharp.Wrappers/MSDOS.cs index 53e96ce3..12093b05 100644 --- a/BurnOutSharp.Wrappers/MSDOS.cs +++ b/BurnOutSharp.Wrappers/MSDOS.cs @@ -90,6 +90,8 @@ namespace BurnOutSharp.Wrappers #endregion + #region Constructors + /// /// Private constructor /// @@ -137,17 +139,26 @@ namespace BurnOutSharp.Wrappers return wrapper; } + #endregion + #region Printing - /// - /// Pretty print the MS-DOS executable information - /// + /// public override void Print() { Console.WriteLine("MS-DOS Executable Information:"); Console.WriteLine("-------------------------"); Console.WriteLine(); + PrintHeader(); + PrintRelocationTable(); + } + + /// + /// Print header information + /// + private void PrintHeader() + { Console.WriteLine(" Header Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Magic number: {BitConverter.ToString(_executable.Header.Magic).Replace("-", string.Empty)}"); @@ -164,7 +175,13 @@ namespace BurnOutSharp.Wrappers Console.WriteLine($" Initial CS value: {_executable.Header.InitialCSValue}"); Console.WriteLine($" Relocation table address: {_executable.Header.RelocationTableAddr}"); Console.WriteLine($" Overlay number: {_executable.Header.OverlayNumber}"); + } + /// + /// Print relocation table information + /// + private void PrintRelocationTable() + { Console.WriteLine(" Relocation Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.Header.RelocationItems == 0 || _executable.RelocationTable.Length == 0) diff --git a/BurnOutSharp.Wrappers/NewExecutable.cs b/BurnOutSharp.Wrappers/NewExecutable.cs index ce40229d..7ebba654 100644 --- a/BurnOutSharp.Wrappers/NewExecutable.cs +++ b/BurnOutSharp.Wrappers/NewExecutable.cs @@ -218,6 +218,8 @@ namespace BurnOutSharp.Wrappers #endregion + #region Constructors + /// /// Private constructor /// @@ -264,23 +266,41 @@ namespace BurnOutSharp.Wrappers }; return wrapper; } - + + #endregion + #region Printing - - /// - /// Pretty print the New Executable information - /// + + /// public override void Print() { Console.WriteLine("New Executable Information:"); Console.WriteLine("-------------------------"); Console.WriteLine(); - Console.WriteLine(" MS-DOS Stub Information:"); - Console.WriteLine(" -------------------------"); - Console.WriteLine(); + // Stub + PrintStubHeader(); + PrintStubExtendedHeader(); - Console.WriteLine(" Header Information:"); + // Header + PrintHeader(); + + // Tables + PrintSegmentTable(); + PrintResourceTable(); + PrintResidentNameTable(); + PrintModuleReferenceTable(); + PrintImportedNameTable(); + PrintEntryTable(); + PrintNonresidentNameTable(); + } + + /// + /// Print stub header information + /// + private void PrintStubHeader() + { + Console.WriteLine(" MS-DOS Stub Header Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Magic number: {BitConverter.ToString(_executable.Stub.Header.Magic).Replace("-", string.Empty)}"); Console.WriteLine($" Last page bytes: {_executable.Stub.Header.LastPageBytes}"); @@ -297,8 +317,14 @@ namespace BurnOutSharp.Wrappers Console.WriteLine($" Relocation table address: {_executable.Stub.Header.RelocationTableAddr}"); Console.WriteLine($" Overlay number: {_executable.Stub.Header.OverlayNumber}"); Console.WriteLine(); + } - Console.WriteLine(" Extended Header Information:"); + /// + /// Print stub extended header information + /// + private void PrintStubExtendedHeader() + { + Console.WriteLine(" MS-DOS Stub Extended Header Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Reserved words: {string.Join(", ", _executable.Stub.Header.Reserved1)}"); Console.WriteLine($" OEM identifier: {_executable.Stub.Header.OEMIdentifier}"); @@ -306,7 +332,13 @@ namespace BurnOutSharp.Wrappers Console.WriteLine($" Reserved words: {string.Join(", ", _executable.Stub.Header.Reserved2)}"); Console.WriteLine($" New EXE header address: {_executable.Stub.Header.NewExeHeaderAddr}"); Console.WriteLine(); + } + /// + /// Print header information + /// + private void PrintHeader() + { Console.WriteLine(" Header Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Magic number: {BitConverter.ToString(_executable.Header.Magic).Replace("-", string.Empty)}"); @@ -341,7 +373,13 @@ namespace BurnOutSharp.Wrappers Console.WriteLine($" Windows SDK revision: {_executable.Header.WindowsSDKRevision}"); Console.WriteLine($" Windows SDK version: {_executable.Header.WindowsSDKVersion}"); Console.WriteLine(); + } + /// + /// Print segment table information + /// + private void PrintSegmentTable() + { Console.WriteLine(" Segment Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.Header.FileSegmentCount == 0 || _executable.SegmentTable.Length == 0) @@ -361,7 +399,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print resource table information + /// + private void PrintResourceTable() + { Console.WriteLine(" Resource Table Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Alignment shift count: {_executable.ResourceTable.AlignmentShiftCount}"); @@ -415,7 +459,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print resident-name table information + /// + private void PrintResidentNameTable() + { Console.WriteLine(" Resident-Name Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.Header.ResidentNameTableOffset == 0 || _executable.ResidentNameTable.Length == 0) @@ -434,7 +484,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print module-reference table information + /// + private void PrintModuleReferenceTable() + { Console.WriteLine(" Module-Reference Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.Header.ModuleReferenceTableSize == 0 || _executable.ModuleReferenceTable.Length == 0) @@ -452,7 +508,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print imported-name table information + /// + private void PrintImportedNameTable() + { Console.WriteLine(" Imported-Name Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.Header.ImportedNamesTableOffset == 0 || _executable.ImportedNameTable.Count == 0) @@ -469,7 +531,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print entry table information + /// + private void PrintEntryTable() + { Console.WriteLine(" Entry Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.Header.EntryTableSize == 0 || _executable.EntryTable.Length == 0) @@ -500,7 +568,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print nonresident-name table information + /// + private void PrintNonresidentNameTable() + { Console.WriteLine(" Nonresident-Name Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.Header.NonResidentNameTableSize == 0 || _executable.NonResidentNameTable.Length == 0) @@ -520,7 +594,7 @@ namespace BurnOutSharp.Wrappers } Console.WriteLine(); } - + #endregion } } \ No newline at end of file diff --git a/BurnOutSharp.Wrappers/PortableExecutable.cs b/BurnOutSharp.Wrappers/PortableExecutable.cs index f7cab54e..cf9bf32e 100644 --- a/BurnOutSharp.Wrappers/PortableExecutable.cs +++ b/BurnOutSharp.Wrappers/PortableExecutable.cs @@ -137,7 +137,7 @@ namespace BurnOutSharp.Wrappers public uint OH_BaseOfCode => _executable.OptionalHeader.BaseOfCode; /// - public uint? OH_BaseOfData => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32 + public uint? OH_BaseOfData => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32 ? (uint?)_executable.OptionalHeader.BaseOfData : null; @@ -146,7 +146,7 @@ namespace BurnOutSharp.Wrappers #region Windows-Specific Fields /// - public ulong OH_ImageBase => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32 + public ulong OH_ImageBase => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32 ? _executable.OptionalHeader.ImageBase_PE32 : _executable.OptionalHeader.ImageBase_PE32Plus; @@ -193,22 +193,22 @@ namespace BurnOutSharp.Wrappers public Models.PortableExecutable.DllCharacteristics OH_DllCharacteristics => _executable.OptionalHeader.DllCharacteristics; /// - public ulong OH_SizeOfStackReserve => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32 + 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 + 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 + 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 + public ulong OH_SizeOfHeapCommit => _executable.OptionalHeader.Magic == Models.PortableExecutable.OptionalHeaderMagicNumber.PE32 ? _executable.OptionalHeader.SizeOfHeapCommit_PE32 : _executable.OptionalHeader.SizeOfHeapCommit_PE32Plus; @@ -315,6 +315,25 @@ namespace BurnOutSharp.Wrappers #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 /// @@ -322,23 +341,26 @@ namespace BurnOutSharp.Wrappers { get { - // 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++) + lock (_sectionNamesLock) { - var section = _executable.SectionTable[i]; + // Use the cached data if possible + if (_sectionNames != null) + return _sectionNames; - // TODO: Handle long section names with leading `/` - byte[] sectionNameBytes = section.Name; - string sectionNameString = Encoding.UTF8.GetString(sectionNameBytes).TrimEnd('\0'); - _sectionNames[i] = sectionNameString; + // 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; } - - return _sectionNames; } } @@ -353,16 +375,16 @@ namespace BurnOutSharp.Wrappers /// private Models.PortableExecutable.Executable _executable; + /// + /// Overlay data, if it exists + /// + private byte[] _overlayData = null; + /// /// Array of sanitized section names /// private string[] _sectionNames = null; - /// - /// Lock object for concurrent modifications on - /// - private readonly object _rawSectionsLock = new object(); - /// /// Cached raw section data /// @@ -370,6 +392,27 @@ namespace BurnOutSharp.Wrappers #endregion + #region Lock Objects + + /// + /// Lock object for concurrent modifications on + /// + private readonly object _overlayDataLock = new object(); + + /// + /// Lock object for concurrent modifications on + /// + private readonly object _sectionNamesLock = new object(); + + /// + /// Lock object for concurrent modifications on + /// + private readonly object _rawSectionsLock = new object(); + + #endregion + + #region Constructors + /// /// Private constructor /// @@ -417,6 +460,14 @@ namespace BurnOutSharp.Wrappers return wrapper; } + #endregion + + // TODO: Write methods for manifest and version data + // TODO: Cache both objects for easy access + // TODO: Cache all resource objects, key has to be "path" + // TODO: Cache all certificate objects + // TODO: Cache all import/export tables + /// /// Get raw section data from the source file /// @@ -446,8 +497,10 @@ namespace BurnOutSharp.Wrappers uint sectionAddress = section.VirtualAddress.ConvertVirtualAddress(_executable.SectionTable); if (sectionAddress == 0) return null; + uint sectionSize = section.SizeOfRawData; + // TODO: Use section name and index to combat duplicates lock (_rawSectionsLock) { // If we already have cached data, just use that immediately @@ -465,20 +518,38 @@ namespace BurnOutSharp.Wrappers #region Printing - /// - /// Pretty print the New Executable information - /// + /// public override void Print() { Console.WriteLine("Portable Executable Information:"); Console.WriteLine("-------------------------"); Console.WriteLine(); - Console.WriteLine(" MS-DOS Stub Information:"); - Console.WriteLine(" -------------------------"); - Console.WriteLine(); + // Stub + PrintStubHeader(); + PrintStubExtendedHeader(); - Console.WriteLine(" Header Information:"); + // Header + PrintCOFFFileHeader(); + PrintOptionalHeader(); + + // Tables + PrintSectionTable(); + PrintCOFFSymbolTable(); + PrintAttributeCertificateTable(); + PrintDelayLoadDirectoryTable(); + PrintDebugTable(); + PrintExportTable(); + PrintImportTable(); + PrintResourceDirectoryTable(); + } + + /// + /// Print stub header information + /// + private void PrintStubHeader() + { + Console.WriteLine(" MS-DOS Stub Header Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Magic number: {BitConverter.ToString(_executable.Stub.Header.Magic).Replace("-", string.Empty)}"); Console.WriteLine($" Last page bytes: {_executable.Stub.Header.LastPageBytes}"); @@ -495,8 +566,14 @@ namespace BurnOutSharp.Wrappers Console.WriteLine($" Relocation table address: {_executable.Stub.Header.RelocationTableAddr}"); Console.WriteLine($" Overlay number: {_executable.Stub.Header.OverlayNumber}"); Console.WriteLine(); + } - Console.WriteLine(" Extended Header Information:"); + /// + /// Print stub extended header information + /// + private void PrintStubExtendedHeader() + { + Console.WriteLine(" MS-DOS Stub Extended Header Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Reserved words: {string.Join(", ", _executable.Stub.Header.Reserved1)}"); Console.WriteLine($" OEM identifier: {_executable.Stub.Header.OEMIdentifier}"); @@ -504,7 +581,13 @@ namespace BurnOutSharp.Wrappers Console.WriteLine($" Reserved words: {string.Join(", ", _executable.Stub.Header.Reserved2)}"); Console.WriteLine($" New EXE header address: {_executable.Stub.Header.NewExeHeaderAddr}"); Console.WriteLine(); + } + /// + /// Print COFF file header information + /// + private void PrintCOFFFileHeader() + { Console.WriteLine(" COFF File Header Information:"); Console.WriteLine(" -------------------------"); Console.WriteLine($" Signature: {BitConverter.ToString(_executable.Signature).Replace("-", string.Empty)}"); @@ -516,7 +599,13 @@ namespace BurnOutSharp.Wrappers Console.WriteLine($" Size of optional header: {_executable.COFFFileHeader.SizeOfOptionalHeader}"); Console.WriteLine($" Characteristics: {_executable.COFFFileHeader.Characteristics}"); Console.WriteLine(); + } + /// + /// Print optional header information + /// + private void PrintOptionalHeader() + { Console.WriteLine(" Optional Header Information:"); Console.WriteLine(" -------------------------"); if (_executable.COFFFileHeader.SizeOfOptionalHeader == 0 || _executable.OptionalHeader == null) @@ -572,7 +661,7 @@ namespace BurnOutSharp.Wrappers Console.WriteLine($" Size of heap commit: {_executable.OptionalHeader.SizeOfHeapCommit_PE32Plus}"); Console.WriteLine($" Loader flags: {_executable.OptionalHeader.LoaderFlags}"); Console.WriteLine($" Number of data-directory entries: {_executable.OptionalHeader.NumberOfRvaAndSizes}"); - + if (_executable.OptionalHeader.ExportTable != null) { Console.WriteLine(" Export Table (1)"); @@ -671,7 +760,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print section table information + /// + private void PrintSectionTable() + { Console.WriteLine(" Section Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.COFFFileHeader.NumberOfSections == 0 || _executable.SectionTable.Length == 0) @@ -699,7 +794,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print COFF symbol table information + /// + private void PrintCOFFSymbolTable() + { Console.WriteLine(" COFF Symbol Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.COFFFileHeader.PointerToSymbolTable == 0 @@ -848,7 +949,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print attribute certificate table information + /// + private void PrintAttributeCertificateTable() + { Console.WriteLine(" Attribute Certificate Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.OptionalHeader?.CertificateTable == null @@ -897,7 +1004,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print delay-load directory table information + /// + private void PrintDelayLoadDirectoryTable() + { Console.WriteLine(" Delay-Load Directory Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.OptionalHeader?.DelayImportDescriptor == null @@ -918,7 +1031,13 @@ namespace BurnOutSharp.Wrappers Console.WriteLine($" Timestamp = {_executable.DelayLoadDirectoryTable.TimeStamp}"); } Console.WriteLine(); + } + /// + /// Print debug table information + /// + private void PrintDebugTable() + { Console.WriteLine(" Debug Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.OptionalHeader?.Debug == null @@ -945,7 +1064,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print export table information + /// + private void PrintExportTable() + { Console.WriteLine(" Export Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.OptionalHeader?.ExportTable == null @@ -1041,7 +1166,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print import table information + /// + private void PrintImportTable() + { Console.WriteLine(" Import Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.OptionalHeader?.ImportTable == null @@ -1166,7 +1297,13 @@ namespace BurnOutSharp.Wrappers } } Console.WriteLine(); + } + /// + /// Print resource directory table information + /// + private void PrintResourceDirectoryTable() + { Console.WriteLine(" Resource Directory Table Information:"); Console.WriteLine(" -------------------------"); if (_executable.OptionalHeader?.ResourceTable == null @@ -1888,7 +2025,7 @@ namespace BurnOutSharp.Wrappers Console.WriteLine(); } - + #endregion } } \ No newline at end of file