From e305f78f5ff1c0bc1e757ee2a0ca7c90a1c4d02b Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 16 Oct 2017 21:06:41 +0100 Subject: [PATCH] Added support for LE/LX executables. --- README.md | 4 +- exeinfo/Program.cs | 7 ++ libexeinfo/LX/Consts.cs | 41 +++++++ libexeinfo/LX/Enums.cs | 114 ++++++++++++++++++ libexeinfo/LX/Info.cs | 181 ++++++++++++++++++++++++++++ libexeinfo/LX/LX.cs | 156 ++++++++++++++++++++++++ libexeinfo/LX/Structs.cs | 226 +++++++++++++++++++++++++++++++++++ libexeinfo/libexeinfo.csproj | 8 +- 8 files changed, 735 insertions(+), 2 deletions(-) create mode 100644 libexeinfo/LX/Consts.cs create mode 100644 libexeinfo/LX/Enums.cs create mode 100644 libexeinfo/LX/Info.cs create mode 100644 libexeinfo/LX/LX.cs create mode 100644 libexeinfo/LX/Structs.cs diff --git a/README.md b/README.md index 139f53d..b321a21 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,6 @@ Supported executable formats ============================ * Atari ST executable * MZ (aka DOS relocatable executable) -* NE (Microsoft New Executable) \ No newline at end of file +* NE (Microsoft New Executable) +* LE (Microsoft Linear Executable) +* LX (IBM Linear eXecutable) \ No newline at end of file diff --git a/exeinfo/Program.cs b/exeinfo/Program.cs index 0c21f3e..6094426 100644 --- a/exeinfo/Program.cs +++ b/exeinfo/Program.cs @@ -52,6 +52,7 @@ namespace exeinfo MZ mzExe = new MZ(exeFs); NE neExe = new NE(exeFs); AtariST stExe = new AtariST(exeFs); + LX lxExe = new LX(exeFs); if (mzExe.IsMZ) { @@ -117,6 +118,12 @@ namespace exeinfo Console.Write(stExe.GetInfo()); } + if (lxExe.IsLX) + { + recognized = true; + Console.Write(lxExe.GetInfo()); + } + if (!recognized) Console.WriteLine("Executable format not recognized"); } diff --git a/libexeinfo/LX/Consts.cs b/libexeinfo/LX/Consts.cs new file mode 100644 index 0000000..418470d --- /dev/null +++ b/libexeinfo/LX/Consts.cs @@ -0,0 +1,41 @@ +// +// Consts.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2017 Copyright © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +namespace libexeinfo +{ + public partial class LX + { + /// + /// Linear Executable signature, "LE" + /// + public const ushort Signature16 = 0x454C; + /// + /// Linear eXecutable signature, "LX" + /// + public const ushort Signature = 0x584C; + } +} diff --git a/libexeinfo/LX/Enums.cs b/libexeinfo/LX/Enums.cs new file mode 100644 index 0000000..cc1a314 --- /dev/null +++ b/libexeinfo/LX/Enums.cs @@ -0,0 +1,114 @@ +// +// Enums.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2017 Copyright © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +namespace libexeinfo +{ + public partial class LX + { + /// + /// Executable module flags. + /// + [Flags] + public enum ModuleFlags : uint + { + /// + /// Per-Process Library Initialization + /// + PerProcessLibrary = 0x04, + /// + /// Internal fixups for the module have been applied + /// + InternalFixups = 0x10, + /// + /// External fixups for the module have been applied + /// + ExternalFixups = 0x20, + /// + /// Incompatible with Presentation Manager + /// + PMIncompatible = 0x100, + /// + /// Compatible with Presentation Manager + /// + PMCompatible = 0x200, + /// + /// Uses Presentation Manager + /// + UsesPM = 0x300, + /// + /// Module is not loadable. Contains errors or is being linked + /// + NotLoadable = 0x2000, + /// + /// Library module + /// + Library = 0x8000, + /// + /// Protected Memory Library module + /// + ProtectedMemoryLibrary = 0x18000, + /// + /// Physical Device Driver module + /// + PhysicalDeviceDriver = 0x20000, + /// + /// Virtual Device Driver module + /// + VirtualDeviceDriver = 0x28000, + /// + /// Per-process Library Termination + /// + PerProcessTermination = 0x40000000 + } + + public enum TargetCpu : ushort + { + Unknown = 0, + i286 = 1, + i386 = 2, + i486 = 3, + Pentium = 4, + i860 = 0x20, + N11 = 0x21, + MIPS1 = 0x40, + MIPS2 = 0x41, + MIPS3 = 0x42 + } + + /// + /// Target operating system. + /// + public enum TargetOS : ushort + { + Unknown = 0, + OS2 = 1, + Windows = 2, + DOS = 3, + Win32 = 4 + } + } +} \ No newline at end of file diff --git a/libexeinfo/LX/Info.cs b/libexeinfo/LX/Info.cs new file mode 100644 index 0000000..f0f24a7 --- /dev/null +++ b/libexeinfo/LX/Info.cs @@ -0,0 +1,181 @@ +// +// Info.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2017 Copyright © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace libexeinfo +{ + public partial class LX + { + public static string GetInfo(LXHeader header) + { + StringBuilder sb = new StringBuilder(); + if(header.signature == Signature16) + sb.AppendLine("Linear Executable (LE):"); + else + sb.AppendLine("Linear eXecutable (LX):"); + + if (header.os_type == TargetOS.OS2) + { + sb.AppendLine("\tOS/2 application"); + if (header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && !header.module_flags.HasFlag(ModuleFlags.PMCompatible)) + sb.AppendLine("\tApplication is full screen, unaware of Presentation Manager"); + else if (!header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && header.module_flags.HasFlag(ModuleFlags.PMCompatible)) + sb.AppendLine("\tApplication is aware of Presentation Manager, but doesn't use it"); + else if (header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && header.module_flags.HasFlag(ModuleFlags.PMCompatible)) + sb.AppendLine("\tApplication uses Presentation Manager"); + } + else if (header.os_type == TargetOS.Windows || header.os_type == TargetOS.Win32 || header.os_type == TargetOS.Unknown) + { + if (header.os_type == TargetOS.Windows || header.os_type == TargetOS.Unknown) + sb.AppendLine("\t16-bit Windows application"); + else if (header.os_type == TargetOS.Win32) + sb.AppendLine("\t32-bit Windows application"); + if (header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && !header.module_flags.HasFlag(ModuleFlags.PMCompatible)) + sb.AppendLine("\tApplication is full screen, unaware of Windows"); + else if (!header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && header.module_flags.HasFlag(ModuleFlags.PMCompatible)) + sb.AppendLine("\tApplication is aware of Windows, but doesn't use it"); + else if (header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && header.module_flags.HasFlag(ModuleFlags.PMCompatible)) + sb.AppendLine("\tApplication uses Windows"); + } + else if (header.os_type == TargetOS.DOS) + { + sb.AppendLine("\tDOS application"); + if (header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && !header.module_flags.HasFlag(ModuleFlags.PMCompatible)) + sb.AppendLine("\tApplication is full screen, unaware of Windows"); + else if (!header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && header.module_flags.HasFlag(ModuleFlags.PMCompatible)) + sb.AppendLine("\tApplication is aware of Windows, but doesn't use it"); + else if (header.module_flags.HasFlag(ModuleFlags.PMIncompatible) && header.module_flags.HasFlag(ModuleFlags.PMCompatible)) + sb.AppendLine("\tApplication uses Windows"); + } + else + { + sb.AppendFormat("\tApplication for unknown OS {0}", (ushort)header.os_type).AppendLine(); + } + + sb.AppendFormat("\tByte ordering: {0}", header.byte_order == 1 ? "Big-endian" : "Little-Endian").AppendLine(); + sb.AppendFormat("\tWord ordering: {0}", header.word_order == 1 ? "Big-endian" : "Little-Endian").AppendLine(); + sb.AppendFormat("\tFormat level: {0}", header.format_level).AppendLine(); + sb.AppendFormat("\tExecutable version: {0}", header.module_version).AppendLine(); + + switch(header.cpu_type) + { + case TargetCpu.i286: + sb.AppendLine("\tExecutable requires at least an 80286 processor to run."); + break; + case TargetCpu.i386: + sb.AppendLine("\tExecutable requires at least an 80386 processor to run."); + break; + case TargetCpu.i486: + sb.AppendLine("\tExecutable requires at least an 80486 processor to run."); + break; + case TargetCpu.Pentium: + sb.AppendLine("\tExecutable requires at least a Pentium processor to run."); + break; + case TargetCpu.i860: + sb.AppendLine("\tExecutable requires at least an Intel 860 processor to run."); + break; + case TargetCpu.N11: + sb.AppendLine("\tExecutable requires at least an Intel N11 processor to run."); + break; + case TargetCpu.MIPS1: + sb.AppendLine("\tExecutable requires at least a MIPS I processor to run."); + break; + case TargetCpu.MIPS2: + sb.AppendLine("\tExecutable requires at least a MIPS II processor to run."); + break; + case TargetCpu.MIPS3: + sb.AppendLine("\tExecutable requires at least a MIPS III processor to run."); + break; + default: + sb.AppendFormat("\tExecutable requires unknown cpu with type code {0} to run.", (ushort)header.cpu_type).AppendLine(); + break; + } + + if (header.module_flags.HasFlag(ModuleFlags.PerProcessLibrary)) + sb.AppendLine("Library should be initialized per-process."); + if (header.module_flags.HasFlag(ModuleFlags.PerProcessTermination)) + sb.AppendLine("Library should be terminated per-process."); + if (header.module_flags.HasFlag(ModuleFlags.InternalFixups)) + sb.AppendLine("Internal fixups have been applied."); + if (header.module_flags.HasFlag(ModuleFlags.ExternalFixups)) + sb.AppendLine("External fixups have been applied."); + if (header.module_flags.HasFlag(ModuleFlags.NotLoadable)) + sb.AppendLine("Executable is not loadable, it contains errors or is still being linked."); + + if(header.module_flags.HasFlag(ModuleFlags.VirtualDeviceDriver)) + sb.AppendLine("Executable is a driver for a virtual device."); + else if (header.module_flags.HasFlag(ModuleFlags.PhysicalDeviceDriver)) + sb.AppendLine("Executable is a driver for a physical device."); + else if (header.module_flags.HasFlag(ModuleFlags.ProtectedMemoryLibrary)) + sb.AppendLine("Executable is a protected mode library."); + else if (header.module_flags.HasFlag(ModuleFlags.Library)) + sb.AppendLine("Executable is a library."); + + sb.AppendFormat("\tThis executable contains {0} pages", header.module_pages_no).AppendLine(); + sb.AppendFormat("\tObject number to which the Entry Address is relative: {0}", header.eip_object).AppendLine(); + sb.AppendFormat("\tEntry address of module: {0:X8}h", header.eip).AppendLine(); + sb.AppendFormat("\tObject number to which the ESP is relative: {0}", header.esp_object).AppendLine(); + sb.AppendFormat("\tStarting stack address of module: {0:X8}h", header.esp).AppendLine(); + sb.AppendFormat("\tOne page is {0} bytes", header.page_size).AppendLine(); + sb.AppendFormat("\tShift left bits for page offsets: {0}", header.page_off_shift).AppendLine(); + sb.AppendFormat("\tTotal size of the fixup information: {0}", header.fixup_size).AppendLine(); + sb.AppendFormat("\tChecksum for fixup information: 0x{0:X8}", header.fixup_checksum).AppendLine(); + sb.AppendFormat("\tMemory resident tables are {0} bytes long", header.loader_size).AppendLine(); + sb.AppendFormat("\tChecksum for loader section: 0x{0:X8}", header.loader_checksum).AppendLine(); + sb.AppendFormat("\tObject table starts at {0} and contains {1} objects", header.obj_table_off, header.obj_no).AppendLine(); + sb.AppendFormat("\tObject page table starts at {0}", header.obj_page_table_off).AppendLine(); + sb.AppendFormat("\tObject iterated pages starts at {0}", header.obj_iter_pages_off).AppendLine(); + sb.AppendFormat("\tResources table starts at {0} and contains {1} entries", header.resource_table_off, header.resource_entries).AppendLine(); + sb.AppendFormat("\tResident name table starts at {0}", header.resident_names_off).AppendLine(); + sb.AppendFormat("\tEntry table starts at {0}", header.entry_table_off).AppendLine(); + sb.AppendFormat("\tModule format directives table starts at {0} and contains {1} entries", header.directives_off, header.directives_no).AppendLine(); + sb.AppendFormat("\tFixup page table starts at {0}", header.fixup_page_table_off).AppendLine(); + sb.AppendFormat("\tFixup record table starts at {0}", header.fixup_record_table_off).AppendLine(); + sb.AppendFormat("\tImport module name table starts at {0} and contains {1} entries", header.import_module_table_off, header.import_module_entries).AppendLine(); + sb.AppendFormat("\tImport procedure name table starts at {0}", header.import_proc_table_off).AppendLine(); + sb.AppendFormat("\tPer-page checksum table starts at {0}", header.perpage_checksum_off).AppendLine(); + sb.AppendFormat("\tData pages start at {0}", header.data_pages_off).AppendLine(); + sb.AppendFormat("\t{0} pages to preload in this executable", header.preload_pages_no).AppendLine(); + sb.AppendFormat("\tNon-resident names table starts at {0} and runs for {1} bytes", header.nonresident_name_table_off, header.nonresident_name_table_len).AppendLine(); + sb.AppendFormat("\tNon-resident name table checksum: 0x{0:X8}", header.nonresident_name_table_checksum).AppendLine(); + sb.AppendFormat("\tThe auto data segment object number: {0}", header.auto_ds_obj_no).AppendLine(); + sb.AppendFormat("\tDebug information starts at {0} and is {1} bytes", header.debug_info_off, header.debug_info_len).AppendLine(); + sb.AppendFormat("\tInstance pages in preload section: {0}", header.instance_preload_no).AppendLine(); + sb.AppendFormat("\tInstance pages in demand section: {0}", header.instance_demand_no).AppendLine(); + sb.AppendFormat("\tHeap size added to the auto ds object: {0}", header.heap_size).AppendLine(); + return sb.ToString(); + } + + public string GetInfo() + { + return GetInfo(Header); + } + } +} diff --git a/libexeinfo/LX/LX.cs b/libexeinfo/LX/LX.cs new file mode 100644 index 0000000..5f520b6 --- /dev/null +++ b/libexeinfo/LX/LX.cs @@ -0,0 +1,156 @@ +// +// NE.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2017 Copyright © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace libexeinfo +{ + /// + /// Represents a Microsoft/IBM Linear EXecutable + /// + // TODO: Big-endian (really needed?) + public partial class LX + { + /// + /// The that contains the executable represented by this instance + /// + public readonly FileStream BaseStream; + /// + /// Header for this executable + /// + public readonly LXHeader Header; + /// + /// If true this instance correctly represents a Microsoft/IBM Linear EXecutable + /// + public readonly bool IsLX; + public readonly MZ BaseExecutable; + + /// + /// Initializes a new instance of the class. + /// + /// Executable path. + public LX(string path) + { + IsLX = false; + BaseStream = File.Open(path, FileMode.Open, FileAccess.Read); + BaseExecutable = new MZ(BaseStream); + if(BaseExecutable.IsMZ) + { + if(BaseExecutable.Header.new_offset < BaseStream.Length) + { + BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin); + byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))]; + BaseStream.Read(buffer, 0, buffer.Length); + IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length); + Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); + Header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader)); + Marshal.FreeHGlobal(hdrPtr); + IsLX = Header.signature == Signature || Header.signature == Signature16; + } + } + } + + /// + /// Initializes a new instance of the class. + /// + /// Stream containing the executable. + public LX(FileStream stream) + { + IsLX = false; + BaseStream = stream; + BaseExecutable = new MZ(BaseStream); + if (BaseExecutable.IsMZ) + { + if (BaseExecutable.Header.new_offset < BaseStream.Length) + { + BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin); + byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))]; + BaseStream.Read(buffer, 0, buffer.Length); + IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length); + Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); + Header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader)); + Marshal.FreeHGlobal(hdrPtr); + IsLX = Header.signature == Signature || Header.signature == Signature16; + } + } + } + + /// + /// Identifies if the specified executable is a Microsoft/IBM Linear EXecutable + /// + /// true if the specified executable is a Microsoft/IBM Linear EXecutable, false otherwise. + /// Executable path. + public static bool Identify(string path) + { + FileStream BaseStream = File.Open(path, FileMode.Open, FileAccess.Read); + MZ BaseExecutable = new MZ(BaseStream); + if (BaseExecutable.IsMZ) + { + if (BaseExecutable.Header.new_offset < BaseStream.Length) + { + BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin); + byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))]; + BaseStream.Read(buffer, 0, buffer.Length); + IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length); + Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); + LXHeader Header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader)); + Marshal.FreeHGlobal(hdrPtr); + return Header.signature == Signature || Header.signature == Signature16; + } + } + + return false; + } + + /// + /// Identifies if the specified executable is a Microsoft/IBM Linear EXecutable + /// + /// true if the specified executable is a Microsoft/IBM Linear EXecutable, false otherwise. + /// Stream containing the executable. + public static bool Identify(FileStream stream) + { + FileStream BaseStream = stream; + MZ BaseExecutable = new MZ(BaseStream); + if (BaseExecutable.IsMZ) + { + if (BaseExecutable.Header.new_offset < BaseStream.Length) + { + BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin); + byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))]; + BaseStream.Read(buffer, 0, buffer.Length); + IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length); + Marshal.Copy(buffer, 0, hdrPtr, buffer.Length); + LXHeader Header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader)); + Marshal.FreeHGlobal(hdrPtr); + return Header.signature == Signature || Header.signature == Signature16; + } + } + + return false; + } + } +} diff --git a/libexeinfo/LX/Structs.cs b/libexeinfo/LX/Structs.cs new file mode 100644 index 0000000..7b45185 --- /dev/null +++ b/libexeinfo/LX/Structs.cs @@ -0,0 +1,226 @@ +// +// Structs.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2017 Copyright © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Runtime.InteropServices; + +namespace libexeinfo +{ + public partial class LX + { + /// + /// Header for a Microsoft Linear Executable and IBM Linear eXecutable + /// + [StructLayout(LayoutKind.Sequential/*, Pack = 2*/)] + public struct LXHeader + { + /// + /// Executable signature + /// + public ushort signature; + /// + /// Byte ordering + /// + public byte byte_order; + /// + /// Word ordering + /// + public byte word_order; + /// + /// Format level, should be 0 + /// + public uint format_level; + /// + /// Type of CPU required by this executable to run + /// + public TargetCpu cpu_type; + /// + /// Type of operating system requires by this executable to run + /// + public TargetOS os_type; + /// + /// Executable version + /// + public uint module_version; + /// + /// Executable flags + /// + public ModuleFlags module_flags; + /// + /// Pages contained in this module + /// + public uint module_pages_no; + /// + /// Object number to which the Entry Address is relative + /// + public uint eip_object; + /// + /// Entry address of module + /// + public uint eip; + /// + /// Object number to which the ESP is relative + /// + public uint esp_object; + /// + /// Starting stack address of module + /// + public uint esp; + /// + /// Size of one page + /// + public uint page_size; + /// + /// Shift left bits for page offsets + /// + public uint page_off_shift; + /// + /// Total size of the fixup information + /// + public uint fixup_size; + /// + /// Checksum for fixup information + /// + public uint fixup_checksum; + /// + /// Size of memory resident tables + /// + public uint loader_size; + /// + /// Checksum for loader section + /// + public uint loader_checksum; + /// + /// Object table offset + /// + public uint obj_table_off; + /// + /// Object table count + /// + public uint obj_no; + /// + /// Object page table offset + /// + public uint obj_page_table_off; + /// + /// Object iterated pages offset + /// + public uint obj_iter_pages_off; + /// + /// Resource table offset + /// + public uint resource_table_off; + /// + /// Entries in resource table + /// + public uint resource_entries; + /// + /// Resident name table offset + /// + public uint resident_names_off; + /// + /// Entry table offset + /// + public uint entry_table_off; + /// + /// Module format directives table offset + /// + public uint directives_off; + /// + /// Entries in module format directives table + /// + public uint directives_no; + /// + /// Fixup page table offset + /// + public uint fixup_page_table_off; + /// + /// Fixup record table offset + /// + public uint fixup_record_table_off; + /// + /// Import module name table offset + /// + public uint import_module_table_off; + /// + /// Entries in the import module name table + /// + public uint import_module_entries; + /// + /// Import procedure name table offset + /// + public uint import_proc_table_off; + /// + /// Per-page checksum table offset + /// + public uint perpage_checksum_off; + /// + /// Data pages offset + /// + public uint data_pages_off; + /// + /// Number of preload pages for this module + /// + public uint preload_pages_no; + /// + /// Non-resident name table offset + /// + public uint nonresident_name_table_off; + /// + /// Number of bytes in the non-resident name table + /// + public uint nonresident_name_table_len; + /// + /// Non-resident name table checksum + /// + public uint nonresident_name_table_checksum; + /// + /// The auto data segment object number + /// + public uint auto_ds_obj_no; + /// + /// Debug information offset + /// + public uint debug_info_off; + /// + /// Debug information length + /// + public uint debug_info_len; + /// + /// Instance pages in preload section + /// + public uint instance_preload_no; + /// + /// Instance pages in demand section + /// + public uint instance_demand_no; + /// + /// Heap size added to the auto ds object + /// + public uint heap_size; + } + } +} \ No newline at end of file diff --git a/libexeinfo/libexeinfo.csproj b/libexeinfo/libexeinfo.csproj index bd60a2d..934146e 100644 --- a/libexeinfo/libexeinfo.csproj +++ b/libexeinfo/libexeinfo.csproj @@ -48,7 +48,6 @@ - @@ -59,6 +58,12 @@ + + + + + + @@ -73,6 +78,7 @@ +