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 |
+ |
|
19 |
+ |
[Flags] |
20 |
+ |
public enum MachineTypeFlags |
21 |
+ |
{ |
22 |
+ |
x86 = 0x14C, |
23 |
+ |
Alpha = 0x184, |
24 |
+ |
ARM = 0x1C0, |
25 |
+ |
MIPS16R3000 = 0x162, |
26 |
+ |
MIPS16R4000 = 0x166, |
27 |
+ |
MIPS16R10000 = 0x168, |
28 |
+ |
PowerPCLE = 0x1F0, |
29 |
+ |
PowerPCBE = 0x1F2, |
30 |
+ |
Itanium = 0x200, |
31 |
+ |
MIPS16 = 0x266, |
32 |
+ |
Alpha64 = 0x284, |
33 |
+ |
MIPSFPU = 0x366, |
34 |
+ |
MIPSFPU16 = 0x466, |
35 |
+ |
x64 = 0x8664, |
36 |
+ |
} |
37 |
+ |
|
38 |
|
[TypeConverter(typeof(ExpandableObjectConverter))] |
39 |
|
[StructLayout(LayoutKind.Sequential)] |
40 |
|
public struct IMAGE_DOS_HEADER |
81 |
|
public ushort[] e_res2 { get { return _e_res2; } } |
82 |
|
public string e_lfanew { get { return string.Format("0x{0:x8}", _e_lfanew); } } |
83 |
|
|
84 |
+ |
public override string ToString() |
85 |
+ |
{ |
86 |
+ |
return Encoding.UTF8.GetString(BitConverter.GetBytes(_e_magic)); |
87 |
+ |
} |
88 |
|
} |
89 |
|
[TypeConverter(typeof(ExpandableObjectConverter))] |
90 |
|
[StructLayout(LayoutKind.Sequential)] |
91 |
|
public struct IMAGE_NT_HEADERS |
92 |
|
{ |
93 |
< |
public UInt32 Signature; |
94 |
< |
public IMAGE_FILE_HEADER FileHeader; |
95 |
< |
public IMAGE_OPTIONAL_HEADER32 OptionalHeader32; |
96 |
< |
public IMAGE_OPTIONAL_HEADER64 OptionalHeader64; |
93 |
> |
public UInt32 _Signature; |
94 |
> |
public IMAGE_FILE_HEADER _FileHeader; |
95 |
> |
public IMAGE_OPTIONAL_HEADER32 _OptionalHeader32; |
96 |
> |
public IMAGE_OPTIONAL_HEADER64 _OptionalHeader64; |
97 |
> |
|
98 |
> |
public string Signature { get { return string.Format("0x{0:x8}", _Signature); } } |
99 |
> |
public IMAGE_FILE_HEADER FileHeader { get { return _FileHeader; } } |
100 |
> |
public IMAGE_OPTIONAL_HEADER32 OptionalHeader32 { get { return _OptionalHeader32;} } |
101 |
> |
public IMAGE_OPTIONAL_HEADER64 OptionalHeader64 { get { return _OptionalHeader64;} } |
102 |
> |
|
103 |
> |
public override string ToString() |
104 |
> |
{ |
105 |
> |
return Encoding.UTF8.GetString(BitConverter.GetBytes(_Signature)); |
106 |
> |
} |
107 |
|
} |
108 |
|
[TypeConverter(typeof(ExpandableObjectConverter))] |
109 |
|
[StructLayout(LayoutKind.Sequential)] |
110 |
|
public struct IMAGE_FILE_HEADER |
111 |
|
{ |
112 |
< |
public UInt16 Machine; |
113 |
< |
public UInt16 NumberOfSections; |
114 |
< |
public UInt32 TimeDateStamp; |
115 |
< |
public UInt32 PointerToSymbolTable; |
116 |
< |
public UInt32 NumberOfSymbols; |
117 |
< |
public UInt16 SizeOfOptionalHeader; |
118 |
< |
public UInt16 Characteristics; |
112 |
> |
public UInt16 _MachineType; |
113 |
> |
public UInt16 _NumberOfSections; |
114 |
> |
public UInt32 _TimeDateStamp; |
115 |
> |
public UInt32 _PointerToSymbolTable; |
116 |
> |
public UInt32 _NumberOfSymbols; |
117 |
> |
public UInt16 _SizeOfOptionalHeader; |
118 |
> |
public UInt16 _Characteristics; |
119 |
> |
|
120 |
> |
|
121 |
> |
public string MachineType { get { return ((MachineTypeFlags)_MachineType).ToString(); } } |
122 |
> |
public string NumberOfSections { get { return string.Format("0x{0:x4}", _NumberOfSections); } } |
123 |
> |
public string TimeDateStamp { get { return string.Format("{0} (0x{1:x8})", GetDateTimeFromDosDateTime(_TimeDateStamp).ToString(), _TimeDateStamp); } } |
124 |
> |
public string PointerToSymbolTable { get { return string.Format("0x{0:x8}", _PointerToSymbolTable); } } |
125 |
> |
public string NumberOfSymbols { get { return string.Format("0x{0:x8}", _NumberOfSymbols); } } |
126 |
> |
public string SizeOfOptionalHeader { get { return string.Format("0x{0:x4}", _SizeOfOptionalHeader); } } |
127 |
> |
public string Characteristics { get { return string.Format("0x{0:x4}", _Characteristics); } } |
128 |
> |
public override string ToString() |
129 |
> |
{ |
130 |
> |
return MachineType; |
131 |
> |
} |
132 |
> |
|
133 |
> |
private DateTime GetDateTimeFromDosDateTime(UInt32 i32TimeDate) |
134 |
> |
{ |
135 |
> |
UInt16 i16Time = (UInt16)(i32TimeDate & 0xFFFF); |
136 |
> |
UInt16 i16Date = (UInt16)((i32TimeDate & 0xFFFF0000) >> 16); |
137 |
> |
return GetDateTimeFromDosDateTime(i16Time, i16Date); |
138 |
> |
} |
139 |
> |
private DateTime GetDateTimeFromDosDateTime(UInt16 i16Time, UInt16 i16Date) |
140 |
> |
{ |
141 |
> |
int iYear = 0; |
142 |
> |
int iMonth = 1; |
143 |
> |
int iDay = 1; |
144 |
> |
int iHour = 0; |
145 |
> |
int iMinute = 0; |
146 |
> |
int iSecond = 0; |
147 |
> |
iDay = (i16Date & 0x1F); |
148 |
> |
iMonth = ((i16Date & 0x01E0) >> 5); |
149 |
> |
iYear = 1980 + ((i16Date & 0xFE00) >> 9); |
150 |
> |
iSecond = (i16Time & 0x1F) * 2; |
151 |
> |
iMinute = ((i16Time & 0x07E0) >> 5); |
152 |
> |
iHour = ((i16Time & 0x0F800) >> 11); |
153 |
> |
return new DateTime(iYear, iMonth, iDay, iHour, iMinute, iSecond); |
154 |
> |
|
155 |
> |
} |
156 |
> |
|
157 |
|
} |
158 |
|
[TypeConverter(typeof(ExpandableObjectConverter))] |
159 |
|
[StructLayout(LayoutKind.Sequential)] |
240 |
|
public struct IMAGE_SECTION_HEADER |
241 |
|
{ |
242 |
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] |
243 |
< |
public string Name; |
244 |
< |
public Misc Misc; |
245 |
< |
public UInt32 VirtualAddress; |
246 |
< |
public UInt32 SizeOfRawData; |
247 |
< |
public UInt32 PointerToRawData; |
248 |
< |
public UInt32 PointerToRelocations; |
249 |
< |
public UInt32 PointerToLinenumbers; |
250 |
< |
public UInt16 NumberOfRelocations; |
251 |
< |
public UInt16 NumberOfLinenumbers; |
252 |
< |
public UInt32 Characteristics; |
243 |
> |
public string _Name; |
244 |
> |
public Misc _Misc; |
245 |
> |
public UInt32 _VirtualAddress; |
246 |
> |
public UInt32 _SizeOfRawData; |
247 |
> |
public UInt32 _PointerToRawData; |
248 |
> |
public UInt32 _PointerToRelocations; |
249 |
> |
public UInt32 _PointerToLinenumbers; |
250 |
> |
public UInt16 _NumberOfRelocations; |
251 |
> |
public UInt16 _NumberOfLinenumbers; |
252 |
> |
public UInt32 _Characteristics; |
253 |
> |
|
254 |
> |
public string Name { get { return _Name; } } |
255 |
> |
public Misc Misc { get { return _Misc; } } |
256 |
> |
public string VirtualAddress { get { return string.Format("0x{0:x8}", _VirtualAddress); } } |
257 |
> |
public string SizeOfRawData { get { return string.Format("0x{0:x8}", _SizeOfRawData); } } |
258 |
> |
public string PointerToRawData { get { return string.Format("0x{0:x8}", _PointerToRawData); } } |
259 |
> |
public string PointerToRelocations { get { return string.Format("0x{0:x8}", _PointerToRelocations); } } |
260 |
> |
public string PointerToLinenumbers { get { return string.Format("0x{0:x8}", _PointerToLinenumbers); } } |
261 |
> |
public string NumberOfRelocations { get { return string.Format("0x{0:x4}", _NumberOfRelocations); } } |
262 |
> |
public string NumberOfLinenumbers { get { return string.Format("0x{0:x4}", _NumberOfLinenumbers); } } |
263 |
> |
public string Characteristics { get { return string.Format("0x{0:x8}", _Characteristics); } } |
264 |
> |
public override string ToString() |
265 |
> |
{ |
266 |
> |
return Name; |
267 |
> |
} |
268 |
|
} |
269 |
|
[TypeConverter(typeof(ExpandableObjectConverter))] |
270 |
|
[StructLayout(LayoutKind.Explicit)] |
271 |
|
public struct Misc |
272 |
|
{ |
273 |
|
[FieldOffset(0)] |
274 |
< |
public UInt32 PhysicalAddress; |
274 |
> |
public UInt32 _PhysicalAddress; |
275 |
|
[FieldOffset(0)] |
276 |
< |
public UInt32 VirtualSize; |
276 |
> |
public UInt32 _VirtualSize; |
277 |
> |
|
278 |
> |
public string PhysicalAddress { get { return string.Format("0x{0:x8}", _PhysicalAddress); } } |
279 |
> |
public string VirtualSize { get { return string.Format("0x{0:x8}", _VirtualSize); } } |
280 |
> |
|
281 |
|
} |
282 |
|
|
283 |
|
#endregion |
333 |
|
{ |
334 |
|
get |
335 |
|
{ |
336 |
< |
PEData _data = new PEData(_dosHeader, _ntHeaders, _sectionHeaders); |
336 |
> |
PEData _data = new PEData(_dosHeader, _ntHeaders, _sectionHeaders.ToArray()); |
337 |
|
return _data; |
338 |
|
} |
339 |
|
} |
340 |
|
#region t |
341 |
|
public class PEData |
342 |
|
{ |
343 |
< |
public PEData():this(new IMAGE_DOS_HEADER(),new IMAGE_NT_HEADERS(),new List<IMAGE_SECTION_HEADER>()) { } |
344 |
< |
public PEData(IMAGE_DOS_HEADER DosHeader, IMAGE_NT_HEADERS NTHeader, IList<IMAGE_SECTION_HEADER> SectionHeaders) |
343 |
> |
public PEData() : this(new IMAGE_DOS_HEADER(), new IMAGE_NT_HEADERS(), new IMAGE_SECTION_HEADER[] { }) { } |
344 |
> |
public PEData(IMAGE_DOS_HEADER DosHeader, IMAGE_NT_HEADERS NTHeader, IMAGE_SECTION_HEADER[] SectionHeaders) |
345 |
|
{ |
346 |
|
this.DosHeader = DosHeader; |
347 |
|
this.NTHeader = NTHeader; |
349 |
|
} |
350 |
|
public IMAGE_DOS_HEADER DosHeader { get; private set; } |
351 |
|
public IMAGE_NT_HEADERS NTHeader { get; private set; } |
352 |
< |
public IList<IMAGE_SECTION_HEADER> SectionHeaders { get; private set; } |
352 |
> |
public IMAGE_SECTION_HEADER[] SectionHeaders { get; private set; } |
353 |
|
} |
354 |
|
|
355 |
|
#endregion |
379 |
|
reader.BaseStream.Seek(_dosHeader._e_lfanew, SeekOrigin.Begin); |
380 |
|
|
381 |
|
// Read NT Headers |
382 |
< |
_ntHeaders.Signature = MarshalBytesTo<UInt32>(reader); |
382 |
> |
_ntHeaders._Signature = MarshalBytesTo<UInt32>(reader); |
383 |
|
|
384 |
|
// Make sure we have 'PE' in the pe signature |
385 |
< |
if (_ntHeaders.Signature != 0x4550) |
385 |
> |
if (_ntHeaders._Signature != 0x4550) |
386 |
|
{ |
387 |
|
throw new InvalidOperationException("Invalid portable executable signature in NT header."); |
388 |
|
} |
389 |
|
|
390 |
< |
_ntHeaders.FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader); |
390 |
> |
_ntHeaders._FileHeader = MarshalBytesTo<IMAGE_FILE_HEADER>(reader); |
391 |
|
// Read optional headers |
392 |
|
if (Is32bitAssembly()) |
393 |
|
{ |
414 |
|
log.verbose.debug.writeline("\t\tPointer To Raw Data: 0x{0:x8}", header.PointerToRawData); |
415 |
|
|
416 |
|
// Skip to beginning of a section |
417 |
< |
reader.BaseStream.Seek(header.PointerToRawData, SeekOrigin.Begin); |
417 |
> |
reader.BaseStream.Seek(header._PointerToRawData, SeekOrigin.Begin); |
418 |
|
|
419 |
|
// Read section data... and do something with it |
420 |
< |
byte[] sectiondata = reader.ReadBytes((int)header.SizeOfRawData); |
420 |
> |
byte[] sectiondata = reader.ReadBytes((int)header._SizeOfRawData); |
421 |
|
} |
422 |
|
reader.Close(); |
423 |
|
} |
441 |
|
|
442 |
|
public UInt32 GetPESignature() |
443 |
|
{ |
444 |
< |
return _ntHeaders.Signature; |
444 |
> |
return _ntHeaders._Signature; |
445 |
|
} |
446 |
|
|
447 |
|
public IMAGE_FILE_HEADER GetFileHeader() |
466 |
|
|
467 |
|
public bool Is32bitAssembly() |
468 |
|
{ |
469 |
< |
return ((_ntHeaders.FileHeader.Characteristics & 0x0100) == 0x0100); |
469 |
> |
return ((_ntHeaders.FileHeader._Characteristics & 0x0100) == 0x0100); |
470 |
|
} |
471 |
|
|
472 |
|
private void Load64bitOptionalHeaders(BinaryReader reader) |
473 |
|
{ |
474 |
< |
_ntHeaders.OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader); |
474 |
> |
_ntHeaders._OptionalHeader64 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER64>(reader); |
475 |
|
|
476 |
|
// Should have 10 data directories |
477 |
|
if (_ntHeaders.OptionalHeader64.NumberOfRvaAndSizes != 0x10) |
491 |
|
|
492 |
|
private void Load32bitOptionalHeaders(BinaryReader reader) |
493 |
|
{ |
494 |
< |
_ntHeaders.OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader); |
494 |
> |
_ntHeaders._OptionalHeader32 = MarshalBytesTo<IMAGE_OPTIONAL_HEADER32>(reader); |
495 |
|
|
496 |
|
// Should have 10 data directories |
497 |
|
if (_ntHeaders.OptionalHeader32.NumberOfRvaAndSizes != 0x10) |