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, 8 months ago) by william
File size: 40009 byte(s)
Log Message:
+ add DataSectionFlags

File Contents

# User Rev Content
1 william 299 #define ENABLE_LOGGING
2     using System;
3 william 159 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 william 318 using System.ComponentModel;
11 william 323 using RomCheater.PluginFramework.Events;
12     using Sojaner.MemoryScanner;
13 william 159
14 william 323 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 william 159 namespace Sojaner.MemoryScanner
40     {
41     public class PEReader
42     {
43 william 294 // Code (C) Sergey utilized from: http://www.sergeyakopov.com/2010/11/03/reading-pe-format-using-data-marshalling-in-net/
44     #region Structs
45 william 343 #region helpers
46 william 319 [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 william 320 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 william 319
84 william 320 }
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 william 343 #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 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
277 william 294 [StructLayout(LayoutKind.Sequential)]
278     public struct IMAGE_DOS_HEADER
279 william 290 {
280 william 318 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 william 294 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
295 william 318 public UInt16[] _e_res1;
296     public UInt16 _e_oemid;
297     public UInt16 _e_oeminfo;
298 william 294 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
299 william 318 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 william 319 public override string ToString()
323     {
324     return Encoding.UTF8.GetString(BitConverter.GetBytes(_e_magic));
325     }
326 william 290 }
327 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
328 william 294 [StructLayout(LayoutKind.Sequential)]
329     public struct IMAGE_NT_HEADERS
330 william 159 {
331 william 319 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 william 341 public IMAGE_OPTIONAL_HEADER32 OptionalHeader32 { get { return _OptionalHeader32; } }
339     public IMAGE_OPTIONAL_HEADER64 OptionalHeader64 { get { return _OptionalHeader64; } }
340 william 319
341     public override string ToString()
342     {
343     return Encoding.UTF8.GetString(BitConverter.GetBytes(_Signature));
344     }
345 william 159 }
346 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
347 william 159 [StructLayout(LayoutKind.Sequential)]
348     public struct IMAGE_FILE_HEADER
349     {
350 william 319 public UInt16 _MachineType;
351     public UInt16 _NumberOfSections;
352 william 322 public Int32 _TimeDateStamp;
353 william 319 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 william 322 private DateTime GetDateTimeFromDosDateTime(Int32 i32TimeDate)
372 william 319 {
373 william 322 Int16 i16Time = (Int16)(i32TimeDate & 0xFFFF);
374     Int16 i16Date = (Int16)((i32TimeDate & 0xFFFF0000) >> 16);
375 william 319 return GetDateTimeFromDosDateTime(i16Time, i16Date);
376     }
377 william 322 private DateTime GetDateTimeFromDosDateTime(Int16 i16Time, Int16 i16Date)
378 william 319 {
379 william 322 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 william 319 }
400    
401 william 159 }
402 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
403 william 341 [StructLayout(LayoutKind.Sequential)]
404 william 294 public struct IMAGE_OPTIONAL_HEADER32
405 william 159 {
406 william 341 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 william 320
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 william 341 public string SectionAlignment { get { return string.Format("0x{0:x8}", _SectionAlignment); } }
453     public string FileAlignment { get { return string.Format("0x{0:x8}", _FileAlignment); } }
454 william 320
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 william 341 public string DllCharacteristics { get { return string.Format("0x{0:x4}", _DllCharacteristics); } }
469 william 320
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 william 159 }
482 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
483 william 341 [StructLayout(LayoutKind.Sequential)]
484 william 294 public struct IMAGE_OPTIONAL_HEADER64
485 william 159 {
486 william 341 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 william 320
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 william 159 }
562 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
563 william 294 [StructLayout(LayoutKind.Sequential)]
564     public struct IMAGE_DATA_DIRECTORY
565 william 159 {
566 william 320 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 william 159 }
572 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
573 william 294 [StructLayout(LayoutKind.Sequential)]
574     public struct IMAGE_SECTION_HEADER
575 william 159 {
576 william 294 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
577 william 319 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 william 343 public DataSectionFlags _Characteristics;
587 william 319
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 william 343 public string Characteristics { get { return _Characteristics.ToString(); } }
598 william 319 public override string ToString()
599     {
600     return Name;
601     }
602 william 159 }
603 william 318 [TypeConverter(typeof(ExpandableObjectConverter))]
604 william 159 [StructLayout(LayoutKind.Explicit)]
605 william 294 public struct Misc
606 william 159 {
607     [FieldOffset(0)]
608 william 319 public UInt32 _PhysicalAddress;
609 william 294 [FieldOffset(0)]
610 william 319 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 william 294 }
616 william 159
617 william 294 #endregion
618 william 159
619 william 294 #region Fields
620 william 159
621 william 294 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 william 159
626 william 299 #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 william 323 public PEData GetPEData
667 william 318 {
668 william 341 get
669 william 318 {
670 william 319 PEData _data = new PEData(_dosHeader, _ntHeaders, _sectionHeaders.ToArray());
671 william 318 return _data;
672     }
673     }
674 william 323 #region PEData
675 william 318 public class PEData
676     {
677 william 319 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 william 318 {
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 william 319 public IMAGE_SECTION_HEADER[] SectionHeaders { get; private set; }
687 william 324
688     public bool Is32bitAssembly()
689     {
690     return ((NTHeader.FileHeader._Characteristics & 0x0100) == 0x0100);
691     }
692 william 318 }
693    
694     #endregion
695    
696 william 294 public PEReader(FileInfo fi) : this(fi.FullName) { }
697     public PEReader(string filename)
698 william 341 {
699 william 294 Exception ErrorInfo = null;
700     using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
701     {
702     try
703     {
704 william 299 log.verbose.debug.writeline("Reading PE Format from: {0}", filename);
705 william 294 BinaryReader reader = new BinaryReader(fs);
706     // Reset reader position, just in case
707     reader.BaseStream.Seek(0, SeekOrigin.Begin);
708 william 159
709 william 294 // Read MS-DOS header section
710     _dosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(reader);
711     // MS-DOS magic number should read 'MZ'
712 william 318 if (_dosHeader._e_magic != 0x5a4d)
713 william 294 {
714     throw new InvalidOperationException("File is not a portable executable.");
715     }
716 william 159
717 william 294 // Skip MS-DOS stub and seek reader to NT Headers
718 william 318 reader.BaseStream.Seek(_dosHeader._e_lfanew, SeekOrigin.Begin);
719 william 159
720 william 294 // Read NT Headers
721 william 319 _ntHeaders._Signature = MarshalBytesTo<UInt32>(reader);
722 william 159
723 william 294 // Make sure we have 'PE' in the pe signature
724 william 319 if (_ntHeaders._Signature != 0x4550)
725 william 294 {
726     throw new InvalidOperationException("Invalid portable executable signature in NT header.");
727     }
728 william 159
729 william 341 _ntHeaders._FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader);
730 william 294 // Read optional headers
731     if (Is32bitAssembly())
732     {
733 william 299 log.verbose.debug.writeline("\tDetected a 32Bit PE Executable");
734 william 294 Load32bitOptionalHeaders(reader);
735     }
736     else
737     {
738 william 299 log.verbose.debug.writeline("\tDetected a 64Bit PE Executable");
739 william 294 Load64bitOptionalHeaders(reader);
740     }
741 william 159
742 william 294 // Read section data
743 william 299 log.verbose.debug.writeline("\tTotal Section Headers: {0}", _sectionHeaders.Count);
744 william 294 foreach (IMAGE_SECTION_HEADER header in _sectionHeaders)
745     {
746     int section_index = _sectionHeaders.IndexOf(header) + 1;
747 william 299 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 william 159
755 william 294 // Skip to beginning of a section
756 william 319 reader.BaseStream.Seek(header._PointerToRawData, SeekOrigin.Begin);
757 william 159
758 william 294 // Read section data... and do something with it
759 william 319 byte[] sectiondata = reader.ReadBytes((int)header._SizeOfRawData);
760 william 294 }
761     reader.Close();
762     }
763     catch (Exception ex)
764     {
765     ErrorInfo = ex;
766     throw ErrorInfo;
767     }
768     }
769     if (ErrorInfo != null)
770     {
771 william 299 log.verbose.error.writeline("Error Reading PE Format from: {0}", filename);
772     log.verbose.error.writeline(ErrorInfo.ToString());
773 william 294 }
774     }
775 william 159
776 william 294 public IMAGE_DOS_HEADER GetDOSHeader()
777     {
778     return _dosHeader;
779     }
780 william 159
781 william 294 public UInt32 GetPESignature()
782     {
783 william 319 return _ntHeaders._Signature;
784 william 294 }
785 william 159
786 william 294 public IMAGE_FILE_HEADER GetFileHeader()
787     {
788     return _ntHeaders.FileHeader;
789     }
790 william 159
791 william 294 public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
792     {
793     return _ntHeaders.OptionalHeader32;
794     }
795 william 159
796 william 294 public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
797     {
798     return _ntHeaders.OptionalHeader64;
799     }
800 william 159
801 william 294 public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
802     {
803     return _sectionHeaders;
804     }
805 william 159
806 william 294 public bool Is32bitAssembly()
807 william 159 {
808 william 319 return ((_ntHeaders.FileHeader._Characteristics & 0x0100) == 0x0100);
809 william 159 }
810 william 294
811     private void Load64bitOptionalHeaders(BinaryReader reader)
812 william 293 {
813 william 319 _ntHeaders._OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader);
814 william 293
815 william 294 // Should have 10 data directories
816 william 320 if (_ntHeaders.OptionalHeader64._NumberOfRvaAndSizes != 0x10)
817 william 294 {
818     throw new InvalidOperationException("Invalid number of data directories in NT header");
819     }
820 william 293
821 william 294 // Scan data directories and load section headers
822 william 341 for (int i = 0; i < _ntHeaders.OptionalHeader64._NumberOfRvaAndSizes; i++)
823     {
824     if (_ntHeaders._OptionalHeader64._DataDirectory[i]._Size > 0)
825     {
826 william 342 IMAGE_SECTION_HEADER ish = MarshalBytesTo<IMAGE_SECTION_HEADER>(reader);
827     if (ish._SizeOfRawData != 0)
828     _sectionHeaders.Add(ish);
829 william 341 }
830     }
831 william 294 }
832 william 293
833 william 294 private void Load32bitOptionalHeaders(BinaryReader reader)
834     {
835 william 319 _ntHeaders._OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader);
836 william 293
837 william 294 // Should have 10 data directories
838 william 320 if (_ntHeaders.OptionalHeader32._NumberOfRvaAndSizes != 0x10)
839 william 294 {
840     throw new InvalidOperationException("Invalid number of data directories in NT header");
841     }
842 william 339
843 william 341 // 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 william 342 IMAGE_SECTION_HEADER ish = MarshalBytesTo<IMAGE_SECTION_HEADER>(reader);
849     if (ish._SizeOfRawData != 0)
850     _sectionHeaders.Add(ish);
851 william 341 }
852     }
853 william 294 }
854 william 293
855 william 294 private static T MarshalBytesTo<T>(BinaryReader reader)
856     {
857     // Unmanaged data
858     byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
859 william 293
860 william 294 // 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 william 293
863 william 294 // 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 william 293
866 william 294 // Deallocate pointer
867     handle.Free();
868 william 293
869 william 294 return theStructure;
870 william 293 }
871 william 159 }
872     }