/[RomCheater]/trunk/Win32/Sojaner.MemoryScanner/PEReader.cs
ViewVC logotype

Diff of /trunk/Win32/Sojaner.MemoryScanner/PEReader.cs

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

--- trunk/Win32/Sojaner.MemoryScanner/PEReader.cs	2012/06/05 10:27:16	293
+++ trunk/Win32/Sojaner.MemoryScanner/PEReader.cs	2012/06/05 10:48:07	294
@@ -11,606 +11,340 @@
 {
     public class PEReader
     {
-        public PEReader(FileInfo fi) : this(fi.FullName) { }
-        public PEReader(string filename) 
-        {
-            Exception ErrorInfo = null;
-            try
-            {
-                this.Read(filename, out ErrorInfo);
-            }
-            catch (Exception ex)
-            {
-                logger.Error.WriteLine("PEReader: Failed to read process: {0}", filename);
-                if (ErrorInfo != null)
-                {
-                    //logger.Error.WriteLine(ErrorInfo.GetBaseException().ToString());
-                    throw ErrorInfo;
-                }
-                else
-                {
-                    //logger.Error.WriteLine(ex.GetBaseException().ToString());
-                    throw ex;
-                }           
-            }
-        }
-
-        #region marshalling
-        private void Read(string filename, out Exception ErrorInfo)
+        // Code (C) Sergey utilized from: http://www.sergeyakopov.com/2010/11/03/reading-pe-format-using-data-marshalling-in-net/
+        #region Structs
+        [StructLayout(LayoutKind.Sequential)]
+        public struct IMAGE_DOS_HEADER
         {
-            ErrorInfo = null;
-            try
-            {
-                logger.Debug.WriteLine("Reading Exe: {0}", filename);
-
-                using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
-                {
-                    try
-                    {
-                        byte[] data = new byte[] { };
-                        GCHandle pinnedPacket = new GCHandle();
-                        int size = 0;
-                        BinaryReader br = new BinaryReader(fs);
-
-                        #region IMAGE_DOS_HEADER
-                        size = Marshal.SizeOf(typeof(IMAGE_DOS_HEADER));
-                        data = br.ReadBytes(size);
-                        pinnedPacket = GCHandle.Alloc(data, GCHandleType.Pinned);
-                        IMAGE_DOS_HEADER DOS_HEADER = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(pinnedPacket.AddrOfPinnedObject(), typeof(IMAGE_DOS_HEADER));
-                        pinnedPacket.Free();
-                        #endregion
-
-                        // skip the old dos stub
-                        br.BaseStream.Seek(DOS_HEADER.e_lfanew, SeekOrigin.Begin);
-
-                        #region IMAGE_NT_HEADERS
-                        size = Marshal.SizeOf(typeof(IMAGE_NT_HEADERS));
-                        data = br.ReadBytes(size);
-                        pinnedPacket = GCHandle.Alloc(data, GCHandleType.Pinned);
-                        IMAGE_NT_HEADERS NT_HEADER = (IMAGE_NT_HEADERS)Marshal.PtrToStructure(pinnedPacket.AddrOfPinnedObject(), typeof(IMAGE_NT_HEADERS));
-                        pinnedPacket.Free();
-                        #endregion
-
-                        StringBuilder section_header_string_builder = new StringBuilder();
-                        List<IMAGE_SECTION_HEADER> section_headers = new List<IMAGE_SECTION_HEADER>();
-                        section_header_string_builder.AppendFormat("Section headers:{0}", System.Environment.NewLine);
-                        for (int i = 0; i < NT_HEADER.FileHeader.NumberOfSections; i++)
-                        {
-                            size = Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER));
-                            data = br.ReadBytes(size);
-                            pinnedPacket = GCHandle.Alloc(data, GCHandleType.Pinned);
-                            IMAGE_SECTION_HEADER SECTION_HEADER = (IMAGE_SECTION_HEADER)Marshal.PtrToStructure(pinnedPacket.AddrOfPinnedObject(), typeof(IMAGE_SECTION_HEADER));
-                            section_headers.Add(SECTION_HEADER);
-                            pinnedPacket.Free();
-                            section_header_string_builder.AppendFormat("Section Header: {0}{1}", new string(SECTION_HEADER.Name).Replace("\0",""), System.Environment.NewLine);
-
-                        }
-                        logger.VerboseDebug.WriteLine(section_header_string_builder.ToString());
-                        br.Close();
-                    }
-                    catch (Exception ex)
-                    {
-                        ErrorInfo = ex;
-                    }
-                }
-            }
-            catch (Exception ex)
-            {
-                ErrorInfo = ex;
-            }
+            public UInt16 e_magic;
+            public UInt16 e_cblp;
+            public UInt16 e_cp;
+            public UInt16 e_crlc;
+            public UInt16 e_cparhdr;
+            public UInt16 e_minalloc;
+            public UInt16 e_maxalloc;
+            public UInt16 e_ss;
+            public UInt16 e_sp;
+            public UInt16 e_csum;
+            public UInt16 e_ip;
+            public UInt16 e_cs;
+            public UInt16 e_lfarlc;
+            public UInt16 e_ovno;
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
+            public UInt16[] e_res1;
+            public UInt16 e_oemid;
+            public UInt16 e_oeminfo;
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
+            public UInt16[] e_res2;
+            public UInt32 e_lfanew;
         }
