From 72ddaef7b1535292bc60c617adbd9f89a0c84210 Mon Sep 17 00:00:00 2001 From: Katy Coe Date: Fri, 4 Dec 2020 14:38:06 +0100 Subject: [PATCH] IL2CPP: Prepare Code/Metadata struct data for de-obfuscation --- Il2CppInspector.Common/IL2CPP/Arrange.cs | 63 +++++++++++++++++++ Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs | 2 + 2 files changed, 65 insertions(+) create mode 100644 Il2CppInspector.Common/IL2CPP/Arrange.cs diff --git a/Il2CppInspector.Common/IL2CPP/Arrange.cs b/Il2CppInspector.Common/IL2CPP/Arrange.cs new file mode 100644 index 0000000..c4ec5cb --- /dev/null +++ b/Il2CppInspector.Common/IL2CPP/Arrange.cs @@ -0,0 +1,63 @@ +/* + Copyright 2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty + + All rights reserved. +*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; + +namespace Il2CppInspector +{ + // Some IL2CPP applications obfuscate the order of fields in Il2CppCodeRegistration and Il2CppMetadataRegistration + // specifically to defeat IL2CPP reverse engineering tools. We make an imperfect attempt to defeat this below + // by re-arranging the fields back into their original order. This can be greatly improved and more deeply validated. + // Devs: Please don't burn development resources on obfuscation. It's a waste of your time and mine. Spend it making good games instead. + partial class Il2CppBinary + { + private void Arrange() { + // Get number of pointer/count pairs in each structure + var codeItemsCount = Metadata.Sizeof(typeof(Il2CppCodeRegistration), Image.Version, Image.Bits / 8) / (Image.Bits / 8) / 2; + var metaItemsCount = Metadata.Sizeof(typeof(Il2CppMetadataRegistration), Image.Version, Image.Bits / 8) / (Image.Bits / 8) / 2; + + // Read as list of tuples + var codeArray = Image.ReadMappedArray(CodeRegistrationPointer, codeItemsCount * 2); + var codeItems = Enumerable.Range(0, codeArray.Length / 2).Select(i => (Pointer: codeArray[i*2 + 1], Count: codeArray[i*2])); + + var metaArray = Image.ReadMappedArray(MetadataRegistrationPointer, metaItemsCount * 2); + var metaItems = Enumerable.Range(0, metaArray.Length / 2).Select(i => (Pointer: metaArray[i*2 + 1], Count: metaArray[i*2])); + + // Things we need + + // Il2CppCodeRegistration: + // methodPointers (<=24.1) -> list of function pointers + // genericMethodPointers -> list of function pointers (first is zero) + // invokerPointers -> list of function pointers + // customAttributeGenerators -> list of function pointers + // codeGenModules (>=24.2) -> list of Il2CppCodeGenModule* + + if (CodeRegistration.methodPointersCount <= CodeRegistration.genericMethodPointersCount && Image.Version <= 24.1) + throw new Exception("Generic pointers greater than method pointers"); + if (CodeRegistration.genericMethodPointersCount <= CodeRegistration.invokerPointersCount) + throw new Exception("Invoker pointers greater than generic pointers"); + + // Seems to always be true but I'm not sure we can realistically guarantee this + if (CodeRegistration.customAttributeGenerators < CodeRegistration.invokerPointersCount && Image.Version <= 24.1) + throw new Exception("Custom attribute generators less than invoker pointers"); + + // Il2CppMetadataRegistration: + // genericInsts -> list of Il2CppGenericInst* (argc is count of Il2CppType* at data pointer argv; datapoint = GenericParameterIndex) + // genericMethodTable -> list of Il2CppGenericMethodFunctionsDefinitions (genericMethodIndex, methodIndex, invokerIndex) + // types -> list of Il2CppType* + // methodSpecs -> list of Il2CppMethodSpec + // methodReferences (<=16) -> list of uint + // fieldOffsets (fieldOffsetsArePointers) -> either a list of data pointers (some zero, some VAs not mappable) to list of uints, or a list of uints + // metadataUsages (>=19, <27) -> list of unmappable data pointers + } + } +} diff --git a/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs b/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs index 71cb63c..e754a26 100644 --- a/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs +++ b/Il2CppInspector.Common/IL2CPP/Il2CppBinary.cs @@ -208,6 +208,8 @@ namespace Il2CppInspector CodeRegistration = Image.ReadMappedObject(codeRegistration); MetadataRegistration = Image.ReadMappedObject(metadataRegistration); + Arrange(); + // Do basic validatation that MetadataRegistration and CodeRegistration are sane /* * TODO: Validation can be greatly expanded upon later, eg. pointers in these two structs should actually be pointers