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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 294 - (hide annotations) (download)
Tue Jun 5 10:48:07 2012 UTC (8 years, 11 months ago) by william
File size: 13829 byte(s)
+ setup logging format

1 william 159 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 william 294 // 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 william 290 {
19 william 294 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 william 290 }
41 william 159
42 william 294 [StructLayout(LayoutKind.Sequential)]
43     public struct IMAGE_NT_HEADERS
44 william 159 {
45 william 294 public UInt32 Signature;
46     public IMAGE_FILE_HEADER FileHeader;
47     public IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
48     public IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
49 william 159 }
50    
51     [StructLayout(LayoutKind.Sequential)]
52     public struct IMAGE_FILE_HEADER
53     {
54 william 294 public UInt16 Machine;
55 william 159 public UInt16 NumberOfSections;
56     public UInt32 TimeDateStamp;
57     public UInt32 PointerToSymbolTable;
58     public UInt32 NumberOfSymbols;
59     public UInt16 SizeOfOptionalHeader;
60 william 294 public UInt16 Characteristics;
61 william 159 }
62 william 294
63 william 159 [StructLayout(LayoutKind.Sequential)]
64 william 294 public struct IMAGE_OPTIONAL_HEADER32
65 william 159 {
66 william 294 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 william 159 }
99    
100 william 294 [StructLayout(LayoutKind.Sequential)]
101     public struct IMAGE_OPTIONAL_HEADER64
102 william 159 {
103 william 294 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 william 159 }
135 william 294
136     [StructLayout(LayoutKind.Sequential)]
137     public struct IMAGE_DATA_DIRECTORY
138 william 159 {
139 william 294 public UInt32 VirtualAddress;
140     public UInt32 Size;
141 william 159 }
142    
143 william 294 [StructLayout(LayoutKind.Sequential)]
144     public struct IMAGE_SECTION_HEADER
145 william 159 {
146 william 294 [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 william 159 }
158 william 294
159 william 159 [StructLayout(LayoutKind.Explicit)]
160 william 294 public struct Misc
161 william 159 {
162     [FieldOffset(0)]
163 william 294 public UInt32 PhysicalAddress;
164     [FieldOffset(0)]
165     public UInt32 VirtualSize;
166     }
167 william 159
168 william 294 #endregion
169 william 159
170 william 294 #region Fields
171 william 159
172 william 294 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 william 159
176 william 294 #endregion
177 william 159
178 william 294 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 william 159
191 william 294 // 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 william 159
199 william 294 // Skip MS-DOS stub and seek reader to NT Headers
200     reader.BaseStream.Seek(_dosHeader.e_lfanew, SeekOrigin.Begin);
201 william 159
202 william 294 // Read NT Headers
203     _ntHeaders.Signature = MarshalBytesTo<UInt32>(reader);
204 william 159
205 william 294 // 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 william 159
211 william 294 _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 william 159
224 william 294 // 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 william 159
237 william 294 // Skip to beginning of a section
238     reader.BaseStream.Seek(header.PointerToRawData, SeekOrigin.Begin);
239 william 159
240 william 294 // 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 william 159
258 william 294 public IMAGE_DOS_HEADER GetDOSHeader()
259     {
260     return _dosHeader;
261     }
262 william 159
263 william 294 public UInt32 GetPESignature()
264     {
265     return _ntHeaders.Signature;
266     }
267 william 159
268 william 294 public IMAGE_FILE_HEADER GetFileHeader()
269     {
270     return _ntHeaders.FileHeader;
271     }
272 william 159
273 william 294 public IMAGE_OPTIONAL_HEADER32 GetOptionalHeaders32()
274     {
275     return _ntHeaders.OptionalHeader32;
276     }
277 william 159
278 william 294 public IMAGE_OPTIONAL_HEADER64 GetOptionalHeaders64()
279     {
280     return _ntHeaders.OptionalHeader64;
281     }
282 william 159
283 william 294 public IList<IMAGE_SECTION_HEADER> GetSectionHeaders()
284     {
285     return _sectionHeaders;
286     }
287 william 159
288 william 294 public bool Is32bitAssembly()
289 william 159 {
290 william 294 return ((_ntHeaders.FileHeader.Characteristics & 0x0100) == 0x0100);
291 william 159 }
292 william 294
293     private void Load64bitOptionalHeaders(BinaryReader reader)
294 william 293 {
295 william 294 _ntHeaders.OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader);
296 william 293
297 william 294 // 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 william 293
303 william 294 // 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 william 293
313 william 294 private void Load32bitOptionalHeaders(BinaryReader reader)
314     {
315     _ntHeaders.OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader);
316 william 293
317 william 294 // 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 william 293
323 william 294 // 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 william 293
333 william 294 private static T MarshalBytesTo<T>(BinaryReader reader)
334     {
335     // Unmanaged data
336     byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
337 william 293
338 william 294 // 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 william 293
341 william 294 // 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 william 293
344 william 294 // Deallocate pointer
345     handle.Free();
346 william 293
347 william 294 return theStructure;
348 william 293 }
349 william 159 }
350     }

  ViewVC Help
Powered by ViewVC 1.1.22