-        #endregion
 
-        #region header support
-        #region IMAGE_DATA_DIRECTORY
         [StructLayout(LayoutKind.Sequential)]
-        public struct IMAGE_DATA_DIRECTORY
+        public struct IMAGE_NT_HEADERS
         {
-            public UInt32 VirtualAddress;
-            public UInt32 Size;
-            public bool HasAddress { get { return (VirtualAddress != 0); } }
-            public bool HasSize { get { return (Size > 0); } }
+            public UInt32 Signature;
+            public IMAGE_FILE_HEADER FileHeader;
+            public IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
+            public IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
         }
-        #endregion
-        #region IMAGE_FILE_HEADER
+
         [StructLayout(LayoutKind.Sequential)]
         public struct IMAGE_FILE_HEADER
         {
-            public MachineType Machine;
+            public UInt16 Machine;
             public UInt16 NumberOfSections;
             public UInt32 TimeDateStamp;
             public UInt32 PointerToSymbolTable;
             public UInt32 NumberOfSymbols;
             public UInt16 SizeOfOptionalHeader;
-            public DllCharacteristicsType Characteristics;
+            public UInt16 Characteristics;
         }
-        #endregion
-        #region IMAGE_DOS_HEADER
+
         [StructLayout(LayoutKind.Sequential)]
