/[RomCheater]/trunk/Win32/Sojaner.MemoryScanner/PEReader.cs
ViewVC logotype

Contents of /trunk/Win32/Sojaner.MemoryScanner/PEReader.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 318 - (show annotations) (download)
Tue Jun 5 17:57:37 2012 UTC (8 years, 2 months ago) by william
File size: 18273 byte(s)
+ add support for displaying PE Struct data into property grid (read-only)

1 #define ENABLE_LOGGING
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.IO;
7 using RomCheater.Logging;
8 using System.Runtime.InteropServices;
9 using System.Diagnostics;
10 using System.ComponentModel;
11
12 namespace Sojaner.MemoryScanner
13 {
14 public class PEReader
15 {
16 // Code (C) Sergey utilized from: http://www.sergeyakopov.com/2010/11/03/reading-pe-format-using-data-marshalling-in-net/
17 #region Structs
18 [TypeConverter(typeof(ExpandableObjectConverter))]
19 [StructLayout(LayoutKind.Sequential)]
20 public struct IMAGE_DOS_HEADER
21 {
22 public UInt16 _e_magic;
23 public UInt16 _e_cblp;
24 public UInt16 _e_cp;
25 public UInt16 _e_crlc;
26 public UInt16 _e_cparhdr;
27 public UInt16 _e_minalloc;
28 public UInt16 _e_maxalloc;
29 public UInt16 _e_ss;
30 public UInt16 _e_sp;
31 public UInt16 _e_csum;
32 public UInt16 _e_ip;
33 public UInt16 _e_cs;
34 public UInt16 _e_lfarlc;
35 public UInt16 _e_ovno;
36 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
37 public UInt16[] _e_res1;
38 public UInt16 _e_oemid;
39 public UInt16 _e_oeminfo;
40 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
41 public UInt16[] _e_res2;
42 public UInt32 _e_lfanew;
43
44 public string e_magic { get { return string.Format("0x{0:x4}", _e_magic); } }
45 public string e_cblp { get { return string.Format("0x{0:x4}", _e_cblp); } }
46 public string e_cp { get { return string.Format("0x{0:x4}", _e_cp); } }
47 public string e_crlc { get { return string.Format("0x{0:x4}", _e_crlc); } }
48 public string e_cparhdr { get { return string.Format("0x{0:x4}", _e_cparhdr); } }
49 public string e_minalloc { get { return string.Format("0x{0:x4}", _e_minalloc); } }
50 public string e_maxalloc { get { return string.Format("0x{0:x4}", _e_maxalloc); } }
51 public string e_ss { get { return string.Format("0x{0:x4}", _e_ss); } }
52 public string e_sp { get { return string.Format("0x{0:x4}", _e_sp); } }
53 public string e_csum { get { return string.Format("0x{0:x4}", _e_csum); } }
54 public string e_ip { get { return string.Format("0x{0:x4}", _e_ip); } }
55 public string e_cs { get { return string.Format("0x{0:x4}", _e_cs); } }
56 public string e_lfarlc { get { return string.Format("0x{0:x4}", _e_lfarlc); } }
57 public string e_ovno { get { return string.Format("0x{0:x4}", _e_ovno); } }
58 public ushort[] e_res1 { get { return _e_res1; } }
59 public string e_oemid { get { return string.Format("0x{0:x4}", _e_oemid); } }
60 public string e_oeminfo { get { return string.Format("0x{0:x4}", _e_oeminfo); } }
61 public ushort[] e_res2 { get { return _e_res2; } }
62 public string e_lfanew { get { return string.Format("0x{0:x8}", _e_lfanew); } }
63
64 }
65 [TypeConverter(typeof(ExpandableObjectConverter))]
66 [StructLayout(LayoutKind.Sequential)]
67 public struct IMAGE_NT_HEADERS
68 {
69 public UInt32 Signature;
70 public IMAGE_FILE_HEADER FileHeader;
71 public IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
72 public IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
73 }
74 [TypeConverter(typeof(ExpandableObjectConverter))]
75 [StructLayout(LayoutKind.Sequential)]
76 public struct IMAGE_FILE_HEADER
77 {
78 public UInt16 Machine;
79 public UInt16 NumberOfSections;
80 public UInt32 TimeDateStamp;
81 public UInt32 PointerToSymbolTable;
82 public UInt32 NumberOfSymbols;
83 public UInt16 SizeOfOptionalHeader;
84 public UInt16 Characteristics;
85 }
86 [TypeConverter(typeof(ExpandableObjectConverter))]
87 [StructLayout(LayoutKind.Sequential)]
88 public struct IMAGE_OPTIONAL_HEADER32
89 {
90 public UInt16 Magic;
91 public Byte MajorLinkerVersion;
92 public Byte MinorLinkerVersion;
93 public UInt32 SizeOfCode;
94 public UInt32 SizeOfInitializedData;
95 public UInt32 SizeOfUninitializedData;
96 public UInt32 AddressOfEntryPoint;
97 public UInt32 BaseOfCode;
98 public UInt32 BaseOfData;
99 public UInt32 ImageBase;
100 public UInt32 SectionAlignment;
101 public UInt32 FileAlignment;
102 public UInt16 MajorOperatingSystemVersion;
103 public UInt16 MinorOperatingSystemVersion;
104 public UInt16 MajorImageVersion;
105 public UInt16 MinorImageVersion;
106 public UInt16 MajorSubsystemVersion;
107 public UInt16 MinorSubsystemVersion;
108 public UInt32 Win32VersionValue;
109 public UInt32 SizeOfImage;
110 public UInt32 SizeOfHeaders;
111 public UInt32 CheckSum;
112 public UInt16 Subsystem;
113 public UInt16 DllCharacteristics;
114 public UInt32 SizeOfStackReserve;
115 public UInt32 SizeOfStackCommit;
116 public UInt32 SizeOfHeapReserve;
117 public UInt32 SizeOfHeapCommit;
118 public UInt32 LoaderFlags;
119 public UInt32 NumberOfRvaAndSizes;
120 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
121 public IMAGE_DATA_DIRECTORY[] DataDirectory;
122 }
123 [TypeConverter(typeof(ExpandableObjectConverter))]
124 [StructLayout(LayoutKind.Sequential)]
125 public struct IMAGE_OPTIONAL_HEADER64
126 {
127 public UInt16 Magic;
128 public Byte MajorLinkerVersion;
129 public Byte MinorLinkerVersion;
130 public UInt32 SizeOfCode;
131 public UInt32 SizeOfInitializedData;
132 public UInt32 SizeOfUninitializedData;
133 public UInt32 AddressOfEntryPoint;
134 public UInt32 BaseOfCode;
135 public UInt64 ImageBase;
136 public UInt32 SectionAlignment;
137 public UInt32 FileAlignment;
138 public UInt16 MajorOperatingSystemVersion;
139 public UInt16 MinorOperatingSystemVersion;
140 public UInt16 MajorImageVersion;
141 public UInt16 MinorImageVersion;
142 public UInt16 MajorSubsystemVersion;
143 public UInt16 MinorSubsystemVersion;
144 public UInt32 Win32VersionValue;
145 public UInt32 SizeOfImage;
146 public UInt32 SizeOfHeaders;
147 public UInt32 CheckSum;
148 public UInt16 Subsystem;
149 public UInt16 DllCharacteristics;
150 public UInt64 SizeOfStackReserve;
151 public UInt64 SizeOfStackCommit;
152 public UInt64 SizeOfHeapReserve;
153 public UInt64 SizeOfHeapCommit;
154 public UInt32 LoaderFlags;
155 public UInt32 NumberOfRvaAndSizes;
156 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
157 public IMAGE_DATA_DIRECTORY[] DataDirectory;
158 }
159 [TypeConverter(typeof(ExpandableObjectConverter))]
160 [StructLayout(LayoutKind.Sequential)]
161 public struct IMAGE_DATA_DIRECTORY
162 {
163 public UInt32 VirtualAddress;
164 public UInt32 Size;
165 }
166 [TypeConverter(typeof(ExpandableObjectConverter))]
167 [StructLayout(LayoutKind.Sequential)]
168 public struct IMAGE_SECTION_HEADER
169 {
170 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
171 public string Name;
172 public Misc Misc;
173 public UInt32 VirtualAddress;
174 public UInt32 SizeOfRawData;
175 public UInt32 PointerToRawData;
176 public UInt32 PointerToRelocations;
177 public UInt32 PointerToLinenumbers;
178 public UInt16 NumberOfRelocations;
179 public UInt16 NumberOfLinenumbers;
180 public UInt32 Characteristics;
181 }
182 [TypeConverter(typeof(ExpandableObjectConverter))]
183 [StructLayout(LayoutKind.Explicit)]
184 public struct Misc
185 {
186 [FieldOffset(0)]
187 public UInt32 PhysicalAddress;
188 [FieldOffset(0)]
189 public UInt32 VirtualSize;
190 }
191
192 #endregion
193
194 #region Fields
195
196 private readonly IMAGE_DOS_HEADER _dosHeader;
197 private IMAGE_NT_HEADERS _ntHeaders;
198 private readonly IList<IMAGE_SECTION_HEADER> _sectionHeaders = new List<IMAGE_SECTION_HEADER>();
199 #endregion
200
201 #region logging implementation
202 private static class log
203 {
204 public static class verbose
205 {
206 public static class debug
207 {
208 public static void writeline(string format, params object[] args)
209 {
210 #if ENABLE_LOGGING
211 logger.VerboseDebug.WriteLine(format, args);
212 #endif
213 }
214 public static void write(string format, params object[] args)
215 {
216 #if ENABLE_LOGGING
217 logger.VerboseDebug.Write(format, args);
218 #endif
219 }
220 }
221 public static class error
222 {
223 public static void writeline(string format, params object[] args)
224 {
225 #if ENABLE_LOGGING
226 logger.VerboseError.WriteLine(format, args);
227 #endif
228 }
229 public static void write(string format, params object[] args)
230 {
231 #if ENABLE_LOGGING
232 logger.VerboseError.Write(format, args);
233 #endif
234 }
235 }
236 }
237 }
238 #endregion
239
240
241 public PEData GetData
242 {
243 get
244 {
245 PEData _data = new PEData(_dosHeader, _ntHeaders, _sectionHeaders);
246 return _data;
247 }
248 }
249 #region t
250 public class PEData
251 {
252 public PEData():this(new IMAGE_DOS_HEADER(),new IMAGE_NT_HEADERS(),new List<IMAGE_SECTION_HEADER>()) { }
253 public PEData(IMAGE_DOS_HEADER DosHeader, IMAGE_NT_HEADERS NTHeader, IList<IMAGE_SECTION_HEADER> SectionHeaders)
254 {
255 this.DosHeader = DosHeader;
256 this.NTHeader = NTHeader;
257 this.SectionHeaders = SectionHeaders;
258 }
259 public IMAGE_DOS_HEADER DosHeader { get; private set; }
260 public IMAGE_NT_HEADERS NTHeader { get; private set; }
261 public IList<IMAGE_SECTION_HEADER> SectionHeaders { get; private set; }
262 }
263
264 #endregion
265
266 public PEReader(FileInfo fi) : this(fi.FullName) { }
267 public PEReader(string filename)
268 {
269 Exception ErrorInfo = null;
270 using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
271 {
272 try
273 {
274 log.verbose.debug.writeline("Reading PE Format from: {0}", filename);
275 BinaryReader reader = new BinaryReader(fs);
276 // Reset reader position, just in case
277 reader.BaseStream.Seek(0, SeekOrigin.Begin);
278
279 // Read MS-DOS header section
280 _dosHeader = MarshalBytesTo<IMAGE_DOS_HEADER>(reader);
281 // MS-DOS magic number should read 'MZ'
282 if (_dosHeader._e_magic != 0x5a4d)
283 {
284 throw new InvalidOperationException("File is not a portable executable.");
285 }
286
287 // Skip MS-DOS stub and seek reader to NT Headers
288 reader.BaseStream.Seek(_dosHeader._e_lfanew, SeekOrigin.Begin);
289
290 // Read NT Headers
291 _ntHeaders.Signature = MarshalBytesTo<UInt32>(reader);
292
293 // Make sure we have 'PE' in the pe signature
294 if (_ntHeaders.Signature != 0x4550)
295 {
296 throw new InvalidOperationException("Invalid portable executable signature in NT header.");
297 }
298
299 _ntHeaders.FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader);
300 // Read optional headers
301 if (Is32bitAssembly())
302 {
303 log.verbose.debug.writeline("\tDetected a 32Bit PE Executable");
304 Load32bitOptionalHeaders(reader);
305 }
306 else
307 {
308 log.verbose.debug.writeline("\tDetected a 64Bit PE Executable");
309 Load64bitOptionalHeaders(reader);
310 }
311
312 // Read section data
313 log.verbose.debug.writeline("\tTotal Section Headers: {0}", _sectionHeaders.Count);
314 foreach (IMAGE_SECTION_HEADER header in _sectionHeaders)
315 {
316 int section_index = _sectionHeaders.IndexOf(header) + 1;
317 log.verbose.debug.writeline("\tSection Header: {0} of {1}", section_index, _sectionHeaders.Count);
318 log.verbose.debug.writeline("\t\tName: {0}", header.Name);
319 log.verbose.debug.writeline("\t\tVirtual Address: 0x{0:x8}", header.VirtualAddress);
320 log.verbose.debug.writeline("\t\tPhysical Address: 0x{0:x8}", header.Misc.PhysicalAddress);
321 log.verbose.debug.writeline("\t\tVirtual Size: 0x{0:x8}", header.Misc.VirtualSize);
322 log.verbose.debug.writeline("\t\tRaw Data Size: 0x{0:x8}", header.SizeOfRawData);
323 log.verbose.debug.writeline("\t\tPointer To Raw Data: 0x{0:x8}", header.PointerToRawData);
324
325 // Skip to beginning of a section
326 reader.BaseStream.Seek(header.PointerToRawData, SeekOrigin.Begin);
327
328 // Read section data... and do something with it
329 byte[] sectiondata = reader.ReadBytes((int)header.SizeOfRawData);
330 }
331 reader.Close();
332 }
333 catch (Exception ex)
334 {
335 ErrorInfo = ex;
336 throw ErrorInfo;
337 }
338 }
339 if (ErrorInfo != null)
340 {
341 log.verbose.error.writeline("Error Reading PE Format from: {0}", filename);
342 log.verbose.error.writeline(ErrorInfo.ToString());
343 }
344 }
345
346 public IMAGE_DOS_HEADER GetDOSHeader()
347 {
348 return _dosHeader;
349 }
350
351 public UInt32 GetPESignature()
352 {
353 return _ntHeaders.Signature;
354 }
355
356 public IMAGE_FILE_HEADER GetFileHeader()
357 {
358 return _ntHeaders.FileHeader;
359 }
360
361 public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
362 {
363 return _ntHeaders.OptionalHeader32;
364 }
365
366 public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
367 {
368 return _ntHeaders.OptionalHeader64;
369 }
370
371 public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
372 {
373 return _sectionHeaders;
374 }
375
376 public bool Is32bitAssembly()
377 {
378 return ((_ntHeaders.FileHeader.Characteristics & 0x0100) == 0x0100);
379 }
380
381 private void Load64bitOptionalHeaders(BinaryReader reader)
382 {
383 _ntHeaders.OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader);
384
385 // Should have 10 data directories
386 if (_ntHeaders.OptionalHeader64.NumberOfRvaAndSizes != 0x10)
387 {
388 throw new InvalidOperationException("Invalid number of data directories in NT header");
389 }
390
391 // Scan data directories and load section headers
392 for (int i = 0; i < _ntHeaders.OptionalHeader64.NumberOfRvaAndSizes; i++)
393 {
394 if (_ntHeaders.OptionalHeader64.DataDirectory[i].Size > 0)
395 {
396 _sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
397 }
398 }
399 }
400
401 private void Load32bitOptionalHeaders(BinaryReader reader)
402 {
403 _ntHeaders.OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader);
404
405 // Should have 10 data directories
406 if (_ntHeaders.OptionalHeader32.NumberOfRvaAndSizes != 0x10)
407 {
408 throw new InvalidOperationException("Invalid number of data directories in NT header");
409 }
410
411 // Scan data directories and load section headers
412 for (int i = 0; i < _ntHeaders.OptionalHeader32.NumberOfRvaAndSizes; i++)
413 {
414 if (_ntHeaders.OptionalHeader32.DataDirectory[i].Size > 0)
415 {
416 _sectionHeaders.Add(MarshalBytesTo<IMAGE_SECTION_HEADER>(reader));
417 }
418 }
419 }
420
421 private static T MarshalBytesTo<T>(BinaryReader reader)
422 {
423 // Unmanaged data
424 byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
425
426 // Create a pointer to the unmanaged data pinned in memory to be accessed by unmanaged code
427 GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
428
429 // Use our previously created pointer to unmanaged data and marshal to the specified type
430 T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
431
432 // Deallocate pointer
433 handle.Free();
434
435 return theStructure;
436 }
437 }
438 }

  ViewVC Help
Powered by ViewVC 1.1.22