diff --git a/Il2CppInspector.Common/FileFormatReaders/FormatLayouts/MachO.cs b/Il2CppInspector.Common/FileFormatReaders/FormatLayouts/MachO.cs index 8df3d8c..143c467 100644 --- a/Il2CppInspector.Common/FileFormatReaders/FormatLayouts/MachO.cs +++ b/Il2CppInspector.Common/FileFormatReaders/FormatLayouts/MachO.cs @@ -25,6 +25,8 @@ namespace Il2CppInspector LC_DYSYMTAB = 0xb, LC_SEGMENT_64 = 0x19, LC_ENCRYPTION_INFO = 0x21, + LC_DYLD_INFO = 0x22, + LC_DYLD_INFO_ONLY = 0x80000022, LC_FUNCTION_STARTS = 0x26, LC_ENCRYPTION_INFO_64 = 0x2C, @@ -90,6 +92,20 @@ namespace Il2CppInspector public uint Size; } + internal class MachODyldInfoCommand + { + public uint RebaseOffset; + public uint RebaseSize; + public uint BindOffset; + public uint BindSize; + public uint WeakBindOffset; + public uint WeakBindSize; + public uint LazyBindOffset; + public uint LazyBindSize; + public uint ExportOffset; + public uint ExportSize; + } + internal class MachOSymtabCommand { public uint SymOffset; diff --git a/Il2CppInspector.Common/FileFormatReaders/MachOReader.cs b/Il2CppInspector.Common/FileFormatReaders/MachOReader.cs index 6b3a85f..3bb52c0 100644 --- a/Il2CppInspector.Common/FileFormatReaders/MachOReader.cs +++ b/Il2CppInspector.Common/FileFormatReaders/MachOReader.cs @@ -1,5 +1,5 @@ /* - Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com + Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty All rights reserved. */ @@ -60,6 +60,8 @@ namespace Il2CppInspector private MachOSection funcTab; private MachOSymtabCommand symTab; + private List exports = new List(); + protected MachOReader(Stream stream) : base(stream) { } public override string Format => "Mach-O " + (Bits == 32 ? "32-bit" : "64-bit"); @@ -103,6 +105,8 @@ namespace Il2CppInspector // Segments case MachO cmd when cmd == lc_Segment: var segment = ReadObject>(); + + // Code and data if (segment.Name == "__TEXT" || segment.Name == "__DATA") { for (int s = 0; s < segment.NumSections; s++) { var section = ReadObject>(); @@ -128,6 +132,14 @@ namespace Il2CppInspector // TODO: Implement Mach-O dynamic symbol table break; + // Compressed dyld information + case MachO.LC_DYLD_INFO: + case MachO.LC_DYLD_INFO_ONLY: + var dyld = ReadObject(); + + loadExportTrie(dyld.ExportOffset); + break; + // Encryption check // If cryptid == 1, this binary is encrypted with FairPlay DRM case MachO.LC_ENCRYPTION_INFO: @@ -159,6 +171,51 @@ namespace Il2CppInspector return true; } + // Handle export trie + private void loadExportTrie(uint trieOffset, uint nodeOffset = 0, string partialSymbol = "") { + Position = trieOffset + nodeOffset; + + var size = ULEB128.Decode(this); + + // Terminal information + if (size != 0) { + var flags = ReadByte(); + var symbolKind = flags & 0x03; + var symbolType = (flags >> 2) & 0x03; + + // 0 = regular, 1 = weak, 2 = re-export, 3 = stub + switch (symbolType) { + case 0: + var address = ULEB128.Decode(this); + exports.Add(new Export {Name = partialSymbol, VirtualAddress = GlobalOffset + address}); + break; + case 1: + var weakAddress = ULEB128.Decode(this); + exports.Add(new Export {Name = partialSymbol, VirtualAddress = GlobalOffset + weakAddress}); + break; + case 2: + var ordinal = ULEB128.Decode(this); + var name = ReadNullTerminatedString(); + break; + case 3: + var stubOffset = ULEB128.Decode(this); + var resolverOffset = ULEB128.Decode(this); + break; + } + } + + var branchCount = ReadByte(); + + for (int branch = 0; branch < branchCount; branch++) { + var prefix = ReadNullTerminatedString(); + var childNodeOffset = (uint) ULEB128.Decode(this); + + var currentPosition = Position; + loadExportTrie(trieOffset, childNodeOffset, partialSymbol + prefix); + Position = currentPosition; + } + } + public override uint[] GetFunctionTable() => ReadArray(funcTab.ImageOffset, conv.Int(funcTab.Size) / (Bits / 8)).Select(x => MapVATR(conv.ULong(x)) & 0xffff_fffe).ToArray(); public override Dictionary GetSymbolTable() { @@ -180,7 +237,10 @@ namespace Il2CppInspector if (value != 0) symbols.TryAdd(name, value); } + return symbols; } + + public override IEnumerable GetExports() => exports; } } diff --git a/Il2CppInspector.Common/ULEB128.cs b/Il2CppInspector.Common/ULEB128.cs new file mode 100644 index 0000000..2d0da25 --- /dev/null +++ b/Il2CppInspector.Common/ULEB128.cs @@ -0,0 +1,23 @@ +/* + Copyright 2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty + + All rights reserved. +*/ + +using System.IO; + +namespace Il2CppInspector +{ + internal class ULEB128 + { + public static ulong Decode(IFileFormatReader next) { + ulong uleb = 0; + byte b = 0x80; + for (var shift = 0; b >> 7 == 1; shift += 7) { + b = next.ReadByte(); + uleb |= (ulong) (b & 0x7f) << shift; + } + return uleb; + } + } +}