From 0e3b80b502dc9785d85f8675a367cee766724e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leo=20J=C3=A4=C3=A4skel=C3=A4inen?= Date: Mon, 14 Sep 2020 11:07:24 +0300 Subject: [PATCH] Support AAB file format --- .../FileFormatReaders/AABReader.cs | 73 +++++++++++++++++++ .../IL2CPP/Il2CppInspector.cs | 15 +++- 2 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 Il2CppInspector.Common/FileFormatReaders/AABReader.cs diff --git a/Il2CppInspector.Common/FileFormatReaders/AABReader.cs b/Il2CppInspector.Common/FileFormatReaders/AABReader.cs new file mode 100644 index 0000000..07d0a45 --- /dev/null +++ b/Il2CppInspector.Common/FileFormatReaders/AABReader.cs @@ -0,0 +1,73 @@ +/* + Copyright 2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty + + All rights reserved. +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; + +namespace Il2CppInspector +{ + // This is a wrapper for multiple binary files of different architectures within a single AAB + internal class AABReader : FileFormatReader + { + private ZipArchive zip; + private ZipArchiveEntry[] binaryFiles; + + public AABReader(Stream stream) : base(stream) { } + + protected override bool Init() { + + // Check if it's a zip file first because ZipFile.OpenRead is extremely slow if it isn't + // 0x04034B50 = magic file header + // 0x02014B50 = central directory file header (will appear if we merged a split AAB in memory) + var magic = ReadUInt32(); + if (magic != 0x04034B50 && magic != 0x02014B50) + return false; + + try { + zip = new ZipArchive(BaseStream); + + // Get list of binary files + binaryFiles = zip.Entries.Where(f => f.FullName.StartsWith("base/lib/") && f.Name == "libil2cpp.so").ToArray(); + + // This package doesn't contain an IL2CPP binary + if (!binaryFiles.Any()) + return false; + } + + // Not an archive + catch (InvalidDataException) { + return false; + } + + NumImages = (uint) binaryFiles.Count(); + return true; + } + + public override IFileFormatReader this[uint index] { + get { + Console.WriteLine($"Extracting binary from {binaryFiles[index].FullName}"); + IFileFormatReader loaded = null; + + // ZipArchiveEntry does not support seeking so we have to close and re-open for each possible load format + var binary = binaryFiles[index].Open(); + loaded = ElfReader32.Load(binary, OnStatusUpdate); + binary.Close(); + + if (loaded != null) + return loaded; + + binary = binaryFiles[index].Open(); + loaded = ElfReader64.Load(binary, OnStatusUpdate); + binary.Close(); + + return loaded; + } + } + } +} diff --git a/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs b/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs index bcc3285..c79cd53 100644 --- a/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs +++ b/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs @@ -147,7 +147,7 @@ namespace Il2CppInspector usages.TryAdd(metadataUsagePair.destinationindex, MetadataUsage.FromEncodedIndex(this, metadataUsagePair.encodedSourceIndex)); } } - + // Metadata usages (addresses) // Unfortunately the value supplied in MetadataRegistration.matadataUsagesCount seems to be incorrect, // so we have to calculate the correct number of usages above before reading the usage address list from the binary @@ -393,6 +393,7 @@ namespace Il2CppInspector } MemoryStream metadataMemoryStream = null, binaryMemoryStream = null; + ZipArchiveEntry androidAAB = null; ZipArchiveEntry ipaBinaryFolder = null; var binaryFiles = new List(); @@ -412,6 +413,14 @@ namespace Il2CppInspector var metadataFile = zip.Entries.FirstOrDefault(f => f.FullName == "assets/bin/Data/Managed/Metadata/global-metadata.dat"); binaryFiles.AddRange(zip.Entries.Where(f => f.FullName.StartsWith("lib/") && f.Name == "libil2cpp.so")); + // Check for Android AAB + androidAAB = zip.Entries.FirstOrDefault(f => f.FullName == "base/resources.pb"); + + if (androidAAB != null) { + metadataFile = zip.Entries.FirstOrDefault(f => f.FullName == "base/assets/bin/Data/Managed/Metadata/global-metadata.dat"); + binaryFiles.AddRange(zip.Entries.Where(f => f.FullName.StartsWith("base/lib/") && f.Name == "libil2cpp.so")); + } + // Check for iOS IPA ipaBinaryFolder = zip.Entries.FirstOrDefault(f => f.FullName.StartsWith("Payload/") && f.FullName.EndsWith(".app/") && f.FullName.Count(x => x == '/') == 2); @@ -452,8 +461,8 @@ namespace Il2CppInspector binaryMemoryStream.Position = 0; } - // Single APKs may have one or more binaries, one per architecture - // We'll read the entire APK and load those via APKReader + // AABs or single APKs may have one or more binaries, one per architecture + // We'll read the entire AAB/APK and load those via AABReader/APKReader else if (packageFiles.Count() == 1) { binaryMemoryStream = new MemoryStream(File.ReadAllBytes(packageFiles.First())); }