-        public struct IMAGE_DOS_HEADER
+        public struct IMAGE_OPTIONAL_HEADER32
         {
-            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
-            public char[] e_magic;       // Magic number
-            public UInt16 e_cblp;    // Bytes on last page of file
-            public UInt16 e_cp;      // Pages in file
-            public UInt16 e_crlc;    // Relocations
-            public UInt16 e_cparhdr;     // Size of header in paragraphs
-            public UInt16 e_minalloc;    // Minimum extra paragraphs needed
-            public UInt16 e_maxalloc;    // Maximum extra paragraphs needed
-            public UInt16 e_ss;      // Initial (relative) SS value
-            public UInt16 e_sp;      // Initial SP value
-            public UInt16 e_csum;    // Checksum
-            public UInt16 e_ip;      // Initial IP value
-            public UInt16 e_cs;      // Initial (relative) CS value
-            public UInt16 e_lfarlc;      // File address of relocation table
-            public UInt16 e_ovno;    // Overlay number
-            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
-            public UInt16[] e_res1;    // Reserved words
-            public UInt16 e_oemid;       // OEM identifier (for e_oeminfo)
-            public UInt16 e_oeminfo;     // OEM information; e_oemid specific
-            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
-            public UInt16[] e_res2;    // Reserved words
-            public Int32 e_lfanew;      // File address of new exe header
-            private string _e_magic
-            {
-                get { return new string(e_magic); }
-            }
-            public bool isValid
-            {
-                get { return _e_magic == "MZ"; }
-            }
+            public UInt16 Magic;
+            public Byte MajorLinkerVersion;
+            public Byte MinorLinkerVersion;
+            public UInt32 SizeOfCode;
+            public UInt32 SizeOfInitializedData;
+            public UInt32 SizeOfUninitializedData;
+            public UInt32 AddressOfEntryPoint;
+            public UInt32 BaseOfCode;
+            public UInt32 BaseOfData;
+            public UInt32 ImageBase;
+            public UInt32 SectionAlignment;
+            public UInt32 FileAlignment;
+            public UInt16 MajorOperatingSystemVersion;
+            public UInt16 MinorOperatingSystemVersion;
+            public UInt16 MajorImageVersion;
+            public UInt16 MinorImageVersion;
+            public UInt16 MajorSubsystemVersion;
+            public UInt16 MinorSubsystemVersion;
+            public UInt32 Win32VersionValue;
+            public UInt32 SizeOfImage;
+            public UInt32 SizeOfHeaders;
+            public UInt32 CheckSum;
+            public UInt16 Subsystem;
+            public UInt16 DllCharacteristics;
+            public UInt32 SizeOfStackReserve;
+            public UInt32 SizeOfStackCommit;
+            public UInt32 SizeOfHeapReserve;
+            public UInt32 SizeOfHeapCommit;
+            public UInt32 LoaderFlags;
+            public UInt32 NumberOfRvaAndSizes;
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+            public IMAGE_DATA_DIRECTORY[] DataDirectory;
         }
-        #endregion
-        #region IMAGE_NT_HEADERS
-        [StructLayout(LayoutKind.Explicit)]
-        public struct IMAGE_NT_HEADERS
-        {
-            [FieldOffset(0)]
-            public uint Signature;
-            [FieldOffset(4)]
-            public IMAGE_FILE_HEADER FileHeader;
-            [FieldOffset(24)]
-            public IMAGE_OPTIONAL_HEADER OptionalHeader;
-
-            private string _Signature
-            {
-                get { return Encoding.ASCII.GetString(BitConverter.GetBytes(Signature)); }
-            }
 
-            public bool isValid
-            {
-                get { return _Signature == "PE\0\0" && (OptionalHeader.Magic == MagicType.IMAGE_NT_OPTIONAL_HDR32_MAGIC || OptionalHeader.Magic == MagicType.IMAGE_NT_OPTIONAL_HDR64_MAGIC); }
-            }
-        }
-        #endregion
-        #region MachineType
-        public enum MachineType : ushort
+        [StructLayout(LayoutKind.Sequential)]
+        public struct IMAGE_OPTIONAL_HEADER64
         {
-            Native = 0,
-            I386 = 0x014c,
-            Itanium = 0x0200,
-            x64 = 0x8664
+            public UInt16 Magic;
+            public Byte MajorLinkerVersion;
+            public Byte MinorLinkerVersion;
+            public UInt32 SizeOfCode;
+            public UInt32 SizeOfInitializedData;
+            public UInt32 SizeOfUninitializedData;
+            public UInt32 AddressOfEntryPoint;
+            public UInt32 BaseOfCode;
+            public UInt64 ImageBase;
+            public UInt32 SectionAlignment;
+            public UInt32 FileAlignment;
+            public UInt16 MajorOperatingSystemVersion;
+            public UInt16 MinorOperatingSystemVersion;
+            public UInt16 MajorImageVersion;
+            public UInt16 MinorImageVersion;
+            public UInt16 MajorSubsystemVersion;
+            public UInt16 MinorSubsystemVersion;
+            public UInt32 Win32VersionValue;
+            public UInt32 SizeOfImage;
+            public UInt32 SizeOfHeaders;
+            public UInt32 CheckSum;
+            public UInt16 Subsystem;
+            public UInt16 DllCharacteristics;
+            public UInt64 SizeOfStackReserve;
+            public UInt64 SizeOfStackCommit;
+            public UInt64 SizeOfHeapReserve;
+            public UInt64 SizeOfHeapCommit;
+            public UInt32 LoaderFlags;
+            public UInt32 NumberOfRvaAndSizes;
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+            public IMAGE_DATA_DIRECTORY[] DataDirectory;
         }
