/[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 294 - (show annotations) (download)
Tue Jun 5 10:48:07 2012 UTC (8 years, 7 months ago) by william
File size: 13829 byte(s)
+ setup logging format

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

  ViewVC Help
Powered by ViewVC 1.1.22