ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/Win32/Sojaner.MemoryScanner/PEReader.cs
Revision: 343
Committed: Fri Jun 8 02:25:34 2012 UTC (11 years, 6 months ago) by william
File size: 40009 byte(s)
Log Message:
+ add DataSectionFlags

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 using RomCheater.PluginFramework.Events;
12 using Sojaner.MemoryScanner;
13
14 namespace RomCheater.PluginFramework.Events
15 {
16 public interface IAcceptPEData
17 {
18 void SetPEViewerData(PEReader.PEData peData);
19 }
20 public interface IAcceptsPEData
21 {
22 event BaseEventHandler<PEViewerDataUpdatedEvent> OnPEDataUpdated;
23 }
24 public interface IPEViewerDataUpdatedEvent
25 {
26 PEReader.PEData PEData { get; }
27 }
28 public class PEViewerDataUpdatedEvent : BaseEventArgs, IPEViewerDataUpdatedEvent
29 {
30 public PEViewerDataUpdatedEvent() : this(new PEReader.PEData()) { }
31 public PEViewerDataUpdatedEvent(object sender) : this(sender, new PEReader.PEData()) { }
32 public PEViewerDataUpdatedEvent(PEReader.PEData peData) : base() { this.PEData = peData; }
33 public PEViewerDataUpdatedEvent(object sender, PEReader.PEData peData) : base(sender) { this.PEData = peData; }
34 #region IPEViewerDataUpdatedEvent members
35 public PEReader.PEData PEData { get; private set; }
36 #endregion
37 }
38 }
39 namespace Sojaner.MemoryScanner
40 {
41 public class PEReader
42 {
43 // Code (C) Sergey utilized from: http://www.sergeyakopov.com/2010/11/03/reading-pe-format-using-data-marshalling-in-net/
44 #region Structs
45 #region helpers
46 [Flags]
47 public enum MachineTypeFlags
48 {
49 x86 = 0x14C,
50 Alpha = 0x184,
51 ARM = 0x1C0,
52 MIPS16R3000 = 0x162,
53 MIPS16R4000 = 0x166,
54 MIPS16R10000 = 0x168,
55 PowerPCLE = 0x1F0,
56 PowerPCBE = 0x1F2,
57 Itanium = 0x200,
58 MIPS16 = 0x266,
59 Alpha64 = 0x284,
60 MIPSFPU = 0x366,
61 MIPSFPU16 = 0x466,
62 x64 = 0x8664,
63 }
64 public enum MagicType : ushort
65 {
66 NT_OPTIONAL_HEADER_NOT_PRESENT, // 0
67 NT_OPTIONAL_HEADER_32 = 0x10b,
68 NT_OPTIONAL_HEADER_64 = 0x20b
69 }
70 public enum SubSystemType : ushort
71 {
72 IMAGE_SUBSYSTEM_UNKNOWN = 0,
73 IMAGE_SUBSYSTEM_NATIVE = 1,
74 IMAGE_SUBSYSTEM_WINDOWS_GUI = 2,
75 IMAGE_SUBSYSTEM_WINDOWS_CUI = 3,
76 IMAGE_SUBSYSTEM_POSIX_CUI = 7,
77 IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9,
78 IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
79 IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
80 IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12,
81 IMAGE_SUBSYSTEM_EFI_ROM = 13,
82 IMAGE_SUBSYSTEM_XBOX = 14
83
84 }
85 public enum DllCharacteristicsType : ushort
86 {
87 RES_0 = 0x0001,
88 RES_1 = 0x0002,
89 RES_2 = 0x0004,
90 RES_3 = 0x0008,
91 IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040,
92 IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
93 IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100,
94 IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200,
95 IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400,
96 IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800,
97 RES_4 = 0x1000,
98 IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000,
99 IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
100 }
101 #region DataSectionFlags
102 [Flags]
103 public enum DataSectionFlags : uint
104 {
105 /// <summary>
106 /// Reserved for future use.
107 /// </summary>
108 TypeReg = 0x00000000,
109 /// <summary>
110 /// Reserved for future use.
111 /// </summary>
112 TypeDsect = 0x00000001,
113 /// <summary>
114 /// Reserved for future use.
115 /// </summary>
116 TypeNoLoad = 0x00000002,
117 /// <summary>
118 /// Reserved for future use.
119 /// </summary>
120 TypeGroup = 0x00000004,
121 /// <summary>
122 /// The section should not be padded to the next boundary. This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files.
123 /// </summary>
124 TypeNoPadded = 0x00000008,
125 /// <summary>
126 /// Reserved for future use.
127 /// </summary>
128 TypeCopy = 0x00000010,
129 /// <summary>
130 /// The section contains executable code.
131 /// </summary>
132 ContentCode = 0x00000020,
133 /// <summary>
134 /// The section contains initialized data.
135 /// </summary>
136 ContentInitializedData = 0x00000040,
137 /// <summary>
138 /// The section contains uninitialized data.
139 /// </summary>
140 ContentUninitializedData = 0x00000080,
141 /// <summary>
142 /// Reserved for future use.
143 /// </summary>
144 LinkOther = 0x00000100,
145 /// <summary>
146 /// The section contains comments or other information. The .drectve section has this type. This is valid for object files only.
147 /// </summary>
148 LinkInfo = 0x00000200,
149 /// <summary>
150 /// Reserved for future use.
151 /// </summary>
152 TypeOver = 0x00000400,
153 /// <summary>
154 /// The section will not become part of the image. This is valid only for object files.
155 /// </summary>
156 LinkRemove = 0x00000800,
157 /// <summary>
158 /// The section contains COMDAT data. For more information, see section 5.5.6, COMDAT Sections (Object Only). This is valid only for object files.
159 /// </summary>
160 LinkComDat = 0x00001000,
161 /// <summary>
162 /// Reset speculative exceptions handling bits in the TLB entries for this section.
163 /// </summary>
164 NoDeferSpecExceptions = 0x00004000,
165 /// <summary>
166 /// The section contains data referenced through the global pointer (GP).
167 /// </summary>
168 RelativeGP = 0x00008000,
169 /// <summary>
170 /// Reserved for future use.
171 /// </summary>
172 MemPurgeable = 0x00020000,
173 /// <summary>
174 /// Reserved for future use.
175 /// </summary>
176 Memory16Bit = 0x00020000,
177 /// <summary>
178 /// Reserved for future use.
179 /// </summary>
180 MemoryLocked = 0x00040000,
181 /// <summary>
182 /// Reserved for future use.
183 /// </summary>
184 MemoryPreload = 0x00080000,
185 /// <summary>
186 /// Align data on a 1-byte boundary. Valid only for object files.
187 /// </summary>
188 Align1Bytes = 0x00100000,
189 /// <summary>
190 /// Align data on a 2-byte boundary. Valid only for object files.
191 /// </summary>
192 Align2Bytes = 0x00200000,
193 /// <summary>
194 /// Align data on a 4-byte boundary. Valid only for object files.
195 /// </summary>
196 Align4Bytes = 0x00300000,
197 /// <summary>
198 /// Align data on an 8-byte boundary. Valid only for object files.
199 /// </summary>
200 Align8Bytes = 0x00400000,
201 /// <summary>
202 /// Align data on a 16-byte boundary. Valid only for object files.
203 /// </summary>
204 Align16Bytes = 0x00500000,
205 /// <summary>
206 /// Align data on a 32-byte boundary. Valid only for object files.
207 /// </summary>
208 Align32Bytes = 0x00600000,
209 /// <summary>
210 /// Align data on a 64-byte boundary. Valid only for object files.
211 /// </summary>
212 Align64Bytes = 0x00700000,
213 /// <summary>
214 /// Align data on a 128-byte boundary. Valid only for object files.
215 /// </summary>
216 Align128Bytes = 0x00800000,
217 /// <summary>
218 /// Align data on a 256-byte boundary. Valid only for object files.
219 /// </summary>
220 Align256Bytes = 0x00900000,
221 /// <summary>
222 /// Align data on a 512-byte boundary. Valid only for object files.
223 /// </summary>
224 Align512Bytes = 0x00A00000,
225 /// <summary>
226 /// Align data on a 1024-byte boundary. Valid only for object files.
227 /// </summary>
228 Align1024Bytes = 0x00B00000,
229 /// <summary>
230 /// Align data on a 2048-byte boundary. Valid only for object files.
231 /// </summary>
232 Align2048Bytes = 0x00C00000,
233 /// <summary>
234 /// Align data on a 4096-byte boundary. Valid only for object files.
235 /// </summary>
236 Align4096Bytes = 0x00D00000,
237 /// <summary>
238 /// Align data on an 8192-byte boundary. Valid only for object files.
239 /// </summary>
240 Align8192Bytes = 0x00E00000,
241 /// <summary>
242 /// The section contains extended relocations.
243 /// </summary>
244 LinkExtendedRelocationOverflow = 0x01000000,
245 /// <summary>
246 /// The section can be discarded as needed.
247 /// </summary>
248 MemoryDiscardable = 0x02000000,
249 /// <summary>
250 /// The section cannot be cached.
251 /// </summary>
252 MemoryNotCached = 0x04000000,
253 /// <summary>
254 /// The section is not pageable.
255 /// </summary>
256 MemoryNotPaged = 0x08000000,
257 /// <summary>
258 /// The section can be shared in memory.
259 /// </summary>
260 MemoryShared = 0x10000000,
261 /// <summary>
262 /// The section can be executed as code.
263 /// </summary>
264 MemoryExecute = 0x20000000,
265 /// <summary>
266 /// The section can be read.
267 /// </summary>
268 MemoryRead = 0x40000000,
269 /// <summary>
270 /// The section can be written to.
271 /// </summary>
272 MemoryWrite = 0x80000000
273 }
274 #endregion
275 #endregion
276 [TypeConverter(typeof(ExpandableObjectConverter))]
277 [StructLayout(LayoutKind.Sequential)]
278 public struct IMAGE_DOS_HEADER
279 {
280 public UInt16 _e_magic;
281 public UInt16 _e_cblp;
282 public UInt16 _e_cp;
283 public UInt16 _e_crlc;
284 public UInt16 _e_cparhdr;
285 public UInt16 _e_minalloc;
286 public UInt16 _e_maxalloc;
287 public UInt16 _e_ss;
288 public UInt16 _e_sp;
289 public UInt16 _e_csum;
290 public UInt16 _e_ip;
291 public UInt16 _e_cs;
292 public UInt16 _e_lfarlc;
293 public UInt16 _e_ovno;
294 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
295 public UInt16[] _e_res1;
296 public UInt16 _e_oemid;
297 public UInt16 _e_oeminfo;
298 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
299 public UInt16[] _e_res2;
300 public UInt32 _e_lfanew;
301
302 public string e_magic { get { return string.Format("0x{0:x4}", _e_magic); } }
303 public string e_cblp { get { return string.Format("0x{0:x4}", _e_cblp); } }
304 public string e_cp { get { return string.Format("0x{0:x4}", _e_cp); } }
305 public string e_crlc { get { return string.Format("0x{0:x4}", _e_crlc); } }
306 public string e_cparhdr { get { return string.Format("0x{0:x4}", _e_cparhdr); } }
307 public string e_minalloc { get { return string.Format("0x{0:x4}", _e_minalloc); } }
308 public string e_maxalloc { get { return string.Format("0x{0:x4}", _e_maxalloc); } }
309 public string e_ss { get { return string.Format("0x{0:x4}", _e_ss); } }
310 public string e_sp { get { return string.Format("0x{0:x4}", _e_sp); } }
311 public string e_csum { get { return string.Format("0x{0:x4}", _e_csum); } }
312 public string e_ip { get { return string.Format("0x{0:x4}", _e_ip); } }
313 public string e_cs { get { return string.Format("0x{0:x4}", _e_cs); } }
314 public string e_lfarlc { get { return string.Format("0x{0:x4}", _e_lfarlc); } }
315 public string e_ovno { get { return string.Format("0x{0:x4}", _e_ovno); } }
316 public ushort[] e_res1 { get { return _e_res1; } }
317 public string e_oemid { get { return string.Format("0x{0:x4}", _e_oemid); } }
318 public string e_oeminfo { get { return string.Format("0x{0:x4}", _e_oeminfo); } }
319 public ushort[] e_res2 { get { return _e_res2; } }
320 public string e_lfanew { get { return string.Format("0x{0:x8}", _e_lfanew); } }
321
322 public override string ToString()
323 {
324 return Encoding.UTF8.GetString(BitConverter.GetBytes(_e_magic));
325 }
326 }
327 [TypeConverter(typeof(ExpandableObjectConverter))]
328 [StructLayout(LayoutKind.Sequential)]
329 public struct IMAGE_NT_HEADERS
330 {
331 public UInt32 _Signature;
332 public IMAGE_FILE_HEADER _FileHeader;
333 public IMAGE_OPTIONAL_HEADER32 _OptionalHeader32;
334 public IMAGE_OPTIONAL_HEADER64 _OptionalHeader64;
335
336 public string Signature { get { return string.Format("0x{0:x8}", _Signature); } }
337 public IMAGE_FILE_HEADER FileHeader { get { return _FileHeader; } }
338 public IMAGE_OPTIONAL_HEADER32 OptionalHeader32 { get { return _OptionalHeader32; } }
339 public IMAGE_OPTIONAL_HEADER64 OptionalHeader64 { get { return _OptionalHeader64; } }
340
341 public override string ToString()
342 {
343 return Encoding.UTF8.GetString(BitConverter.GetBytes(_Signature));
344 }
345 }
346 [TypeConverter(typeof(ExpandableObjectConverter))]
347 [StructLayout(LayoutKind.Sequential)]
348 public struct IMAGE_FILE_HEADER
349 {
350 public UInt16 _MachineType;
351 public UInt16 _NumberOfSections;
352 public Int32 _TimeDateStamp;
353 public UInt32 _PointerToSymbolTable;
354 public UInt32 _NumberOfSymbols;
355 public UInt16 _SizeOfOptionalHeader;
356 public UInt16 _Characteristics;
357
358
359 public string MachineType { get { return ((MachineTypeFlags)_MachineType).ToString(); } }
360 public string NumberOfSections { get { return string.Format("0x{0:x4}", _NumberOfSections); } }
361 public string TimeDateStamp { get { return string.Format("{0} (0x{1:x8})", GetDateTimeFromDosDateTime(_TimeDateStamp).ToString(), _TimeDateStamp); } }
362 public string PointerToSymbolTable { get { return string.Format("0x{0:x8}", _PointerToSymbolTable); } }
363 public string NumberOfSymbols { get { return string.Format("0x{0:x8}", _NumberOfSymbols); } }
364 public string SizeOfOptionalHeader { get { return string.Format("0x{0:x4}", _SizeOfOptionalHeader); } }
365 public string Characteristics { get { return string.Format("0x{0:x4}", _Characteristics); } }
366 public override string ToString()
367 {
368 return MachineType;
369 }
370
371 private DateTime GetDateTimeFromDosDateTime(Int32 i32TimeDate)
372 {
373 Int16 i16Time = (Int16)(i32TimeDate & 0xFFFF);
374 Int16 i16Date = (Int16)((i32TimeDate & 0xFFFF0000) >> 16);
375 return GetDateTimeFromDosDateTime(i16Time, i16Date);
376 }
377 private DateTime GetDateTimeFromDosDateTime(Int16 i16Time, Int16 i16Date)
378 {
379 try
380 {
381 int iYear = 0;
382 int iMonth = 1;
383 int iDay = 1;
384 int iHour = 0;
385 int iMinute = 0;
386 int iSecond = 0;
387 iDay = (i16Date & 0x1F);
388 iMonth = ((i16Date & 0x01E0) >> 5);
389 iYear = 1980 + ((i16Date & 0xFE00) >> 9);
390 iSecond = (i16Time & 0x1F) * 2;
391 iMinute = ((i16Time & 0x07E0) >> 5);
392 iHour = ((i16Time & 0x0F800) >> 11);
393 return new DateTime(iYear, iMonth, iDay, iHour, iMinute, iSecond);
394 }
395 catch
396 {
397 return new DateTime();
398 }
399 }
400
401 }
402 [TypeConverter(typeof(ExpandableObjectConverter))]
403 [StructLayout(LayoutKind.Sequential)]
404 public struct IMAGE_OPTIONAL_HEADER32
405 {
406 public UInt16 _Magic;
407 public Byte _MajorLinkerVersion;
408 public Byte _MinorLinkerVersion;
409 public UInt32 _SizeOfCode;
410 public UInt32 _SizeOfInitializedData;
411 public UInt32 _SizeOfUninitializedData;
412 public UInt32 _AddressOfEntryPoint;
413 public UInt32 _BaseOfCode;
414 public UInt32 _BaseOfData; // 32-but specific
415 public UInt32 _ImageBase;
416 public UInt32 _SectionAlignment;
417 public UInt32 _FileAlignment;
418 public UInt16 _MajorOperatingSystemVersion;
419 public UInt16 _MinorOperatingSystemVersion;
420 public UInt16 _MajorImageVersion;
421 public UInt16 _MinorImageVersion;
422 public UInt16 _MajorSubsystemVersion;
423 public UInt16 _MinorSubsystemVersion;
424 public UInt32 _Win32VersionValue;
425 public UInt32 _SizeOfImage;
426 public UInt32 _SizeOfHeaders;
427 public UInt32 _CheckSum;
428 public UInt16 _Subsystem;
429 public UInt16 _DllCharacteristics;
430 public UInt32 _SizeOfStackReserve;
431 public UInt32 _SizeOfStackCommit;
432 public UInt32 _SizeOfHeapReserve;
433 public UInt32 _SizeOfHeapCommit;
434 public UInt32 _LoaderFlags;
435 public UInt32 _NumberOfRvaAndSizes;
436 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
437 public IMAGE_DATA_DIRECTORY[] _DataDirectory;
438
439
440 public string Magic { get { return ((MagicType)_Magic).ToString(); } }
441 public string MajorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
442 public string MinorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
443
444 public string SizeOfCode { get { return string.Format("0x{0:x2}", _SizeOfCode); } }
445 public string SizeOfInitializedData { get { return string.Format("0x{0:x8}", _SizeOfInitializedData); } }
446 public string SizeOfUninitializedData { get { return string.Format("0x{0:x8}", _SizeOfUninitializedData); } }
447 public string AddressOfEntryPoint { get { return string.Format("0x{0:x8}", _AddressOfEntryPoint); } }
448 public string BaseOfCode { get { return string.Format("0x{0:x8}", _BaseOfCode); } }
449 public string BaseOfData { get { return string.Format("0x{0:x8}", _BaseOfData); } }
450 public string ImageBase { get { return string.Format("0x{0:x16}", _ImageBase); } }
451
452 public string SectionAlignment { get { return string.Format("0x{0:x8}", _SectionAlignment); } }
453 public string FileAlignment { get { return string.Format("0x{0:x8}", _FileAlignment); } }
454
455 public string MajorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MajorOperatingSystemVersion); } }
456 public string MinorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MinorOperatingSystemVersion); } }
457 public string MajorImageVersion { get { return string.Format("0x{0:x4}", _MajorImageVersion); } }
458 public string MinorImageVersion { get { return string.Format("0x{0:x4}", _MinorImageVersion); } }
459 public string MajorSubsystemVersion { get { return string.Format("0x{0:x4}", _MajorSubsystemVersion); } }
460 public string MinorSubsystemVersion { get { return string.Format("0x{0:x4}", _MinorSubsystemVersion); } }
461
462 public string Win32VersionValue { get { return string.Format("0x{0:x8}", _Win32VersionValue); } }
463 public string SizeOfImage { get { return string.Format("0x{0:x8}", _SizeOfImage); } }
464 public string SizeOfHeaders { get { return string.Format("0x{0:x8}", _SizeOfHeaders); } }
465 public string CheckSum { get { return string.Format("0x{0:x8}", _CheckSum); } }
466
467 public string Subsystem { get { return ((SubSystemType)_Subsystem).ToString(); } }
468 public string DllCharacteristics { get { return string.Format("0x{0:x4}", _DllCharacteristics); } }
469
470 public string SizeOfStackReserve { get { return string.Format("0x{0:x16}", _SizeOfStackReserve); } }
471 public string SizeOfStackCommit { get { return string.Format("0x{0:x16}", _SizeOfStackCommit); } }
472 public string SizeOfHeapReserve { get { return string.Format("0x{0:x16}", _SizeOfHeapReserve); } }
473 public string SizeOfHeapCommit { get { return string.Format("0x{0:x16}", _SizeOfHeapCommit); } }
474
475 public string LoaderFlags { get { return string.Format("0x{0:x8}", _LoaderFlags); } }
476 public string NumberOfRvaAndSizes { get { return string.Format("0x{0:x8}", _NumberOfRvaAndSizes); } }
477 public override string ToString()
478 {
479 return Magic;
480 }
481 }
482 [TypeConverter(typeof(ExpandableObjectConverter))]
483 [StructLayout(LayoutKind.Sequential)]
484 public struct IMAGE_OPTIONAL_HEADER64
485 {
486 public UInt16 _Magic;
487 public Byte _MajorLinkerVersion;
488 public Byte _MinorLinkerVersion;
489 public UInt32 _SizeOfCode;
490 public UInt32 _SizeOfInitializedData;
491 public UInt32 _SizeOfUninitializedData;
492 public UInt32 _AddressOfEntryPoint;
493 public UInt32 _BaseOfCode;
494 public UInt64 _ImageBase;
495 public UInt32 _SectionAlignment;
496 public UInt32 _FileAlignment;
497 public UInt16 _MajorOperatingSystemVersion;
498 public UInt16 _MinorOperatingSystemVersion;
499 public UInt16 _MajorImageVersion;
500 public UInt16 _MinorImageVersion;
501 public UInt16 _MajorSubsystemVersion;
502 public UInt16 _MinorSubsystemVersion;
503 public UInt32 _Win32VersionValue;
504 public UInt32 _SizeOfImage;
505 public UInt32 _SizeOfHeaders;
506 public UInt32 _CheckSum;
507 public UInt16 _Subsystem;
508 public UInt16 _DllCharacteristics;
509 public UInt64 _SizeOfStackReserve;
510 public UInt64 _SizeOfStackCommit;
511 public UInt64 _SizeOfHeapReserve;
512 public UInt64 _SizeOfHeapCommit;
513 public UInt32 _LoaderFlags;
514 public UInt32 _NumberOfRvaAndSizes;
515 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
516 public IMAGE_DATA_DIRECTORY[] _DataDirectory;
517
518
519 public string Magic { get { return ((MagicType)_Magic).ToString(); } }
520 public string MajorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
521 public string MinorLinkerVersion { get { return string.Format("0x{0:x2}", _MajorLinkerVersion); } }
522
523 public string SizeOfCode { get { return string.Format("0x{0:x2}", _SizeOfCode); } }
524 public string SizeOfInitializedData { get { return string.Format("0x{0:x8}", _SizeOfInitializedData); } }
525 public string SizeOfUninitializedData { get { return string.Format("0x{0:x8}", _SizeOfUninitializedData); } }
526 public string AddressOfEntryPoint { get { return string.Format("0x{0:x8}", _AddressOfEntryPoint); } }
527 public string BaseOfCode { get { return string.Format("0x{0:x8}", _BaseOfCode); } }
528
529 public string ImageBase { get { return string.Format("0x{0:x16}", _ImageBase); } }
530
531 public string SectionAlignment { get { return string.Format("0x{0:x8}", _SectionAlignment); } }
532 public string FileAlignment { get { return string.Format("0x{0:x8}", _FileAlignment); } }
533
534 public string MajorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MajorOperatingSystemVersion); } }
535 public string MinorOperatingSystemVersion { get { return string.Format("0x{0:x4}", _MinorOperatingSystemVersion); } }
536 public string MajorImageVersion { get { return string.Format("0x{0:x4}", _MajorImageVersion); } }
537 public string MinorImageVersion { get { return string.Format("0x{0:x4}", _MinorImageVersion); } }
538 public string MajorSubsystemVersion { get { return string.Format("0x{0:x4}", _MajorSubsystemVersion); } }
539 public string MinorSubsystemVersion { get { return string.Format("0x{0:x4}", _MinorSubsystemVersion); } }
540
541 public string Win32VersionValue { get { return string.Format("0x{0:x8}", _Win32VersionValue); } }
542 public string SizeOfImage { get { return string.Format("0x{0:x8}", _SizeOfImage); } }
543 public string SizeOfHeaders { get { return string.Format("0x{0:x8}", _SizeOfHeaders); } }
544 public string CheckSum { get { return string.Format("0x{0:x8}", _CheckSum); } }
545
546 public string Subsystem { get { return ((SubSystemType)_Subsystem).ToString(); } }
547 public string DllCharacteristics { get { return string.Format("0x{0:x4}", _DllCharacteristics); } }
548
549 public string SizeOfStackReserve { get { return string.Format("0x{0:x16}", _SizeOfStackReserve); } }
550 public string SizeOfStackCommit { get { return string.Format("0x{0:x16}", _SizeOfStackCommit); } }
551 public string SizeOfHeapReserve { get { return string.Format("0x{0:x16}", _SizeOfHeapReserve); } }
552 public string SizeOfHeapCommit { get { return string.Format("0x{0:x16}", _SizeOfHeapCommit); } }
553
554 public string LoaderFlags { get { return string.Format("0x{0:x8}", _LoaderFlags); } }
555 public string NumberOfRvaAndSizes { get { return string.Format("0x{0:x8}", _NumberOfRvaAndSizes); } }
556
557 public override string ToString()
558 {
559 return Magic;
560 }
561 }
562 [TypeConverter(typeof(ExpandableObjectConverter))]
563 [StructLayout(LayoutKind.Sequential)]
564 public struct IMAGE_DATA_DIRECTORY
565 {
566 public UInt32 _VirtualAddress;
567 public UInt32 _Size;
568
569 public string VirtualAddress { get { return string.Format("0x{0:x8}", _VirtualAddress); } }
570 public string Size { get { return string.Format("0x{0:x8}", _Size); } }
571 }
572 [TypeConverter(typeof(ExpandableObjectConverter))]
573 [StructLayout(LayoutKind.Sequential)]
574 public struct IMAGE_SECTION_HEADER
575 {
576 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
577 public string _Name;
578 public Misc _Misc;
579 public UInt32 _VirtualAddress;
580 public UInt32 _SizeOfRawData;
581 public UInt32 _PointerToRawData;
582 public UInt32 _PointerToRelocations;
583 public UInt32 _PointerToLinenumbers;
584 public UInt16 _NumberOfRelocations;
585 public UInt16 _NumberOfLinenumbers;
586 public DataSectionFlags _Characteristics;
587
588 public string Name { get { return _Name; } }
589 public Misc Misc { get { return _Misc; } }
590 public string VirtualAddress { get { return string.Format("0x{0:x8}", _VirtualAddress); } }
591 public string SizeOfRawData { get { return string.Format("0x{0:x8}", _SizeOfRawData); } }
592 public string PointerToRawData { get { return string.Format("0x{0:x8}", _PointerToRawData); } }
593 public string PointerToRelocations { get { return string.Format("0x{0:x8}", _PointerToRelocations); } }
594 public string PointerToLinenumbers { get { return string.Format("0x{0:x8}", _PointerToLinenumbers); } }
595 public string NumberOfRelocations { get { return string.Format("0x{0:x4}", _NumberOfRelocations); } }
596 public string NumberOfLinenumbers { get { return string.Format("0x{0:x4}", _NumberOfLinenumbers); } }
597 public string Characteristics { get { return _Characteristics.ToString(); } }
598 public override string ToString()
599 {
600 return Name;
601 }
602 }
603 [TypeConverter(typeof(ExpandableObjectConverter))]
604 [StructLayout(LayoutKind.Explicit)]
605 public struct Misc
606 {
607 [FieldOffset(0)]
608 public UInt32 _PhysicalAddress;
609 [FieldOffset(0)]
610 public UInt32 _VirtualSize;
611
612 public string PhysicalAddress { get { return string.Format("0x{0:x8}", _PhysicalAddress); } }
613 public string VirtualSize { get { return string.Format("0x{0:x8}", _VirtualSize); } }
614
615 }
616
617 #endregion
618
619 #region Fields
620
621 private readonly IMAGE_DOS_HEADER _dosHeader;
622 private IMAGE_NT_HEADERS _ntHeaders;
623 private readonly IList<IMAGE_SECTION_HEADER> _sectionHeaders = new List<IMAGE_SECTION_HEADER>();
624 #endregion
625
626 #region logging implementation
627 private static class log
628 {
629 public static class verbose
630 {
631 public static class debug
632 {
633 public static void writeline(string format, params object[] args)
634 {
635 #if ENABLE_LOGGING
636 logger.VerboseDebug.WriteLine(format, args);
637 #endif
638 }
639 public static void write(string format, params object[] args)
640 {
641 #if ENABLE_LOGGING
642 logger.VerboseDebug.Write(format, args);
643 #endif
644 }
645 }
646 public static class error
647 {
648 public static void writeline(string format, params object[] args)
649 {
650 #if ENABLE_LOGGING
651 logger.VerboseError.WriteLine(format, args);
652 #endif
653 }
654 public static void write(string format, params object[] args)
655 {
656 #if ENABLE_LOGGING
657 logger.VerboseError.Write(format, args);
658 #endif
659 }
660 }
661 }
662 }
663 #endregion
664
665
666 public PEData GetPEData
667 {
668 get
669 {
670 PEData _data = new PEData(_dosHeader, _ntHeaders, _sectionHeaders.ToArray());
671 return _data;
672 }
673 }
674 #region PEData
675 public class PEData
676 {
677 public PEData() : this(new IMAGE_DOS_HEADER(), new IMAGE_NT_HEADERS(), new IMAGE_SECTION_HEADER[] { }) { }
678 public PEData(IMAGE_DOS_HEADER DosHeader, IMAGE_NT_HEADERS NTHeader, IMAGE_SECTION_HEADER[] SectionHeaders)
679 {
680 this.DosHeader = DosHeader;
681 this.NTHeader = NTHeader;
682 this.SectionHeaders = SectionHeaders;
683 }
684 public IMAGE_DOS_HEADER DosHeader { get; private set; }
685 public IMAGE_NT_HEADERS NTHeader { get; private set; }
686 public IMAGE_SECTION_HEADER[] SectionHeaders { get; private set; }
687
688 public bool Is32bitAssembly()
689 {
690 return ((NTHeader.FileHeader._Characteristics & 0x0100) == 0x0100);
691 }
692 }
693
694 #endregion
695
696 public PEReader(FileInfo fi) : this(fi.FullName) { }
697 public PEReader(string filename)
698 {
699 Exception ErrorInfo = null;
700 using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
701 {
702 try
703 {
704 log.verbose.debug.writeline("Reading PE Format from: {0}", filename);
705 BinaryReader reader = new BinaryReader(fs);
706 // Reset reader position, just in case
707 reader.BaseStream.Seek(0, SeekOrigin.Begin);
708
709 // Read MS-DOS header section
710 _dosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(reader);
711 // MS-DOS magic number should read 'MZ'
712 if (_dosHeader._e_magic != 0x5a4d)
713 {
714 throw new InvalidOperationException("File is not a portable executable.");
715 }
716
717 // Skip MS-DOS stub and seek reader to NT Headers
718 reader.BaseStream.Seek(_dosHeader._e_lfanew, SeekOrigin.Begin);
719
720 // Read NT Headers
721 _ntHeaders._Signature = MarshalBytesTo<UInt32>(reader);
722
723 // Make sure we have 'PE' in the pe signature
724 if (_ntHeaders._Signature != 0x4550)
725 {
726 throw new InvalidOperationException("Invalid portable executable signature in NT header.");
727 }
728
729 _ntHeaders._FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader);
730 // Read optional headers
731 if (Is32bitAssembly())
732 {
733 log.verbose.debug.writeline("\tDetected a 32Bit PE Executable");
734 Load32bitOptionalHeaders(reader);
735 }
736 else
737 {
738 log.verbose.debug.writeline("\tDetected a 64Bit PE Executable");
739 Load64bitOptionalHeaders(reader);
740 }
741
742 // Read section data
743 log.verbose.debug.writeline("\tTotal Section Headers: {0}", _sectionHeaders.Count);
744 foreach (IMAGE_SECTION_HEADER header in _sectionHeaders)
745 {
746 int section_index = _sectionHeaders.IndexOf(header) + 1;
747 log.verbose.debug.writeline("\tSection Header: {0} of {1}", section_index, _sectionHeaders.Count);
748 log.verbose.debug.writeline("\t\tName: {0}", header.Name);
749 log.verbose.debug.writeline("\t\tVirtual Address: 0x{0:x8}", header.VirtualAddress);
750 log.verbose.debug.writeline("\t\tPhysical Address: 0x{0:x8}", header.Misc.PhysicalAddress);
751 log.verbose.debug.writeline("\t\tVirtual Size: 0x{0:x8}", header.Misc.VirtualSize);
752 log.verbose.debug.writeline("\t\tRaw Data Size: 0x{0:x8}", header.SizeOfRawData);
753 log.verbose.debug.writeline("\t\tPointer To Raw Data: 0x{0:x8}", header.PointerToRawData);
754
755 // Skip to beginning of a section
756 reader.BaseStream.Seek(header._PointerToRawData, SeekOrigin.Begin);
757
758 // Read section data... and do something with it
759 byte[] sectiondata = reader.ReadBytes((int)header._SizeOfRawData);
760 }
761 reader.Close();
762 }
763 catch (Exception ex)
764 {
765 ErrorInfo = ex;
766 throw ErrorInfo;
767 }
768 }
769 if (ErrorInfo != null)
770 {
771 log.verbose.error.writeline("Error Reading PE Format from: {0}", filename);
772 log.verbose.error.writeline(ErrorInfo.ToString());
773 }
774 }
775
776 public IMAGE_DOS_HEADER GetDOSHeader()
777 {
778 return _dosHeader;
779 }
780
781 public UInt32 GetPESignature()
782 {
783 return _ntHeaders._Signature;
784 }
785
786 public IMAGE_FILE_HEADER GetFileHeader()
787 {
788 return _ntHeaders.FileHeader;
789 }
790
791 public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
792 {
793 return _ntHeaders.OptionalHeader32;
794 }
795
796 public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
797 {
798 return _ntHeaders.OptionalHeader64;
799 }
800
801 public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
802 {
803 return _sectionHeaders;
804 }
805
806 public bool Is32bitAssembly()
807 {
808 return ((_ntHeaders.FileHeader._Characteristics & 0x0100) == 0x0100);
809 }
810
811 private void Load64bitOptionalHeaders(BinaryReader reader)
812 {
813 _ntHeaders._OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader);
814
815 // Should have 10 data directories
816 if (_ntHeaders.OptionalHeader64._NumberOfRvaAndSizes != 0x10)
817 {
818 throw new InvalidOperationException("Invalid number of data directories in NT header");
819 }
820
821 // Scan data directories and load section headers
822 for (int i = 0; i < _ntHeaders.OptionalHeader64._NumberOfRvaAndSizes; i++)
823 {
824 if (_ntHeaders._OptionalHeader64._DataDirectory[i]._Size > 0)
825 {
826 IMAGE_SECTION_HEADER ish = MarshalBytesTo<IMAGE_SECTION_HEADER>(reader);
827 if (ish._SizeOfRawData != 0)
828 _sectionHeaders.Add(ish);
829 }
830 }
831 }
832
833 private void Load32bitOptionalHeaders(BinaryReader reader)
834 {
835 _ntHeaders._OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader);
836
837 // Should have 10 data directories
838 if (_ntHeaders.OptionalHeader32._NumberOfRvaAndSizes != 0x10)
839 {
840 throw new InvalidOperationException("Invalid number of data directories in NT header");
841 }
842
843 // Scan data directories and load section headers
844 for (int i = 0; i < _ntHeaders.OptionalHeader32._NumberOfRvaAndSizes; i++)
845 {
846 if (_ntHeaders._OptionalHeader32._DataDirectory[i]._Size > 0)
847 {
848 IMAGE_SECTION_HEADER ish = MarshalBytesTo<IMAGE_SECTION_HEADER>(reader);
849 if (ish._SizeOfRawData != 0)
850 _sectionHeaders.Add(ish);
851 }
852 }
853 }
854
855 private static T MarshalBytesTo<T>(BinaryReader reader)
856 {
857 // Unmanaged data
858 byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
859
860 // Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code
861 GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
862
863 // Use our previously created pointer to unmanaged data and marshal to the specified type
864 T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
865
866 // Deallocate pointer
867 handle.Free();
868
869 return theStructure;
870 }
871 }
872 }