ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/Win32/Sojaner.MemoryScanner/PEReader.cs
Revision: 321
Committed: Tue Jun 5 23:12:53 2012 UTC (10 years, 11 months ago) by william
File size: 31252 byte(s)
Log Message:
GetDateTimeFromDosDateTime iYear = 1970 (not 1980)

File Contents

# Content
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 public enum MagicType : ushort
38 {
39 NT_OPTIONAL_HEADER_NOT_PRESENT, // 0
40 NT_OPTIONAL_HEADER_32 = 0x10b,
41 NT_OPTIONAL_HEADER_64 = 0x20b
42 }
43 public enum SubSystemType : ushort
44 {
45 IMAGE_SUBSYSTEM_UNKNOWN = 0,
46 IMAGE_SUBSYSTEM_NATIVE = 1,
47 IMAGE_SUBSYSTEM_WINDOWS_GUI = 2,
48 IMAGE_SUBSYSTEM_WINDOWS_CUI = 3,
49 IMAGE_SUBSYSTEM_POSIX_CUI = 7,
50 IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9,
51 IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
52 IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
53 IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12,
54 IMAGE_SUBSYSTEM_EFI_ROM = 13,
55 IMAGE_SUBSYSTEM_XBOX = 14
56
57 }
58 public enum DllCharacteristicsType : ushort
59 {
60 RES_0 = 0x0001,
61 RES_1 = 0x0002,
62 RES_2 = 0x0004,
63 RES_3 = 0x0008,
64 IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040,
65 IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
66 IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100,
67 IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200,
68 IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400,
69 IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800,
70 RES_4 = 0x1000,
71 IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000,
72 IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
73 }
74 [TypeConverter(typeof(ExpandableObjectConverter))]
75 [StructLayout(LayoutKind.Sequential)]
76 public struct IMAGE_DOS_HEADER
77 {
78 public UInt16 _e_magic;
79 public UInt16 _e_cblp;
80 public UInt16 _e_cp;
81 public UInt16 _e_crlc;
82 public UInt16 _e_cparhdr;
83 public UInt16 _e_minalloc;
84 public UInt16 _e_maxalloc;
85 public UInt16 _e_ss;
86 public UInt16 _e_sp;
87 public UInt16 _e_csum;
88 public UInt16 _e_ip;
89 public UInt16 _e_cs;
90 public UInt16 _e_lfarlc;
91 public UInt16 _e_ovno;
92 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
93 public UInt16[] _e_res1;
94 public UInt16 _e_oemid;
95 public UInt16 _e_oeminfo;
96 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
97 public UInt16[] _e_res2;
98 public UInt32 _e_lfanew;
99
100 public string e_magic { get { return string.Format("0x{0:x4}", _e_magic); } }
101 public string e_cblp { get { return string.Format("0x{0:x4}", _e_cblp); } }
102 public string e_cp { get { return string.Format("0x{0:x4}", _e_cp); } }
103 public string e_crlc { get { return string.Format("0x{0:x4}", _e_crlc); } }
104 public string e_cparhdr { get { return string.Format("0x{0:x4}", _e_cparhdr); } }
105 public string e_minalloc { get { return string.Format("0x{0:x4}", _e_minalloc); } }
106 public string e_maxalloc { get { return string.Format("0x{0:x4}", _e_maxalloc); } }
107 public string e_ss { get { return string.Format("0x{0:x4}", _e_ss); } }
108 public string e_sp { get { return string.Format("0x{0:x4}", _e_sp); } }
109 public string e_csum { get { return string.Format("0x{0:x4}", _e_csum); } }
110 public string e_ip { get { return string.Format("0x{0:x4}", _e_ip); } }
111 public string e_cs { get { return string.Format("0x{0:x4}", _e_cs); } }
112 public string e_lfarlc { get { return string.Format("0x{0:x4}", _e_lfarlc); } }
113 public string e_ovno { get { return string.Format("0x{0:x4}", _e_ovno); } }
114 public ushort[] e_res1 { get { return _e_res1; } }
115 public string e_oemid { get { return string.Format("0x{0:x4}", _e_oemid); } }
116 public string e_oeminfo { get { return string.Format("0x{0:x4}", _e_oeminfo); } }
117 public ushort[] e_res2 { get { return _e_res2; } }
118 public string e_lfanew { get { return string.Format("0x{0:x8}", _e_lfanew); } }
119
120 public override string ToString()
121 {
122 return Encoding.UTF8.GetString(BitConverter.GetBytes(_e_magic));
123 }
124 }
125 [TypeConverter(typeof(ExpandableObjectConverter))]
126 [StructLayout(LayoutKind.Sequential)]
127 public struct IMAGE_NT_HEADERS
128 {
129 public UInt32 _Signature;
130 public IMAGE_FILE_HEADER _FileHeader;
131 public IMAGE_OPTIONAL_HEADER32 _OptionalHeader32;
132 public IMAGE_OPTIONAL_HEADER64 _OptionalHeader64;
133
134 public string Signature { get { return string.Format("0x{0:x8}", _Signature); } }
135 public IMAGE_FILE_HEADER FileHeader { get { return _FileHeader; } }
136 public IMAGE_OPTIONAL_HEADER32 OptionalHeader32 { get { return _OptionalHeader32;} }
137 public IMAGE_OPTIONAL_HEADER64 OptionalHeader64 { get { return _OptionalHeader64;} }
138
139 public override string ToString()
140 {
141 return Encoding.UTF8.GetString(BitConverter.GetBytes(_Signature));
142 }
143 }
144 [TypeConverter(typeof(ExpandableObjectConverter))]
145 [StructLayout(LayoutKind.Sequential)]
146 public struct IMAGE_FILE_HEADER
147 {
148 public UInt16 _MachineType;
149 public UInt16 _NumberOfSections;
150 public UInt32 _TimeDateStamp;
151 public UInt32 _PointerToSymbolTable;
152 public UInt32 _NumberOfSymbols;
153 public UInt16 _SizeOfOptionalHeader;
154 public UInt16 _Characteristics;
155
156
157 public string MachineType { get { return ((MachineTypeFlags)_MachineType).ToString(); } }
158 public string NumberOfSections { get { return string.Format("0x{0:x4}", _NumberOfSections); } }
159 public string TimeDateStamp { get { return string.Format("{0} (0x{1:x8})", GetDateTimeFromDosDateTime(_TimeDateStamp).ToString(), _TimeDateStamp); } }
160 public string PointerToSymbolTable { get { return string.Format("0x{0:x8}", _PointerToSymbolTable); } }
161 public string NumberOfSymbols { get { return string.Format("0x{0:x8}", _NumberOfSymbols); } }
162 public string SizeOfOptionalHeader { get { return string.Format("0x{0:x4}", _SizeOfOptionalHeader); } }
163 public string Characteristics { get { return string.Format("0x{0:x4}", _Characteristics); } }
164 public override string ToString()
165 {
166 return MachineType;
167 }
168
169 private DateTime GetDateTimeFromDosDateTime(UInt32 i32TimeDate)
170 {
171 UInt16 i16Time = (UInt16)(i32TimeDate & 0xFFFF);
172 UInt16 i16Date = (UInt16)((i32TimeDate & 0xFFFF0000) >> 16);
173 return GetDateTimeFromDosDateTime(i16Time, i16Date);
174 }
175 private DateTime GetDateTimeFromDosDateTime(UInt16 i16Time, UInt16 i16Date)
176 {
177 int iYear = 0;
178 int iMonth = 1;
179 int iDay = 1;
180 int iHour = 0;
181 int iMinute = 0;
182 int iSecond = 0;
183 iDay = (i16Date & 0x1F);
184 iMonth = ((i16Date & 0x01E0) >> 5);
185 iYear = 1970 + ((i16Date & 0xFE00) >> 9);
186 iSecond = (i16Time & 0x1F) * 2;
187 iMinute = ((i16Time & 0x07E0) >> 5);
188 iHour = ((i16Time & 0x0F800) >> 11);
189 return new DateTime(iYear, iMonth, iDay, iHour, iMinute, iSecond);
190 }
191
192 }
193 [TypeConverter(typeof(ExpandableObjectConverter))]
194 [StructLayout(LayoutKind.Sequential)]
195 public struct IMAGE_OPTIONAL_HEADER32
196 {
197 public UInt16 _Magic;
198 public Byte _MajorLinkerVersion;
199 public Byte _MinorLinkerVersion;
200 public UInt32 _SizeOfCode;
201 public UInt32 _SizeOfInitializedData;
202 public UInt32 _SizeOfUninitializedData;
203 public UInt32 _AddressOfEntryPoint;
204 public UInt32 _BaseOfCode;
205 public UInt32 _BaseOfData; // 32-but specific
206 public UInt32 _ImageBase;
207 public UInt32 _SectionAlignment;
208 public UInt32 _FileAlignment;
209 public UInt16 _MajorOperatingSystemVersion;
210 public UInt16 _MinorOperatingSystemVersion;
211 public UInt16 _MajorImageVersion;
212 public UInt16 _MinorImageVersion;
213 public UInt16 _MajorSubsystemVersion;
214 public UInt16 _MinorSubsystemVersion;
215 public UInt32 _Win32VersionValue;
216 public UInt32 _SizeOfImage;
217 public UInt32 _SizeOfHeaders;
218 public UInt32 _CheckSum;
219 public UInt16 _Subsystem;
220 public UInt16 _DllCharacteristics;
221 public UInt32 _SizeOfStackReserve;
222 public UInt32 _SizeOfStackCommit;
223 public UInt32 _SizeOfHeapReserve;
224 public UInt32 _SizeOfHeapCommit;
225 public UInt32 _LoaderFlags;
226 public UInt32 _NumberOfRvaAndSizes;
227 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
228 public IMAGE_DATA_DIRECTORY[] _DataDirectory;
229
230
231 public string Magic { get { return ((MagicType)_Magic).ToString(); } }
232 public string MajorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
233 public string MinorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
234
235 public string SizeOfCode { get { return string.Format("0x{0:x2}", _SizeOfCode); } }
236 public string SizeOfInitializedData { get { return string.Format("0x{0:x8}", _SizeOfInitializedData); } }
237 public string SizeOfUninitializedData { get { return string.Format("0x{0:x8}", _SizeOfUninitializedData); } }
238 public string AddressOfEntryPoint { get { return string.Format("0x{0:x8}", _AddressOfEntryPoint); } }
239 public string BaseOfCode { get { return string.Format("0x{0:x8}", _BaseOfCode); } }
240 public string BaseOfData { get { return string.Format("0x{0:x8}", _BaseOfData); } }
241 public string ImageBase { get { return string.Format("0x{0:x16}", _ImageBase); } }
242
243 public string SectionAlignment { get { return string.Format("0x{0:x8}", _SectionAlignment); } }
244 public string FileAlignment { get { return string.Format("0x{0:x8}", _FileAlignment); } }
245
246 public string MajorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MajorOperatingSystemVersion); } }
247 public string MinorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MinorOperatingSystemVersion); } }
248 public string MajorImageVersion { get { return string.Format("0x{0:x4}", _MajorImageVersion); } }
249 public string MinorImageVersion { get { return string.Format("0x{0:x4}", _MinorImageVersion); } }
250 public string MajorSubsystemVersion { get { return string.Format("0x{0:x4}", _MajorSubsystemVersion); } }
251 public string MinorSubsystemVersion { get { return string.Format("0x{0:x4}", _MinorSubsystemVersion); } }
252
253 public string Win32VersionValue { get { return string.Format("0x{0:x8}", _Win32VersionValue); } }
254 public string SizeOfImage { get { return string.Format("0x{0:x8}", _SizeOfImage); } }
255 public string SizeOfHeaders { get { return string.Format("0x{0:x8}", _SizeOfHeaders); } }
256 public string CheckSum { get { return string.Format("0x{0:x8}", _CheckSum); } }
257
258 public string Subsystem { get { return ((SubSystemType)_Subsystem).ToString(); } }
259 public string DllCharacteristics { get { return string.Format("0x{0:x4}", _DllCharacteristics); } }
260
261 public string SizeOfStackReserve { get { return string.Format("0x{0:x16}", _SizeOfStackReserve); } }
262 public string SizeOfStackCommit { get { return string.Format("0x{0:x16}", _SizeOfStackCommit); } }
263 public string SizeOfHeapReserve { get { return string.Format("0x{0:x16}", _SizeOfHeapReserve); } }
264 public string SizeOfHeapCommit { get { return string.Format("0x{0:x16}", _SizeOfHeapCommit); } }
265
266 public string LoaderFlags { get { return string.Format("0x{0:x8}", _LoaderFlags); } }
267 public string NumberOfRvaAndSizes { get { return string.Format("0x{0:x8}", _NumberOfRvaAndSizes); } }
268 public override string ToString()
269 {
270 return Magic;
271 }
272 }
273 [TypeConverter(typeof(ExpandableObjectConverter))]
274 [StructLayout(LayoutKind.Sequential)]
275 public struct IMAGE_OPTIONAL_HEADER64
276 {
277 public UInt16 _Magic;
278 public Byte _MajorLinkerVersion;
279 public Byte _MinorLinkerVersion;
280 public UInt32 _SizeOfCode;
281 public UInt32 _SizeOfInitializedData;
282 public UInt32 _SizeOfUninitializedData;
283 public UInt32 _AddressOfEntryPoint;
284 public UInt32 _BaseOfCode;
285 public UInt64 _ImageBase;
286 public UInt32 _SectionAlignment;
287 public UInt32 _FileAlignment;
288 public UInt16 _MajorOperatingSystemVersion;
289 public UInt16 _MinorOperatingSystemVersion;
290 public UInt16 _MajorImageVersion;
291 public UInt16 _MinorImageVersion;
292 public UInt16 _MajorSubsystemVersion;
293 public UInt16 _MinorSubsystemVersion;
294 public UInt32 _Win32VersionValue;
295 public UInt32 _SizeOfImage;
296 public UInt32 _SizeOfHeaders;
297 public UInt32 _CheckSum;
298 public UInt16 _Subsystem;
299 public UInt16 _DllCharacteristics;
300 public UInt64 _SizeOfStackReserve;
301 public UInt64 _SizeOfStackCommit;
302 public UInt64 _SizeOfHeapReserve;
303 public UInt64 _SizeOfHeapCommit;
304 public UInt32 _LoaderFlags;
305 public UInt32 _NumberOfRvaAndSizes;
306 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
307 public IMAGE_DATA_DIRECTORY[] _DataDirectory;
308
309
310 public string Magic { get { return ((MagicType)_Magic).ToString(); } }
311 public string MajorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
312 public string MinorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
313
314 public string SizeOfCode { get { return string.Format("0x{0:x2}", _SizeOfCode); } }
315 public string SizeOfInitializedData { get { return string.Format("0x{0:x8}", _SizeOfInitializedData); } }
316 public string SizeOfUninitializedData { get { return string.Format("0x{0:x8}", _SizeOfUninitializedData); } }
317 public string AddressOfEntryPoint { get { return string.Format("0x{0:x8}", _AddressOfEntryPoint); } }
318 public string BaseOfCode { get { return string.Format("0x{0:x8}", _BaseOfCode); } }
319
320 public string ImageBase { get { return string.Format("0x{0:x16}", _ImageBase); } }
321
322 public string SectionAlignment { get { return string.Format("0x{0:x8}", _SectionAlignment); } }
323 public string FileAlignment { get { return string.Format("0x{0:x8}", _FileAlignment); } }
324
325 public string MajorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MajorOperatingSystemVersion); } }
326 public string MinorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MinorOperatingSystemVersion); } }
327 public string MajorImageVersion { get { return string.Format("0x{0:x4}", _MajorImageVersion); } }
328 public string MinorImageVersion { get { return string.Format("0x{0:x4}", _MinorImageVersion); } }
329 public string MajorSubsystemVersion { get { return string.Format("0x{0:x4}", _MajorSubsystemVersion); } }
330 public string MinorSubsystemVersion { get { return string.Format("0x{0:x4}", _MinorSubsystemVersion); } }
331
332 public string Win32VersionValue { get { return string.Format("0x{0:x8}", _Win32VersionValue); } }
333 public string SizeOfImage { get { return string.Format("0x{0:x8}", _SizeOfImage); } }
334 public string SizeOfHeaders { get { return string.Format("0x{0:x8}", _SizeOfHeaders); } }
335 public string CheckSum { get { return string.Format("0x{0:x8}", _CheckSum); } }
336
337 public string Subsystem { get { return ((SubSystemType)_Subsystem).ToString(); } }
338 public string DllCharacteristics { get { return string.Format("0x{0:x4}", _DllCharacteristics); } }
339
340 public string SizeOfStackReserve { get { return string.Format("0x{0:x16}", _SizeOfStackReserve); } }
341 public string SizeOfStackCommit { get { return string.Format("0x{0:x16}", _SizeOfStackCommit); } }
342 public string SizeOfHeapReserve { get { return string.Format("0x{0:x16}", _SizeOfHeapReserve); } }
343 public string SizeOfHeapCommit { get { return string.Format("0x{0:x16}", _SizeOfHeapCommit); } }
344
345 public string LoaderFlags { get { return string.Format("0x{0:x8}", _LoaderFlags); } }
346 public string NumberOfRvaAndSizes { get { return string.Format("0x{0:x8}", _NumberOfRvaAndSizes); } }
347
348 public override string ToString()
349 {
350 return Magic;
351 }
352 }
353 [TypeConverter(typeof(ExpandableObjectConverter))]
354 [StructLayout(LayoutKind.Sequential)]
355 public struct IMAGE_DATA_DIRECTORY
356 {
357 public UInt32 _VirtualAddress;
358 public UInt32 _Size;
359
360 public string VirtualAddress { get { return string.Format("0x{0:x8}", _VirtualAddress); } }
361 public string Size { get { return string.Format("0x{0:x8}", _Size); } }
362 }
363 [TypeConverter(typeof(ExpandableObjectConverter))]
364 [StructLayout(LayoutKind.Sequential)]
365 public struct IMAGE_SECTION_HEADER
366 {
367 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
368 public string _Name;
369 public Misc _Misc;
370 public UInt32 _VirtualAddress;
371 public UInt32 _SizeOfRawData;
372 public UInt32 _PointerToRawData;
373 public UInt32 _PointerToRelocations;
374 public UInt32 _PointerToLinenumbers;
375 public UInt16 _NumberOfRelocations;
376 public UInt16 _NumberOfLinenumbers;
377 public UInt32 _Characteristics;
378
379 public string Name { get { return _Name; } }
380 public Misc Misc { get { return _Misc; } }
381 public string VirtualAddress { get { return string.Format("0x{0:x8}", _VirtualAddress); } }
382 public string SizeOfRawData { get { return string.Format("0x{0:x8}", _SizeOfRawData); } }
383 public string PointerToRawData { get { return string.Format("0x{0:x8}", _PointerToRawData); } }
384 public string PointerToRelocations { get { return string.Format("0x{0:x8}", _PointerToRelocations); } }
385 public string PointerToLinenumbers { get { return string.Format("0x{0:x8}", _PointerToLinenumbers); } }
386 public string NumberOfRelocations { get { return string.Format("0x{0:x4}", _NumberOfRelocations); } }
387 public string NumberOfLinenumbers { get { return string.Format("0x{0:x4}", _NumberOfLinenumbers); } }
388 public string Characteristics { get { return string.Format("0x{0:x8}", _Characteristics); } }
389 public override string ToString()
390 {
391 return Name;
392 }
393 }
394 [TypeConverter(typeof(ExpandableObjectConverter))]
395 [StructLayout(LayoutKind.Explicit)]
396 public struct Misc
397 {
398 [FieldOffset(0)]
399 public UInt32 _PhysicalAddress;
400 [FieldOffset(0)]
401 public UInt32 _VirtualSize;
402
403 public string PhysicalAddress { get { return string.Format("0x{0:x8}", _PhysicalAddress); } }
404 public string VirtualSize { get { return string.Format("0x{0:x8}", _VirtualSize); } }
405
406 }
407
408 #endregion
409
410 #region Fields
411
412 private readonly IMAGE_DOS_HEADER _dosHeader;
413 private IMAGE_NT_HEADERS _ntHeaders;
414 private readonly IList<IMAGE_SECTION_HEADER> _sectionHeaders = new List<IMAGE_SECTION_HEADER>();
415 #endregion
416
417 #region logging implementation
418 private static class log
419 {
420 public static class verbose
421 {
422 public static class debug
423 {
424 public static void writeline(string format, params object[] args)
425 {
426 #if ENABLE_LOGGING
427 logger.VerboseDebug.WriteLine(format, args);
428 #endif
429 }
430 public static void write(string format, params object[] args)
431 {
432 #if ENABLE_LOGGING
433 logger.VerboseDebug.Write(format, args);
434 #endif
435 }
436 }
437 public static class error
438 {
439 public static void writeline(string format, params object[] args)
440 {
441 #if ENABLE_LOGGING
442 logger.VerboseError.WriteLine(format, args);
443 #endif
444 }
445 public static void write(string format, params object[] args)
446 {
447 #if ENABLE_LOGGING
448 logger.VerboseError.Write(format, args);
449 #endif
450 }
451 }
452 }
453 }
454 #endregion
455
456
457 public PEData GetData
458 {
459 get
460 {
461 PEData _data = new PEData(_dosHeader, _ntHeaders, _sectionHeaders.ToArray());
462 return _data;
463 }
464 }
465 #region t
466 public class PEData
467 {
468 public PEData() : this(new IMAGE_DOS_HEADER(), new IMAGE_NT_HEADERS(), new IMAGE_SECTION_HEADER[] { }) { }
469 public PEData(IMAGE_DOS_HEADER DosHeader, IMAGE_NT_HEADERS NTHeader, IMAGE_SECTION_HEADER[] SectionHeaders)
470 {
471 this.DosHeader = DosHeader;
472 this.NTHeader = NTHeader;
473 this.SectionHeaders = SectionHeaders;
474 }
475 public IMAGE_DOS_HEADER DosHeader { get; private set; }
476 public IMAGE_NT_HEADERS NTHeader { get; private set; }
477 public IMAGE_SECTION_HEADER[] SectionHeaders { get; private set; }
478 }
479
480 #endregion
481
482 public PEReader(FileInfo fi) : this(fi.FullName) { }
483 public PEReader(string filename)
484 {
485 Exception ErrorInfo = null;
486 using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
487 {
488 try
489 {
490 log.verbose.debug.writeline("Reading PE Format from: {0}", filename);
491 BinaryReader reader = new BinaryReader(fs);
492 // Reset reader position, just in case
493 reader.BaseStream.Seek(0, SeekOrigin.Begin);
494
495 // Read MS-DOS header section
496 _dosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(reader);
497 // MS-DOS magic number should read 'MZ'
498 if (_dosHeader._e_magic != 0x5a4d)
499 {
500 throw new InvalidOperationException("File is not a portable executable.");
501 }
502
503 // Skip MS-DOS stub and seek reader to NT Headers
504 reader.BaseStream.Seek(_dosHeader._e_lfanew, SeekOrigin.Begin);
505
506 // Read NT Headers
507 _ntHeaders._Signature = MarshalBytesTo<UInt32>(reader);
508
509 // Make sure we have 'PE' in the pe signature
510 if (_ntHeaders._Signature != 0x4550)
511 {
512 throw new InvalidOperationException("Invalid portable executable signature in NT header.");
513 }
514
515 _ntHeaders._FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader);
516 // Read optional headers
517 if (Is32bitAssembly())
518 {
519 log.verbose.debug.writeline("\tDetected a 32Bit PE Executable");
520 Load32bitOptionalHeaders(reader);
521 }
522 else
523 {
524 log.verbose.debug.writeline("\tDetected a 64Bit PE Executable");
525 Load64bitOptionalHeaders(reader);
526 }
527
528 // Read section data
529 log.verbose.debug.writeline("\tTotal Section Headers: {0}", _sectionHeaders.Count);
530 foreach (IMAGE_SECTION_HEADER header in _sectionHeaders)
531 {
532 int section_index = _sectionHeaders.IndexOf(header) + 1;
533 log.verbose.debug.writeline("\tSection Header: {0} of {1}", section_index, _sectionHeaders.Count);
534 log.verbose.debug.writeline("\t\tName: {0}", header.Name);
535 log.verbose.debug.writeline("\t\tVirtual Address: 0x{0:x8}", header.VirtualAddress);
536 log.verbose.debug.writeline("\t\tPhysical Address: 0x{0:x8}", header.Misc.PhysicalAddress);
537 log.verbose.debug.writeline("\t\tVirtual Size: 0x{0:x8}", header.Misc.VirtualSize);
538 log.verbose.debug.writeline("\t\tRaw Data Size: 0x{0:x8}", header.SizeOfRawData);
539 log.verbose.debug.writeline("\t\tPointer To Raw Data: 0x{0:x8}", header.PointerToRawData);
540
541 // Skip to beginning of a section
542 reader.BaseStream.Seek(header._PointerToRawData, SeekOrigin.Begin);
543
544 // Read section data... and do something with it
545 byte[] sectiondata = reader.ReadBytes((int)header._SizeOfRawData);
546 }
547 reader.Close();
548 }
549 catch (Exception ex)
550 {
551 ErrorInfo = ex;
552 throw ErrorInfo;
553 }
554 }
555 if (ErrorInfo != null)
556 {
557 log.verbose.error.writeline("Error Reading PE Format from: {0}", filename);
558 log.verbose.error.writeline(ErrorInfo.ToString());
559 }
560 }
561
562 public IMAGE_DOS_HEADER GetDOSHeader()
563 {
564 return _dosHeader;
565 }
566
567 public UInt32 GetPESignature()
568 {
569 return _ntHeaders._Signature;
570 }
571
572 public IMAGE_FILE_HEADER GetFileHeader()
573 {
574 return _ntHeaders.FileHeader;
575 }
576
577 public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
578 {
579 return _ntHeaders.OptionalHeader32;
580 }
581
582 public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
583 {
584 return _ntHeaders.OptionalHeader64;
585 }
586
587 public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
588 {
589 return _sectionHeaders;
590 }
591
592 public bool Is32bitAssembly()
593 {
594 return ((_ntHeaders.FileHeader._Characteristics & 0x0100) == 0x0100);
595 }
596
597 private void Load64bitOptionalHeaders(BinaryReader reader)
598 {
599 _ntHeaders._OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader);
600
601 // Should have 10 data directories
602 if (_ntHeaders.OptionalHeader64._NumberOfRvaAndSizes != 0x10)
603 {
604 throw new InvalidOperationException("Invalid number of data directories in NT header");
605 }
606
607 // Scan data directories and load section headers
608 for (int i = 0; i < _ntHeaders.OptionalHeader64._NumberOfRvaAndSizes; i++)
609 {
610 if (_ntHeaders._OptionalHeader64._DataDirectory[i]._Size > 0)
611 {
612 _sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
613 }
614 }
615 }
616
617 private void Load32bitOptionalHeaders(BinaryReader reader)
618 {
619 _ntHeaders._OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader);
620
621 // Should have 10 data directories
622 if (_ntHeaders.OptionalHeader32._NumberOfRvaAndSizes != 0x10)
623 {
624 throw new InvalidOperationException("Invalid number of data directories in NT header");
625 }
626
627 // Scan data directories and load section headers
628 for (int i = 0; i < _ntHeaders.OptionalHeader32._NumberOfRvaAndSizes; i++)
629 {
630 if (_ntHeaders._OptionalHeader32._DataDirectory[i]._Size > 0)
631 {
632 _sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
633 }
634 }
635 }
636
637 private static T MarshalBytesTo<T>(BinaryReader reader)
638 {
639 // Unmanaged data
640 byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
641
642 // Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code
643 GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
644
645 // Use our previously created pointer to unmanaged data and marshal to the specified type
646 T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
647
648 // Deallocate pointer
649 handle.Free();
650
651 return theStructure;
652 }
653 }
654 }