PE32+: Initial support

This commit is contained in:
Katy Coe
2019-10-28 22:13:20 +01:00
parent 94b87fa6f0
commit 1496bbb623
2 changed files with 46 additions and 17 deletions

View File

@@ -9,8 +9,14 @@ using NoisyCowStudios.Bin2Object;
namespace Il2CppInspector namespace Il2CppInspector
{ {
// Source: https://github.com/dotnet/llilc/blob/master/include/clr/ntimage.h // Source: https://github.com/dotnet/llilc/blob/master/include/clr/ntimage.h
#pragma warning disable CS0649
public enum PE : uint
{
IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b,
IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b
}
#pragma warning disable CS0649
// _IMAGE_FILE_HEADER // _IMAGE_FILE_HEADER
internal class COFFHeader internal class COFFHeader
{ {
@@ -24,9 +30,22 @@ namespace Il2CppInspector
} }
// _IMAGE_OPTIONAL_HEADER // _IMAGE_OPTIONAL_HEADER
internal class PEOptHeader32 internal interface IPEOptHeader
{ {
public ushort Magic; PE ExpectedMagic { get; }
ushort Magic { get; }
ulong ImageBase { get; }
RvaEntry[] DataDirectory { get; }
}
internal class PEOptHeader32 : IPEOptHeader
{
public PE ExpectedMagic => PE.IMAGE_NT_OPTIONAL_HDR32_MAGIC;
public ushort Magic => f_Magic;
public ulong ImageBase => f_ImageBase;
public RvaEntry[] DataDirectory => f_DataDirectory;
public ushort f_Magic;
public byte MajorLinkerVersion; public byte MajorLinkerVersion;
public byte MinorLinkerVersion; public byte MinorLinkerVersion;
public uint SizeOfCode; public uint SizeOfCode;
@@ -35,7 +54,7 @@ namespace Il2CppInspector
public uint AddressOfEntryPoint; public uint AddressOfEntryPoint;
public uint BaseOfCode; public uint BaseOfCode;
public uint BaseOfData; public uint BaseOfData;
public uint ImageBase; public uint f_ImageBase;
public uint SectionAlignment; public uint SectionAlignment;
public uint FileAlignment; public uint FileAlignment;
public ushort MajorOSVersion; public ushort MajorOSVersion;
@@ -57,13 +76,18 @@ namespace Il2CppInspector
public uint LoaderFlags; public uint LoaderFlags;
public uint NumberOfRvaAndSizes; public uint NumberOfRvaAndSizes;
[ArrayLength(FieldName = "NumberOfRvaAndSizes")] [ArrayLength(FieldName = "NumberOfRvaAndSizes")]
public RvaEntry[] DataDirectory; public RvaEntry[] f_DataDirectory;
} }
// _IMAGE_OPTIONAL_HEADER64 // _IMAGE_OPTIONAL_HEADER64
internal class PEOptHeader64 internal class PEOptHeader64 : IPEOptHeader
{ {
public ushort Magic; public PE ExpectedMagic => PE.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
public ushort Magic => f_Magic;
public ulong ImageBase => f_ImageBase;
public RvaEntry[] DataDirectory => f_DataDirectory;
public ushort f_Magic;
public byte MajorLinkerVersion; public byte MajorLinkerVersion;
public byte MinorLinkerVersion; public byte MinorLinkerVersion;
public uint SizeOfCode; public uint SizeOfCode;
@@ -71,7 +95,7 @@ namespace Il2CppInspector
public uint SizeOfUninitializedData; public uint SizeOfUninitializedData;
public uint AddressOfEntryPoint; public uint AddressOfEntryPoint;
public uint BaseOfCode; public uint BaseOfCode;
public ulong ImageBase; public ulong f_ImageBase;
public uint SectionAlignment; public uint SectionAlignment;
public uint FileAlignment; public uint FileAlignment;
public ushort MajorOSVersion; public ushort MajorOSVersion;
@@ -93,7 +117,7 @@ namespace Il2CppInspector
public uint LoaderFlags; public uint LoaderFlags;
public uint NumberOfRvaAndSizes; public uint NumberOfRvaAndSizes;
[ArrayLength(FieldName = "NumberOfRvaAndSizes")] [ArrayLength(FieldName = "NumberOfRvaAndSizes")]
public RvaEntry[] DataDirectory; public RvaEntry[] f_DataDirectory;
} }
internal class RvaEntry internal class RvaEntry

View File

@@ -13,13 +13,13 @@ namespace Il2CppInspector
internal class PEReader : FileFormatReader<PEReader> internal class PEReader : FileFormatReader<PEReader>
{ {
private COFFHeader coff; private COFFHeader coff;
private PEOptHeader32 pe; private IPEOptHeader pe;
private PESection[] sections; private PESection[] sections;
private uint pFuncTable; private uint pFuncTable;
public PEReader(Stream stream) : base(stream) {} public PEReader(Stream stream) : base(stream) {}
public override string Format => "PE"; public override string Format => pe is PEOptHeader32 ? "PE32" : "PE32+";
public override string Arch => coff.Machine switch { public override string Arch => coff.Machine switch {
0x8664 => "x64", // IMAGE_FILE_MACHINE_AMD64 0x8664 => "x64", // IMAGE_FILE_MACHINE_AMD64
@@ -34,7 +34,7 @@ namespace Il2CppInspector
// IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20B // IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20B
// IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10B // IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10B
// Could also use coff.Characteristics (IMAGE_FILE_32BIT_MACHINE) or coff.Machine // Could also use coff.Characteristics (IMAGE_FILE_32BIT_MACHINE) or coff.Machine
public override int Bits => pe.Magic == 0x20B ? 64 : 32; public override int Bits => (PE) pe.Magic == PE.IMAGE_NT_OPTIONAL_HDR64_MAGIC ? 64 : 32;
protected override bool Init() { protected override bool Init() {
// Check for MZ signature "MZ" // Check for MZ signature "MZ"
@@ -52,15 +52,20 @@ namespace Il2CppInspector
coff = ReadObject<COFFHeader>(); coff = ReadObject<COFFHeader>();
// Ensure presence of PE Optional header // Ensure presence of PE Optional header
// Size will always be 0x60 + (0x10 ' 0x8) for 16 RVA entries @ 8 bytes each // Size will always be 0x60 (32-bit) or 0x70 (64-bit) + (0x10 ' 0x8) for 16 RVA entries @ 8 bytes each
if (coff.SizeOfOptionalHeader != 0xE0) if (!((coff.SizeOfOptionalHeader == 0xE0 ? 32 :
coff.SizeOfOptionalHeader == 0xF0 ? (int?) 64 : null) is var likelyWordSize))
return false; return false;
// Read PE optional header // Read PE optional header
pe = ReadObject<PEOptHeader32>(); pe = likelyWordSize switch {
32 => ReadObject<PEOptHeader32>(),
64 => ReadObject<PEOptHeader64>(),
_ => null
};
// Ensure IMAGE_NT_OPTIONAL_HDR32_MAGIC (32-bit) // Confirm architecture magic number matches expected word size
if (pe.Magic != 0x10B) if ((PE) pe.Magic != pe.ExpectedMagic)
return false; return false;
// Get IAT // Get IAT