Re-factor Metadata and file format code
This commit is contained in:
93
Il2CppInspector/FileFormatReaders/ElfReader.cs
Normal file
93
Il2CppInspector/FileFormatReaders/ElfReader.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright 2017 Perfare - https://github.com/Perfare/Il2CppDumper
|
||||
Copyright 2017 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
internal class ElfReader : FileFormatReader<ElfReader>
|
||||
{
|
||||
private program_header_table[] program_table_element;
|
||||
private elf_header elf_header;
|
||||
|
||||
public ElfReader(Stream stream) : base(stream) { }
|
||||
|
||||
public override string Arch {
|
||||
get {
|
||||
switch (elf_header.e_machine) {
|
||||
case 0x03:
|
||||
return "x86";
|
||||
case 0x28:
|
||||
return "ARM";
|
||||
default:
|
||||
return "Unsupported";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool Init() {
|
||||
elf_header = ReadObject<elf_header>();
|
||||
|
||||
if (elf_header.m_dwFormat != 0x464c457f) {
|
||||
// Not an ELF file
|
||||
return false;
|
||||
}
|
||||
if (elf_header.m_arch == 2)//64
|
||||
{
|
||||
// 64-bit not supported
|
||||
return false;
|
||||
}
|
||||
program_table_element = ReadArray<program_header_table>(elf_header.e_phoff, elf_header.e_phnum);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override uint[] GetSearchLocations() {
|
||||
// Find dynamic section
|
||||
var dynamic = new elf_32_shdr();
|
||||
var PT_DYNAMIC = program_table_element.First(x => x.p_type == 2u);
|
||||
dynamic.sh_offset = PT_DYNAMIC.p_offset;
|
||||
dynamic.sh_size = PT_DYNAMIC.p_filesz;
|
||||
|
||||
// We need GOT, INIT_ARRAY and INIT_ARRAYSZ
|
||||
uint _GLOBAL_OFFSET_TABLE_ = 0;
|
||||
var init_array = new elf_32_shdr();
|
||||
Position = dynamic.sh_offset;
|
||||
var dynamicend = dynamic.sh_offset + dynamic.sh_size;
|
||||
while (Position < dynamicend) {
|
||||
var tag = ReadInt32();
|
||||
if (tag == 3) //DT_PLTGOT
|
||||
{
|
||||
_GLOBAL_OFFSET_TABLE_ = ReadUInt32();
|
||||
continue;
|
||||
}
|
||||
else if (tag == 25) //DT_INIT_ARRAY
|
||||
{
|
||||
init_array.sh_offset = MapVATR(ReadUInt32());
|
||||
continue;
|
||||
}
|
||||
else if (tag == 27) //DT_INIT_ARRAYSZ
|
||||
{
|
||||
init_array.sh_size = ReadUInt32();
|
||||
continue;
|
||||
}
|
||||
Position += 4;
|
||||
}
|
||||
if (_GLOBAL_OFFSET_TABLE_ == 0)
|
||||
throw new InvalidOperationException("Unable to get GLOBAL_OFFSET_TABLE from PT_DYNAMIC");
|
||||
GlobalOffset = _GLOBAL_OFFSET_TABLE_;
|
||||
return ReadArray<uint>(init_array.sh_offset, (int) init_array.sh_size / 4);
|
||||
}
|
||||
|
||||
public override uint MapVATR(uint uiAddr)
|
||||
{
|
||||
var program_header_table = program_table_element.First(x => uiAddr >= x.p_vaddr && uiAddr <= (x.p_vaddr + x.p_memsz));
|
||||
return uiAddr - (program_header_table.p_vaddr - program_header_table.p_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
89
Il2CppInspector/FileFormatReaders/FormatLayouts/Elf.cs
Normal file
89
Il2CppInspector/FileFormatReaders/FormatLayouts/Elf.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright 2017 Perfare - https://github.com/Perfare/Il2CppDumper
|
||||
Copyright 2017 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
using NoisyCowStudios.Bin2Object;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
internal class elf_header
|
||||
{
|
||||
// 0x7f followed by ELF in ascii
|
||||
public uint m_dwFormat;
|
||||
|
||||
// 1 - 32 bit
|
||||
// 2 - 64 bit
|
||||
public byte m_arch;
|
||||
|
||||
// 1 - little endian
|
||||
// 2 - big endian
|
||||
public byte m_endian;
|
||||
|
||||
// 1 is original elf format
|
||||
public byte m_version;
|
||||
|
||||
// set based on OS, refer to OSABI enum
|
||||
public byte m_osabi;
|
||||
|
||||
// refer to elf documentation
|
||||
public byte m_osabi_ver;
|
||||
|
||||
// unused
|
||||
[ArrayLength(FixedSize=7)]
|
||||
public byte[] e_pad;//byte[7]
|
||||
|
||||
// 1 - relocatable
|
||||
// 2 - executable
|
||||
// 3 - shared
|
||||
// 4 - core
|
||||
public ushort e_type;
|
||||
|
||||
// refer to isa enum
|
||||
public ushort e_machine;
|
||||
|
||||
public uint e_version;
|
||||
|
||||
public uint e_entry;
|
||||
public uint e_phoff;
|
||||
public uint e_shoff;
|
||||
public uint e_flags;
|
||||
public ushort e_ehsize;
|
||||
public ushort e_phentsize;
|
||||
public ushort e_phnum;
|
||||
public ushort e_shentsize;
|
||||
public ushort e_shnum;
|
||||
public ushort e_shtrndx;
|
||||
}
|
||||
|
||||
internal class program_header_table
|
||||
{
|
||||
public uint p_type;
|
||||
public uint p_offset;
|
||||
public uint p_vaddr;
|
||||
public uint p_paddr;
|
||||
public uint p_filesz;
|
||||
public uint p_memsz;
|
||||
public uint p_flags;
|
||||
public uint p_align;
|
||||
//public byte[] p_data;忽略
|
||||
}
|
||||
|
||||
internal class elf_32_shdr
|
||||
{
|
||||
public uint sh_name;
|
||||
public uint sh_type;
|
||||
public uint sh_flags;
|
||||
public uint sh_addr;
|
||||
public uint sh_offset;
|
||||
public uint sh_size;
|
||||
public uint sh_link;
|
||||
public uint sh_info;
|
||||
public uint sh_addralign;
|
||||
public uint sh_entsize;
|
||||
}
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
123
Il2CppInspector/FileFormatReaders/FormatLayouts/MachO.cs
Normal file
123
Il2CppInspector/FileFormatReaders/FormatLayouts/MachO.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright 2017 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using NoisyCowStudios.Bin2Object;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
// Structures and enums: https://opensource.apple.com/source/cctools/cctools-870/include/mach-o/loader.h
|
||||
|
||||
public enum MachO : uint
|
||||
{
|
||||
MH_MAGIC = 0xfeedface,
|
||||
MH_CIGAM = 0xcefaedfe,
|
||||
MH_MAGIC_64 = 0xfeedfacf,
|
||||
MH_CIGAM_64 = 0xcffaedfe,
|
||||
|
||||
MH_EXECUTE = 0x2,
|
||||
|
||||
LC_SEGMENT = 0x1,
|
||||
LC_SEGMENT_64 = 0x19,
|
||||
LC_FUNCTION_STARTS = 0x26,
|
||||
|
||||
CPU_TYPE_X86 = 7,
|
||||
CPU_TYPE_X86_64 = 0x01000000 + CPU_TYPE_X86,
|
||||
CPU_TYPE_ARM = 12,
|
||||
CPU_TYPE_ARM64 = 0x01000000 + CPU_TYPE_ARM
|
||||
}
|
||||
|
||||
internal class MachOHeader
|
||||
{
|
||||
public uint Magic;
|
||||
public uint CPUType;
|
||||
public uint CPUSubType;
|
||||
public uint FileType;
|
||||
public uint NumCommands;
|
||||
public uint SizeOfCommands;
|
||||
public uint Flags;
|
||||
// 64-bit header has an extra 32-bit Reserved field
|
||||
}
|
||||
|
||||
internal class MachOLoadCommand
|
||||
{
|
||||
public uint Command;
|
||||
public uint Size;
|
||||
}
|
||||
|
||||
internal class MachOSegmentCommand
|
||||
{
|
||||
// MachOLoadCommand
|
||||
[String(FixedSize = 16)]
|
||||
public string Name;
|
||||
public uint VirtualAddress;
|
||||
public uint VirtualSize;
|
||||
public uint ImageOffset;
|
||||
public uint ImageSize;
|
||||
public uint VMMaxProt;
|
||||
public uint VMInitProt;
|
||||
public uint NumSections;
|
||||
public uint Flags;
|
||||
}
|
||||
|
||||
internal class MachOSegmentCommand64
|
||||
{
|
||||
// MachOLoadCommand
|
||||
[String(FixedSize = 16)]
|
||||
public string Name;
|
||||
public ulong VirtualAddress;
|
||||
public ulong VirtualSize;
|
||||
public ulong ImageOffset;
|
||||
public ulong ImageSize;
|
||||
public uint VMMaxProt;
|
||||
public uint VMInitProt;
|
||||
public uint NumSections;
|
||||
public uint Flags;
|
||||
}
|
||||
|
||||
internal class MachOSection
|
||||
{
|
||||
[String(FixedSize = 16)]
|
||||
public string Name;
|
||||
[String(FixedSize = 16)]
|
||||
public string SegmentName;
|
||||
public uint Address;
|
||||
public uint Size;
|
||||
public uint ImageOffset;
|
||||
public uint Align;
|
||||
public uint ImageRelocOffset;
|
||||
public uint NumRelocEntries;
|
||||
public uint Flags;
|
||||
public uint Reserved1;
|
||||
public uint Reserved2;
|
||||
}
|
||||
|
||||
internal class MachOSection64
|
||||
{
|
||||
[String(FixedSize = 16)]
|
||||
public string Name;
|
||||
[String(FixedSize = 16)]
|
||||
public string SegmentName;
|
||||
public ulong Address;
|
||||
public ulong Size;
|
||||
public uint ImageOffset;
|
||||
public uint Align;
|
||||
public uint ImageRelocOffset;
|
||||
public uint NumRelocEntries;
|
||||
public uint Flags;
|
||||
public uint Reserved1;
|
||||
public uint Reserved2;
|
||||
public uint Reserved3;
|
||||
}
|
||||
|
||||
internal class MachOLinkEditDataCommand
|
||||
{
|
||||
// MachOLoadCommand
|
||||
public uint Offset;
|
||||
public uint Size;
|
||||
}
|
||||
}
|
||||
78
Il2CppInspector/FileFormatReaders/FormatLayouts/PE.cs
Normal file
78
Il2CppInspector/FileFormatReaders/FormatLayouts/PE.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright 2017 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
using NoisyCowStudios.Bin2Object;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
internal class COFFHeader
|
||||
{
|
||||
public ushort Machine;
|
||||
public ushort NumberOfSections;
|
||||
public uint TimeDateStamp;
|
||||
public uint PointerToSymbolTable;
|
||||
public uint NumberOfSymbols;
|
||||
public ushort SizeOfOptionalHeader;
|
||||
public ushort Characteristics;
|
||||
}
|
||||
|
||||
internal class PEOptHeader
|
||||
{
|
||||
public ushort signature;
|
||||
public byte MajorLinkerVersion;
|
||||
public byte MinorLinkerVersion;
|
||||
public uint SizeOfCode;
|
||||
public uint SizeOfInitializedData;
|
||||
public uint SizeOfUninitializedData;
|
||||
public uint AddressOfEntryPoint;
|
||||
public uint BaseOfCode;
|
||||
public uint BaseOfData;
|
||||
public uint ImageBase;
|
||||
public uint SectionAlignment;
|
||||
public uint FileAlignment;
|
||||
public ushort MajorOSVersion;
|
||||
public ushort MinorOSVersion;
|
||||
public ushort MajorImageVersion;
|
||||
public ushort MinorImageVersion;
|
||||
public ushort MajorSubsystemVersion;
|
||||
public ushort MinorSubsystemVersion;
|
||||
public uint Win32VersionValue;
|
||||
public uint SizeOfImage;
|
||||
public uint SizeOfHeaders;
|
||||
public uint Checksum;
|
||||
public ushort Subsystem;
|
||||
public ushort DLLCharacteristics;
|
||||
public uint SizeOfStackReserve;
|
||||
public uint SizeOfStackCommit;
|
||||
public uint SizeOfHeapReserve;
|
||||
public uint SizeOfHeapCommit;
|
||||
public uint LoaderFlags;
|
||||
public uint NumberOfRvaAndSizes;
|
||||
[ArrayLength(FieldName = "NumberOfRvaAndSizes")]
|
||||
public RvaEntry[] DataDirectory;
|
||||
}
|
||||
|
||||
internal class RvaEntry
|
||||
{
|
||||
public uint VirtualAddress;
|
||||
public uint Size;
|
||||
}
|
||||
|
||||
internal class PESection
|
||||
{
|
||||
[String(FixedSize=8)]
|
||||
public string Name;
|
||||
public uint SizeMemory;
|
||||
public uint BaseMemory; // RVA
|
||||
public uint SizeImage; // Size in file
|
||||
public uint BaseImage; // Base address in file
|
||||
[ArrayLength(FixedSize=12)]
|
||||
public byte[] Reserved;
|
||||
public uint Flags;
|
||||
}
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
36
Il2CppInspector/FileFormatReaders/FormatLayouts/UB.cs
Normal file
36
Il2CppInspector/FileFormatReaders/FormatLayouts/UB.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright 2017 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using NoisyCowStudios.Bin2Object;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
// Structures and enums: https://cocoaintheshell.whine.fr/2009/07/universal-binary-mach-o-format/
|
||||
|
||||
public enum UB : uint
|
||||
{
|
||||
FAT_MAGIC = 0xcafebabe
|
||||
}
|
||||
|
||||
// Big-endian
|
||||
internal class FatHeader
|
||||
{
|
||||
public uint Magic;
|
||||
public uint NumArch;
|
||||
}
|
||||
|
||||
// Big-endian
|
||||
internal class FatArch
|
||||
{
|
||||
public uint CPUType;
|
||||
public uint CPUSubType;
|
||||
public uint Offset;
|
||||
public uint Size;
|
||||
public uint Align;
|
||||
}
|
||||
}
|
||||
157
Il2CppInspector/FileFormatReaders/MachOReader.cs
Normal file
157
Il2CppInspector/FileFormatReaders/MachOReader.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Copyright 2017 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NoisyCowStudios.Bin2Object;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
internal class MachOReader : FileFormatReader<MachOReader>
|
||||
{
|
||||
private MachOHeader header;
|
||||
private uint pFuncTable;
|
||||
private uint sFuncTable;
|
||||
private bool is64;
|
||||
private List<MachOSection> sections = new List<MachOSection>();
|
||||
private List<MachOSection64> sections64 = new List<MachOSection64>();
|
||||
|
||||
public MachOReader(Stream stream) : base(stream) { }
|
||||
|
||||
public override string Arch {
|
||||
get {
|
||||
switch ((MachO)header.CPUType) {
|
||||
case MachO.CPU_TYPE_ARM:
|
||||
case MachO.CPU_TYPE_ARM64:
|
||||
return "ARM";
|
||||
case MachO.CPU_TYPE_X86:
|
||||
case MachO.CPU_TYPE_X86_64:
|
||||
return "x86";
|
||||
default:
|
||||
return "Unsupported";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool Init() {
|
||||
// Detect endianness - default is little-endianness
|
||||
MachO magic = (MachO)ReadUInt32();
|
||||
if (magic == MachO.MH_CIGAM || magic == MachO.MH_CIGAM_64) {
|
||||
Endianness = Endianness.Big;
|
||||
}
|
||||
else if (magic != MachO.MH_MAGIC && magic != MachO.MH_MAGIC_64) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Console.WriteLine("Endianness: {0}", Endianness);
|
||||
|
||||
Position -= sizeof(uint);
|
||||
header = ReadObject<MachOHeader>();
|
||||
|
||||
// 64-bit files have an extra 4 bytes after the header
|
||||
is64 = false;
|
||||
if (magic == MachO.MH_MAGIC_64) {
|
||||
is64 = true;
|
||||
ReadUInt32();
|
||||
}
|
||||
Console.WriteLine("Architecture: {0}-bit", is64 ? 64 : 32);
|
||||
|
||||
// Must be executable file
|
||||
if ((MachO) header.FileType != MachO.MH_EXECUTE)
|
||||
return false;
|
||||
|
||||
Console.WriteLine("CPU Type: " + (MachO)header.CPUType);
|
||||
|
||||
MachOLinkEditDataCommand functionStarts = null;
|
||||
|
||||
for (var c = 0; c < header.NumCommands; c++) {
|
||||
var startPos = Position;
|
||||
var loadCommand = ReadObject<MachOLoadCommand>();
|
||||
|
||||
if ((MachO)loadCommand.Command == MachO.LC_SEGMENT) {
|
||||
var segment = ReadObject<MachOSegmentCommand>();
|
||||
if (segment.Name == "__TEXT" || segment.Name == "__DATA") {
|
||||
for (int s = 0; s < segment.NumSections; s++) {
|
||||
var section = ReadObject<MachOSection>();
|
||||
sections.Add(section);
|
||||
if (section.Name == "__text")
|
||||
GlobalOffset = section.Address - section.ImageOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((MachO)loadCommand.Command == MachO.LC_SEGMENT_64) {
|
||||
var segment = ReadObject<MachOSegmentCommand64>();
|
||||
if (segment.Name == "__TEXT" || segment.Name == "__DATA") {
|
||||
for (int s = 0; s < segment.NumSections; s++) {
|
||||
var section64 = ReadObject<MachOSection64>();
|
||||
sections64.Add(section64);
|
||||
if (section64.Name == "__text")
|
||||
GlobalOffset = (uint)section64.Address - section64.ImageOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((MachO)loadCommand.Command == MachO.LC_FUNCTION_STARTS) {
|
||||
functionStarts = ReadObject<MachOLinkEditDataCommand>();
|
||||
}
|
||||
|
||||
// There might be other data after the load command so always use the specified total size to step forwards
|
||||
Position = startPos + loadCommand.Size;
|
||||
}
|
||||
|
||||
// Must find LC_FUNCTION_STARTS load command
|
||||
if (functionStarts == null)
|
||||
return false;
|
||||
|
||||
pFuncTable = functionStarts.Offset;
|
||||
sFuncTable = functionStarts.Size;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override uint[] GetSearchLocations() {
|
||||
Position = pFuncTable;
|
||||
var functionPointers = new List<uint>();
|
||||
|
||||
// Decompress ELB128 list of function offsets
|
||||
// https://en.wikipedia.org/wiki/LEB128
|
||||
uint previous = 0;
|
||||
while (Position < pFuncTable + sFuncTable) {
|
||||
uint result = 0;
|
||||
int shift = 0;
|
||||
byte b;
|
||||
do {
|
||||
b = ReadByte();
|
||||
result |= (uint)((b & 0x7f) << shift);
|
||||
shift += 7;
|
||||
} while ((b & 0x80) != 0);
|
||||
if (result > 0) {
|
||||
if (previous == 0)
|
||||
result &= 0xffffffc;
|
||||
previous += result;
|
||||
functionPointers.Add(previous);
|
||||
}
|
||||
}
|
||||
return functionPointers.ToArray();
|
||||
}
|
||||
|
||||
public override void FinalizeInit(Il2CppReader il2cpp) {
|
||||
// Mach-O function pointers have an annoying habit of being 1-off
|
||||
il2cpp.PtrCodeRegistration.methodPointers =
|
||||
il2cpp.PtrCodeRegistration.methodPointers.Select(x => x - 1).ToArray();
|
||||
}
|
||||
|
||||
public override uint MapVATR(uint uiAddr) {
|
||||
if (!is64) {
|
||||
var section = sections.First(x => uiAddr >= x.Address && uiAddr <= (x.Address + x.Size));
|
||||
return uiAddr - (section.Address - section.ImageOffset);
|
||||
}
|
||||
var section64 = sections64.First(x => uiAddr >= x.Address && uiAddr <= (x.Address + x.Size));
|
||||
return uiAddr - ((uint)section64.Address - section64.ImageOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
101
Il2CppInspector/FileFormatReaders/PEReader.cs
Normal file
101
Il2CppInspector/FileFormatReaders/PEReader.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright 2017 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
internal class PEReader : FileFormatReader<PEReader>
|
||||
{
|
||||
private COFFHeader coff;
|
||||
private PEOptHeader pe;
|
||||
private PESection[] sections;
|
||||
private uint pFuncTable;
|
||||
|
||||
public PEReader(Stream stream) : base(stream) {}
|
||||
|
||||
public override string Arch {
|
||||
get {
|
||||
switch (coff.Machine) {
|
||||
case 0x14C:
|
||||
return "x86";
|
||||
case 0x1C0: // ARMv7
|
||||
case 0x1C4: // ARMv7 Thumb (T1)
|
||||
return "ARM";
|
||||
default:
|
||||
return "Unsupported";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool Init() {
|
||||
// Check for MZ signature "MZ"
|
||||
if (ReadUInt16() != 0x5A4D)
|
||||
return false;
|
||||
|
||||
// Get offset to PE header from DOS header
|
||||
Position = 0x3C;
|
||||
Position = ReadUInt32();
|
||||
|
||||
// Check PE signature "PE\0\0"
|
||||
if (ReadUInt32() != 0x00004550)
|
||||
return false;
|
||||
|
||||
// Read COFF Header
|
||||
coff = ReadObject<COFFHeader>();
|
||||
|
||||
// Ensure presence of PE Optional header
|
||||
// Size will always be 0x60 + (0x10 ' 0x8) for 16 RVA entries @ 8 bytes each
|
||||
if (coff.SizeOfOptionalHeader != 0xE0)
|
||||
return false;
|
||||
|
||||
// Read PE optional header
|
||||
pe = ReadObject<PEOptHeader>();
|
||||
|
||||
// Ensure IMAGE_NT_OPTIONAL_HDR32_MAGIC (32-bit)
|
||||
if (pe.signature != 0x10B)
|
||||
return false;
|
||||
|
||||
// Get IAT
|
||||
var IATStart = pe.DataDirectory[12].VirtualAddress;
|
||||
var IATSize = pe.DataDirectory[12].Size;
|
||||
|
||||
// Get sections table
|
||||
sections = ReadArray<PESection>(coff.NumberOfSections);
|
||||
|
||||
// Confirm that .rdata section begins at same place as IAT
|
||||
var rData = sections.First(x => x.Name == ".rdata");
|
||||
if (rData.BaseMemory != IATStart)
|
||||
return false;
|
||||
|
||||
// Calculate start of function pointer table
|
||||
pFuncTable = rData.BaseImage + IATSize + 8;
|
||||
GlobalOffset = pe.ImageBase;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override uint[] GetSearchLocations() {
|
||||
Position = pFuncTable;
|
||||
var addrs = new List<uint>();
|
||||
uint addr;
|
||||
while ((addr = ReadUInt32()) != 0)
|
||||
addrs.Add(MapVATR(addr) & 0xfffffffc);
|
||||
return addrs.ToArray();
|
||||
}
|
||||
|
||||
public override uint MapVATR(uint uiAddr) {
|
||||
if (uiAddr == 0)
|
||||
return 0;
|
||||
|
||||
var section = sections.First(x => uiAddr - GlobalOffset >= x.BaseMemory &&
|
||||
uiAddr - GlobalOffset < x.BaseMemory + x.SizeMemory);
|
||||
return uiAddr - section.BaseMemory - GlobalOffset + section.BaseImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
Il2CppInspector/FileFormatReaders/UBReader.cs
Normal file
47
Il2CppInspector/FileFormatReaders/UBReader.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2017 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
|
||||
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NoisyCowStudios.Bin2Object;
|
||||
|
||||
namespace Il2CppInspector
|
||||
{
|
||||
internal class UBReader : FileFormatReader<UBReader>
|
||||
{
|
||||
private FatHeader header;
|
||||
|
||||
public UBReader(Stream stream) : base(stream) { }
|
||||
|
||||
protected override bool Init() {
|
||||
// Fat headers are always big-endian regardless of architectures
|
||||
Endianness = Endianness.Big;
|
||||
|
||||
header = ReadObject<FatHeader>();
|
||||
|
||||
if ((UB) header.Magic != UB.FAT_MAGIC)
|
||||
return false;
|
||||
|
||||
NumImages = header.NumArch;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override IFileFormatReader this[uint index] {
|
||||
get {
|
||||
Position = 0x8 + 0x14 * index; // sizeof(FatHeader), sizeof(FatArch)
|
||||
Endianness = Endianness.Big;
|
||||
|
||||
var arch = ReadObject<FatArch>();
|
||||
|
||||
Position = arch.Offset;
|
||||
Endianness = Endianness.Little;
|
||||
return MachOReader.Load(new MemoryStream(ReadBytes((int)arch.Size)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user