-        #endregion
-        #region MagicType
-        public enum MagicType : ushort
+
+        [StructLayout(LayoutKind.Sequential)]
+        public struct IMAGE_DATA_DIRECTORY
         {
-            IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b,
-            IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b
+            public UInt32 VirtualAddress;
+            public UInt32 Size;
         }
-        #endregion
-        #region SubSystemType
-        public enum SubSystemType : ushort
-        {
-            IMAGE_SUBSYSTEM_UNKNOWN = 0,
-            IMAGE_SUBSYSTEM_NATIVE = 1,
-            IMAGE_SUBSYSTEM_WINDOWS_GUI = 2,
-            IMAGE_SUBSYSTEM_WINDOWS_CUI = 3,
-            IMAGE_SUBSYSTEM_POSIX_CUI = 7,
-            IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9,
-            IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
-            IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
-            IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12,
-            IMAGE_SUBSYSTEM_EFI_ROM = 13,
-            IMAGE_SUBSYSTEM_XBOX = 14
 
+        [StructLayout(LayoutKind.Sequential)]
+        public struct IMAGE_SECTION_HEADER
+        {
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
+            public string Name;
+            public Misc Misc;
+            public UInt32 VirtualAddress;
+            public UInt32 SizeOfRawData;
+            public UInt32 PointerToRawData;
+            public UInt32 PointerToRelocations;
+            public UInt32 PointerToLinenumbers;
+            public UInt16 NumberOfRelocations;
+            public UInt16 NumberOfLinenumbers;
+            public UInt32 Characteristics;
         }
-        #endregion
-        #region DllCharacteristicsType
-        [Flags]
-        public enum DllCharacteristicsType : ushort
-        {
-            RES_0 = 0x0001,
-            RES_1 = 0x0002,
-            RES_2 = 0x0004,
-            RES_3 = 0x0008,
-            IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040,
-            IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
-            IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100,
-            IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200,
-            IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400,
-            IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800,
-            RES_4 = 0x1000,
-            IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000,
-            IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
-        }
-        #endregion
-        #region IMAGE_OPTIONAL_HEADER
+
         [StructLayout(LayoutKind.Explicit)]
-        public struct IMAGE_OPTIONAL_HEADER
+        public struct Misc
         {
             [FieldOffset(0)]
-            public MagicType Magic;
-
-            [FieldOffset(2)]
-            public byte MajorLinkerVersion;
-
-            [FieldOffset(3)]
-            public byte MinorLinkerVersion;
-
-            [FieldOffset(4)]
-            public uint SizeOfCode;
-
-            [FieldOffset(8)]
-            public uint SizeOfInitializedData;
-
-            [FieldOffset(12)]
-            public uint SizeOfUninitializedData;
-
-            [FieldOffset(16)]
-            public uint AddressOfEntryPoint;
-
-            [FieldOffset(20)]
-            public uint BaseOfCode;
-
-            // PE32 contains this additional field
-            [FieldOffset(24)]
-            public uint BaseOfData;
-
-            [FieldOffset(28)]
-            public uint ImageBase;
-
-            [FieldOffset(32)]
-            public uint SectionAlignment;
-
-            [FieldOffset(36)]
-            public uint FileAlignment;
-
-            [FieldOffset(40)]
-            public ushort MajorOperatingSystemVersion;
-
-            [FieldOffset(42)]
-            public ushort MinorOperatingSystemVersion;
-
-            [FieldOffset(44)]
-            public ushort MajorImageVersion;
-
-            [FieldOffset(46)]
-            public ushort MinorImageVersion;
-
-            [FieldOffset(48)]
-            public ushort MajorSubsystemVersion;
-
-            [FieldOffset(50)]
-            public ushort MinorSubsystemVersion;
-
-            [FieldOffset(52)]
-            public uint Win32VersionValue;
-
-            [FieldOffset(56)]
-            public uint SizeOfImage;
-
-            [FieldOffset(60)]
-            public uint SizeOfHeaders;
-
-            [FieldOffset(64)]
-            public uint CheckSum;
-
-            [FieldOffset(68)]
-            public SubSystemType Subsystem;
-
-            [FieldOffset(70)]
-            public DllCharacteristicsType DllCharacteristics;
-
-            [FieldOffset(72)]
-            public uint SizeOfStackReserve;
-
-            [FieldOffset(76)]
-            public uint SizeOfStackCommit;
-
-            [FieldOffset(80)]
-            public uint SizeOfHeapReserve;
-
-            [FieldOffset(84)]
-            public uint SizeOfHeapCommit;
+            public UInt32 PhysicalAddress;
+            [FieldOffset(0)]
+            public UInt32 VirtualSize;
+        }
 
-            [FieldOffset(88)]
-            public uint LoaderFlags;
+        #endregion
 
-            [FieldOffset(92)]
-            public uint NumberOfRvaAndSizes;
+        #region Fields
 
-            [FieldOffset(96)]
-            public IMAGE_DATA_DIRECTORY ExportTable;
+        private readonly IMAGE_DOS_HEADER _dosHeader;
+        private IMAGE_NT_HEADERS _ntHeaders;
+        private readonly IList<IMAGE_SECTION_HEADER> _sectionHeaders = new List<IMAGE_SECTION_HEADER>();
 
-            [FieldOffset(104)]
-            public IMAGE_DATA_DIRECTORY ImportTable;
+        #endregion
 
-            [FieldOffset(112)]
-            public IMAGE_DATA_DIRECTORY ResourceTable;
+        public PEReader(FileInfo fi) : this(fi.FullName) { }
+        public PEReader(string filename)
+        {
+            Exception ErrorInfo = null;
+            using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
+            {
+                try
+                {
+                    logger.VerboseDebug.WriteLine("Reading PE Format from: {0}", filename);
+                    BinaryReader reader = new BinaryReader(fs);
+                    // Reset reader position, just in case
+                    reader.BaseStream.Seek(0, SeekOrigin.Begin);
+
+                    // Read MS-DOS header section
+                    _dosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(reader);
+                    // MS-DOS magic number should read 'MZ'
+                    if (_dosHeader.e_magic != 0x5a4d)
+                    {
+                        throw new InvalidOperationException("File is not a portable executable.");
+                    }
 
-            [FieldOffset(120)]
-            public IMAGE_DATA_DIRECTORY ExceptionTable;
+                    // Skip MS-DOS stub and seek reader to NT Headers
+                    reader.BaseStream.Seek(_dosHeader.e_lfanew, SeekOrigin.Begin);
 
-            [FieldOffset(128)]
-            public IMAGE_DATA_DIRECTORY CertificateTable;
+                    // Read NT Headers
+                    _ntHeaders.Signature = MarshalBytesTo<UInt32>(reader);
 
-            [FieldOffset(136)]
-            public IMAGE_DATA_DIRECTORY BaseRelocationTable;
+                    // Make sure we have 'PE' in the pe signature
+                    if (_ntHeaders.Signature != 0x4550)
+                    {
+                        throw new InvalidOperationException("Invalid portable executable signature in NT header.");
+                    }
 
-            [FieldOffset(144)]
-            public IMAGE_DATA_DIRECTORY Debug;
+                    _ntHeaders.FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader);                    
+                    // Read optional headers
+                    if (Is32bitAssembly())
+                    {
+                        logger.VerboseDebug.WriteLine("Detected a 32Bit PE Executable");
+                        Load32bitOptionalHeaders(reader);
+                    }
+                    else
+                    {
+                        logger.VerboseDebug.WriteLine("Detected a 64Bit PE Executable");
+                        Load64bitOptionalHeaders(reader);
+                    }
 
-            [FieldOffset(152)]
-            public IMAGE_DATA_DIRECTORY Architecture;
+                    // Read section data
+                    logger.VerboseDebug.WriteLine("Total Section Headers: {0}", _sectionHeaders.Count);
+                    foreach (IMAGE_SECTION_HEADER header in _sectionHeaders)
+                    {
+                        int section_index = _sectionHeaders.IndexOf(header) + 1;
+                        logger.VerboseDebug.WriteLine("Section Header: {0} of {1}", section_index, _sectionHeaders.Count);
+                        logger.VerboseDebug.WriteLine("\tName: {0}", header.Name);
+                        logger.VerboseDebug.WriteLine("\tVirtual Address: 0x{0:x8}", header.VirtualAddress);
+                        logger.VerboseDebug.WriteLine("\tPhysical Address: 0x{0:x8}", header.Misc.PhysicalAddress);
+                        logger.VerboseDebug.WriteLine("\tVirtual Size: 0x{0:x8}", header.Misc.VirtualSize);
+                        logger.VerboseDebug.WriteLine("\tRaw Data Size: 0x{0:x8}", header.SizeOfRawData);
+                        logger.VerboseDebug.WriteLine("\tPointer To Raw Data: 0x{0:x8}", header.PointerToRawData);
 
-            [FieldOffset(160)]
-            public IMAGE_DATA_DIRECTORY GlobalPtr;
+                        // Skip to beginning of a section
+                        reader.BaseStream.Seek(header.PointerToRawData, SeekOrigin.Begin);
 
-            [FieldOffset(168)]
-            public IMAGE_DATA_DIRECTORY TLSTable;
+                        // Read section data... and do something with it
+                        byte[] sectiondata = reader.ReadBytes((int)header.SizeOfRawData);
+                    }
+                    reader.Close();
+                }
+                catch (Exception ex)
+                {
+                    ErrorInfo = ex;
+                    throw ErrorInfo;
+                }
+            }
+            if (ErrorInfo != null)
+            {
+                logger.VerboseError.WriteLine("Error Reading PE Format from: {0}",filename);
+                logger.VerboseError.WriteLine(ErrorInfo.ToString());
+            }
+        }
 
