--- trunk/Win32/Sojaner.MemoryScanner/PEReader.cs 2012/05/28 05:55:59 161 +++ trunk/Win32/Sojaner.MemoryScanner/PEReader.cs 2012/06/05 18:39:06 319 @@ -1,4 +1,5 @@ -using System; +#define ENABLE_LOGGING +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,351 +7,523 @@ using RomCheater.Logging; using System.Runtime.InteropServices; using System.Diagnostics; +using System.ComponentModel; namespace Sojaner.MemoryScanner { public class PEReader { - public PEReader(FileInfo fi) : this(fi.FullName) { } - public PEReader(string filename) { this.Read(filename); } + // Code (C) Sergey utilized from: http://www.sergeyakopov.com/2010/11/03/reading-pe-format-using-data-marshalling-in-net/ + #region Structs - #region marshalling - private void Read(string filename) + [Flags] + public enum MachineTypeFlags { - logger.Debug.WriteLine("Reading Exe: {0}", filename); - - using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)) - { - 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 - - - br.Close(); - } - - + 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, } - #endregion - #region header support - #region IMAGE_DATA_DIRECTORY - [StructLayout(LayoutKind.Sequential)] - public struct IMAGE_DATA_DIRECTORY - { - public UInt32 VirtualAddress; - public UInt32 Size; - public bool HasAddress { get { return (VirtualAddress != 0); } } - public bool HasSize { get { return (Size > 0); } } - } - #endregion - #region IMAGE_FILE_HEADER - [StructLayout(LayoutKind.Sequential)] - public struct IMAGE_FILE_HEADER - { - public MachineType Machine; - public UInt16 NumberOfSections; - public UInt32 TimeDateStamp; - public UInt32 PointerToSymbolTable; - public UInt32 NumberOfSymbols; - public UInt16 SizeOfOptionalHeader; - public DllCharacteristicsType Characteristics; - } - #endregion - #region IMAGE_DOS_HEADER + [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_DOS_HEADER { - [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 + 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; // Reserved words - public UInt16 e_oemid; // OEM identifier (for e_oeminfo) - public UInt16 e_oeminfo; // OEM information; e_oemid specific + public UInt16[] _e_res1; + public UInt16 _e_oemid; + public UInt16 _e_oeminfo; [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 + 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() { - get { return _e_magic == "MZ"; } + return Encoding.UTF8.GetString(BitConverter.GetBytes(_e_magic)); } } - #endregion - #region IMAGE_NT_HEADERS - [StructLayout(LayoutKind.Explicit)] + [TypeConverter(typeof(ExpandableObjectConverter))] + [StructLayout(LayoutKind.Sequential)] public struct IMAGE_NT_HEADERS { - [FieldOffset(0)] - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] - public char[] Signature; - - [FieldOffset(4)] - public IMAGE_FILE_HEADER FileHeader; + 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;} } - [FieldOffset(24)] - public IMAGE_OPTIONAL_HEADER OptionalHeader; - - private string _Signature + public override string ToString() { - get { return new string(Signature); } + 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; } - public bool isValid + private DateTime GetDateTimeFromDosDateTime(UInt32 i32TimeDate) { - get { return _Signature == "PE\0\0" && (OptionalHeader.Magic == MagicType.IMAGE_NT_OPTIONAL_HDR32_MAGIC || OptionalHeader.Magic == MagicType.IMAGE_NT_OPTIONAL_HDR64_MAGIC); } + 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 = 1980 + ((i16Date & 0xFE00) >> 9); + iSecond = (i16Time & 0x1F) * 2; + iMinute = ((i16Time & 0x07E0) >> 5); + iHour = ((i16Time & 0x0F800) >> 11); + return new DateTime(iYear, iMonth, iDay, iHour, iMinute, iSecond); + + } + } - #endregion - #region MachineType - public enum MachineType : ushort + [TypeConverter(typeof(ExpandableObjectConverter))] + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_OPTIONAL_HEADER32 { - 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 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 MagicType - public enum MagicType : ushort + [TypeConverter(typeof(ExpandableObjectConverter))] + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_OPTIONAL_HEADER64 { - IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b, - IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b + 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 SubSystemType - public enum SubSystemType : ushort + [TypeConverter(typeof(ExpandableObjectConverter))] + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_DATA_DIRECTORY { - 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 UInt32 VirtualAddress; + public UInt32 Size; } - #endregion - #region DllCharacteristicsType - [Flags] - public enum DllCharacteristicsType : ushort + [TypeConverter(typeof(ExpandableObjectConverter))] + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_SECTION_HEADER { - 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 + [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; + } } - #endregion - #region IMAGE_OPTIONAL_HEADER + [TypeConverter(typeof(ExpandableObjectConverter))] [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; + public UInt32 _PhysicalAddress; + [FieldOffset(0)] + public UInt32 _VirtualSize; - [FieldOffset(52)] - public uint Win32VersionValue; + public string PhysicalAddress { get { return string.Format("0x{0:x8}", _PhysicalAddress); } } + public string VirtualSize { get { return string.Format("0x{0:x8}", _VirtualSize); } } - [FieldOffset(56)] - public uint SizeOfImage; + } - [FieldOffset(60)] - public uint SizeOfHeaders; + #endregion - [FieldOffset(64)] - public uint CheckSum; + #region Fields - [FieldOffset(68)] - public SubSystemType Subsystem; + private readonly IMAGE_DOS_HEADER _dosHeader; + private IMAGE_NT_HEADERS _ntHeaders; + private readonly IList _sectionHeaders = new List(); + #endregion - [FieldOffset(70)] - public DllCharacteristicsType DllCharacteristics; + #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 - [FieldOffset(72)] - public uint SizeOfStackReserve; - [FieldOffset(76)] - public uint SizeOfStackCommit; + 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; } + } - [FieldOffset(80)] - public uint SizeOfHeapReserve; + #endregion - [FieldOffset(84)] - public uint SizeOfHeapCommit; + 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()); + } + } - [FieldOffset(88)] - public uint LoaderFlags; + public IMAGE_DOS_HEADER GetDOSHeader() + { + return _dosHeader; + } - [FieldOffset(92)] - public uint NumberOfRvaAndSizes; + public UInt32 GetPESignature() + { + return _ntHeaders._Signature; + } - [FieldOffset(96)] - public IMAGE_DATA_DIRECTORY ExportTable; + public IMAGE_FILE_HEADER GetFileHeader() + { + return _ntHeaders.FileHeader; + } - [FieldOffset(104)] - public IMAGE_DATA_DIRECTORY ImportTable; + public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32() + { + return _ntHeaders.OptionalHeader32; + } - [FieldOffset(112)] - public IMAGE_DATA_DIRECTORY ResourceTable; + public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64() + { + return _ntHeaders.OptionalHeader64; + } - [FieldOffset(120)] - public IMAGE_DATA_DIRECTORY ExceptionTable; + public IList GetSectionHeaders() + { + return _sectionHeaders; + } - [FieldOffset(128)] - public IMAGE_DATA_DIRECTORY CertificateTable; + public bool Is32bitAssembly() + { + return ((_ntHeaders.FileHeader._Characteristics & 0x0100) == 0x0100); + } - [FieldOffset(136)] - public IMAGE_DATA_DIRECTORY BaseRelocationTable; + private void Load64bitOptionalHeaders(BinaryReader reader) + { + _ntHeaders._OptionalHeader64 = MarshalBytesTo(reader); - [FieldOffset(144)] - public IMAGE_DATA_DIRECTORY Debug; + // Should have 10 data directories + if (_ntHeaders.OptionalHeader64.NumberOfRvaAndSizes != 0x10) + { + throw new InvalidOperationException("Invalid number of data directories in NT header"); + } - [FieldOffset(152)] - public IMAGE_DATA_DIRECTORY Architecture; + // 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)); + } + } + } - [FieldOffset(160)] - public IMAGE_DATA_DIRECTORY GlobalPtr; + private void Load32bitOptionalHeaders(BinaryReader reader) + { + _ntHeaders._OptionalHeader32 = MarshalBytesTo(reader); - [FieldOffset(168)] - public IMAGE_DATA_DIRECTORY TLSTable; + // Should have 10 data directories + if (_ntHeaders.OptionalHeader32.NumberOfRvaAndSizes != 0x10) + { + throw new InvalidOperationException("Invalid number of data directories in NT header"); + } - [FieldOffset(176)] - public IMAGE_DATA_DIRECTORY LoadConfigTable; + // 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)); + } + } + } - [FieldOffset(184)] - public IMAGE_DATA_DIRECTORY BoundImport; + private static T MarshalBytesTo(BinaryReader reader) + { + // Unmanaged data + byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T))); - [FieldOffset(192)] - public IMAGE_DATA_DIRECTORY IAT; + // Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code + GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - [FieldOffset(200)] - public IMAGE_DATA_DIRECTORY DelayImportDescriptor; + // Use our previously created pointer to unmanaged data and marshal to the specified type + T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); - [FieldOffset(208)] - public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; + // Deallocate pointer + handle.Free(); - [FieldOffset(216)] - public IMAGE_DATA_DIRECTORY Reserved; - } - #endregion - #region IMAGE_EXPORT_DIRECTORY - [StructLayout(LayoutKind.Sequential)] - public struct IMAGE_EXPORT_DIRECTORY - { - 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 theStructure; } - #endregion - #endregion } }