Parent Directory
|
Revision Log
|
Patch
--- trunk/Win32/Sojaner.MemoryScanner/PEReader.cs 2012/06/05 10:48:07 294 +++ 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,6 +7,7 @@ using RomCheater.Logging; using System.Runtime.InteropServices; using System.Diagnostics; +using System.ComponentModel; namespace Sojaner.MemoryScanner { @@ -13,53 +15,147 @@ { // 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, + } + + [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; + 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; + 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 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 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 Machine; - public UInt16 NumberOfSections; - public UInt32 TimeDateStamp; - public UInt32 PointerToSymbolTable; - public UInt32 NumberOfSymbols; - public UInt16 SizeOfOptionalHeader; - public UInt16 Characteristics; - } + 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 = 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); + + } + + } + [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_OPTIONAL_HEADER32 { @@ -96,7 +192,7 @@ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public IMAGE_DATA_DIRECTORY[] DataDirectory; } - + [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_OPTIONAL_HEADER64 { @@ -132,37 +228,56 @@ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public IMAGE_DATA_DIRECTORY[] DataDirectory; } - + [TypeConverter(typeof(ExpandableObjectConverter))] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_DATA_DIRECTORY { public UInt32 VirtualAddress; public UInt32 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; + 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; + public UInt32 _PhysicalAddress; [FieldOffset(0)] - public UInt32 VirtualSize; + 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 @@ -172,18 +287,82 @@ private readonly IMAGE_DOS_HEADER _dosHeader; private IMAGE_NT_HEADERS _ntHeaders; private readonly IList<IMAGE_SECTION_HEADER> _sectionHeaders = new List<IMAGE_SECTION_HEADER>(); + #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 { - logger.VerboseDebug.WriteLine("Reading PE Format from: {0}", filename); + 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); @@ -191,54 +370,54 @@ // Read MS-DOS header section _dosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(reader); // MS-DOS magic number should read 'MZ' - if (_dosHeader.e_magic != 0x5a4d) + 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); + reader.BaseStream.Seek(_dosHeader._e_lfanew, SeekOrigin.Begin); // Read NT Headers - _ntHeaders.Signature = MarshalBytesTo<UInt32>(reader); + _ntHeaders._Signature = MarshalBytesTo<UInt32>(reader); // Make sure we have 'PE' in the pe signature - if (_ntHeaders.Signature != 0x4550) + if (_ntHeaders._Signature != 0x4550) { throw new InvalidOperationException("Invalid portable executable signature in NT header."); } - _ntHeaders.FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader); + _ntHeaders._FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader); // Read optional headers if (Is32bitAssembly()) { - logger.VerboseDebug.WriteLine("Detected a 32Bit PE Executable"); + log.verbose.debug.writeline("\tDetected a 32Bit PE Executable"); Load32bitOptionalHeaders(reader); } else { - logger.VerboseDebug.WriteLine("Detected a 64Bit PE Executable"); + log.verbose.debug.writeline("\tDetected a 64Bit PE Executable"); Load64bitOptionalHeaders(reader); } // Read section data - logger.VerboseDebug.WriteLine("Total Section Headers: {0}", _sectionHeaders.Count); + log.verbose.debug.writeline("\tTotal 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); + 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); + reader.BaseStream.Seek(header._PointerToRawData, SeekOrigin.Begin); // Read section data... and do something with it - byte[] sectiondata = reader.ReadBytes((int)header.SizeOfRawData); + byte[] sectiondata = reader.ReadBytes((int)header._SizeOfRawData); } reader.Close(); } @@ -250,8 +429,8 @@ } if (ErrorInfo != null) { - logger.VerboseError.WriteLine("Error Reading PE Format from: {0}",filename); - logger.VerboseError.WriteLine(ErrorInfo.ToString()); + log.verbose.error.writeline("Error Reading PE Format from: {0}", filename); + log.verbose.error.writeline(ErrorInfo.ToString()); } } @@ -262,7 +441,7 @@ public UInt32 GetPESignature() { - return _ntHeaders.Signature; + return _ntHeaders._Signature; } public IMAGE_FILE_HEADER GetFileHeader() @@ -287,12 +466,12 @@ public bool Is32bitAssembly() { - return ((_ntHeaders.FileHeader.Characteristics & 0x0100) == 0x0100); + return ((_ntHeaders.FileHeader._Characteristics & 0x0100) == 0x0100); } private void Load64bitOptionalHeaders(BinaryReader reader) { - _ntHeaders.OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader); + _ntHeaders._OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader); // Should have 10 data directories if (_ntHeaders.OptionalHeader64.NumberOfRvaAndSizes != 0x10) @@ -312,7 +491,7 @@ private void Load32bitOptionalHeaders(BinaryReader reader) { - _ntHeaders.OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader); + _ntHeaders._OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader); // Should have 10 data directories if (_ntHeaders.OptionalHeader32.NumberOfRvaAndSizes != 0x10)
ViewVC Help | |
Powered by ViewVC 1.1.22 |