-            [FieldOffset(176)]
-            public IMAGE_DATA_DIRECTORY LoadConfigTable;
+        public IMAGE_DOS_HEADER GetDOSHeader()
+        {
+            return _dosHeader;
+        }
 
-            [FieldOffset(184)]
-            public IMAGE_DATA_DIRECTORY BoundImport;
+        public UInt32 GetPESignature()
+        {
+            return _ntHeaders.Signature;
+        }
 
-            [FieldOffset(192)]
-            public IMAGE_DATA_DIRECTORY IAT;
+        public IMAGE_FILE_HEADER GetFileHeader()
+        {
+            return _ntHeaders.FileHeader;
+        }
 
-            [FieldOffset(200)]
-            public IMAGE_DATA_DIRECTORY DelayImportDescriptor;
+        public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
+        {
+            return _ntHeaders.OptionalHeader32;
+        }
 
-            [FieldOffset(208)]
-            public IMAGE_DATA_DIRECTORY CLRRuntimeHeader;
+        public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
+        {
+            return _ntHeaders.OptionalHeader64;
+        }
 
-            [FieldOffset(216)]
-            public IMAGE_DATA_DIRECTORY Reserved;
+        public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
+        {
+            return _sectionHeaders;
         }
-        #endregion
-        #region IMAGE_EXPORT_DIRECTORY
-        [StructLayout(LayoutKind.Sequential)]
-        public struct IMAGE_EXPORT_DIRECTORY
+
+        public bool Is32bitAssembly()
         {
-            public UInt32 Characteristics;
-            public UInt32 TimeDateStamp;
-            public UInt16 MajorVersion;
-            public UInt16 MinorVersion;
-            public UInt32 Name;
-            public UInt32 Base;
-            public UInt32 NumberOfFunctions;
-            public UInt32 NumberOfNames;
-            public UInt32 AddressOfFunctions;     // RVA from base of image
-            public UInt32 AddressOfNames;     // RVA from base of image
-            public UInt32 AddressOfNameOrdinals;  // RVA from base of image
+            return ((_ntHeaders.FileHeader.Characteristics & 0x0100) == 0x0100);
         }
