PE32+: Initial support
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user