diff --git a/BurnOutSharp/ExecutableType/Microsoft/IMAGE_DATA_DIRECTORY.cs b/BurnOutSharp/ExecutableType/Microsoft/Headers/DataDirectoryHeader.cs
similarity index 50%
rename from BurnOutSharp/ExecutableType/Microsoft/IMAGE_DATA_DIRECTORY.cs
rename to BurnOutSharp/ExecutableType/Microsoft/Headers/DataDirectoryHeader.cs
index 42f36217..2405fe2f 100644
--- a/BurnOutSharp/ExecutableType/Microsoft/IMAGE_DATA_DIRECTORY.cs
+++ b/BurnOutSharp/ExecutableType/Microsoft/Headers/DataDirectoryHeader.cs
@@ -3,10 +3,10 @@ using System.IO;
using System.Runtime.InteropServices;
using BurnOutSharp.Tools;
-namespace BurnOutSharp.ExecutableType.Microsoft
+namespace BurnOutSharp.ExecutableType.Microsoft.Headers
{
[StructLayout(LayoutKind.Sequential)]
- internal class IMAGE_DATA_DIRECTORY
+ internal class DataDirectoryHeader
{
///
/// The first field, VirtualAddress, is actually the RVA of the table.
@@ -19,24 +19,24 @@ namespace BurnOutSharp.ExecutableType.Microsoft
///
public uint Size;
- public static IMAGE_DATA_DIRECTORY Deserialize(Stream stream)
+ public static DataDirectoryHeader Deserialize(Stream stream)
{
- var idd = new IMAGE_DATA_DIRECTORY();
+ var ddh = new DataDirectoryHeader();
- idd.VirtualAddress = stream.ReadUInt32();
- idd.Size = stream.ReadUInt32();
+ ddh.VirtualAddress = stream.ReadUInt32();
+ ddh.Size = stream.ReadUInt32();
- return idd;
+ return ddh;
}
- public static IMAGE_DATA_DIRECTORY Deserialize(byte[] content, int offset)
+ public static DataDirectoryHeader Deserialize(byte[] content, int offset)
{
- var idd = new IMAGE_DATA_DIRECTORY();
+ var ddh = new DataDirectoryHeader();
- idd.VirtualAddress = BitConverter.ToUInt32(content, offset); offset += 4;
- idd.Size = BitConverter.ToUInt32(content, offset); offset += 4;
+ ddh.VirtualAddress = BitConverter.ToUInt32(content, offset); offset += 4;
+ ddh.Size = BitConverter.ToUInt32(content, offset); offset += 4;
- return idd;
+ return ddh;
}
}
}
\ No newline at end of file
diff --git a/BurnOutSharp/ExecutableType/Microsoft/Headers/NewExecutableHeader.cs b/BurnOutSharp/ExecutableType/Microsoft/Headers/NewExecutableHeader.cs
new file mode 100644
index 00000000..4964a9e9
--- /dev/null
+++ b/BurnOutSharp/ExecutableType/Microsoft/Headers/NewExecutableHeader.cs
@@ -0,0 +1,255 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using BurnOutSharp.Tools;
+
+namespace BurnOutSharp.ExecutableType.Microsoft.Headers
+{
+ ///
+ /// The NE header is a relatively large structure with multiple characteristics.
+ /// Because of the age of the format some items are unclear in meaning.
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal class NewExecutableHeader
+ {
+ ///
+ /// "NE" [00]
+ ///
+ public ushort Magic;
+
+ ///
+ /// The major linker version [02]
+ ///
+ public byte LinkerVersion;
+
+ ///
+ /// The minor linker version [03]
+ ///
+ public byte LinkerRevision;
+
+ ///
+ /// Offset of Entry Table [04]
+ ///
+ public ushort EntryTableOffset;
+
+ ///
+ /// Length of entry table in bytes [06]
+ ///
+ public ushort EntryTableSize;
+
+ ///
+ /// 32-bit CRC of entire contents of file [08]
+ ///
+ public uint CrcChecksum;
+
+ ///
+ /// Program flags, bitmapped [0C]
+ ///
+ public byte ProgramFlags;
+
+ ///
+ /// Application flags, bitmapped [0D]
+ ///
+ public byte ApplicationFlags;
+
+ ///
+ /// Automatic data segment number [0E]
+ ///
+ public ushort Autodata;
+
+ ///
+ /// Initial heap allocation [10]
+ ///
+ public ushort InitialHeapAlloc;
+
+ ///
+ /// Initial stack allocation [12]
+ ///
+ public ushort InitialStackAlloc;
+
+ ///
+ /// CS:IP entry point, CS is index into segment table [14]
+ ///
+ public uint InitialCSIPSetting;
+
+ ///
+ /// SS:SP inital stack pointer, SS is index into segment table [18]
+ ///
+ public uint InitialSSSPSetting;
+
+ ///
+ /// Number of segments in segment table [1C]
+ ///
+ public ushort FileSegmentCount;
+
+ ///
+ /// Entries in Module Reference Table [1E]
+ ///
+ public ushort ModuleReferenceTableSize;
+
+ ///
+ /// Size of non-resident name table [20]
+ ///
+ public ushort NonResidentNameTableSize;
+
+ ///
+ /// Offset of Segment Table [22]
+ ///
+ public ushort SegmentTableOffset;
+
+ ///
+ /// Offset of Resource Table [24]
+ ///
+ public ushort ResourceTableOffset;
+
+ ///
+ /// Offset of resident name table [26]
+ ///
+ public ushort ResidentNameTableOffset;
+
+ ///
+ /// Offset of Module Reference Table [28]
+ ///
+ public ushort ModuleReferenceTableOffset;
+
+ ///
+ /// Offset of Imported Names Table [2A]
+ ///
+ public ushort ImportedNamesTableOffset;
+
+ ///
+ /// Offset of Non-resident Names Table [2C]
+ ///
+ public uint NonResidentNamesTableOffset;
+
+ ///
+ /// Count of moveable entry points listed in entry table [30]
+ ///
+ public ushort MovableEntriesCount;
+
+ ///
+ /// File allignment size shift count (0-9 (default 512 byte pages)) [32]
+ ///
+ public ushort SegmentAlignmentShiftCount;
+
+ ///
+ /// Count of resource table entries [34]
+ ///
+ public ushort ResourceEntriesCount;
+
+ ///
+ /// Target operating system [36]
+ ///
+ public byte TargetOperatingSystem;
+
+ ///
+ /// Other OS/2 flags [37]
+ ///
+ public byte AdditionalFlags;
+
+ ///
+ /// Offset to return thunks or start of gangload area [38]
+ ///
+ public ushort ReturnThunkOffset;
+
+ ///
+ /// Offset to segment reference thunks or size of gangload area [3A]
+ ///
+ public ushort SegmentReferenceThunkOffset;
+
+ ///
+ /// Minimum code swap area size [3C]
+ ///
+ public ushort MinCodeSwapAreaSize;
+
+ ///
+ /// Windows SDK revison number [3E]
+ ///
+ public byte WindowsSDKRevision;
+
+ ///
+ /// Windows SDK version number [3F]
+ ///
+ public byte WindowsSDKVersion;
+
+ public static NewExecutableHeader Deserialize(Stream stream)
+ {
+ var neh = new NewExecutableHeader();
+
+ neh.Magic = stream.ReadUInt16();
+ neh.LinkerVersion = stream.ReadByteValue();
+ neh.LinkerRevision = stream.ReadByteValue();
+ neh.EntryTableOffset = stream.ReadUInt16();
+ neh.EntryTableSize = stream.ReadUInt16();
+ neh.CrcChecksum = stream.ReadUInt32();
+ neh.ProgramFlags = stream.ReadByteValue();
+ neh.ApplicationFlags = stream.ReadByteValue();
+ neh.Autodata = stream.ReadUInt16();
+ neh.InitialHeapAlloc = stream.ReadUInt16();
+ neh.InitialStackAlloc = stream.ReadUInt16();
+ neh.InitialCSIPSetting = stream.ReadUInt32();
+ neh.InitialSSSPSetting = stream.ReadUInt32();
+ neh.FileSegmentCount = stream.ReadUInt16();
+ neh.ModuleReferenceTableSize = stream.ReadUInt16();
+ neh.NonResidentNameTableSize = stream.ReadUInt16();
+ neh.SegmentTableOffset = stream.ReadUInt16();
+ neh.ResourceTableOffset = stream.ReadUInt16();
+ neh.ResidentNameTableOffset = stream.ReadUInt16();
+ neh.ModuleReferenceTableOffset = stream.ReadUInt16();
+ neh.ImportedNamesTableOffset = stream.ReadUInt16();
+ neh.NonResidentNamesTableOffset = stream.ReadUInt32();
+ neh.MovableEntriesCount = stream.ReadUInt16();
+ neh.SegmentAlignmentShiftCount = stream.ReadUInt16();
+ neh.ResourceEntriesCount = stream.ReadUInt16();
+ neh.TargetOperatingSystem = stream.ReadByteValue();
+ neh.AdditionalFlags = stream.ReadByteValue();
+ neh.ReturnThunkOffset = stream.ReadUInt16();
+ neh.SegmentReferenceThunkOffset = stream.ReadUInt16();
+ neh.MinCodeSwapAreaSize = stream.ReadUInt16();
+ neh.WindowsSDKRevision = stream.ReadByteValue();
+ neh.WindowsSDKVersion = stream.ReadByteValue();
+
+ return neh;
+ }
+
+ public static NewExecutableHeader Deserialize(byte[] contents, int offset)
+ {
+ var neh = new NewExecutableHeader();
+
+ neh.Magic = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.LinkerVersion = contents[offset++];
+ neh.LinkerRevision = contents[offset++];
+ neh.EntryTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.EntryTableSize = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.CrcChecksum = BitConverter.ToUInt32(contents, offset); offset += 4;
+ neh.ProgramFlags = contents[offset++];
+ neh.ApplicationFlags = contents[offset++];
+ neh.Autodata = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.InitialHeapAlloc = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.InitialStackAlloc = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.InitialCSIPSetting = BitConverter.ToUInt32(contents, offset); offset += 4;
+ neh.InitialSSSPSetting = BitConverter.ToUInt32(contents, offset); offset += 4;
+ neh.FileSegmentCount = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.ModuleReferenceTableSize = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.NonResidentNameTableSize = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.SegmentTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.ResourceTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.ResidentNameTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.ModuleReferenceTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.ImportedNamesTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.NonResidentNamesTableOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.MovableEntriesCount = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.SegmentAlignmentShiftCount = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.ResourceEntriesCount = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.TargetOperatingSystem = contents[offset++];
+ neh.AdditionalFlags = contents[offset++];
+ neh.ReturnThunkOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.SegmentReferenceThunkOffset = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.MinCodeSwapAreaSize = BitConverter.ToUInt16(contents, offset); offset += 2;
+ neh.WindowsSDKRevision = contents[offset++];
+ neh.WindowsSDKVersion = contents[offset++];
+
+ return neh;
+ }
+ }
+}
diff --git a/BurnOutSharp/ExecutableType/Microsoft/Headers/OptionalHeader.cs b/BurnOutSharp/ExecutableType/Microsoft/Headers/OptionalHeader.cs
index 6fc771fc..beefb919 100644
--- a/BurnOutSharp/ExecutableType/Microsoft/Headers/OptionalHeader.cs
+++ b/BurnOutSharp/ExecutableType/Microsoft/Headers/OptionalHeader.cs
@@ -232,7 +232,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
/// Data-directory entries following the optional header
///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES)]
- public IMAGE_DATA_DIRECTORY[] DataDirectories;
+ public DataDirectoryHeader[] DataDirectories;
#endregion
@@ -292,10 +292,10 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
ioh.LoaderFlags = stream.ReadUInt32();
ioh.NumberOfRvaAndSizes = stream.ReadUInt32();
- ioh.DataDirectories = new IMAGE_DATA_DIRECTORY[Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+ ioh.DataDirectories = new DataDirectoryHeader[Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
for (int i = 0; i < Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
{
- ioh.DataDirectories[i] = IMAGE_DATA_DIRECTORY.Deserialize(stream);
+ ioh.DataDirectories[i] = DataDirectoryHeader.Deserialize(stream);
}
return ioh;
@@ -361,10 +361,10 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
ioh.LoaderFlags = BitConverter.ToUInt32(content, offset); offset += 4;
ioh.NumberOfRvaAndSizes = BitConverter.ToUInt32(content, offset); offset += 4;
- ioh.DataDirectories = new IMAGE_DATA_DIRECTORY[Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+ ioh.DataDirectories = new DataDirectoryHeader[Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
for (int i = 0; i < Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
{
- ioh.DataDirectories[i] = IMAGE_DATA_DIRECTORY.Deserialize(content, offset); offset += 8;
+ ioh.DataDirectories[i] = DataDirectoryHeader.Deserialize(content, offset); offset += 8;
}
return ioh;
diff --git a/BurnOutSharp/ExecutableType/Microsoft/IMAGE_OS2_HEADER.cs b/BurnOutSharp/ExecutableType/Microsoft/IMAGE_OS2_HEADER.cs
deleted file mode 100644
index 3b7a4c2d..00000000
--- a/BurnOutSharp/ExecutableType/Microsoft/IMAGE_OS2_HEADER.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
- *
- * Data structure definitions for the OS/2 & Windows
- * executable file format.
- *
- * Modified by IVS on 24-Jan-1991 for Resource DeCompiler
- * (C) Copyright IVS 1991
- *
- * http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
- */
-
-using System.IO;
-using System.Runtime.InteropServices;
-using BurnOutSharp.Tools;
-
-namespace BurnOutSharp.ExecutableType.Microsoft
-{
- ///
- /// New .EXE header
- ///
- [StructLayout(LayoutKind.Sequential)]
- internal class IMAGE_OS2_HEADER
- {
- public ushort Magic; // 00 Magic number NE_MAGIC
- public byte LinkerVersion; // 02 Linker Version number
- public byte LinkerRevision; // 03 Linker Revision number
- public ushort EntryTableOffset; // 04 Offset of Entry Table
- public ushort EntryTableSize; // 06 Number of bytes in Entry Table
- public uint CrcChecksum; // 08 Checksum of whole file
- public ushort Flags; // 0C Flag word
- public ushort Autodata; // 0E Automatic data segment number
- public ushort InitialHeapAlloc; // 10 Initial heap allocation
- public ushort InitialStackAlloc; // 12 Initial stack allocation
- public uint InitialCSIPSetting; // 14 Initial CS:IP setting
- public uint InitialSSSPSetting; // 18 Initial SS:SP setting
- public ushort FileSegmentCount; // 1C Count of file segments
- public ushort ModuleReferenceTableSize; // 1E Entries in Module Reference Table
- public ushort NonResidentNameTableSize; // 20 Size of non-resident name table
- public ushort SegmentTableOffset; // 22 Offset of Segment Table
- public ushort ResourceTableOffset; // 24 Offset of Resource Table
- public ushort ResidentNameTableOffset; // 26 Offset of resident name table
- public ushort ModuleReferenceTableOffset; // 28 Offset of Module Reference Table
- public ushort ImportedNamesTableOffset; // 2A Offset of Imported Names Table
- public uint NonResidentNamesTableOffset; // 2C Offset of Non-resident Names Table
- public ushort MovableEntriesCount; // 30 Count of movable entries
- public ushort SegmentAlignmentShiftCount; // 32 Segment alignment shift count
- public ushort ResourceEntriesCount; // 34 Count of resource entries
- public byte TargetOperatingSystem; // 36 Target operating system
- public byte AdditionalFlags; // 37 Additional flags
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.NERESWORDS)]
- public ushort[] Reserved; // 38 3 reserved words
- public byte WindowsSDKRevision; // 3E Windows SDK revison number
- public byte WindowsSDKVersion; // 3F Windows SDK version number
-
- public static IMAGE_OS2_HEADER Deserialize(Stream stream)
- {
- var ioh = new IMAGE_OS2_HEADER();
-
- ioh.Magic = stream.ReadUInt16();
- ioh.LinkerVersion = stream.ReadByteValue();
- ioh.LinkerRevision = stream.ReadByteValue();
- ioh.EntryTableOffset = stream.ReadUInt16();
- ioh.EntryTableSize = stream.ReadUInt16();
- ioh.CrcChecksum = stream.ReadUInt32();
- ioh.Flags = stream.ReadUInt16();
- ioh.Autodata = stream.ReadUInt16();
- ioh.InitialHeapAlloc = stream.ReadUInt16();
- ioh.InitialStackAlloc = stream.ReadUInt16();
- ioh.InitialCSIPSetting = stream.ReadUInt32();
- ioh.InitialSSSPSetting = stream.ReadUInt32();
- ioh.FileSegmentCount = stream.ReadUInt16();
- ioh.ModuleReferenceTableSize = stream.ReadUInt16();
- ioh.NonResidentNameTableSize = stream.ReadUInt16();
- ioh.SegmentTableOffset = stream.ReadUInt16();
- ioh.ResourceTableOffset = stream.ReadUInt16();
- ioh.ResidentNameTableOffset = stream.ReadUInt16();
- ioh.ModuleReferenceTableOffset = stream.ReadUInt16();
- ioh.ImportedNamesTableOffset = stream.ReadUInt16();
- ioh.NonResidentNamesTableOffset = stream.ReadUInt32();
- ioh.MovableEntriesCount = stream.ReadUInt16();
- ioh.SegmentAlignmentShiftCount = stream.ReadUInt16();
- ioh.ResourceEntriesCount = stream.ReadUInt16();
- ioh.TargetOperatingSystem = stream.ReadByteValue();
- ioh.AdditionalFlags = stream.ReadByteValue();
- ioh.Reserved = new ushort[Constants.NERESWORDS];
- for (int i = 0; i < Constants.NERESWORDS; i++)
- {
- ioh.Reserved[i] = stream.ReadUInt16();
- }
- ioh.WindowsSDKRevision = stream.ReadByteValue();
- ioh.WindowsSDKVersion = stream.ReadByteValue();
-
- return ioh;
- }
- }
-}
diff --git a/BurnOutSharp/ExecutableType/Microsoft/NewExecutable.cs b/BurnOutSharp/ExecutableType/Microsoft/NewExecutable.cs
new file mode 100644
index 00000000..c5e04499
--- /dev/null
+++ b/BurnOutSharp/ExecutableType/Microsoft/NewExecutable.cs
@@ -0,0 +1,96 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using BurnOutSharp.ExecutableType.Microsoft.Headers;
+
+namespace BurnOutSharp.ExecutableType.Microsoft
+{
+ ///
+ /// The WIN-NE executable format, designed for Windows 3.x, was the "NE", or "New Executable" format.
+ /// Again, a 16bit format, it alleviated the maximum size restrictions that the MZ format had.
+ ///
+ internal class NewExecutable
+ {
+ #region Headers
+
+ ///
+ /// he DOS stub is a valid MZ exe.
+ /// This enables the develper to package both an MS-DOS and Win16 version of the program,
+ /// but normally just prints "This Program requires Microsoft Windows".
+ /// The e_lfanew field (offset 0x3C) points to the NE header.
+ //
+ public MSDOSExecutableHeader DOSStubHeader;
+
+ ///
+ /// The NE header is a relatively large structure with multiple characteristics.
+ /// Because of the age of the format some items are unclear in meaning.
+ ///
+ public NewExecutableHeader NewExecutableHeader;
+
+ #endregion
+
+ // TODO: Add more and more parts of a standard NE executable, not just the header
+
+ public static NewExecutable Deserialize(Stream stream)
+ {
+ NewExecutable nex = new NewExecutable();
+
+ try
+ {
+ // Attempt to read the DOS header first
+ nex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(stream); stream.Seek(nex.DOSStubHeader.NewExeHeaderAddr, SeekOrigin.Begin);
+ if (nex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
+ return null;
+
+ // If the new header address is invalid for the file, it's not a NE
+ if (nex.DOSStubHeader.NewExeHeaderAddr >= stream.Length)
+ return null;
+
+ // Then attempt to read the NE header
+ nex.NewExecutableHeader = NewExecutableHeader.Deserialize(stream);
+ if (nex.NewExecutableHeader.Magic != Constants.IMAGE_OS2_SIGNATURE)
+ return null;
+
+ }
+ catch (Exception ex)
+ {
+ //Console.WriteLine($"Errored out on a file: {ex}");
+ return null;
+ }
+
+ return nex;
+ }
+
+ public static NewExecutable Deserialize(byte[] content, int offset)
+ {
+ NewExecutable nex = new NewExecutable();
+
+ try
+ {
+ unsafe
+ {
+ // Attempt to read the DOS header first
+ nex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(content, offset); offset = nex.DOSStubHeader.NewExeHeaderAddr;
+ if (nex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
+ return null;
+
+ // If the new header address is invalid for the file, it's not a PE
+ if (nex.DOSStubHeader.NewExeHeaderAddr >= content.Length)
+ return null;
+
+ // Then attempt to read the NE header
+ nex.NewExecutableHeader = NewExecutableHeader.Deserialize(content, offset); offset += Marshal.SizeOf(nex.NewExecutableHeader);
+ if (nex.NewExecutableHeader.Magic != Constants.IMAGE_OS2_SIGNATURE)
+ return null;
+ }
+ }
+ catch (Exception ex)
+ {
+ //Console.WriteLine($"Errored out on a file: {ex}");
+ return null;
+ }
+
+ return nex;
+ }
+ }
+}
\ No newline at end of file