-        #endregion
-        #endregion
-        #region IMAGE_SECTION_HEADER
-        [StructLayout(LayoutKind.Explicit)]
-        public struct IMAGE_SECTION_HEADER
+
+        private void Load64bitOptionalHeaders(BinaryReader reader)
         {
-            [FieldOffset(0)]
-            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
-            public char[] Name;
+            _ntHeaders.OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader);
 
-            [FieldOffset(8)]
-            public UInt32 VirtualSize;
+            // Should have 10 data directories
+            if (_ntHeaders.OptionalHeader64.NumberOfRvaAndSizes != 0x10)
+            {
+                throw new InvalidOperationException("Invalid number of data directories in NT header");
+            }
 
-            [FieldOffset(12)]
-            public UInt32 VirtualAddress;
+            // Scan data directories and load section headers
+            for (int i = 0; i < _ntHeaders.OptionalHeader64.NumberOfRvaAndSizes; i++)
+            {
+                if (_ntHeaders.OptionalHeader64.DataDirectory[i].Size > 0)
+                {
+                    _sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
+                }
+            }
+        }
 
-            [FieldOffset(16)]
-            public UInt32 SizeOfRawData;
+        private void Load32bitOptionalHeaders(BinaryReader reader)
+        {
+            _ntHeaders.OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader);
 
