#define ENABLE_LOGGING using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using RomCheater.Logging; using System.Runtime.InteropServices; using System.Diagnostics; using System.ComponentModel; namespace Sojaner.MemoryScanner { public class PEReader { // Code (C) Sergey utilized from: http://www.sergeyakopov.com/2010/11/03/reading-pe-format-using-data-marshalling-in-net/ #region Structs [Flags] public enum MachineTypeFlags { x86 = 0x14C, Alpha = 0x184, ARM = 0x1C0, MIPS16R3000 = 0x162, MIPS16R4000 = 0x166, MIPS16R10000 = 0x168, PowerPCLE = 0x1F0, PowerPCBE = 0x1F2, Itanium = 0x200, MIPS16 = 0x266, Alpha64 = 0x284, MIPSFPU = 0x366, MIPSFPU16 = 0x466, x64 = 0x8664, } public enum MagicType : ushort { NT_OPTIONAL_HEADER_NOT_PRESENT, // 0 NT_OPTIONAL_HEADER_32 = 0x10b, NT_OPTIONAL_HEADER_64 = 0x20b } 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 } 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 } [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_DOS_HEADER { 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; public string e_magic { get { return string.Format("0x{0:x4}", _e_magic); } } public string e_cblp { get { return string.Format("0x{0:x4}", _e_cblp); } } public string e_cp { get { return string.Format("0x{0:x4}", _e_cp); } } public string e_crlc { get { return string.Format("0x{0:x4}", _e_crlc); } } public string e_cparhdr { get { return string.Format("0x{0:x4}", _e_cparhdr); } } public string e_minalloc { get { return string.Format("0x{0:x4}", _e_minalloc); } } public string e_maxalloc { get { return string.Format("0x{0:x4}", _e_maxalloc); } } public string e_ss { get { return string.Format("0x{0:x4}", _e_ss); } } public string e_sp { get { return string.Format("0x{0:x4}", _e_sp); } } public string e_csum { get { return string.Format("0x{0:x4}", _e_csum); } } public string e_ip { get { return string.Format("0x{0:x4}", _e_ip); } } public string e_cs { get { return string.Format("0x{0:x4}", _e_cs); } } public string e_lfarlc { get { return string.Format("0x{0:x4}", _e_lfarlc); } } public string e_ovno { get { return string.Format("0x{0:x4}", _e_ovno); } } public ushort[] e_res1 { get { return _e_res1; } } public string e_oemid { get { return string.Format("0x{0:x4}", _e_oemid); } } public string e_oeminfo { get { return string.Format("0x{0:x4}", _e_oeminfo); } } public ushort[] e_res2 { get { return _e_res2; } } public string e_lfanew { get { return string.Format("0x{0:x8}", _e_lfanew); } } public override string ToString() { return Encoding.UTF8.GetString(BitConverter.GetBytes(_e_magic)); } } [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_NT_HEADERS { public UInt32 _Signature; public IMAGE_FILE_HEADER _FileHeader; public IMAGE_OPTIONAL_HEADER32 _OptionalHeader32; public IMAGE_OPTIONAL_HEADER64 _OptionalHeader64; public string Signature { get { return string.Format("0x{0:x8}", _Signature); } } public IMAGE_FILE_HEADER FileHeader { get { return _FileHeader; } } public IMAGE_OPTIONAL_HEADER32 OptionalHeader32 { get { return _OptionalHeader32;} } public IMAGE_OPTIONAL_HEADER64 OptionalHeader64 { get { return _OptionalHeader64;} } public override string ToString() { return Encoding.UTF8.GetString(BitConverter.GetBytes(_Signature)); } } [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_FILE_HEADER { public UInt16 _MachineType; public UInt16 _NumberOfSections; public UInt32 _TimeDateStamp; public UInt32 _PointerToSymbolTable; public UInt32 _NumberOfSymbols; public UInt16 _SizeOfOptionalHeader; public UInt16 _Characteristics; public string MachineType { get { return ((MachineTypeFlags)_MachineType).ToString(); } } public string NumberOfSections { get { return string.Format("0x{0:x4}", _NumberOfSections); } } public string TimeDateStamp { get { return string.Format("{0} (0x{1:x8})", GetDateTimeFromDosDateTime(_TimeDateStamp).ToString(), _TimeDateStamp); } } public string PointerToSymbolTable { get { return string.Format("0x{0:x8}", _PointerToSymbolTable); } } public string NumberOfSymbols { get { return string.Format("0x{0:x8}", _NumberOfSymbols); } } public string SizeOfOptionalHeader { get { return string.Format("0x{0:x4}", _SizeOfOptionalHeader); } } public string Characteristics { get { return string.Format("0x{0:x4}", _Characteristics); } } public override string ToString() { return MachineType; } private DateTime GetDateTimeFromDosDateTime(UInt32 i32TimeDate) { UInt16 i16Time = (UInt16)(i32TimeDate & 0xFFFF); UInt16 i16Date = (UInt16)((i32TimeDate & 0xFFFF0000) >> 16); return GetDateTimeFromDosDateTime(i16Time, i16Date); } private DateTime GetDateTimeFromDosDateTime(UInt16 i16Time, UInt16 i16Date) { int iYear = 0; int iMonth = 1; int iDay = 1; int iHour = 0; int iMinute = 0; int iSecond = 0; iDay = (i16Date & 0x1F); iMonth = ((i16Date & 0x01E0) >> 5); iYear = 1970 + ((i16Date & 0xFE00) >> 9); iSecond = (i16Time & 0x1F) * 2; iMinute = ((i16Time & 0x07E0) >> 5); iHour = ((i16Time & 0x0F800) >> 11); return new DateTime(iYear, iMonth, iDay, iHour, iMinute, iSecond); } } [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_OPTIONAL_HEADER32 { 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; // 32-but specific 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; public string Magic { get { return ((MagicType)_Magic).ToString(); } } public string MajorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } } public string MinorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } } public string SizeOfCode { get { return string.Format("0x{0:x2}", _SizeOfCode); } } public string SizeOfInitializedData { get { return string.Format("0x{0:x8}", _SizeOfInitializedData); } } public string SizeOfUninitializedData { get { return string.Format("0x{0:x8}", _SizeOfUninitializedData); } } public string AddressOfEntryPoint { get { return string.Format("0x{0:x8}", _AddressOfEntryPoint); } } public string BaseOfCode { get { return string.Format("0x{0:x8}", _BaseOfCode); } } public string BaseOfData { get { return string.Format("0x{0:x8}", _BaseOfData); } } public string ImageBase { get { return string.Format("0x{0:x16}", _ImageBase); } } public string SectionAlignment { get { return string.Format("0x{0:x8}", _SectionAlignment); } } public string FileAlignment { get { return string.Format("0x{0:x8}", _FileAlignment); } } public string MajorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MajorOperatingSystemVersion); } } public string MinorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MinorOperatingSystemVersion); } } public string MajorImageVersion { get { return string.Format("0x{0:x4}", _MajorImageVersion); } } public string MinorImageVersion { get { return string.Format("0x{0:x4}", _MinorImageVersion); } } public string MajorSubsystemVersion { get { return string.Format("0x{0:x4}", _MajorSubsystemVersion); } } public string MinorSubsystemVersion { get { return string.Format("0x{0:x4}", _MinorSubsystemVersion); } } public string Win32VersionValue { get { return string.Format("0x{0:x8}", _Win32VersionValue); } } public string SizeOfImage { get { return string.Format("0x{0:x8}", _SizeOfImage); } } public string SizeOfHeaders { get { return string.Format("0x{0:x8}", _SizeOfHeaders); } } public string CheckSum { get { return string.Format("0x{0:x8}", _CheckSum); } } public string Subsystem { get { return ((SubSystemType)_Subsystem).ToString(); } } public string DllCharacteristics { get { return string.Format("0x{0:x4}", _DllCharacteristics); } } public string SizeOfStackReserve { get { return string.Format("0x{0:x16}", _SizeOfStackReserve); } } public string SizeOfStackCommit { get { return string.Format("0x{0:x16}", _SizeOfStackCommit); } } public string SizeOfHeapReserve { get { return string.Format("0x{0:x16}", _SizeOfHeapReserve); } } public string SizeOfHeapCommit { get { return string.Format("0x{0:x16}", _SizeOfHeapCommit); } } public string LoaderFlags { get { return string.Format("0x{0:x8}", _LoaderFlags); } } public string NumberOfRvaAndSizes { get { return string.Format("0x{0:x8}", _NumberOfRvaAndSizes); } } public override string ToString() { return Magic; } } [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_OPTIONAL_HEADER64 { 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; public string Magic { get { return ((MagicType)_Magic).ToString(); } } public string MajorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } } public string MinorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } } public string SizeOfCode { get { return string.Format("0x{0:x2}", _SizeOfCode); } } public string SizeOfInitializedData { get { return string.Format("0x{0:x8}", _SizeOfInitializedData); } } public string SizeOfUninitializedData { get { return string.Format("0x{0:x8}", _SizeOfUninitializedData); } } public string AddressOfEntryPoint { get { return string.Format("0x{0:x8}", _AddressOfEntryPoint); } } public string BaseOfCode { get { return string.Format("0x{0:x8}", _BaseOfCode); } } public string ImageBase { get { return string.Format("0x{0:x16}", _ImageBase); } } public string SectionAlignment { get { return string.Format("0x{0:x8}", _SectionAlignment); } } public string FileAlignment { get { return string.Format("0x{0:x8}", _FileAlignment); } } public string MajorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MajorOperatingSystemVersion); } } public string MinorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MinorOperatingSystemVersion); } } public string MajorImageVersion { get { return string.Format("0x{0:x4}", _MajorImageVersion); } } public string MinorImageVersion { get { return string.Format("0x{0:x4}", _MinorImageVersion); } } public string MajorSubsystemVersion { get { return string.Format("0x{0:x4}", _MajorSubsystemVersion); } } public string MinorSubsystemVersion { get { return string.Format("0x{0:x4}", _MinorSubsystemVersion); } } public string Win32VersionValue { get { return string.Format("0x{0:x8}", _Win32VersionValue); } } public string SizeOfImage { get { return string.Format("0x{0:x8}", _SizeOfImage); } } public string SizeOfHeaders { get { return string.Format("0x{0:x8}", _SizeOfHeaders); } } public string CheckSum { get { return string.Format("0x{0:x8}", _CheckSum); } } public string Subsystem { get { return ((SubSystemType)_Subsystem).ToString(); } } public string DllCharacteristics { get { return string.Format("0x{0:x4}", _DllCharacteristics); } } public string SizeOfStackReserve { get { return string.Format("0x{0:x16}", _SizeOfStackReserve); } } public string SizeOfStackCommit { get { return string.Format("0x{0:x16}", _SizeOfStackCommit); } } public string SizeOfHeapReserve { get { return string.Format("0x{0:x16}", _SizeOfHeapReserve); } } public string SizeOfHeapCommit { get { return string.Format("0x{0:x16}", _SizeOfHeapCommit); } } public string LoaderFlags { get { return string.Format("0x{0:x8}", _LoaderFlags); } } public string NumberOfRvaAndSizes { get { return string.Format("0x{0:x8}", _NumberOfRvaAndSizes); } } public override string ToString() { return Magic; } } [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_DATA_DIRECTORY { public UInt32 _VirtualAddress; public UInt32 _Size; public string VirtualAddress { get { return string.Format("0x{0:x8}", _VirtualAddress); } } public string Size { get { return string.Format("0x{0:x8}", _Size); } } } [TypeConverter(typeof(ExpandableObjectConverter))] [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; public string Name { get { return _Name; } } public Misc Misc { get { return _Misc; } } public string VirtualAddress { get { return string.Format("0x{0:x8}", _VirtualAddress); } } public string SizeOfRawData { get { return string.Format("0x{0:x8}", _SizeOfRawData); } } public string PointerToRawData { get { return string.Format("0x{0:x8}", _PointerToRawData); } } public string PointerToRelocations { get { return string.Format("0x{0:x8}", _PointerToRelocations); } } public string PointerToLinenumbers { get { return string.Format("0x{0:x8}", _PointerToLinenumbers); } } public string NumberOfRelocations { get { return string.Format("0x{0:x4}", _NumberOfRelocations); } } public string NumberOfLinenumbers { get { return string.Format("0x{0:x4}", _NumberOfLinenumbers); } } public string Characteristics { get { return string.Format("0x{0:x8}", _Characteristics); } } public override string ToString() { return Name; } } [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Explicit)] public struct Misc { [FieldOffset(0)] public UInt32 _PhysicalAddress; [FieldOffset(0)] public UInt32 _VirtualSize; public string PhysicalAddress { get { return string.Format("0x{0:x8}", _PhysicalAddress); } } public string VirtualSize { get { return string.Format("0x{0:x8}", _VirtualSize); } } } #endregion #region Fields private readonly IMAGE_DOS_HEADER _dosHeader; private IMAGE_NT_HEADERS _ntHeaders; private readonly IList _sectionHeaders = new List(); #endregion #region logging implementation private static class log { public static class verbose { public static class debug { public static void writeline(string format, params object[] args) { #if ENABLE_LOGGING logger.VerboseDebug.WriteLine(format, args); #endif } public static void write(string format, params object[] args) { #if ENABLE_LOGGING logger.VerboseDebug.Write(format, args); #endif } } public static class error { public static void writeline(string format, params object[] args) { #if ENABLE_LOGGING logger.VerboseError.WriteLine(format, args); #endif } public static void write(string format, params object[] args) { #if ENABLE_LOGGING logger.VerboseError.Write(format, args); #endif } } } } #endregion public PEData GetData { get { PEData _data = new PEData(_dosHeader, _ntHeaders, _sectionHeaders.ToArray()); return _data; } } #region t public class PEData { public PEData() : this(new IMAGE_DOS_HEADER(), new IMAGE_NT_HEADERS(), new IMAGE_SECTION_HEADER[] { }) { } public PEData(IMAGE_DOS_HEADER DosHeader, IMAGE_NT_HEADERS NTHeader, IMAGE_SECTION_HEADER[] SectionHeaders) { this.DosHeader = DosHeader; this.NTHeader = NTHeader; this.SectionHeaders = SectionHeaders; } public IMAGE_DOS_HEADER DosHeader { get; private set; } public IMAGE_NT_HEADERS NTHeader { get; private set; } public IMAGE_SECTION_HEADER[] SectionHeaders { get; private set; } } #endregion 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 { log.verbose.debug.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(reader); // MS-DOS magic number should read 'MZ' if (_dosHeader._e_magic != 0x5a4d) { throw new InvalidOperationException("File is not a portable executable."); } // Skip MS-DOS stub and seek reader to NT Headers reader.BaseStream.Seek(_dosHeader._e_lfanew, SeekOrigin.Begin); // Read NT Headers _ntHeaders._Signature = MarshalBytesTo(reader); // Make sure we have 'PE' in the pe signature if (_ntHeaders._Signature != 0x4550) { throw new InvalidOperationException("Invalid portable executable signature in NT header."); } _ntHeaders._FileHeader = MarshalBytesTo(reader); // Read optional headers if (Is32bitAssembly()) { log.verbose.debug.writeline("\tDetected a 32Bit PE Executable"); Load32bitOptionalHeaders(reader); } else { log.verbose.debug.writeline("\tDetected a 64Bit PE Executable"); Load64bitOptionalHeaders(reader); } // Read section data log.verbose.debug.writeline("\tTotal Section Headers: {0}", _sectionHeaders.Count); foreach (IMAGE_SECTION_HEADER header in _sectionHeaders) { int section_index = _sectionHeaders.IndexOf(header) + 1; log.verbose.debug.writeline("\tSection Header: {0} of {1}", section_index, _sectionHeaders.Count); log.verbose.debug.writeline("\t\tName: {0}", header.Name); log.verbose.debug.writeline("\t\tVirtual Address: 0x{0:x8}", header.VirtualAddress); log.verbose.debug.writeline("\t\tPhysical Address: 0x{0:x8}", header.Misc.PhysicalAddress); log.verbose.debug.writeline("\t\tVirtual Size: 0x{0:x8}", header.Misc.VirtualSize); log.verbose.debug.writeline("\t\tRaw Data Size: 0x{0:x8}", header.SizeOfRawData); log.verbose.debug.writeline("\t\tPointer To Raw Data: 0x{0:x8}", header.PointerToRawData); // Skip to beginning of a section reader.BaseStream.Seek(header._PointerToRawData, SeekOrigin.Begin); // 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) { log.verbose.error.writeline("Error Reading PE Format from: {0}", filename); log.verbose.error.writeline(ErrorInfo.ToString()); } } public IMAGE_DOS_HEADER GetDOSHeader() { return _dosHeader; } public UInt32 GetPESignature() { return _ntHeaders._Signature; } public IMAGE_FILE_HEADER GetFileHeader() { return _ntHeaders.FileHeader; } public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32() { return _ntHeaders.OptionalHeader32; } public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64() { return _ntHeaders.OptionalHeader64; } public IList GetSectionHeaders() { return _sectionHeaders; } public bool Is32bitAssembly() { return ((_ntHeaders.FileHeader._Characteristics & 0x0100) == 0x0100); } private void Load64bitOptionalHeaders(BinaryReader reader) { _ntHeaders._OptionalHeader64 = MarshalBytesTo(reader); // Should have 10 data directories if (_ntHeaders.OptionalHeader64._NumberOfRvaAndSizes != 0x10) { throw new InvalidOperationException("Invalid number of data directories in NT header"); } // 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(reader)); } } } private void Load32bitOptionalHeaders(BinaryReader reader) { _ntHeaders._OptionalHeader32 = MarshalBytesTo(reader); // Should have 10 data directories if (_ntHeaders.OptionalHeader32._NumberOfRvaAndSizes != 0x10) { throw new InvalidOperationException("Invalid number of data directories in NT header"); } // 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(reader)); } } } private static T MarshalBytesTo(BinaryReader reader) { // Unmanaged data byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T))); // Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); // Use our previously created pointer to unmanaged data and marshal to the specified type T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); // Deallocate pointer handle.Free(); return theStructure; } } }