Add progress callbacks to Il2CppBinary and Il2CppInspector

This commit is contained in:
Katy Coe
2020-12-06 17:33:07 +01:00
parent 440ec60404
commit 515365e9e9
8 changed files with 41 additions and 27 deletions

View File

@@ -13,9 +13,10 @@ namespace Il2CppInspector
{ {
internal class Il2CppBinaryARM : Il2CppBinary internal class Il2CppBinaryARM : Il2CppBinary
{ {
public Il2CppBinaryARM(IFileFormatReader stream) : base(stream) { } public Il2CppBinaryARM(IFileFormatReader stream, EventHandler<string> statusCallback = null) : base(stream, statusCallback) { }
public Il2CppBinaryARM(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration) : base(stream, codeRegistration, metadataRegistration) { } public Il2CppBinaryARM(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration, EventHandler<string> statusCallback = null)
: base(stream, codeRegistration, metadataRegistration, statusCallback) { }
// ARMv7-A Architecture Reference Manual: https://static.docs.arm.com/ddi0406/c/DDI0406C_C_arm_architecture_reference_manual.pdf // ARMv7-A Architecture Reference Manual: https://static.docs.arm.com/ddi0406/c/DDI0406C_C_arm_architecture_reference_manual.pdf

View File

@@ -12,9 +12,10 @@ namespace Il2CppInspector
// A64 ISA reference: https://static.docs.arm.com/ddi0596/a/DDI_0596_ARM_a64_instruction_set_architecture.pdf // A64 ISA reference: https://static.docs.arm.com/ddi0596/a/DDI_0596_ARM_a64_instruction_set_architecture.pdf
internal class Il2CppBinaryARM64 : Il2CppBinary internal class Il2CppBinaryARM64 : Il2CppBinary
{ {
public Il2CppBinaryARM64(IFileFormatReader stream) : base(stream) { } public Il2CppBinaryARM64(IFileFormatReader stream, EventHandler<string> statusCallback = null) : base(stream, statusCallback) { }
public Il2CppBinaryARM64(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration) : base(stream, codeRegistration, metadataRegistration) { } public Il2CppBinaryARM64(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration, EventHandler<string> statusCallback = null)
: base(stream, codeRegistration, metadataRegistration, statusCallback) { }
private (uint reg, ulong page)? getAdrp(uint inst, ulong pc) { private (uint reg, ulong page)? getAdrp(uint inst, ulong pc) {
if ((inst.Bits(24, 8) & 0b_1000_1111) != 1 << 7) if ((inst.Bits(24, 8) & 0b_1000_1111) != 1 << 7)

View File

@@ -13,8 +13,10 @@ namespace Il2CppInspector
{ {
internal class Il2CppBinaryX64 : Il2CppBinary internal class Il2CppBinaryX64 : Il2CppBinary
{ {
public Il2CppBinaryX64(IFileFormatReader stream) : base(stream) { } public Il2CppBinaryX64(IFileFormatReader stream, EventHandler<string> statusCallback = null) : base(stream, statusCallback) { }
public Il2CppBinaryX64(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration) : base(stream, codeRegistration, metadataRegistration) { }
public Il2CppBinaryX64(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration, EventHandler<string> statusCallback = null)
: base(stream, codeRegistration, metadataRegistration, statusCallback) { }
// Format of 64-bit LEA: // Format of 64-bit LEA:
// 0x48/0x4C - REX prefix signifying 64-bit mode with 64-bit operand size (REX prefix bits: Volume 2A, page 2-9) (bit 2 is register bit 3) // 0x48/0x4C - REX prefix signifying 64-bit mode with 64-bit operand size (REX prefix bits: Volume 2A, page 2-9) (bit 2 is register bit 3)

View File

@@ -11,8 +11,10 @@ namespace Il2CppInspector
{ {
internal class Il2CppBinaryX86 : Il2CppBinary internal class Il2CppBinaryX86 : Il2CppBinary
{ {
public Il2CppBinaryX86(IFileFormatReader stream) : base(stream) { } public Il2CppBinaryX86(IFileFormatReader stream, EventHandler<string> statusCallback = null) : base(stream, statusCallback) { }
public Il2CppBinaryX86(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration) : base(stream, codeRegistration, metadataRegistration) { }
public Il2CppBinaryX86(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration, EventHandler<string> statusCallback = null)
: base(stream, codeRegistration, metadataRegistration, statusCallback) { }
protected override (ulong, ulong) ConsiderCode(IFileFormatReader image, uint loc) { protected override (ulong, ulong) ConsiderCode(IFileFormatReader image, uint loc) {
ulong metadata, code; ulong metadata, code;

View File

@@ -80,17 +80,22 @@ namespace Il2CppInspector
// One assembly may contain multiple modules // One assembly may contain multiple modules
public Dictionary<string, Il2CppCodeGenModule> Modules { get; private set; } public Dictionary<string, Il2CppCodeGenModule> Modules { get; private set; }
protected Il2CppBinary(IFileFormatReader stream) { private EventHandler<string> OnStatusUpdate { get; set; }
private void StatusUpdate(string status) => OnStatusUpdate?.Invoke(this, status);
protected Il2CppBinary(IFileFormatReader stream, EventHandler<string> statusCallback = null) {
Image = stream; Image = stream;
OnStatusUpdate = statusCallback;
} }
protected Il2CppBinary(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration) { protected Il2CppBinary(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration, EventHandler<string> statusCallback = null) {
Image = stream; Image = stream;
OnStatusUpdate = statusCallback;
Configure(codeRegistration, metadataRegistration); Configure(codeRegistration, metadataRegistration);
} }
// Load and initialize a binary of any supported architecture // Load and initialize a binary of any supported architecture
private static Il2CppBinary LoadImpl(IFileFormatReader stream) { private static Il2CppBinary LoadImpl(IFileFormatReader stream, EventHandler<string> statusCallback) {
// Get type from image architecture // Get type from image architecture
var type = Assembly.GetExecutingAssembly().GetType("Il2CppInspector.Il2CppBinary" + stream.Arch.ToUpper()); var type = Assembly.GetExecutingAssembly().GetType("Il2CppInspector.Il2CppBinary" + stream.Arch.ToUpper());
if (type == null) if (type == null)
@@ -102,12 +107,12 @@ namespace Il2CppInspector
stream[0].Stream.PrimitiveMappings.Add(typeof(ulong), typeof(uint)); stream[0].Stream.PrimitiveMappings.Add(typeof(ulong), typeof(uint));
} }
return (Il2CppBinary) Activator.CreateInstance(type, stream[0]); return (Il2CppBinary) Activator.CreateInstance(type, stream[0], statusCallback);
} }
// Load binary without a global-metadata.dat available // Load binary without a global-metadata.dat available
public static Il2CppBinary Load(IFileFormatReader stream, double metadataVersion) { public static Il2CppBinary Load(IFileFormatReader stream, double metadataVersion, EventHandler<string> statusCallback = null) {
var inst = LoadImpl(stream); var inst = LoadImpl(stream, statusCallback);
return inst.Initialize(metadataVersion) ? inst : null; return inst.Initialize(metadataVersion) ? inst : null;
} }
@@ -116,13 +121,13 @@ namespace Il2CppInspector
// If it is specified and both symbol table and function scanning fail, // If it is specified and both symbol table and function scanning fail,
// Metadata will be used to try to find the required structures with data analysis // Metadata will be used to try to find the required structures with data analysis
// If it is not specified, data analysis will not be performed // If it is not specified, data analysis will not be performed
public static Il2CppBinary Load(IFileFormatReader stream, Metadata metadata) { public static Il2CppBinary Load(IFileFormatReader stream, Metadata metadata, EventHandler<string> statusCallback = null) {
var inst = LoadImpl(stream); var inst = LoadImpl(stream, statusCallback);
return inst.Initialize(metadata) ? inst : null; return inst.Initialize(metadata) ? inst : null;
} }
// Initialize binary without a global-metadata.dat available // Initialize binary without a global-metadata.dat available
public bool Initialize(double metadataVersion) { public bool Initialize(double metadataVersion, EventHandler<string> statusCallback = null) {
Image.Version = metadataVersion; Image.Version = metadataVersion;
if (!((FindMetadataFromSymbols() ?? FindMetadataFromCode()) is var ptrs)) if (!((FindMetadataFromSymbols() ?? FindMetadataFromCode()) is var ptrs))
@@ -133,7 +138,7 @@ namespace Il2CppInspector
} }
// Initialize binary with a global-metadata.dat available // Initialize binary with a global-metadata.dat available
public bool Initialize(Metadata metadata) { public bool Initialize(Metadata metadata, EventHandler<string> statusCallback = null) {
Image.Version = metadata.Version; Image.Version = metadata.Version;
if (!((FindMetadataFromSymbols() ?? FindMetadataFromCode() ?? FindMetadataFromData(metadata)) is var ptrs)) if (!((FindMetadataFromSymbols() ?? FindMetadataFromCode() ?? FindMetadataFromData(metadata)) is var ptrs))

View File

@@ -497,18 +497,18 @@ namespace Il2CppInspector
var streams = GetStreamsFromPackage(packageFiles, silent); var streams = GetStreamsFromPackage(packageFiles, silent);
if (!streams.HasValue) if (!streams.HasValue)
return null; return null;
return LoadFromStream(streams.Value.Binary, streams.Value.Metadata, silent); return LoadFromStream(streams.Value.Binary, streams.Value.Metadata, silent: silent);
} }
// Load from a binary file and metadata file // Load from a binary file and metadata file
public static List<Il2CppInspector> LoadFromFile(string binaryFile, string metadataFile, bool silent = false) public static List<Il2CppInspector> LoadFromFile(string binaryFile, string metadataFile, bool silent = false)
=> LoadFromStream(new FileStream(binaryFile, FileMode.Open, FileAccess.Read, FileShare.Read), => LoadFromStream(new FileStream(binaryFile, FileMode.Open, FileAccess.Read, FileShare.Read),
new MemoryStream(File.ReadAllBytes(metadataFile)), new MemoryStream(File.ReadAllBytes(metadataFile)),
silent); silent: silent);
// Load from a binary stream and metadata stream // Load from a binary stream and metadata stream
// Must be a seekable stream otherwise we catch a System.IO.NotSupportedException // Must be a seekable stream otherwise we catch a System.IO.NotSupportedException
public static List<Il2CppInspector> LoadFromStream(Stream binaryStream, Stream metadataStream, bool silent = false) { public static List<Il2CppInspector> LoadFromStream(Stream binaryStream, Stream metadataStream, EventHandler<string> statusCallback = null, bool silent = false) {
// Silent operation if requested // Silent operation if requested
var stdout = Console.Out; var stdout = Console.Out;
@@ -518,7 +518,7 @@ namespace Il2CppInspector
// Load the metadata file // Load the metadata file
Metadata metadata; Metadata metadata;
try { try {
metadata = new Metadata(metadataStream); metadata = new Metadata(metadataStream, statusCallback);
} }
catch (Exception ex) { catch (Exception ex) {
Console.Error.WriteLine(ex.Message); Console.Error.WriteLine(ex.Message);
@@ -531,7 +531,7 @@ namespace Il2CppInspector
// Load the il2cpp code file (try all available file formats) // Load the il2cpp code file (try all available file formats)
IFileFormatReader stream; IFileFormatReader stream;
try { try {
stream = FileFormatReader.Load(binaryStream); stream = FileFormatReader.Load(binaryStream, statusCallback);
if (stream == null) if (stream == null)
throw new InvalidOperationException("Unsupported executable file format"); throw new InvalidOperationException("Unsupported executable file format");
@@ -553,7 +553,7 @@ namespace Il2CppInspector
// Architecture-agnostic load attempt // Architecture-agnostic load attempt
try { try {
if (Il2CppBinary.Load(image, metadata) is Il2CppBinary binary) { if (Il2CppBinary.Load(image, metadata, statusCallback) is Il2CppBinary binary) {
Console.WriteLine("IL2CPP binary version " + image.Version); Console.WriteLine("IL2CPP binary version " + image.Version);
processors.Add(new Il2CppInspector(binary, metadata)); processors.Add(new Il2CppInspector(binary, metadata));

View File

@@ -45,7 +45,7 @@ namespace Il2CppInspector
public Dictionary<int, string> Strings { get; } = new Dictionary<int, string>(); public Dictionary<int, string> Strings { get; } = new Dictionary<int, string>();
public Metadata(Stream stream) : base(stream) public Metadata(Stream stream, EventHandler<string> statusCallback = null) : base(stream)
{ {
// Read magic bytes // Read magic bytes
if (ReadUInt32() != 0xFAB11BAF) { if (ReadUInt32() != 0xFAB11BAF) {
@@ -170,6 +170,9 @@ namespace Il2CppInspector
// Only do this if we need to because it's very slow // Only do this if we need to because it's very slow
if (stringOffsets.Except(Strings.Keys).Any()) { if (stringOffsets.Except(Strings.Keys).Any()) {
Console.WriteLine("Decrypting strings...");
statusCallback?.Invoke(this, "Decrypting strings");
// Start again // Start again
Strings.Clear(); Strings.Clear();
Position = Header.stringOffset; Position = Header.stringOffset;

View File

@@ -58,7 +58,7 @@ namespace Il2CppInspectorGUI
try { try {
OnStatusUpdate?.Invoke(this, "Processing metadata"); OnStatusUpdate?.Invoke(this, "Processing metadata");
metadata = new Metadata(metadataStream); metadata = new Metadata(metadataStream, StatusUpdate);
return true; return true;
} }
catch (Exception ex) { catch (Exception ex) {
@@ -95,7 +95,7 @@ namespace Il2CppInspectorGUI
// Architecture-agnostic load attempt // Architecture-agnostic load attempt
try { try {
// If we can't load the IL2CPP data here, it's probably packed or obfuscated; ignore it // If we can't load the IL2CPP data here, it's probably packed or obfuscated; ignore it
if (Il2CppBinary.Load(image, metadata) is Il2CppBinary binary) { if (Il2CppBinary.Load(image, metadata, StatusUpdate) is Il2CppBinary binary) {
var inspector = new Inspector(binary, metadata); var inspector = new Inspector(binary, metadata);
// Build type model // Build type model