-            [FieldOffset(20)]
-            public UInt32 PointerToRawData;
+            // Should have 10 data directories
+            if (_ntHeaders.OptionalHeader32.NumberOfRvaAndSizes != 0x10)
+            {
+                throw new InvalidOperationException("Invalid number of data directories in NT header");
+            }
 
-            [FieldOffset(24)]
-            public UInt32 PointerToRelocations;
+            // Scan data directories and load section headers
+            for (int i = 0; i < _ntHeaders.OptionalHeader32.NumberOfRvaAndSizes; i++)
+            {
+                if (_ntHeaders.OptionalHeader32.DataDirectory[i].Size > 0)
+                {
+                    _sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
+                }
+            }
+        }
 
-            [FieldOffset(28)]
-            public UInt32 PointerToLinenumbers;
+        private static T MarshalBytesTo<T>(BinaryReader reader)
+        {
+            // Unmanaged data
+            byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
 
-            [FieldOffset(32)]
-            public UInt16 NumberOfRelocations;
+            // Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code
+            GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
 
-            [FieldOffset(34)]
-            public UInt16 NumberOfLinenumbers;
+            // Use our previously created pointer to unmanaged data and marshal to the specified type
+            T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
 
-            [FieldOffset(36)]
-            public DataSectionFlags Characteristics;
+            // Deallocate pointer
+            handle.Free();
 
-            public string Section
-            {
-                get { return new string(Name); }
-            }
+            return theStructure;
         }
