Example #1
0
        public CppDeclarationGenerator(Il2CppModel model, UnityVersion version)
        {
            this.model = model;
            if (version == null)
            {
                UnityHeader  = UnityHeader.GuessHeadersForModel(model)[0];
                UnityVersion = UnityHeader.MinVersion;
            }
            else
            {
                UnityVersion = version;
                UnityHeader  = UnityHeader.GetHeaderForVersion(version);
                if (UnityHeader.MetadataVersion != model.Package.BinaryImage.Version)
                {
                    /* this can only happen in the CLI frontend with a manually-supplied version number */
                    Console.WriteLine($"Warning: selected version {UnityVersion} (metadata version {UnityHeader.MetadataVersion})" +
                                      $" does not match metadata version {model.Package.BinaryImage.Version}.");
                }
            }

            InitializeNaming();
            InitializeConcreteImplementations();

            // Configure inheritance style based on binary type; this can be overridden by setting InheritanceStyle in the object initializer
            InheritanceStyle = CppCompiler.GuessFromImage(model.Package.BinaryImage);
        }
        public void TestGenericTypes()
        {
            // Arrange
            // We're currently in IlCppTests\bin\Debug\netcoreapp3.0 or similar
            var testPath = Path.GetFullPath(Directory.GetCurrentDirectory() + @"\..\..\..\TestBinaries\GenericTypes");

            // Build model
            var inspectors = Il2CppInspector.LoadFromFile(testPath + @"\GenericTypes.so", testPath + @"\global-metadata.dat");
            var model      = new Il2CppModel(inspectors[0]);

            var asm = model.GetAssembly("GenericTypes.dll");

            // Act
            TypeInfo tDerived     = asm.GetType("Il2CppTests.TestSources.Derived`1");
            TypeInfo tDerivedBase = tDerived.BaseType;

            // TODO: array of Derived<int>
            // TypeInfo tDerivedArray

            TypeInfo tT      = asm.GetType("Il2CppTests.TestSources.Base`2").GenericTypeParameters[0];
            TypeInfo tF      = tDerived.GetField("F").FieldType;
            TypeInfo tNested = asm.GetType("Il2CppTests.TestSources.Derived`1+Nested");

            DisplayGenericType(tDerived, "Derived<V>");
            DisplayGenericType(tDerivedBase, "Base type of Derived<V>");
            //DisplayGenericType(tDerivedArray, "Array of Derived<int>");
            DisplayGenericType(tT, "Type parameter T from Base<T>");
            DisplayGenericType(tF, "Field type, G<Derived<V>>");
            DisplayGenericType(tNested, "Nested type in Derived<V>");

            // Assert
            var checks = new[] {
Example #3
0
        public CppApplicationModel(Il2CppModel model, UnityVersion unityVersion = null, CppCompiler.Type compiler = CppCompiler.Type.BinaryFormat)
        {
            // Set key properties
            Compiler = compiler == CppCompiler.Type.BinaryFormat ? CppCompiler.GuessFromImage(model.Package.BinaryImage) : compiler;

            var unityHeader = unityVersion != null?UnityHeader.GetHeaderForVersion(unityVersion) : UnityHeader.GuessHeadersForModel(model)[0];

            UnityVersion = unityVersion ?? unityHeader.MinVersion;
            ILModel      = model;

            // Check for matching metadata and binary versions
            if (unityHeader.MetadataVersion != model.Package.BinaryImage.Version)
            {
                Console.WriteLine($"Warning: selected version {UnityVersion} (metadata version {unityHeader.MetadataVersion})" +
                                  $" does not match metadata version {model.Package.BinaryImage.Version}.");
            }

            // Get addresses of IL2CPP API function exports
            Exports = model.Package.Binary.Image.GetExports().ToList();

            // Start creation of type model by parsing all of the Unity IL2CPP headers
            Types = CppTypes.FromUnityHeaders(unityHeader, WordSize);

            // TODO: Process every type in the binary
            //var decl = new CppDeclarationGenerator(this);
        }
Example #4
0
        public void TestGenericTypes()
        {
            // Arrange
            // We're currently in IlCppTests\bin\Debug\netcoreapp3.0 or similar
            var testPath = Path.GetFullPath(Directory.GetCurrentDirectory() + @"\..\..\..\TestBinaries\GenericTypes");

            // Build model
            var inspectors = Il2CppInspector.LoadFromFile(testPath + @"\GenericTypes.so", testPath + @"\global-metadata.dat");
            var model      = new Il2CppModel(inspectors[0]);

            var asm = model.GetAssembly("GenericTypes.dll");

            // Act
            TypeInfo tBase         = asm.GetType("Il2CppTests.TestSources.Base`2");
            TypeInfo tDerived      = asm.GetType("Il2CppTests.TestSources.Derived`1");
            TypeInfo tDerivedBase  = tDerived.BaseType;
            TypeInfo tDerivedArray = model.GetType("Il2CppTests.TestSources.Derived`1[System.Int32][]");

            TypeInfo tT      = tBase.GenericTypeParameters[0];
            TypeInfo tU      = tBase.GenericTypeParameters[1];
            TypeInfo tF      = tDerived.GetField("F").FieldType;
            TypeInfo tNested = asm.GetType("Il2CppTests.TestSources.Derived`1+Nested");

            TypeInfo   tNG      = asm.GetType("Il2CppTests.TestSources.NonGeneric");
            TypeInfo   tGCWM    = asm.GetType("Il2CppTests.TestSources.GenericClassWithMethods`1");
            TypeInfo   tCGM     = asm.GetType("Il2CppTests.TestSources.CallGenericMethods");
            MethodInfo mGMDINGC = tNG.GetMethod("GenericMethodDefinitionInNonGenericClass");
            MethodInfo mNGMIGC  = tGCWM.GetMethod("NonGenericMethodInGenericClass");
            MethodInfo mNGMIGC2 = tGCWM.GetMethod("NonGenericMethodInGenericClass2");
            MethodInfo mGMDIGC  = tGCWM.GetMethod("GenericMethodDefinitionInGenericClass");
            MethodInfo mGMDIGC2 = tGCWM.GetMethod("GenericMethodDefinitionInGenericClass2");

            MethodBase mGMDINGC_closed = model.GetGenericMethod(
                "Il2CppTests.TestSources.NonGeneric.GenericMethodDefinitionInNonGenericClass", model.GetType("System.Single"));
            MethodBase mGMDIGC_closed = model.GetGenericMethod(
                "Il2CppTests.TestSources.GenericClassWithMethods`1.GenericMethodDefinitionInGenericClass", model.GetType("System.Int32"));
            MethodBase mGMDIGC2_closed = model.GetGenericMethod(
                "Il2CppTests.TestSources.GenericClassWithMethods`1.GenericMethodDefinitionInGenericClass2", model.GetType("System.String"));

            DisplayGenericType(tBase, "Generic type definition Base<T, U>");
            DisplayGenericType(tDerived, "Derived<V>");
            DisplayGenericType(tDerivedBase, "Base type of Derived<V>");
            DisplayGenericType(tDerivedArray, "Array of Derived<int>");
            DisplayGenericType(tT, "Type parameter T from Base<T,U>");
            DisplayGenericType(tU, "Type parameter U from Base<T,U>");
            DisplayGenericType(tF, "Field type, G<Derived<V>>");
            DisplayGenericType(tNested, "Nested type in Derived<V>");

            // Assert
            var typeChecks = new[] {
Example #5
0
        public void TestNames()
        {
            // Arrange
            // We're currently in IlCppTests\bin\Debug\netcoreapp3.0 or similar
            var testPath = Path.GetFullPath(Directory.GetCurrentDirectory() + @"\..\..\..\TestBinaries\References-ARMv7");

            // Build model
            var inspectors = Il2CppInspector.LoadFromFile(testPath + @"\References-ARMv7.so", testPath + @"\global-metadata.dat");
            var model      = new Il2CppModel(inspectors[0]);

            var asm = model.GetAssembly("References.dll");

            // Act
            var t  = asm.GetType("Il2CppTests.TestSources.Test");
            var m1 = t.GetMethod("MethodWithGenericAndClassRefs");
            var m2 = t.GetMethod("MethodWithInRefOut");
            var p1 = m1.DeclaredParameters;
            var p2 = m2.DeclaredParameters;

            // Assert
            var checks = new[] {
Example #6
0
 public CSharpCodeStubs(Il2CppModel model) => this.model = model;
Example #7
0
        private static int Run(Options options)
        {
            // Banner
            var asmInfo = FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetEntryAssembly().Location);

            Console.WriteLine(asmInfo.ProductName);
            Console.WriteLine("Version " + asmInfo.ProductVersion);
            Console.WriteLine(asmInfo.LegalCopyright);
            Console.WriteLine("");

            // Check excluded namespaces
            if (options.ExcludedNamespaces.Count() == 1 && options.ExcludedNamespaces.First().ToLower() == "none")
            {
                options.ExcludedNamespaces = new List <string>();
            }

            // Check files
            if (!File.Exists(options.BinaryFile))
            {
                Console.Error.WriteLine($"File {options.BinaryFile} does not exist");
                return(1);
            }
            if (!File.Exists(options.MetadataFile))
            {
                Console.Error.WriteLine($"File {options.MetadataFile} does not exist");
                return(1);
            }

            // Creating a Visual Studio solution requires Unity assembly references
            var unityPath           = string.Empty;
            var unityAssembliesPath = string.Empty;

            if (options.CreateSolution)
            {
                unityPath           = Utils.FindPath(options.UnityPath);
                unityAssembliesPath = Utils.FindPath(options.UnityAssembliesPath);

                if (!Directory.Exists(unityPath))
                {
                    Console.Error.WriteLine($"Unity path {unityPath} does not exist");
                    return(1);
                }
                if (!File.Exists(unityPath + @"\Editor\Data\Managed\UnityEditor.dll"))
                {
                    Console.Error.WriteLine($"No Unity installation found at {unityPath}");
                    return(1);
                }
                if (!Directory.Exists(unityAssembliesPath))
                {
                    Console.Error.WriteLine($"Unity assemblies path {unityAssembliesPath} does not exist");
                    return(1);
                }
                if (!File.Exists(unityAssembliesPath + @"\UnityEngine.UI.dll"))
                {
                    Console.Error.WriteLine($"No Unity assemblies found at {unityAssembliesPath}");
                    return(1);
                }

                Console.WriteLine("Using Unity editor at " + unityPath);
                Console.WriteLine("Using Unity assemblies at " + unityAssembliesPath);
            }

            // Analyze data
            List <Il2CppInspector> il2cppInspectors;

            using (var il2cppTimer = new Benchmark("Analyze IL2CPP data"))
                il2cppInspectors = Il2CppInspector.LoadFromFile(options.BinaryFile, options.MetadataFile);

            if (il2cppInspectors == null)
            {
                Environment.Exit(1);
            }

            // Write output file
            int i = 0;

            foreach (var il2cpp in il2cppInspectors)
            {
                // Create model
                Il2CppModel model;
                using (var modelTimer = new Benchmark("Create type model"))
                    model = new Il2CppModel(il2cpp);

                // C# signatures output
                using (var signaturesDumperTimer = new Benchmark("Generate C# code")) {
                    var writer = new CSharpCodeStubs(model)
                    {
                        ExcludedNamespaces = options.ExcludedNamespaces.ToList(),
                        SuppressMetadata   = options.SuppressMetadata,
                        MustCompile        = options.MustCompile
                    };

                    var imageSuffix = i++ > 0 ? "-" + (i - 1) : "";

                    var csOut = options.CSharpOutPath;
                    if (csOut.ToLower().EndsWith(".cs"))
                    {
                        csOut = csOut.Insert(csOut.Length - 3, imageSuffix);
                    }
                    else
                    {
                        csOut += imageSuffix;
                    }

                    if (options.CreateSolution)
                    {
                        writer.WriteSolution(csOut, unityPath, unityAssembliesPath);
                    }

                    else
                    {
                        switch (options.LayoutSchema.ToLower(), options.SortOrder.ToLower())
                        {
 public Il2CppCSharpDumper(Il2CppModel model) => this.model = model;
Example #9
0
        private void runTest(string testPath)
        {
            // Android
            var testFile = testPath + @"\" + Path.GetFileName(testPath) + ".so";

            // Windows
            if (!File.Exists(testFile))
            {
                testFile = testPath + @"\" + Path.GetFileName(testPath) + ".dll";
            }
            if (!File.Exists(testFile))
            {
                testFile = testPath + @"\GameAssembly.dll";
            }
            // iOS
            if (!File.Exists(testFile))
            {
                testFile = testPath + @"\" + Path.GetFileName(testPath);
            }
            // Android
            if (!File.Exists(testFile))
            {
                testFile = testPath + @"\libil2cpp.so";
            }

            var inspectors = Il2CppInspector.LoadFromFile(testFile, testPath + @"\global-metadata.dat");

            // If null here, there was a problem parsing the files
            if (inspectors == null)
            {
                throw new Exception("Could not understand IL2CPP binary or metadata");
            }

            if (inspectors.Count == 0)
            {
                throw new Exception("Could not find any images in the IL2CPP binary");
            }

            // Dump each image in the binary separately
            int i = 0;

            foreach (var il2cpp in inspectors)
            {
                var model      = new Il2CppModel(il2cpp);
                var nameSuffix = i++ > 0 ? "-" + (i - 1) : "";

                new CSharpCodeStubs(model)
                {
                    ExcludedNamespaces = Constants.DefaultExcludedNamespaces,
                    SuppressMetadata   = false,
                    MustCompile        = true
                }.WriteSingleFile(testPath + $@"\test-result{nameSuffix}.cs");

                new IDAPythonScript(model)
                .WriteScriptToFile(testPath + $@"\test-ida-result{nameSuffix}.py");

                new CppScaffolding(model)
                .WriteCppToFile(testPath + $@"\test-result{nameSuffix}.h");
            }

            // Compare test result with expected result
            for (i = 0; i < inspectors.Count; i++)
            {
                var expected = File.ReadAllLines(testPath + @"\..\..\TestExpectedResults\" + Path.GetFileName(testPath) + (i > 0 ? "-" + i : "") + ".cs");
                var actual   = File.ReadAllLines(testPath + @"\test-result" + (i > 0 ? "-" + i : "") + ".cs");

                // Get rid of blank lines and trim the remaining lines
                expected = (from l in expected where !string.IsNullOrWhiteSpace(l) select l.Trim()).ToArray();
                actual   = (from l in actual where !string.IsNullOrWhiteSpace(l) select l.Trim()).ToArray();

                CollectionAssert.AreEqual(expected, actual);
            }
        }
 public IDAPythonScript(Il2CppModel model) => this.model = model;
Example #11
0
 public Il2CppIDAScriptDumper(Il2CppModel model) => this.model = model;
Example #12
0
 public static TypeRef FromDefinitionIndex(Il2CppModel model, int index)
 => new TypeRef
 {
     model = model, definitionIndex = index
 };
Example #13
0
 public static TypeRef FromReferenceIndex(Il2CppModel model, int index)
 => new TypeRef
 {
     model = model, referenceIndex = index
 };
Example #14
0
        private static int Run(Options options)
        {
            // Check excluded namespaces
            if (options.ExcludedNamespaces.Count() == 1 && options.ExcludedNamespaces.First().ToLower() == "none")
            {
                options.ExcludedNamespaces = new List <string>();
            }

            // Check files
            if (!File.Exists(options.BinaryFile))
            {
                Console.Error.WriteLine($"File {options.BinaryFile} does not exist");
                return(1);
            }
            if (!File.Exists(options.MetadataFile))
            {
                Console.Error.WriteLine($"File {options.MetadataFile} does not exist");
                return(1);
            }

            // Analyze data
            List <Il2CppInspector> il2cppInspectors;

            using (var timer = new Benchmark("Analyze IL2CPP data"))
                il2cppInspectors = Il2CppInspector.LoadFromFile(options.BinaryFile, options.MetadataFile);

            if (il2cppInspectors == null)
            {
                Environment.Exit(1);
            }

            // Write output file
            int i = 0;

            foreach (var il2cpp in il2cppInspectors)
            {
                // Create model
                Il2CppModel model;
                using (var timer1 = new Benchmark("Create type model"))
                    model = new Il2CppModel(il2cpp);

                // C# signatures output
                using var timer2 = new Benchmark("Generate C# code");

                var writer = new Il2CppCSharpDumper(model)
                {
                    ExcludedNamespaces = options.ExcludedNamespaces.ToList(),
                    SuppressMetadata   = options.SuppressMetadata,
                    MustCompile        = options.MustCompile
                };

                var imageSuffix = i++ > 0 ? "-" + (i - 1) : "";

                var csOut = options.CSharpOutPath;
                if (csOut.ToLower().EndsWith(".cs"))
                {
                    csOut = csOut.Insert(csOut.Length - 3, imageSuffix);
                }
                else
                {
                    csOut += imageSuffix;
                }

                switch (options.LayoutSchema.ToLower(), options.SortOrder.ToLower())
                {
 public CppScaffolding(Il2CppModel model) => this.model = model;