ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/Win32/Sojaner.MemoryScanner/PEReader.cs
Revision: 320
Committed: Tue Jun 5 19:18:20 2012 UTC (11 years, 3 months ago) by william
File size: 31254 byte(s)
Log Message:
+ add rest of properties to currently present structures for property grid support

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 = 1980 + ((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 }
194 [TypeConverter(typeof(ExpandableObjectConverter))]
195 [StructLayout(LayoutKind.Sequential)]
196 public struct IMAGE_OPTIONAL_HEADER32
197 {
198 public UInt16 _Magic;
199 public Byte _MajorLinkerVersion;
200 public Byte _MinorLinkerVersion;
201 public UInt32 _SizeOfCode;
202 public UInt32 _SizeOfInitializedData;
203 public UInt32 _SizeOfUninitializedData;
204 public UInt32 _AddressOfEntryPoint;
205 public UInt32 _BaseOfCode;
206 public UInt32 _BaseOfData; // 32-but specific
207 public UInt32 _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 UInt32 _SizeOfStackReserve;
223 public UInt32 _SizeOfStackCommit;
224 public UInt32 _SizeOfHeapReserve;
225 public UInt32 _SizeOfHeapCommit;
226 public UInt32 _LoaderFlags;
227 public UInt32 _NumberOfRvaAndSizes;
228 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
229 public IMAGE_DATA_DIRECTORY[] _DataDirectory;
230
231
232 public string Magic { get { return ((MagicType)_Magic).ToString(); } }
233 public string MajorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
234 public string MinorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
235
236 public string SizeOfCode { get { return string.Format("0x{0:x2}", _SizeOfCode); } }
237 public string SizeOfInitializedData { get { return string.Format("0x{0:x8}", _SizeOfInitializedData); } }
238 public string SizeOfUninitializedData { get { return string.Format("0x{0:x8}", _SizeOfUninitializedData); } }
239 public string AddressOfEntryPoint { get { return string.Format("0x{0:x8}", _AddressOfEntryPoint); } }
240 public string BaseOfCode { get { return string.Format("0x{0:x8}", _BaseOfCode); } }
241 public string BaseOfData { get { return string.Format("0x{0:x8}", _BaseOfData); } }
242 public string ImageBase { get { return string.Format("0x{0:x16}", _ImageBase); } }
243
244 public string SectionAlignment { get { return string.Format("0x{0:x8}", _SectionAlignment); } }
245 public string FileAlignment { get { return string.Format("0x{0:x8}", _FileAlignment); } }
246
247 public string MajorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MajorOperatingSystemVersion); } }
248 public string MinorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MinorOperatingSystemVersion); } }
249 public string MajorImageVersion { get { return string.Format("0x{0:x4}", _MajorImageVersion); } }
250 public string MinorImageVersion { get { return string.Format("0x{0:x4}", _MinorImageVersion); } }
251 public string MajorSubsystemVersion { get { return string.Format("0x{0:x4}", _MajorSubsystemVersion); } }
252 public string MinorSubsystemVersion { get { return string.Format("0x{0:x4}", _MinorSubsystemVersion); } }
253
254 public string Win32VersionValue { get { return string.Format("0x{0:x8}", _Win32VersionValue); } }
255 public string SizeOfImage { get { return string.Format("0x{0:x8}", _SizeOfImage); } }
256 public string SizeOfHeaders { get { return string.Format("0x{0:x8}", _SizeOfHeaders); } }
257 public string CheckSum { get { return string.Format("0x{0:x8}", _CheckSum); } }
258
259 public string Subsystem { get { return ((SubSystemType)_Subsystem).ToString(); } }
260 public string DllCharacteristics { get { return string.Format("0x{0:x4}", _DllCharacteristics); } }
261
262 public string SizeOfStackReserve { get { return string.Format("0x{0:x16}", _SizeOfStackReserve); } }
263 public string SizeOfStackCommit { get { return string.Format("0x{0:x16}", _SizeOfStackCommit); } }
264 public string SizeOfHeapReserve { get { return string.Format("0x{0:x16}", _SizeOfHeapReserve); } }
265 public string SizeOfHeapCommit { get { return string.Format("0x{0:x16}", _SizeOfHeapCommit); } }
266
267 public string LoaderFlags { get { return string.Format("0x{0:x8}", _LoaderFlags); } }
268 public string NumberOfRvaAndSizes { get { return string.Format("0x{0:x8}", _NumberOfRvaAndSizes); } }
269 public override string ToString()
270 {
271 return Magic;
272 }
273 }
274 [TypeConverter(typeof(ExpandableObjectConverter))]
275 [StructLayout(LayoutKind.Sequential)]
276 public struct IMAGE_OPTIONAL_HEADER64
277 {
278 public UInt16 _Magic;
279 public Byte _MajorLinkerVersion;
280 public Byte _MinorLinkerVersion;
281 public UInt32 _SizeOfCode;
282 public UInt32 _SizeOfInitializedData;
283 public UInt32 _SizeOfUninitializedData;
284 public UInt32 _AddressOfEntryPoint;
285 public UInt32 _BaseOfCode;
286 public UInt64 _ImageBase;
287 public UInt32 _SectionAlignment;
288 public UInt32 _FileAlignment;
289 public UInt16 _MajorOperatingSystemVersion;
290 public UInt16 _MinorOperatingSystemVersion;
291 public UInt16 _MajorImageVersion;
292 public UInt16 _MinorImageVersion;
293 public UInt16 _MajorSubsystemVersion;
294 public UInt16 _MinorSubsystemVersion;
295 public UInt32 _Win32VersionValue;
296 public UInt32 _SizeOfImage;
297 public UInt32 _SizeOfHeaders;
298 public UInt32 _CheckSum;
299 public UInt16 _Subsystem;
300 public UInt16 _DllCharacteristics;
301 public UInt64 _SizeOfStackReserve;
302 public UInt64 _SizeOfStackCommit;
303 public UInt64 _SizeOfHeapReserve;
304 public UInt64 _SizeOfHeapCommit;
305 public UInt32 _LoaderFlags;
306 public UInt32 _NumberOfRvaAndSizes;
307 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
308 public IMAGE_DATA_DIRECTORY[] _DataDirectory;
309
310
311 public string Magic { get { return ((MagicType)_Magic).ToString(); } }
312 public string MajorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
313 public string MinorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
314
315 public string SizeOfCode { get { return string.Format("0x{0:x2}", _SizeOfCode); } }
316 public string SizeOfInitializedData { get { return string.Format("0x{0:x8}", _SizeOfInitializedData); } }
317 public string SizeOfUninitializedData { get { return string.Format("0x{0:x8}", _SizeOfUninitializedData); } }
318 public string AddressOfEntryPoint { get { return string.Format("0x{0:x8}", _AddressOfEntryPoint); } }
319 public string BaseOfCode { get { return string.Format("0x{0:x8}", _BaseOfCode); } }
320
321 public string ImageBase { get { return string.Format("0x{0:x16}", _ImageBase); } }
322
323 public string SectionAlignment { get { return string.Format("0x{0:x8}", _SectionAlignment); } }
324 public string FileAlignment { get { return string.Format("0x{0:x8}", _FileAlignment); } }
325
326 public string MajorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MajorOperatingSystemVersion); } }
327 public string MinorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MinorOperatingSystemVersion); } }
328 public string MajorImageVersion { get { return string.Format("0x{0:x4}", _MajorImageVersion); } }
329 public string MinorImageVersion { get { return string.Format("0x{0:x4}", _MinorImageVersion); } }
330 public string MajorSubsystemVersion { get { return string.Format("0x{0:x4}", _MajorSubsystemVersion); } }
331 public string MinorSubsystemVersion { get { return string.Format("0x{0:x4}", _MinorSubsystemVersion); } }
332
333 public string Win32VersionValue { get { return string.Format("0x{0:x8}", _Win32VersionValue); } }
334 public string SizeOfImage { get { return string.Format("0x{0:x8}", _SizeOfImage); } }
335 public string SizeOfHeaders { get { return string.Format("0x{0:x8}", _SizeOfHeaders); } }
336 public string CheckSum { get { return string.Format("0x{0:x8}", _CheckSum); } }
337
338 public string Subsystem { get { return ((SubSystemType)_Subsystem).ToString(); } }
339 public string DllCharacteristics { get { return string.Format("0x{0:x4}", _DllCharacteristics); } }
340
341 public string SizeOfStackReserve { get { return string.Format("0x{0:x16}", _SizeOfStackReserve); } }
342 public string SizeOfStackCommit { get { return string.Format("0x{0:x16}", _SizeOfStackCommit); } }
343 public string SizeOfHeapReserve { get { return string.Format("0x{0:x16}", _SizeOfHeapReserve); } }
344 public string SizeOfHeapCommit { get { return string.Format("0x{0:x16}", _SizeOfHeapCommit); } }
345
346 public string LoaderFlags { get { return string.Format("0x{0:x8}", _LoaderFlags); } }
347 public string NumberOfRvaAndSizes { get { return string.Format("0x{0:x8}", _NumberOfRvaAndSizes); } }
348
349 public override string ToString()
350 {
351 return Magic;
352 }
353 }
354 [TypeConverter(typeof(ExpandableObjectConverter))]
355 [StructLayout(LayoutKind.Sequential)]
356 public struct IMAGE_DATA_DIRECTORY
357 {
358 public UInt32 _VirtualAddress;
359 public UInt32 _Size;
360
361 public string VirtualAddress { get { return string.Format("0x{0:x8}", _VirtualAddress); } }
362 public string Size { get { return string.Format("0x{0:x8}", _Size); } }
363 }
364 [TypeConverter(typeof(ExpandableObjectConverter))]
365 [StructLayout(LayoutKind.Sequential)]
366 public struct IMAGE_SECTION_HEADER
367 {
368 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
369 public string _Name;
370 public Misc _Misc;
371 public UInt32 _VirtualAddress;
372 public UInt32 _SizeOfRawData;
373 public UInt32 _PointerToRawData;
374 public UInt32 _PointerToRelocations;
375 public UInt32 _PointerToLinenumbers;
376 public UInt16 _NumberOfRelocations;
377 public UInt16 _NumberOfLinenumbers;
378 public UInt32 _Characteristics;
379
380 public string Name { get { return _Name; } }
381 public Misc Misc { get { return _Misc; } }
382 public string VirtualAddress { get { return string.Format("0x{0:x8}", _VirtualAddress); } }
383 public string SizeOfRawData { get { return string.Format("0x{0:x8}", _SizeOfRawData); } }
384 public string PointerToRawData { get { return string.Format("0x{0:x8}", _PointerToRawData); } }
385 public string PointerToRelocations { get { return string.Format("0x{0:x8}", _PointerToRelocations); } }
386 public string PointerToLinenumbers { get { return string.Format("0x{0:x8}", _PointerToLinenumbers); } }
387 public string NumberOfRelocations { get { return string.Format("0x{0:x4}", _NumberOfRelocations); } }
388 public string NumberOfLinenumbers { get { return string.Format("0x{0:x4}", _NumberOfLinenumbers); } }
389 public string Characteristics { get { return string.Format("0x{0:x8}", _Characteristics); } }
390 public override string ToString()
391 {
392 return Name;
393 }
394 }
395 [TypeConverter(typeof(ExpandableObjectConverter))]
396 [StructLayout(LayoutKind.Explicit)]
397 public struct Misc
398 {
399 [FieldOffset(0)]
400 public UInt32 _PhysicalAddress;
401 [FieldOffset(0)]
402 public UInt32 _VirtualSize;
403
404 public string PhysicalAddress { get { return string.Format("0x{0:x8}", _PhysicalAddress); } }
405 public string VirtualSize { get { return string.Format("0x{0:x8}", _VirtualSize); } }
406
407 }
408
409 #endregion
410
411 #region Fields
412
413 private readonly IMAGE_DOS_HEADER _dosHeader;
414 private IMAGE_NT_HEADERS _ntHeaders;
415 private readonly IList<IMAGE_SECTION_HEADER> _sectionHeaders = new List<IMAGE_SECTION_HEADER>();
416 #endregion
417
418 #region logging implementation
419 private static class log
420 {
421 public static class verbose
422 {
423 public static class debug
424 {
425 public static void writeline(string format, params object[] args)
426 {
427 #if ENABLE_LOGGING
428 logger.VerboseDebug.WriteLine(format, args);
429 #endif
430 }
431 public static void write(string format, params object[] args)
432 {
433 #if ENABLE_LOGGING
434 logger.VerboseDebug.Write(format, args);
435 #endif
436 }
437 }
438 public static class error
439 {
440 public static void writeline(string format, params object[] args)
441 {
442 #if ENABLE_LOGGING
443 logger.VerboseError.WriteLine(format, args);
444 #endif
445 }
446 public static void write(string format, params object[] args)
447 {
448 #if ENABLE_LOGGING
449 logger.VerboseError.Write(format, args);
450 #endif
451 }
452 }
453 }
454 }
455 #endregion
456
457
458 public PEData GetData
459 {
460 get
461 {
462 PEData _data = new PEData(_dosHeader, _ntHeaders, _sectionHeaders.ToArray());
463 return _data;
464 }
465 }
466 #region t
467 public class PEData
468 {
469 public PEData() : this(new IMAGE_DOS_HEADER(), new IMAGE_NT_HEADERS(), new IMAGE_SECTION_HEADER[] { }) { }
470 public PEData(IMAGE_DOS_HEADER DosHeader, IMAGE_NT_HEADERS NTHeader, IMAGE_SECTION_HEADER[] SectionHeaders)
471 {
472 this.DosHeader = DosHeader;
473 this.NTHeader = NTHeader;
474 this.SectionHeaders = SectionHeaders;
475 }
476 public IMAGE_DOS_HEADER DosHeader { get; private set; }
477 public IMAGE_NT_HEADERS NTHeader { get; private set; }
478 public IMAGE_SECTION_HEADER[] SectionHeaders { get; private set; }
479 }
480
481 #endregion
482
483 public PEReader(FileInfo fi) : this(fi.FullName) { }
484 public PEReader(string filename)
485 {
486 Exception ErrorInfo = null;
487 using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
488 {
489 try
490 {
491 log.verbose.debug.writeline("Reading PE Format from: {0}", filename);
492 BinaryReader reader = new BinaryReader(fs);
493 // Reset reader position, just in case
494 reader.BaseStream.Seek(0, SeekOrigin.Begin);
495
496 // Read MS-DOS header section
497 _dosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(reader);
498 // MS-DOS magic number should read 'MZ'
499 if (_dosHeader._e_magic != 0x5a4d)
500 {
501 throw new InvalidOperationException("File is not a portable executable.");
502 }
503
504 // Skip MS-DOS stub and seek reader to NT Headers
505 reader.BaseStream.Seek(_dosHeader._e_lfanew, SeekOrigin.Begin);
506
507 // Read NT Headers
508 _ntHeaders._Signature = MarshalBytesTo<UInt32>(reader);
509
510 // Make sure we have 'PE' in the pe signature
511 if (_ntHeaders._Signature != 0x4550)
512 {
513 throw new InvalidOperationException("Invalid portable executable signature in NT header.");
514 }
515
516 _ntHeaders._FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader);
517 // Read optional headers
518 if (Is32bitAssembly())
519 {
520 log.verbose.debug.writeline("\tDetected a 32Bit PE Executable");
521 Load32bitOptionalHeaders(reader);
522 }
523 else
524 {
525 log.verbose.debug.writeline("\tDetected a 64Bit PE Executable");
526 Load64bitOptionalHeaders(reader);
527 }
528
529 // Read section data
530 log.verbose.debug.writeline("\tTotal Section Headers: {0}", _sectionHeaders.Count);
531 foreach (IMAGE_SECTION_HEADER header in _sectionHeaders)
532 {
533 int section_index = _sectionHeaders.IndexOf(header) + 1;
534 log.verbose.debug.writeline("\tSection Header: {0} of {1}", section_index, _sectionHeaders.Count);
535 log.verbose.debug.writeline("\t\tName: {0}", header.Name);
536 log.verbose.debug.writeline("\t\tVirtual Address: 0x{0:x8}", header.VirtualAddress);
537 log.verbose.debug.writeline("\t\tPhysical Address: 0x{0:x8}", header.Misc.PhysicalAddress);
538 log.verbose.debug.writeline("\t\tVirtual Size: 0x{0:x8}", header.Misc.VirtualSize);
539 log.verbose.debug.writeline("\t\tRaw Data Size: 0x{0:x8}", header.SizeOfRawData);
540 log.verbose.debug.writeline("\t\tPointer To Raw Data: 0x{0:x8}", header.PointerToRawData);
541
542 // Skip to beginning of a section
543 reader.BaseStream.Seek(header._PointerToRawData, SeekOrigin.Begin);
544
545 // Read section data... and do something with it
546 byte[] sectiondata = reader.ReadBytes((int)header._SizeOfRawData);
547 }
548 reader.Close();
549 }
550 catch (Exception ex)
551 {
552 ErrorInfo = ex;
553 throw ErrorInfo;
554 }
555 }
556 if (ErrorInfo != null)
557 {
558 log.verbose.error.writeline("Error Reading PE Format from: {0}", filename);
559 log.verbose.error.writeline(ErrorInfo.ToString());
560 }
561 }
562
563 public IMAGE_DOS_HEADER GetDOSHeader()
564 {
565 return _dosHeader;
566 }
567
568 public UInt32 GetPESignature()
569 {
570 return _ntHeaders._Signature;
571 }
572
573 public IMAGE_FILE_HEADER GetFileHeader()
574 {
575 return _ntHeaders.FileHeader;
576 }
577
578 public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
579 {
580 return _ntHeaders.OptionalHeader32;
581 }
582
583 public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
584 {
585 return _ntHeaders.OptionalHeader64;
586 }
587
588 public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
589 {
590 return _sectionHeaders;
591 }
592
593 public bool Is32bitAssembly()
594 {
595 return ((_ntHeaders.FileHeader._Characteristics & 0x0100) == 0x0100);
596 }
597
598 private void Load64bitOptionalHeaders(BinaryReader reader)
599 {
600 _ntHeaders._OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader);
601
602 // Should have 10 data directories
603 if (_ntHeaders.OptionalHeader64._NumberOfRvaAndSizes != 0x10)
604 {
605 throw new InvalidOperationException("Invalid number of data directories in NT header");
606 }
607
608 // Scan data directories and load section headers
609 for (int i = 0; i < _ntHeaders.OptionalHeader64._NumberOfRvaAndSizes; i++)
610 {
611 if (_ntHeaders._OptionalHeader64._DataDirectory[i]._Size > 0)
612 {
613 _sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
614 }
615 }
616 }
617
618 private void Load32bitOptionalHeaders(BinaryReader reader)
619 {
620 _ntHeaders._OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader);
621
622 // Should have 10 data directories
623 if (_ntHeaders.OptionalHeader32._NumberOfRvaAndSizes != 0x10)
624 {
625 throw new InvalidOperationException("Invalid number of data directories in NT header");
626 }
627
628 // Scan data directories and load section headers
629 for (int i = 0; i < _ntHeaders.OptionalHeader32._NumberOfRvaAndSizes; i++)
630 {
631 if (_ntHeaders._OptionalHeader32._DataDirectory[i]._Size > 0)
632 {
633 _sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
634 }
635 }
636 }
637
638 private static T MarshalBytesTo<T>(BinaryReader reader)
639 {
640 // Unmanaged data
641 byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
642
643 // Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code
644 GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
645
646 // Use our previously created pointer to unmanaged data and marshal to the specified type
647 T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
648
649 // Deallocate pointer
650 handle.Free();
651
652 return theStructure;
653 }
654 }
655 }