ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/Win32/Sojaner.MemoryScanner/PEReader.cs
Revision: 415
Committed: Fri Jun 22 08:33:51 2012 UTC (11 years, 5 months ago) by william
File size: 41592 byte(s)
Log Message:

File Contents

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