1 |
using System; |
2 |
using System.Collections.Generic; |
3 |
using System.Linq; |
4 |
using System.Text; |
5 |
using System.IO; |
6 |
using System.Runtime.InteropServices; |
7 |
using System.Diagnostics; |
8 |
|
9 |
namespace RomCheater.Core |
10 |
{ |
11 |
/// <summary> |
12 |
/// Reads in the header information of the Portable Executable format. |
13 |
/// Provides information such as the date the assembly was compiled. |
14 |
/// </summary> |
15 |
public class PeHeaderReader |
16 |
{ |
17 |
|
18 |
|
19 |
#region Private Fields |
20 |
|
21 |
private UInt32 ntSignature; |
22 |
/// <summary> |
23 |
/// The DOS header |
24 |
/// </summary> |
25 |
private IMAGE_DOS_HEADER dosHeader; |
26 |
/// <summary> |
27 |
/// The file header |
28 |
/// </summary> |
29 |
private IMAGE_FILE_HEADER fileHeader; |
30 |
/// <summary> |
31 |
/// Optional 32 bit file header |
32 |
/// </summary> |
33 |
private IMAGE_OPTIONAL_HEADER32 optionalHeader32; |
34 |
/// <summary> |
35 |
/// Optional 64 bit file header |
36 |
/// </summary> |
37 |
private IMAGE_OPTIONAL_HEADER64 optionalHeader64; |
38 |
/// <summary> |
39 |
/// Image Section headers. Number of sections is in the file header. |
40 |
/// </summary> |
41 |
private IMAGE_SECTION_HEADER[] imageSectionHeaders; |
42 |
|
43 |
#endregion Private Fields |
44 |
|
45 |
#region Public Methods |
46 |
|
47 |
public PeHeaderReader(Process p) |
48 |
{ |
49 |
string filePath = p.MainModule.FileName; |
50 |
// Read in the DLL or EXE and get the timestamp |
51 |
using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)) |
52 |
{ |
53 |
BinaryReader reader = new BinaryReader(stream); |
54 |
dosHeader = FromBinaryReader<IMAGE_DOS_HEADER>(reader); |
55 |
|
56 |
// Add 4 bytes to the offset |
57 |
stream.Seek(dosHeader._e_lfanew, SeekOrigin.Begin); |
58 |
|
59 |
UInt32 ntHeadersSignature = reader.ReadUInt32(); |
60 |
ntSignature = ntHeadersSignature; |
61 |
fileHeader = FromBinaryReader<IMAGE_FILE_HEADER>(reader); |
62 |
if (this.Is32BitHeader) |
63 |
{ |
64 |
optionalHeader32 = FromBinaryReader<IMAGE_OPTIONAL_HEADER32>(reader); |
65 |
//optionalHeader32._VirtualEntryPoint = (uint)p.MainModule.EntryPointAddress; |
66 |
//optionalHeader32._VirtualImageBase = (uint)p.MainModule.BaseAddress; |
67 |
} |
68 |
else |
69 |
{ |
70 |
optionalHeader64 = FromBinaryReader<IMAGE_OPTIONAL_HEADER64>(reader); |
71 |
//optionalHeader64._VirtualEntryPoint = (uint)p.MainModule.EntryPointAddress; |
72 |
//optionalHeader64._VirtualImageBase = (ulong)p.MainModule.BaseAddress; |
73 |
} |
74 |
|
75 |
imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader._NumberOfSections]; |
76 |
for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) |
77 |
{ |
78 |
imageSectionHeaders[headerNo] = FromBinaryReader<IMAGE_SECTION_HEADER>(reader); |
79 |
} |
80 |
|
81 |
} |
82 |
} |
83 |
|
84 |
///// <summary> |
85 |
///// Gets the header of the .NET assembly that called this function |
86 |
///// </summary> |
87 |
///// <returns></returns> |
88 |
//public static PeHeaderReader GetCallingAssemblyHeader() |
89 |
//{ |
90 |
// // Get the path to the calling assembly, which is the path to the |
91 |
// // DLL or EXE that we want the time of |
92 |
// string filePath = System.Reflection.Assembly.GetCallingAssembly().Location; |
93 |
|
94 |
// // Get and return the timestamp |
95 |
// return new PeHeaderReader(filePath); |
96 |
//} |
97 |
|
98 |
///// <summary> |
99 |
///// Gets the header of the .NET assembly that called this function |
100 |
///// </summary> |
101 |
///// <returns></returns> |
102 |
//public static PeHeaderReader GetAssemblyHeader() |
103 |
//{ |
104 |
// // Get the path to the calling assembly, which is the path to the |
105 |
// // DLL or EXE that we want the time of |
106 |
// string filePath = System.Reflection.Assembly.GetAssembly(typeof(PeHeaderReader)).Location; |
107 |
|
108 |
// // Get and return the timestamp |
109 |
// return new PeHeaderReader(filePath); |
110 |
//} |
111 |
|
112 |
/// <summary> |
113 |
/// Reads in a block from a file and converts it to the struct |
114 |
/// type specified by the template parameter |
115 |
/// </summary> |
116 |
/// <typeparam name="T"></typeparam> |
117 |
/// <param name="reader"></param> |
118 |
/// <returns></returns> |
119 |
public static T FromBinaryReader<T>(BinaryReader reader) |
120 |
{ |
121 |
// Read in a byte array |
122 |
byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T))); |
123 |
|
124 |
// Pin the managed memory while, copy it out the data, then unpin it |
125 |
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); |
126 |
T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); |
127 |
handle.Free(); |
128 |
|
129 |
return theStructure; |
130 |
} |
131 |
|
132 |
#endregion Public Methods |
133 |
|
134 |
#region Properties |
135 |
|
136 |
/// <summary> |
137 |
/// Gets if the file header is 32 bit or not |
138 |
/// </summary> |
139 |
public bool Is32BitHeader |
140 |
{ |
141 |
get |
142 |
{ |
143 |
return FileHeader.Characteristics.HasFlag(FileCharacteristicType.Supports32Bit); |
144 |
} |
145 |
} |
146 |
|
147 |
/// <summary> |
148 |
/// Gets the file header |
149 |
/// </summary> |
150 |
public IMAGE_FILE_HEADER FileHeader |
151 |
{ |
152 |
get |
153 |
{ |
154 |
return fileHeader; |
155 |
} |
156 |
} |
157 |
/// <summary> |
158 |
/// Gets the file header |
159 |
/// </summary> |
160 |
public string NTSignature |
161 |
{ |
162 |
get |
163 |
{ |
164 |
ushort sig = (ushort)ntSignature; |
165 |
return string.Format("0x{0:x4} [{1}]", sig, Encoding.ASCII.GetString(BitConverter.GetBytes(sig))); |
166 |
} |
167 |
} |
168 |
/// <summary> |
169 |
/// Gets the file header |
170 |
/// </summary> |
171 |
public IMAGE_DOS_HEADER DosHeader |
172 |
{ |
173 |
get |
174 |
{ |
175 |
return dosHeader; |
176 |
} |
177 |
} |
178 |
/// <summary> |
179 |
/// Gets the optional header |
180 |
/// </summary> |
181 |
public IMAGE_OPTIONAL_HEADER32 OptionalHeader32 |
182 |
{ |
183 |
get |
184 |
{ |
185 |
return optionalHeader32; |
186 |
} |
187 |
} |
188 |
|
189 |
/// <summary> |
190 |
/// Gets the optional header |
191 |
/// </summary> |
192 |
public IMAGE_OPTIONAL_HEADER64 OptionalHeader64 |
193 |
{ |
194 |
get |
195 |
{ |
196 |
return optionalHeader64; |
197 |
} |
198 |
} |
199 |
|
200 |
public IMAGE_SECTION_HEADER[] ImageSectionHeaders |
201 |
{ |
202 |
get |
203 |
{ |
204 |
return imageSectionHeaders; |
205 |
} |
206 |
} |
207 |
|
208 |
///// <summary> |
209 |
///// Gets the timestamp from the file header |
210 |
///// </summary> |
211 |
//public DateTime TimeStamp |
212 |
//{ |
213 |
// get |
214 |
// { |
215 |
// // Timestamp is a date offset from 1970 |
216 |
// DateTime returnValue = new DateTime(1970, 1, 1, 0, 0, 0); |
217 |
|
218 |
// // Add in the number of seconds since 1970/1/1 |
219 |
// returnValue = returnValue.AddSeconds(fileHeader.TimeDateStamp); |
220 |
// // Adjust to local timezone |
221 |
// returnValue += TimeZone.CurrentTimeZone.GetUtcOffset(returnValue); |
222 |
|
223 |
// return returnValue; |
224 |
// } |
225 |
//} |
226 |
|
227 |
#endregion Properties |
228 |
} |
229 |
} |