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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 319 - (hide annotations) (download)
Tue Jun 5 18:39:06 2012 UTC (8 years, 7 months ago) by william
File size: 22791 byte(s)
+ more property grid implementation work

1 william 299 #define ENABLE_LOGGING
2     using System;
3 william 159 using System.Collections.Generic;
4     using System.Linq;
5     using System.Text;
6     using System.IO;
7     using RomCheater.Logging;
8     using System.Runtime.InteropServices;
9     using System.Diagnostics;
10 william 318 using System.ComponentModel;
11 william 159
12     namespace Sojaner.MemoryScanner
13     {
14     public class PEReader
15     {
16 william 294 // Code (C) Sergey utilized from: http://www.sergeyakopov.com/2010/11/03/reading-pe-format-using-data-marshalling-in-net/
17     #region Structs
18 william 319
19     [Flags]
20     public enum MachineTypeFlags
21     {
22     x86 = 0x14C,
23     Alpha = 0x184,
24     ARM = 0x1C0,
25     MIPS16R3000 = 0x162,
26     MIPS16R4000 = 0x166,
27     MIPS16R10000 = 0x168,
28     PowerPCLE = 0x1F0,
29     PowerPCBE = 0x1F2,
30     Itanium = 0x200,
31     MIPS16 = 0x266,
32     Alpha64 = 0x284,
33     MIPSFPU = 0x366,
34     MIPSFPU16 = 0x466,
35     x64 = 0x8664,
36     }
37    
38 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
39 william 294 [StructLayout(LayoutKind.Sequential)]
40     public struct IMAGE_DOS_HEADER
41 william 290 {
42 william 318 public UInt16 _e_magic;
43     public UInt16 _e_cblp;
44     public UInt16 _e_cp;
45     public UInt16 _e_crlc;
46     public UInt16 _e_cparhdr;
47     public UInt16 _e_minalloc;
48     public UInt16 _e_maxalloc;
49     public UInt16 _e_ss;
50     public UInt16 _e_sp;
51     public UInt16 _e_csum;
52     public UInt16 _e_ip;
53     public UInt16 _e_cs;
54     public UInt16 _e_lfarlc;
55     public UInt16 _e_ovno;
56 william 294 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
57 william 318 public UInt16[] _e_res1;
58     public UInt16 _e_oemid;
59     public UInt16 _e_oeminfo;
60 william 294 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
61 william 318 public UInt16[] _e_res2;
62     public UInt32 _e_lfanew;
63    
64     public string e_magic { get { return string.Format("0x{0:x4}", _e_magic); } }
65     public string e_cblp { get { return string.Format("0x{0:x4}", _e_cblp); } }
66     public string e_cp { get { return string.Format("0x{0:x4}", _e_cp); } }
67     public string e_crlc { get { return string.Format("0x{0:x4}", _e_crlc); } }
68     public string e_cparhdr { get { return string.Format("0x{0:x4}", _e_cparhdr); } }
69     public string e_minalloc { get { return string.Format("0x{0:x4}", _e_minalloc); } }
70     public string e_maxalloc { get { return string.Format("0x{0:x4}", _e_maxalloc); } }
71     public string e_ss { get { return string.Format("0x{0:x4}", _e_ss); } }
72     public string e_sp { get { return string.Format("0x{0:x4}", _e_sp); } }
73     public string e_csum { get { return string.Format("0x{0:x4}", _e_csum); } }
74     public string e_ip { get { return string.Format("0x{0:x4}", _e_ip); } }
75     public string e_cs { get { return string.Format("0x{0:x4}", _e_cs); } }
76     public string e_lfarlc { get { return string.Format("0x{0:x4}", _e_lfarlc); } }
77     public string e_ovno { get { return string.Format("0x{0:x4}", _e_ovno); } }
78     public ushort[] e_res1 { get { return _e_res1; } }
79     public string e_oemid { get { return string.Format("0x{0:x4}", _e_oemid); } }
80     public string e_oeminfo { get { return string.Format("0x{0:x4}", _e_oeminfo); } }
81     public ushort[] e_res2 { get { return _e_res2; } }
82     public string e_lfanew { get { return string.Format("0x{0:x8}", _e_lfanew); } }
83    
84 william 319 public override string ToString()
85     {
86     return Encoding.UTF8.GetString(BitConverter.GetBytes(_e_magic));
87     }
88 william 290 }
89 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
90 william 294 [StructLayout(LayoutKind.Sequential)]
91     public struct IMAGE_NT_HEADERS
92 william 159 {
93 william 319 public UInt32 _Signature;
94     public IMAGE_FILE_HEADER _FileHeader;
95     public IMAGE_OPTIONAL_HEADER32 _OptionalHeader32;
96     public IMAGE_OPTIONAL_HEADER64 _OptionalHeader64;
97    
98     public string Signature { get { return string.Format("0x{0:x8}", _Signature); } }
99     public IMAGE_FILE_HEADER FileHeader { get { return _FileHeader; } }
100     public IMAGE_OPTIONAL_HEADER32 OptionalHeader32 { get { return _OptionalHeader32;} }
101     public IMAGE_OPTIONAL_HEADER64 OptionalHeader64 { get { return _OptionalHeader64;} }
102    
103     public override string ToString()
104     {
105     return Encoding.UTF8.GetString(BitConverter.GetBytes(_Signature));
106     }
107 william 159 }
108 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
109 william 159 [StructLayout(LayoutKind.Sequential)]
110     public struct IMAGE_FILE_HEADER
111     {
112 william 319 public UInt16 _MachineType;
113     public UInt16 _NumberOfSections;
114     public UInt32 _TimeDateStamp;
115     public UInt32 _PointerToSymbolTable;
116     public UInt32 _NumberOfSymbols;
117     public UInt16 _SizeOfOptionalHeader;
118     public UInt16 _Characteristics;
119    
120    
121     public string MachineType { get { return ((MachineTypeFlags)_MachineType).ToString(); } }
122     public string NumberOfSections { get { return string.Format("0x{0:x4}", _NumberOfSections); } }
123     public string TimeDateStamp { get { return string.Format("{0} (0x{1:x8})", GetDateTimeFromDosDateTime(_TimeDateStamp).ToString(), _TimeDateStamp); } }
124     public string PointerToSymbolTable { get { return string.Format("0x{0:x8}", _PointerToSymbolTable); } }
125     public string NumberOfSymbols { get { return string.Format("0x{0:x8}", _NumberOfSymbols); } }
126     public string SizeOfOptionalHeader { get { return string.Format("0x{0:x4}", _SizeOfOptionalHeader); } }
127     public string Characteristics { get { return string.Format("0x{0:x4}", _Characteristics); } }
128     public override string ToString()
129     {
130     return MachineType;
131     }
132    
133     private DateTime GetDateTimeFromDosDateTime(UInt32 i32TimeDate)
134     {
135     UInt16 i16Time = (UInt16)(i32TimeDate & 0xFFFF);
136     UInt16 i16Date = (UInt16)((i32TimeDate & 0xFFFF0000) >> 16);
137     return GetDateTimeFromDosDateTime(i16Time, i16Date);
138     }
139     private DateTime GetDateTimeFromDosDateTime(UInt16 i16Time, UInt16 i16Date)
140     {
141     int iYear = 0;
142     int iMonth = 1;
143     int iDay = 1;
144     int iHour = 0;
145     int iMinute = 0;
146     int iSecond = 0;
147     iDay = (i16Date & 0x1F);
148     iMonth = ((i16Date & 0x01E0) >> 5);
149     iYear = 1980 + ((i16Date & 0xFE00) >> 9);
150     iSecond = (i16Time & 0x1F) * 2;
151     iMinute = ((i16Time & 0x07E0) >> 5);
152     iHour = ((i16Time & 0x0F800) >> 11);
153     return new DateTime(iYear, iMonth, iDay, iHour, iMinute, iSecond);
154    
155     }
156    
157 william 159 }
158 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
159 william 159 [StructLayout(LayoutKind.Sequential)]
160 william 294 public struct IMAGE_OPTIONAL_HEADER32
161 william 159 {
162 william 294 public UInt16 Magic;
163     public Byte MajorLinkerVersion;
164     public Byte MinorLinkerVersion;
165     public UInt32 SizeOfCode;
166     public UInt32 SizeOfInitializedData;
167     public UInt32 SizeOfUninitializedData;
168     public UInt32 AddressOfEntryPoint;
169     public UInt32 BaseOfCode;
170     public UInt32 BaseOfData;
171     public UInt32 ImageBase;
172     public UInt32 SectionAlignment;
173     public UInt32 FileAlignment;
174     public UInt16 MajorOperatingSystemVersion;
175     public UInt16 MinorOperatingSystemVersion;
176     public UInt16 MajorImageVersion;
177     public UInt16 MinorImageVersion;
178     public UInt16 MajorSubsystemVersion;
179     public UInt16 MinorSubsystemVersion;
180     public UInt32 Win32VersionValue;
181     public UInt32 SizeOfImage;
182     public UInt32 SizeOfHeaders;
183     public UInt32 CheckSum;
184     public UInt16 Subsystem;
185     public UInt16 DllCharacteristics;
186     public UInt32 SizeOfStackReserve;
187     public UInt32 SizeOfStackCommit;
188     public UInt32 SizeOfHeapReserve;
189     public UInt32 SizeOfHeapCommit;
190     public UInt32 LoaderFlags;
191     public UInt32 NumberOfRvaAndSizes;
192     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
193     public IMAGE_DATA_DIRECTORY[] DataDirectory;
194 william 159 }
195 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
196 william 294 [StructLayout(LayoutKind.Sequential)]
197     public struct IMAGE_OPTIONAL_HEADER64
198 william 159 {
199 william 294 public UInt16 Magic;
200     public Byte MajorLinkerVersion;
201     public Byte MinorLinkerVersion;
202     public UInt32 SizeOfCode;
203     public UInt32 SizeOfInitializedData;
204     public UInt32 SizeOfUninitializedData;
205     public UInt32 AddressOfEntryPoint;
206     public UInt32 BaseOfCode;
207     public UInt64 ImageBase;
208     public UInt32 SectionAlignment;
209     public UInt32 FileAlignment;
210     public UInt16 MajorOperatingSystemVersion;
211     public UInt16 MinorOperatingSystemVersion;
212     public UInt16 MajorImageVersion;
213     public UInt16 MinorImageVersion;
214     public UInt16 MajorSubsystemVersion;
215     public UInt16 MinorSubsystemVersion;
216     public UInt32 Win32VersionValue;
217     public UInt32 SizeOfImage;
218     public UInt32 SizeOfHeaders;
219     public UInt32 CheckSum;
220     public UInt16 Subsystem;
221     public UInt16 DllCharacteristics;
222     public UInt64 SizeOfStackReserve;
223     public UInt64 SizeOfStackCommit;
224     public UInt64 SizeOfHeapReserve;
225     public UInt64 SizeOfHeapCommit;
226     public UInt32 LoaderFlags;
227     public UInt32 NumberOfRvaAndSizes;
228     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
229     public IMAGE_DATA_DIRECTORY[] DataDirectory;
230 william 159 }
231 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
232 william 294 [StructLayout(LayoutKind.Sequential)]
233     public struct IMAGE_DATA_DIRECTORY
234 william 159 {
235 william 294 public UInt32 VirtualAddress;
236     public UInt32 Size;
237 william 159 }
238 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
239 william 294 [StructLayout(LayoutKind.Sequential)]
240     public struct IMAGE_SECTION_HEADER
241 william 159 {
242 william 294 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
243 william 319 public string _Name;
244     public Misc _Misc;
245     public UInt32 _VirtualAddress;
246     public UInt32 _SizeOfRawData;
247     public UInt32 _PointerToRawData;
248     public UInt32 _PointerToRelocations;
249     public UInt32 _PointerToLinenumbers;
250     public UInt16 _NumberOfRelocations;
251     public UInt16 _NumberOfLinenumbers;
252     public UInt32 _Characteristics;
253    
254     public string Name { get { return _Name; } }
255     public Misc Misc { get { return _Misc; } }
256     public string VirtualAddress { get { return string.Format("0x{0:x8}", _VirtualAddress); } }
257     public string SizeOfRawData { get { return string.Format("0x{0:x8}", _SizeOfRawData); } }
258     public string PointerToRawData { get { return string.Format("0x{0:x8}", _PointerToRawData); } }
259     public string PointerToRelocations { get { return string.Format("0x{0:x8}", _PointerToRelocations); } }
260     public string PointerToLinenumbers { get { return string.Format("0x{0:x8}", _PointerToLinenumbers); } }
261     public string NumberOfRelocations { get { return string.Format("0x{0:x4}", _NumberOfRelocations); } }
262     public string NumberOfLinenumbers { get { return string.Format("0x{0:x4}", _NumberOfLinenumbers); } }
263     public string Characteristics { get { return string.Format("0x{0:x8}", _Characteristics); } }
264     public override string ToString()
265     {
266     return Name;
267     }
268 william 159 }
269 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
270 william 159 [StructLayout(LayoutKind.Explicit)]
271 william 294 public struct Misc
272 william 159 {
273     [FieldOffset(0)]
274 william 319 public UInt32 _PhysicalAddress;
275 william 294 [FieldOffset(0)]
276 william 319 public UInt32 _VirtualSize;
277    
278     public string PhysicalAddress { get { return string.Format("0x{0:x8}", _PhysicalAddress); } }
279     public string VirtualSize { get { return string.Format("0x{0:x8}", _VirtualSize); } }
280    
281 william 294 }
282 william 159
283 william 294 #endregion
284 william 159
285 william 294 #region Fields
286 william 159
287 william 294 private readonly IMAGE_DOS_HEADER _dosHeader;
288     private IMAGE_NT_HEADERS _ntHeaders;
289     private readonly IList<IMAGE_SECTION_HEADER> _sectionHeaders = new List<IMAGE_SECTION_HEADER>();
290     #endregion
291 william 159
292 william 299 #region logging implementation
293     private static class log
294     {
295     public static class verbose
296     {
297     public static class debug
298     {
299     public static void writeline(string format, params object[] args)
300     {
301     #if ENABLE_LOGGING
302     logger.VerboseDebug.WriteLine(format, args);
303     #endif
304     }
305     public static void write(string format, params object[] args)
306     {
307     #if ENABLE_LOGGING
308     logger.VerboseDebug.Write(format, args);
309     #endif
310     }
311     }
312     public static class error
313     {
314     public static void writeline(string format, params object[] args)
315     {
316     #if ENABLE_LOGGING
317     logger.VerboseError.WriteLine(format, args);
318     #endif
319     }
320     public static void write(string format, params object[] args)
321     {
322     #if ENABLE_LOGGING
323     logger.VerboseError.Write(format, args);
324     #endif
325     }
326     }
327     }
328     }
329     #endregion
330    
331    
332 william 318 public PEData GetData
333     {
334     get
335     {
336 william 319 PEData _data = new PEData(_dosHeader, _ntHeaders, _sectionHeaders.ToArray());
337 william 318 return _data;
338     }
339     }
340     #region t
341     public class PEData
342     {
343 william 319 public PEData() : this(new IMAGE_DOS_HEADER(), new IMAGE_NT_HEADERS(), new IMAGE_SECTION_HEADER[] { }) { }
344     public PEData(IMAGE_DOS_HEADER DosHeader, IMAGE_NT_HEADERS NTHeader, IMAGE_SECTION_HEADER[] SectionHeaders)
345 william 318 {
346     this.DosHeader = DosHeader;
347     this.NTHeader = NTHeader;
348     this.SectionHeaders = SectionHeaders;
349     }
350     public IMAGE_DOS_HEADER DosHeader { get; private set; }
351     public IMAGE_NT_HEADERS NTHeader { get; private set; }
352 william 319 public IMAGE_SECTION_HEADER[] SectionHeaders { get; private set; }
353 william 318 }
354    
355     #endregion
356    
357 william 294 public PEReader(FileInfo fi) : this(fi.FullName) { }
358     public PEReader(string filename)
359 william 299 {
360 william 294 Exception ErrorInfo = null;
361     using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
362     {
363     try
364     {
365 william 299 log.verbose.debug.writeline("Reading PE Format from: {0}", filename);
366 william 294 BinaryReader reader = new BinaryReader(fs);
367     // Reset reader position, just in case
368     reader.BaseStream.Seek(0, SeekOrigin.Begin);
369 william 159
370 william 294 // Read MS-DOS header section
371     _dosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(reader);
372     // MS-DOS magic number should read 'MZ'
373 william 318 if (_dosHeader._e_magic != 0x5a4d)
374 william 294 {
375     throw new InvalidOperationException("File is not a portable executable.");
376     }
377 william 159
378 william 294 // Skip MS-DOS stub and seek reader to NT Headers
379 william 318 reader.BaseStream.Seek(_dosHeader._e_lfanew, SeekOrigin.Begin);
380 william 159
381 william 294 // Read NT Headers
382 william 319 _ntHeaders._Signature = MarshalBytesTo<UInt32>(reader);
383 william 159
384 william 294 // Make sure we have 'PE' in the pe signature
385 william 319 if (_ntHeaders._Signature != 0x4550)
386 william 294 {
387     throw new InvalidOperationException("Invalid portable executable signature in NT header.");
388     }
389 william 159
390 william 319 _ntHeaders._FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader);
391 william 294 // Read optional headers
392     if (Is32bitAssembly())
393     {
394 william 299 log.verbose.debug.writeline("\tDetected a 32Bit PE Executable");
395 william 294 Load32bitOptionalHeaders(reader);
396     }
397     else
398     {
399 william 299 log.verbose.debug.writeline("\tDetected a 64Bit PE Executable");
400 william 294 Load64bitOptionalHeaders(reader);
401     }
402 william 159
403 william 294 // Read section data
404 william 299 log.verbose.debug.writeline("\tTotal Section Headers: {0}", _sectionHeaders.Count);
405 william 294 foreach (IMAGE_SECTION_HEADER header in _sectionHeaders)
406     {
407     int section_index = _sectionHeaders.IndexOf(header) + 1;
408 william 299 log.verbose.debug.writeline("\tSection Header: {0} of {1}", section_index, _sectionHeaders.Count);
409     log.verbose.debug.writeline("\t\tName: {0}", header.Name);
410     log.verbose.debug.writeline("\t\tVirtual Address: 0x{0:x8}", header.VirtualAddress);
411     log.verbose.debug.writeline("\t\tPhysical Address: 0x{0:x8}", header.Misc.PhysicalAddress);
412     log.verbose.debug.writeline("\t\tVirtual Size: 0x{0:x8}", header.Misc.VirtualSize);
413     log.verbose.debug.writeline("\t\tRaw Data Size: 0x{0:x8}", header.SizeOfRawData);
414     log.verbose.debug.writeline("\t\tPointer To Raw Data: 0x{0:x8}", header.PointerToRawData);
415 william 159
416 william 294 // Skip to beginning of a section
417 william 319 reader.BaseStream.Seek(header._PointerToRawData, SeekOrigin.Begin);
418 william 159
419 william 294 // Read section data... and do something with it
420 william 319 byte[] sectiondata = reader.ReadBytes((int)header._SizeOfRawData);
421 william 294 }
422     reader.Close();
423     }
424     catch (Exception ex)
425     {
426     ErrorInfo = ex;
427     throw ErrorInfo;
428     }
429     }
430     if (ErrorInfo != null)
431     {
432 william 299 log.verbose.error.writeline("Error Reading PE Format from: {0}", filename);
433     log.verbose.error.writeline(ErrorInfo.ToString());
434 william 294 }
435     }
436 william 159
437 william 294 public IMAGE_DOS_HEADER GetDOSHeader()
438     {
439     return _dosHeader;
440     }
441 william 159
442 william 294 public UInt32 GetPESignature()
443     {
444 william 319 return _ntHeaders._Signature;
445 william 294 }
446 william 159
447 william 294 public IMAGE_FILE_HEADER GetFileHeader()
448     {
449     return _ntHeaders.FileHeader;
450     }
451 william 159
452 william 294 public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
453     {
454     return _ntHeaders.OptionalHeader32;
455     }
456 william 159
457 william 294 public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
458     {
459     return _ntHeaders.OptionalHeader64;
460     }
461 william 159
462 william 294 public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
463     {
464     return _sectionHeaders;
465     }
466 william 159
467 william 294 public bool Is32bitAssembly()
468 william 159 {
469 william 319 return ((_ntHeaders.FileHeader._Characteristics & 0x0100) == 0x0100);
470 william 159 }
471 william 294
472     private void Load64bitOptionalHeaders(BinaryReader reader)
473 william 293 {
474 william 319 _ntHeaders._OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader);
475 william 293
476 william 294 // Should have 10 data directories
477     if (_ntHeaders.OptionalHeader64.NumberOfRvaAndSizes != 0x10)
478     {
479     throw new InvalidOperationException("Invalid number of data directories in NT header");
480     }
481 william 293
482 william 294 // Scan data directories and load section headers
483     for (int i = 0; i < _ntHeaders.OptionalHeader64.NumberOfRvaAndSizes; i++)
484     {
485     if (_ntHeaders.OptionalHeader64.DataDirectory[i].Size > 0)
486     {
487     _sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
488     }
489     }
490     }
491 william 293
492 william 294 private void Load32bitOptionalHeaders(BinaryReader reader)
493     {
494 william 319 _ntHeaders._OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader);
495 william 293
496 william 294 // Should have 10 data directories
497     if (_ntHeaders.OptionalHeader32.NumberOfRvaAndSizes != 0x10)
498     {
499     throw new InvalidOperationException("Invalid number of data directories in NT header");
500     }
501 william 293
502 william 294 // Scan data directories and load section headers
503     for (int i = 0; i < _ntHeaders.OptionalHeader32.NumberOfRvaAndSizes; i++)
504     {
505     if (_ntHeaders.OptionalHeader32.DataDirectory[i].Size > 0)
506     {
507     _sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
508     }
509     }
510     }
511 william 293
512 william 294 private static T MarshalBytesTo<T>(BinaryReader reader)
513     {
514     // Unmanaged data
515     byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
516 william 293
517 william 294 // Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code
518     GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
519 william 293
520 william 294 // Use our previously created pointer to unmanaged data and marshal to the specified type
521     T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
522 william 293
523 william 294 // Deallocate pointer
524     handle.Free();
525 william 293
526 william 294 return theStructure;
527 william 293 }
528 william 159 }
529     }

  ViewVC Help
Powered by ViewVC 1.1.22