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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 #define ENABLE_LOGGING
2 using System;
3 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 using System.ComponentModel;
11
12 namespace Sojaner.MemoryScanner
13 {
14 public class PEReader
15 {
16 // Code (C) Sergey utilized from: http://www.sergeyakopov.com/2010/11/03/reading-pe-format-using-data-marshalling-in-net/
17 #region Structs
18
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 [TypeConverter(typeof(ExpandableObjectConverter))]
39 [StructLayout(LayoutKind.Sequential)]
40 public struct IMAGE_DOS_HEADER
41 {
42 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 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
57 public UInt16[] _e_res1;
58 public UInt16 _e_oemid;
59 public UInt16 _e_oeminfo;
60 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
61 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 public override string ToString()
85 {
86 return Encoding.UTF8.GetString(BitConverter.GetBytes(_e_magic));
87 }
88 }
89 [TypeConverter(typeof(ExpandableObjectConverter))]
90 [StructLayout(LayoutKind.Sequential)]
91 public struct IMAGE_NT_HEADERS
92 {
93 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 }
108 [TypeConverter(typeof(ExpandableObjectConverter))]
109 [StructLayout(LayoutKind.Sequential)]
110 public struct IMAGE_FILE_HEADER
111 {
112 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 }
158 [TypeConverter(typeof(ExpandableObjectConverter))]
159 [StructLayout(LayoutKind.Sequential)]
160 public struct IMAGE_OPTIONAL_HEADER32
161 {
162 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 }
195 [TypeConverter(typeof(ExpandableObjectConverter))]
196 [StructLayout(LayoutKind.Sequential)]
197 public struct IMAGE_OPTIONAL_HEADER64
198 {
199 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 }
231 [TypeConverter(typeof(ExpandableObjectConverter))]
232 [StructLayout(LayoutKind.Sequential)]
233 public struct IMAGE_DATA_DIRECTORY
234 {
235 public UInt32 VirtualAddress;
236 public UInt32 Size;
237 }
238 [TypeConverter(typeof(ExpandableObjectConverter))]
239 [StructLayout(LayoutKind.Sequential)]
240 public struct IMAGE_SECTION_HEADER
241 {
242 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
243 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 }
269 [TypeConverter(typeof(ExpandableObjectConverter))]
270 [StructLayout(LayoutKind.Explicit)]
271 public struct Misc
272 {
273 [FieldOffset(0)]
274 public UInt32 _PhysicalAddress;
275 [FieldOffset(0)]
276 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 }
282
283 #endregion
284
285 #region Fields
286
287 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
292 #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 public PEData GetData
333 {
334 get
335 {
336 PEData _data = new PEData(_dosHeader, _ntHeaders, _sectionHeaders.ToArray());
337 return _data;
338 }
339 }
340 #region t
341 public class PEData
342 {
343 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 {
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 public IMAGE_SECTION_HEADER[] SectionHeaders { get; private set; }
353 }
354
355 #endregion
356
357 public PEReader(FileInfo fi) : this(fi.FullName) { }
358 public PEReader(string filename)
359 {
360 Exception ErrorInfo = null;
361 using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
362 {
363 try
364 {
365 log.verbose.debug.writeline("Reading PE Format from: {0}", filename);
366 BinaryReader reader = new BinaryReader(fs);
367 // Reset reader position, just in case
368 reader.BaseStream.Seek(0, SeekOrigin.Begin);
369
370 // Read MS-DOS header section
371 _dosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(reader);
372 // MS-DOS magic number should read 'MZ'
373 if (_dosHeader._e_magic != 0x5a4d)
374 {
375 throw new InvalidOperationException("File is not a portable executable.");
376 }
377
378 // Skip MS-DOS stub and seek reader to NT Headers
379 reader.BaseStream.Seek(_dosHeader._e_lfanew, SeekOrigin.Begin);
380
381 // Read NT Headers
382 _ntHeaders._Signature = MarshalBytesTo<UInt32>(reader);
383
384 // Make sure we have 'PE' in the pe signature
385 if (_ntHeaders._Signature != 0x4550)
386 {
387 throw new InvalidOperationException("Invalid portable executable signature in NT header.");
388 }
389
390 _ntHeaders._FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader);
391 // Read optional headers
392 if (Is32bitAssembly())
393 {
394 log.verbose.debug.writeline("\tDetected a 32Bit PE Executable");
395 Load32bitOptionalHeaders(reader);
396 }
397 else
398 {
399 log.verbose.debug.writeline("\tDetected a 64Bit PE Executable");
400 Load64bitOptionalHeaders(reader);
401 }
402
403 // Read section data
404 log.verbose.debug.writeline("\tTotal Section Headers: {0}", _sectionHeaders.Count);
405 foreach (IMAGE_SECTION_HEADER header in _sectionHeaders)
406 {
407 int section_index = _sectionHeaders.IndexOf(header) + 1;
408 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
416 // Skip to beginning of a section
417 reader.BaseStream.Seek(header._PointerToRawData, SeekOrigin.Begin);
418
419 // Read section data... and do something with it
420 byte[] sectiondata = reader.ReadBytes((int)header._SizeOfRawData);
421 }
422 reader.Close();
423 }
424 catch (Exception ex)
425 {
426 ErrorInfo = ex;
427 throw ErrorInfo;
428 }
429 }
430 if (ErrorInfo != null)
431 {
432 log.verbose.error.writeline("Error Reading PE Format from: {0}", filename);
433 log.verbose.error.writeline(ErrorInfo.ToString());
434 }
435 }
436
437 public IMAGE_DOS_HEADER GetDOSHeader()
438 {
439 return _dosHeader;
440 }
441
442 public UInt32 GetPESignature()
443 {
444 return _ntHeaders._Signature;
445 }
446
447 public IMAGE_FILE_HEADER GetFileHeader()
448 {
449 return _ntHeaders.FileHeader;
450 }
451
452 public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
453 {
454 return _ntHeaders.OptionalHeader32;
455 }
456
457 public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
458 {
459 return _ntHeaders.OptionalHeader64;
460 }
461
462 public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
463 {
464 return _sectionHeaders;
465 }
466
467 public bool Is32bitAssembly()
468 {
469 return ((_ntHeaders.FileHeader._Characteristics & 0x0100) == 0x0100);
470 }
471
472 private void Load64bitOptionalHeaders(BinaryReader reader)
473 {
474 _ntHeaders._OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader);
475
476 // 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
482 // 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
492 private void Load32bitOptionalHeaders(BinaryReader reader)
493 {
494 _ntHeaders._OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader);
495
496 // 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
502 // 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
512 private static T MarshalBytesTo<T>(BinaryReader reader)
513 {
514 // Unmanaged data
515 byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
516
517 // 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
520 // 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
523 // Deallocate pointer
524 handle.Free();
525
526 return theStructure;
527 }
528 }
529 }

  ViewVC Help
Powered by ViewVC 1.1.22