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

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