diff --git a/exeinfo/NE.cs b/exeinfo/NE.cs index 0ef2726..7321fc0 100644 --- a/exeinfo/NE.cs +++ b/exeinfo/NE.cs @@ -1,5 +1,8 @@ using System; using System.Runtime.InteropServices; +using System.IO; +using System.Collections.Generic; +using System.Text; namespace exeinfo { @@ -87,6 +90,44 @@ namespace exeinfo GangloadArea = 1 << 3, } + public struct ResourceTable + { + public ushort alignment_shift; + public ResourceType[] types; + } + + public struct ResourceType + { + public ushort id; + public ushort count; + public uint reserved; + public Resource[] resources; + + // Not sequentially stored + public string name; + } + + public struct Resource + { + public ushort dataOffset; + public ushort length; + public ResourceFlags flags; + public ushort id; + public uint reserved; + + // Not sequentially stored + public string name; + public byte[] data; + } + + [Flags] + public enum ResourceFlags : ushort + { + Moveable = 0x10, + Pure = 0x20, + Preload = 0x40 + } + public static void PrintInfo(Header header) { Console.WriteLine("New Executable (NE):"); @@ -195,7 +236,7 @@ namespace exeinfo 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("\tFile alignment shift: {0}", 512 << 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); @@ -209,5 +250,154 @@ namespace exeinfo Console.WriteLine("\tResident names table starts at {0}", header.resident_names_offset); Console.WriteLine("\tImported names table starts at {0}", header.imported_names_offset); } + + public static ResourceTable GetResources(FileStream exeFs, uint neStart, ushort tableOff) + { + long oldPosition = exeFs.Position; + byte[] DW = new byte[2]; + byte[] DD = new byte[4]; + + exeFs.Position = neStart + tableOff; + ResourceTable table = new ResourceTable(); + exeFs.Read(DW, 0, 2); + table.alignment_shift = BitConverter.ToUInt16(DW, 0); + + List types = new List(); + + while(true) + { + ResourceType type = new ResourceType(); + exeFs.Read(DW, 0, 2); + type.id = BitConverter.ToUInt16(DW, 0); + if (type.id == 0) + break; + + exeFs.Read(DW, 0, 2); + type.count = BitConverter.ToUInt16(DW, 0); + exeFs.Read(DD, 0, 4); + type.reserved = BitConverter.ToUInt32(DD, 0); + + type.resources = new Resource[type.count]; + for (int i = 0; i < type.count; i++) + { + type.resources[i] = new Resource(); + exeFs.Read(DW, 0, 2); + type.resources[i].dataOffset = BitConverter.ToUInt16(DW, 0); + exeFs.Read(DW, 0, 2); + type.resources[i].length = BitConverter.ToUInt16(DW, 0); + exeFs.Read(DW, 0, 2); + type.resources[i].flags = (ResourceFlags)BitConverter.ToUInt16(DW, 0); + exeFs.Read(DW, 0, 2); + type.resources[i].id = BitConverter.ToUInt16(DW, 0); + exeFs.Read(DD, 0, 4); + type.resources[i].reserved = BitConverter.ToUInt32(DD, 0); + } + + types.Add(type); + } + + table.types = types.ToArray(); + + for (int t = 0; t < table.types.Length; t++) + { + if ((table.types[t].id & 0x8000) == 0) + { + byte len; + byte[] str; + exeFs.Position = neStart + tableOff + table.types[t].id; + len = (byte)exeFs.ReadByte(); + str = new byte[len]; + exeFs.Read(str, 0, len); + table.types[t].name = Encoding.ASCII.GetString(str); + } + else + table.types[t].name = IdToName(table.types[t].id); + + for (int r = 0; r < table.types[t].resources.Length; r++) + { + if ((table.types[t].resources[r].id & 0x8000) == 0) + { + byte len; + byte[] str; + exeFs.Position = neStart + tableOff + table.types[t].resources[r].id; + len = (byte)exeFs.ReadByte(); + str = new byte[len]; + exeFs.Read(str, 0, len); + table.types[t].resources[r].name = Encoding.ASCII.GetString(str); + } + else + table.types[t].resources[r].name = string.Format("{0}", table.types[t].resources[r].id & 0x7FFF); + + table.types[t].resources[r].data = new byte[table.types[t].resources[r].length * (1 << table.alignment_shift)]; + exeFs.Position = table.types[t].resources[r].dataOffset * (1 <