From 7ea5ff59b975e19fa18b88be06141eb5c937f5b5 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Tue, 3 Oct 2017 14:54:11 +0100 Subject: [PATCH] Added support for NE. --- exeinfo/NE.cs | 213 +++++++++++++++++++++++++++++++++++++++++ exeinfo/Program.cs | 16 ++++ exeinfo/exeinfo.csproj | 1 + 3 files changed, 230 insertions(+) create mode 100644 exeinfo/NE.cs diff --git a/exeinfo/NE.cs b/exeinfo/NE.cs new file mode 100644 index 0000000..0ef2726 --- /dev/null +++ b/exeinfo/NE.cs @@ -0,0 +1,213 @@ +using System; +using System.Runtime.InteropServices; + +namespace exeinfo +{ + public static class NE + { + public const ushort Signature = 0x454E; + + //[StructLayout(LayoutKind.Sequential, Pack = 2)] + public struct Header + { + public ushort signature; + public byte linker_major; + public byte linker_minor; + public ushort entry_table_offset; + public ushort entry_table_length; + public uint crc; + public ProgramFlags program_flags; + public ApplicationFlags application_flags; + public byte auto_data_segment_index; + public ushort initial_heap; + public ushort initial_stack; + public uint entry_point; + public uint stack_pointer; + public ushort segment_count; + public ushort reference_count; + public ushort nonresident_table_size; + public ushort segment_table_offset; + public ushort resource_table_offset; + public ushort resident_names_offset; + public ushort module_reference_offset; + public ushort imported_names_offset; + public uint nonresident_names_offset; + public ushort movable_entries; + public ushort alignment_shift; + public ushort resource_entries; + public TargetOS target_os; + public OS2Flags os2_flags; + public ushort return_thunks_offset; + public ushort segment_reference_thunks; + public ushort minimum_swap_area; + public byte os_minor; + public byte os_major; + } + + [Flags] + public enum ProgramFlags : byte + { + NoDGroup = 0, + SingleDGroup = 1, + MultipleDGroup = 2, + GlobalInit = 1 << 2, + ProtectedMode = 1 << 3, + i86 = 1 << 4, + i286 = 1 << 5, + i386 = 1 << 6, + i87 = 1 << 7 + } + + public enum TargetOS : byte + { + Unknown = 0, + OS2 = 1, + Windows = 2, + DOS = 3, + Win32 = 4, + Borland = 5 + } + + [Flags] + public enum ApplicationFlags : byte + { + FullScreen = 1, + GUICompatible = 2, + Errors = 1 << 5, + NonConforming = 1 << 6, + DLL = 1 << 7 + } + + [Flags] + public enum OS2Flags : byte + { + LongFilename = 1 << 0, + ProtectedMode2 = 1 << 1, + ProportionalFonts = 1 << 2, + GangloadArea = 1 << 3, + } + + public static void PrintInfo(Header header) + { + Console.WriteLine("New Executable (NE):"); + Console.WriteLine("\tFile's CRC: 0x{0:X8}", header.crc); + Console.WriteLine("\tLinker version: {0}.{1}", header.linker_major, header.linker_minor); + if (header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && !header.program_flags.HasFlag(ProgramFlags.MultipleDGroup)) + Console.WriteLine("\tApplication uses a single shared DGroup"); + else if (!header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && header.program_flags.HasFlag(ProgramFlags.MultipleDGroup)) + Console.WriteLine("\tApplication uses a multiple DGroup"); + else if (header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && header.program_flags.HasFlag(ProgramFlags.MultipleDGroup)) + Console.WriteLine("\tApplication indicates an incorrect DGroup value"); + else if (!header.program_flags.HasFlag(ProgramFlags.SingleDGroup) && !header.program_flags.HasFlag(ProgramFlags.MultipleDGroup)) + Console.WriteLine("\tApplication does not use DGroup"); + if (header.program_flags.HasFlag(ProgramFlags.GlobalInit)) + Console.WriteLine("\tApplication uses global initialization"); + if (header.program_flags.HasFlag(ProgramFlags.ProtectedMode)) + Console.WriteLine("\tApplication uses protected mode"); + if (header.program_flags.HasFlag(ProgramFlags.i86)) + Console.WriteLine("\tApplication uses 8086 instructions"); + if (header.program_flags.HasFlag(ProgramFlags.i286)) + Console.WriteLine("\tApplication uses 80286 instructions"); + if (header.program_flags.HasFlag(ProgramFlags.i386)) + Console.WriteLine("\tApplication uses 80386 instructions"); + if (header.program_flags.HasFlag(ProgramFlags.i87)) + Console.WriteLine("\tApplication uses floating point instructions"); + + if(header.target_os == TargetOS.OS2) + { + Console.WriteLine("\tOS/2 application"); + Console.WriteLine("\tApplication requires OS/2 {0}.{1} to run", header.os_major, header.os_minor); + if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication is full screen, unaware of Presentation Manager"); + else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication is aware of Presentation Manager, but doesn't use it"); + else if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication uses Presentation Manager"); + if (header.os2_flags.HasFlag(OS2Flags.LongFilename)) + Console.WriteLine("\tApplication supports long filenames"); + if (header.os2_flags.HasFlag(OS2Flags.ProtectedMode2)) + Console.WriteLine("\tApplication uses OS/2 2.x protected mode"); + if (header.os2_flags.HasFlag(OS2Flags.ProportionalFonts)) + Console.WriteLine("\tApplication uses OS/2 2.x proportional fonts"); + if (header.os2_flags.HasFlag(OS2Flags.GangloadArea)) + Console.WriteLine("\tGangload area starts at {0} an runs for {1} bytes", header.return_thunks_offset, header.segment_reference_thunks); + else + { + Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset); + Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks); + } + } + else if (header.target_os == TargetOS.Windows || header.target_os == TargetOS.Win32) + { + if (header.target_os == TargetOS.Windows) + Console.WriteLine("\t16-bit Windows application"); + else if (header.target_os == TargetOS.Win32) + Console.WriteLine("\t32-bit Windows application"); + Console.WriteLine("\tApplication requires Windows {0}.{1} to run", header.os_major, header.os_minor); + if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication is full screen, unaware of Windows"); + else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication is aware of Windows, but doesn't use it"); + else if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication uses Windows"); + Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset); + Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks); + } + else if (header.target_os == TargetOS.DOS) + { + Console.WriteLine("\tDOS application"); + Console.WriteLine("\tApplication requires DOS {0}.{1} to run", header.os_major, header.os_minor); + if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication is full screen, unaware of Windows"); + else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication is aware of Windows, but doesn't use it"); + else if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication uses Windows"); + Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset); + Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks); + } + else if (header.target_os == TargetOS.Borland) + { + Console.WriteLine("\tBorland Operating System Services application"); + Console.WriteLine("\tApplication requires DOS {0}.{1} to run", header.os_major, header.os_minor); + if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && !header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication is full screen, unaware of Windows"); + else if (!header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication is aware of Windows, but doesn't use it"); + else if (header.application_flags.HasFlag(ApplicationFlags.FullScreen) && header.application_flags.HasFlag(ApplicationFlags.GUICompatible)) + Console.WriteLine("\tApplication uses Windows"); + Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset); + Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks); + } + else + { + Console.WriteLine("\tApplication for unknown OS {0}", (byte)header.target_os); + Console.WriteLine("\tApplication requires OS {0}.{1} to run", header.os_major, header.os_minor); + Console.WriteLine("\tReturn thunks are at: {0}", header.return_thunks_offset); + Console.WriteLine("\tSegment reference thunks are at: {0}", header.segment_reference_thunks); + } + + if (header.application_flags.HasFlag(ApplicationFlags.Errors)) + Console.WriteLine("\tExecutable has errors"); + if (header.application_flags.HasFlag(ApplicationFlags.NonConforming)) + Console.WriteLine("\tExecutable is non conforming"); + if (header.application_flags.HasFlag(ApplicationFlags.DLL)) + Console.WriteLine("\tExecutable is a dynamic library or a driver"); + + Console.WriteLine("\tMinimum code swap area: {0} bytes", header.minimum_swap_area); + Console.WriteLine("\tFile alignment shift: {0}", 2 << header.alignment_shift); + Console.WriteLine("\tInitial local heap should be {0} bytes", header.initial_heap); + Console.WriteLine("\tInitial stack size should be {0} bytes", header.initial_stack); + Console.WriteLine("\tCS:IP entry point: {0:X4}:{1:X4}", (header.entry_point & 0xFFFF0000) >> 16, header.entry_point & 0xFFFF); + if (!header.application_flags.HasFlag(ApplicationFlags.DLL)) + Console.WriteLine("\tSS:SP initial stack pointer: {0:X4}:{1:X4}", (header.stack_pointer & 0xFFFF0000) >> 16, header.stack_pointer & 0xFFFF); + Console.WriteLine("\tEntry table starts at {0} and runs for {1} bytes", header.entry_table_offset, header.entry_table_length); + Console.WriteLine("\tSegment table starts at {0} and contain {1} segments", header.segment_table_offset, header.segment_count); + Console.WriteLine("\tModule reference table starts at {0} and contain {1} references", header.module_reference_offset, header.reference_count); + Console.WriteLine("\tNon-resident names table starts at {0} and runs for {1} bytes", header.nonresident_names_offset, header.nonresident_table_size); + Console.WriteLine("\tResources table starts at {0} and contains {1} entries", header.resource_table_offset, header.resource_entries); + Console.WriteLine("\tResident names table starts at {0}", header.resident_names_offset); + Console.WriteLine("\tImported names table starts at {0}", header.imported_names_offset); + } + } +} diff --git a/exeinfo/Program.cs b/exeinfo/Program.cs index 63ff91d..65a0027 100644 --- a/exeinfo/Program.cs +++ b/exeinfo/Program.cs @@ -7,6 +7,7 @@ namespace exeinfo class MainClass { static MZ.Header mzHdr; + static NE.Header neHdr; public static void Main(string[] args) { @@ -33,6 +34,21 @@ namespace exeinfo { recognized = true; MZ.PrintInfo(mzHdr); + + if (mzHdr.new_offset < exeFs.Length) + { + exeFs.Seek(mzHdr.new_offset, SeekOrigin.Begin); + + buffer = new byte[Marshal.SizeOf(typeof(NE.Header))]; + exeFs.Read(buffer, 0, buffer.Length); + hdrPtr = Marshal.AllocHGlobal(buffer.Length); + Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); + neHdr = (NE.Header)Marshal.PtrToStructure(hdrPtr, typeof(NE.Header)); + Marshal.FreeHGlobal(hdrPtr); + + if (neHdr.signature == NE.Signature) + NE.PrintInfo(neHdr); + } } if (!recognized) diff --git a/exeinfo/exeinfo.csproj b/exeinfo/exeinfo.csproj index e8e8693..5736f7a 100644 --- a/exeinfo/exeinfo.csproj +++ b/exeinfo/exeinfo.csproj @@ -35,6 +35,7 @@ + \ No newline at end of file