-        #endregion
-        #region DataSectionFlags
-        [Flags]
-        public enum DataSectionFlags : uint
-        {
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            TypeReg = 0x00000000,
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            TypeDsect = 0x00000001,
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            TypeNoLoad = 0x00000002,
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            TypeGroup = 0x00000004,
-            /// <summary>
-            /// The section should not be padded to the next boundary. This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files.
-            /// </summary>
-            TypeNoPadded = 0x00000008,
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            TypeCopy = 0x00000010,
-            /// <summary>
-            /// The section contains executable code.
-            /// </summary>
-            ContentCode = 0x00000020,
-            /// <summary>
-            /// The section contains initialized data.
-            /// </summary>
-            ContentInitializedData = 0x00000040,
-            /// <summary>
-            /// The section contains uninitialized data.
-            /// </summary>
-            ContentUninitializedData = 0x00000080,
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            LinkOther = 0x00000100,
-            /// <summary>
-            /// The section contains comments or other information. The .drectve section has this type. This is valid for object files only.
-            /// </summary>
-            LinkInfo = 0x00000200,
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            TypeOver = 0x00000400,
-            /// <summary>
-            /// The section will not become part of the image. This is valid only for object files.
-            /// </summary>
-            LinkRemove = 0x00000800,
-            /// <summary>
-            /// The section contains COMDAT data. For more information, see section 5.5.6, COMDAT Sections (Object Only). This is valid only for object files.
-            /// </summary>
-            LinkComDat = 0x00001000,
-            /// <summary>
-            /// Reset speculative exceptions handling bits in the TLB entries for this section.
-            /// </summary>
-            NoDeferSpecExceptions = 0x00004000,
-            /// <summary>
-            /// The section contains data referenced through the global pointer (GP).
-            /// </summary>
-            RelativeGP = 0x00008000,
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            MemPurgeable = 0x00020000,
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            Memory16Bit = 0x00020000,
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            MemoryLocked = 0x00040000,
-            /// <summary>
-            /// Reserved for future use.
-            /// </summary>
-            MemoryPreload = 0x00080000,
-            /// <summary>
-            /// Align data on a 1-byte boundary. Valid only for object files.
-            /// </summary>
-            Align1Bytes = 0x00100000,
-            /// <summary>
-            /// Align data on a 2-byte boundary. Valid only for object files.
-            /// </summary>
-            Align2Bytes = 0x00200000,
-            /// <summary>
-            /// Align data on a 4-byte boundary. Valid only for object files.
-            /// </summary>
-            Align4Bytes = 0x00300000,
-            /// <summary>
-            /// Align data on an 8-byte boundary. Valid only for object files.
-            /// </summary>
-            Align8Bytes = 0x00400000,
-            /// <summary>
-            /// Align data on a 16-byte boundary. Valid only for object files.
-            /// </summary>
-            Align16Bytes = 0x00500000,
-            /// <summary>
-            /// Align data on a 32-byte boundary. Valid only for object files.
-            /// </summary>
-            Align32Bytes = 0x00600000,
-            /// <summary>
-            /// Align data on a 64-byte boundary. Valid only for object files.
-            /// </summary>
-            Align64Bytes = 0x00700000,
-            /// <summary>
-            /// Align data on a 128-byte boundary. Valid only for object files.
-            /// </summary>
-            Align128Bytes = 0x00800000,
-            /// <summary>
-            /// Align data on a 256-byte boundary. Valid only for object files.
-            /// </summary>
-            Align256Bytes = 0x00900000,
-            /// <summary>
-            /// Align data on a 512-byte boundary. Valid only for object files.
-            /// </summary>
-            Align512Bytes = 0x00A00000,
-            /// <summary>
-            /// Align data on a 1024-byte boundary. Valid only for object files.
-            /// </summary>
-            Align1024Bytes = 0x00B00000,
-            /// <summary>
-            /// Align data on a 2048-byte boundary. Valid only for object files.
-            /// </summary>
-            Align2048Bytes = 0x00C00000,
-            /// <summary>
-            /// Align data on a 4096-byte boundary. Valid only for object files.
-            /// </summary>
-            Align4096Bytes = 0x00D00000,
-            /// <summary>
-            /// Align data on an 8192-byte boundary. Valid only for object files.
-            /// </summary>
-            Align8192Bytes = 0x00E00000,
-            /// <summary>
-            /// The section contains extended relocations.
-            /// </summary>
-            LinkExtendedRelocationOverflow = 0x01000000,
-            /// <summary>
-            /// The section can be discarded as needed.
-            /// </summary>
-            MemoryDiscardable = 0x02000000,
-            /// <summary>
-            /// The section cannot be cached.
-            /// </summary>
-            MemoryNotCached = 0x04000000,
-            /// <summary>
-            /// The section is not pageable.
-            /// </summary>
-            MemoryNotPaged = 0x08000000,
-            /// <summary>
-            /// The section can be shared in memory.
-            /// </summary>
-            MemoryShared = 0x10000000,
-            /// <summary>
-            /// The section can be executed as code.
-            /// </summary>
-            MemoryExecute = 0x20000000,
-            /// <summary>
-            /// The section can be read.
-            /// </summary>
-            MemoryRead = 0x40000000,
-            /// <summary>
-            /// The section can be written to.
-            /// </summary>
-            MemoryWrite = 0x80000000
-        }
-        #endregion
     }
 }

 

  ViewVC Help
Powered by ViewVC 1.1.22