Exemple #1
0
        private SourceFile(ApkFile apk, JarFile jar, ISpySettings settings, MapFile mapFile, string singleFilePath = null)
        {
            this.apk            = apk;
            this.jar            = jar;
            this.settings       = settings;
            this.mapFile        = mapFile;
            this.singleFilePath = singleFilePath;

#if DEBUG
            classLoader = new AssemblyClassLoader(module.OnClassLoaded);
            var modParams = new ModuleParameters
            {
                AssemblyResolver = new AssemblyResolver(new[] { Frameworks.Instance.FirstOrDefault().Folder }, classLoader, module.OnAssemblyLoaded),
                Kind             = ModuleKind.Dll
            };
            assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("spy", Version.Parse("1.0.0.0")), "main", modParams);
            classLoader.LoadAssembly(assembly);

            var dot42Assembly = modParams.AssemblyResolver.Resolve("dot42");

            // Force loading of classes
            if (jar != null)
            {
                foreach (var fileName in jar.ClassFileNames)
                {
                    OpenClass(fileName);
                }
            }
#endif
        }
Exemple #2
0
        private SourceFile(IApkFile apk, JarFile jar, ISpySettings settings, MapFileLookup mapFile, string singleFilePath = null)
        {
            this.apk = apk;
            this.jar = jar;
            this.settings = settings;
            this.mapFile = mapFile;
            this.singleFilePath = singleFilePath;

#if DEBUG  || ENABLE_SHOW_AST
            classLoader = new AssemblyClassLoader(module.OnClassLoaded);
            var modParams = new ModuleParameters
            {
                AssemblyResolver = new AssemblyResolver(new[] { Frameworks.Instance.FirstOrDefault().Folder }, classLoader, module.OnAssemblyLoaded),
                Kind = ModuleKind.Dll
            };
            assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("spy", Version.Parse("1.0.0.0")), "main", modParams);
            classLoader.LoadAssembly(assembly);

            var dot42Assembly = modParams.AssemblyResolver.Resolve("dot42");

            // Force loading of classes
            if (jar != null)
            {
                foreach (var fileName in jar.ClassFileNames)
                {
                    OpenClass(fileName);
                }
            }
#endif
        }
        private static AssemblyDefinition AssemblyDefinitionFor(Assembly assembly)
        {
            var name = assembly.GetName();

            var moduleParams = new ModuleParameters
            {
                Kind             = ModuleKind.Dll,
                AssemblyResolver = new AppDomainAssemblyResolver()
            };

            var assembly_definition = AssemblyDefinition.CreateAssembly(
                new AssemblyNameDefinition(name.Name, name.Version),
                assembly.ManifestModule.Name, moduleParams);

            assembly_definition.MainModule.Runtime = TargetRuntime.Net_4_0;
            return(assembly_definition);
        }
Exemple #4
0
        public AssemblyEmitter(CompilerArguments compilerArgs, Version version = null)
        {
            if (version == null)
            {
                version = new Version(0, 0, 0, 0);
            }

            var assemblyName     = new AssemblyNameDefinition(Path.GetFileNameWithoutExtension(compilerArgs.OutputPath), version);
            var moduleParameters = new ModuleParameters()
            {
                Kind    = compilerArgs.ModuleKind,
                Runtime = TargetRuntime.Net_4_0
            };

            assemblyDefinition = AssemblyDefinition.CreateAssembly(assemblyName, Path.GetFileName(compilerArgs.OutputPath), moduleParameters);
            AssemblyRegistry.RegisterAssembly(assemblyDefinition);
            outputPath      = compilerArgs.OutputPath;
            DebugBuild      = compilerArgs.DebugBuild;
            functorUsageMap = new Dictionary <TypeReference, bool>();
        }
        static void CreateModule()
        {
            var parameters = new ModuleParameters()
            {
                Kind = ModuleKind.Dll,
                ReflectionImporterProvider = MMReflectionImporter.Provider
            };

            using var module = ModuleDefinition.CreateModule(name, parameters);
            var attr    = Mono.Cecil.TypeAttributes.Public | Mono.Cecil.TypeAttributes.Abstract | Mono.Cecil.TypeAttributes.Sealed | Mono.Cecil.TypeAttributes.Class;
            var typedef = new TypeDefinition("", name, attr)
            {
                BaseType = module.TypeSystem.Object
            };

            module.Types.Add(typedef);

            typedef.Fields.Add(new FieldDefinition(
                                   "state",
                                   Mono.Cecil.FieldAttributes.Public | Mono.Cecil.FieldAttributes.Static,
                                   module.ImportReference(typeof(Dictionary <MethodBase, byte[]>))
                                   ));

            var versionFieldDef = new FieldDefinition(
                "version",
                Mono.Cecil.FieldAttributes.Public | Mono.Cecil.FieldAttributes.Static,
                module.ImportReference(typeof(int))
                )
            {
                Constant = internalVersion
            };

            typedef.Fields.Add(versionFieldDef);

            _ = ReflectionHelper.Load(module);
        }
Exemple #6
0
 public DiscordRichPresenceModule([Import("ModuleParameters")] ModuleParameters moduleParameters) : base(moduleParameters)
 {
     ModuleInstance = this;
 }
Exemple #7
0
 public Gerald([Import("ModuleParameters")] ModuleParameters moduleParameters) : base(moduleParameters)
 {
 }
Exemple #8
0
 public UniversalSearchModule([Import("ModuleParameters")] ModuleParameters moduleParameters) : base(moduleParameters)
 {
     ModuleInstance = this;
 }
Exemple #9
0
 public ExtendedBuildStorage([Import("ModuleParameters")] ModuleParameters moduleParameters) : base(moduleParameters)
 {
     ModuleInstance = this;
 }
Exemple #10
0
        public static int Main(string[] args)
        {
            Console.WriteLine("===Cpp2IL by Samboy063===");
            Console.WriteLine("A Tool to Reverse Unity's \"il2cpp\" Build Process.");
            Console.WriteLine("Running on " + Environment.OSVersion.Platform);

            #region Command Line Parsing

            CommandLineOptions = null;
            Parser.Default.ParseArguments <Options>(args).WithParsed(options => { CommandLineOptions = options; });

            if (CommandLineOptions == null)
            {
                Console.WriteLine("Invalid command line. Exiting.");
                return(1);
            }

            if (!CheckForceOptionsAreValid())
            {
                Console.WriteLine("Read the help.");
                return(1);
            }

            int[]  unityVerUseful;
            string assemblyPath;
            string metadataPath;
            if (CommandLineOptions.ForcedBinaryPath == null)
            {
                var baseGamePath = CommandLineOptions.GamePath;

                Console.WriteLine("Using path: " + baseGamePath);

                if (!Directory.Exists(baseGamePath))
                {
                    Console.WriteLine("Specified game-path does not exist: " + baseGamePath);
                    return(2);
                }

                assemblyPath = Path.Combine(baseGamePath, "GameAssembly.dll");
                var exeName = Path.GetFileNameWithoutExtension(Directory.GetFiles(baseGamePath)
                                                               .First(f => f.EndsWith(".exe") && !BlacklistedExecutableFilenames.Any(bl => f.EndsWith(bl))));

                if (CommandLineOptions.ExeName != null)
                {
                    exeName = CommandLineOptions.ExeName;
                    Console.WriteLine($"Using OVERRIDDEN game name: {exeName}");
                }
                else
                {
                    Console.WriteLine($"Auto-detected game name: {exeName}");
                }

                var unityPlayerPath = Path.Combine(baseGamePath, $"{exeName}.exe");
                metadataPath = Path.Combine(baseGamePath, $"{exeName}_Data", "il2cpp_data", "Metadata", "global-metadata.dat");

                if (!File.Exists(assemblyPath) || !File.Exists(unityPlayerPath) || !File.Exists(metadataPath))
                {
                    Console.WriteLine("Invalid game-path or exe-name specified. Failed to find one of the following:\n" +
                                      $"\t{assemblyPath}\n" +
                                      $"\t{unityPlayerPath}\n" +
                                      $"\t{metadataPath}\n");

                    return(2);
                }

                #endregion

                Console.WriteLine($"Located game EXE: {unityPlayerPath}");
                Console.WriteLine($"Located global-metadata: {metadataPath}");

                #region Unity Version Determination

                Console.WriteLine("\nAttempting to determine Unity version...");

                if (Environment.OSVersion.Platform == PlatformID.Win32NT)
                {
                    var unityVer = FileVersionInfo.GetVersionInfo(unityPlayerPath);

                    unityVerUseful = new[] { unityVer.FileMajorPart, unityVer.FileMinorPart, unityVer.FileBuildPart };
                }
                else
                {
                    //Globalgamemanagers
                    var globalgamemanagersPath = Path.Combine(baseGamePath, $"{exeName}_Data", "globalgamemanagers");
                    var ggmBytes  = File.ReadAllBytes(globalgamemanagersPath);
                    var verString = new StringBuilder();
                    var idx       = 0x14;
                    while (ggmBytes[idx] != 0)
                    {
                        verString.Append(Convert.ToChar(ggmBytes[idx]));
                        idx++;
                    }

                    var unityVer = verString.ToString();
                    unityVer = unityVer.Substring(0, unityVer.IndexOf("f", StringComparison.Ordinal));
                    Console.WriteLine("Read version string from globalgamemanagers: " + unityVer);
                    unityVerUseful = unityVer.Split(".").Select(int.Parse).ToArray();
                }

                Console.WriteLine("This game is built with Unity version " + string.Join(".", unityVerUseful));

                if (unityVerUseful[0] <= 4)
                {
                    Console.WriteLine("Unable to determine a valid unity version. Aborting.");
                    return(1);
                }

                #endregion
            }
            else
            {
                Console.WriteLine("Warning: Using force options, I sure hope you know what you're doing!");
                assemblyPath   = CommandLineOptions.ForcedBinaryPath !;
                metadataPath   = CommandLineOptions.ForcedMetadataPath !;
                unityVerUseful = CommandLineOptions.ForcedUnityVersion !.Split('.').Select(int.Parse).ToArray();
            }

            //Set this flag from command line options
            LibCpp2IlMain.Settings.AllowManualMetadataAndCodeRegInput = !CommandLineOptions.DisableRegistrationPrompts;

            //Disable Method Ptr Mapping and Global Resolving if skipping analysis
            LibCpp2IlMain.Settings.DisableMethodPointerMapping = LibCpp2IlMain.Settings.DisableGlobalResolving = CommandLineOptions.SkipAnalysis;

            if (!LibCpp2IlMain.LoadFromFile(assemblyPath, metadataPath, unityVerUseful))
            {
                Console.WriteLine("Initialization with LibCpp2IL failed.");
                return(1);
            }

            //Dump DLLs

            #region Assembly Generation

            var resolver     = new RegistryAssemblyResolver();
            var moduleParams = new ModuleParameters
            {
                Kind             = ModuleKind.Dll,
                AssemblyResolver = resolver,
                MetadataResolver = new MetadataResolver(resolver)
            };


            Console.WriteLine("Building assemblies...");
            Console.WriteLine("\tPass 1: Creating empty types...");

            Assemblies = AssemblyBuilder.CreateAssemblies(LibCpp2IlMain.TheMetadata !, resolver, moduleParams);

            Utils.BuildPrimitiveMappings();

            Console.WriteLine("\tPass 2: Setting parents and handling inheritance...");

            //Stateful method, no return value
            AssemblyBuilder.ConfigureHierarchy(LibCpp2IlMain.TheMetadata, LibCpp2IlMain.ThePe !);

            Console.WriteLine("\tPass 3: Populating types...");

            var methods = new List <(TypeDefinition type, List <CppMethodData> methods)>();

            //Create out dirs if needed
            var outputPath = Path.GetFullPath("cpp2il_out");
            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }

            var methodOutputDir = Path.Combine(outputPath, "types");
            if (!(CommandLineOptions.SkipAnalysis && CommandLineOptions.SkipMetadataTextFiles) && !Directory.Exists(methodOutputDir))
            {
                Directory.CreateDirectory(methodOutputDir);
            }

            for (var imageIndex = 0; imageIndex < LibCpp2IlMain.TheMetadata.imageDefinitions.Length; imageIndex++)
            {
                var imageDef = LibCpp2IlMain.TheMetadata.imageDefinitions[imageIndex];

                Console.WriteLine($"\t\tPopulating {imageDef.typeCount} types in assembly {imageIndex + 1} of {LibCpp2IlMain.TheMetadata.imageDefinitions.Length}: {imageDef.Name}...");

                var assemblySpecificPath = Path.Combine(methodOutputDir, imageDef.Name.Replace(".dll", ""));
                if (!(CommandLineOptions.SkipMetadataTextFiles && CommandLineOptions.SkipAnalysis) && !Directory.Exists(assemblySpecificPath))
                {
                    Directory.CreateDirectory(assemblySpecificPath);
                }

                methods.AddRange(AssemblyBuilder.ProcessAssemblyTypes(LibCpp2IlMain.TheMetadata, LibCpp2IlMain.ThePe, imageDef));
            }

            //Invert dict for CppToMono
            SharedState.UnmanagedToManagedTypes = SharedState.MonoToCppTypeDefs.ToDictionary(i => i.Value, i => i.Key);

            Console.WriteLine("\tPass 4: Applying type, method, and field attributes...");

            #region Attributes

            var unityEngineAssembly = Assemblies.Find(x => x.MainModule.Types.Any(t => t.Namespace == "UnityEngine" && t.Name == "SerializeField"));
            if (unityEngineAssembly != null)
            {
                foreach (var imageDef in LibCpp2IlMain.TheMetadata.imageDefinitions)
                {
                    //Cache these per-module.
                    var attributeCtorsByClassIndex = new Dictionary <long, MethodReference>();

                    var lastTypeIndex = imageDef.firstTypeIndex + imageDef.typeCount;
                    for (var typeIndex = imageDef.firstTypeIndex; typeIndex < lastTypeIndex; typeIndex++)
                    {
                        var typeDef        = LibCpp2IlMain.TheMetadata.typeDefs[typeIndex];
                        var typeDefinition = SharedState.UnmanagedToManagedTypes[typeDef !];
Exemple #11
0
        public DummyAssemblyGenerator(Il2CppExecutor il2CppExecutor, bool addToken)
        {
            executor = il2CppExecutor;
            metadata = il2CppExecutor.metadata;
            il2Cpp   = il2CppExecutor.il2Cpp;

            //Il2CppDummyDll
            var il2CppDummyDll = Il2CppDummyDll.Create();

            Assemblies.Add(il2CppDummyDll);
            var addressAttribute     = il2CppDummyDll.MainModule.Types.First(x => x.Name == "AddressAttribute").Methods[0];
            var fieldOffsetAttribute = il2CppDummyDll.MainModule.Types.First(x => x.Name == "FieldOffsetAttribute").Methods[0];

            attributeAttribute = il2CppDummyDll.MainModule.Types.First(x => x.Name == "AttributeAttribute").Methods[0];
            var metadataOffsetAttribute = il2CppDummyDll.MainModule.Types.First(x => x.Name == "MetadataOffsetAttribute").Methods[0];
            var tokenAttribute          = il2CppDummyDll.MainModule.Types.First(x => x.Name == "TokenAttribute").Methods[0];

            stringType = il2CppDummyDll.MainModule.TypeSystem.String;

            var resolver         = new MyAssemblyResolver();
            var moduleParameters = new ModuleParameters
            {
                Kind             = ModuleKind.Dll,
                AssemblyResolver = resolver
            };

            resolver.Register(il2CppDummyDll);

            var parameterDefinitionDic = new Dictionary <int, ParameterDefinition>();
            var eventDefinitionDic     = new Dictionary <int, EventDefinition>();

            //创建程序集,同时创建所有类
            foreach (var imageDef in metadata.imageDefs)
            {
                var     imageName    = metadata.GetStringFromIndex(imageDef.nameIndex);
                var     aname        = metadata.assemblyDefs[imageDef.assemblyIndex].aname;
                var     assemblyName = metadata.GetStringFromIndex(aname.nameIndex);
                Version vers;
                if (aname.build >= 0)
                {
                    vers = new Version(aname.major, aname.minor, aname.build, aname.revision);
                }
                else
                {
                    //__Generated
                    vers = new Version(3, 7, 1, 6);
                }
                var assemblyNameDef = new AssemblyNameDefinition(assemblyName, vers);

                /*assemblyNameDef.Culture = metadata.GetStringFromIndex(aname.cultureIndex);
                 * assemblyNameDef.PublicKey = Encoding.UTF8.GetBytes(metadata.GetStringFromIndex(aname.publicKeyIndex));
                 * assemblyNameDef.HashAlgorithm = (AssemblyHashAlgorithm)aname.hash_alg;
                 * assemblyNameDef.Attributes = (AssemblyAttributes)aname.flags;
                 * assemblyNameDef.PublicKeyToken = aname.public_key_token;*/
                var assemblyDefinition = AssemblyDefinition.CreateAssembly(assemblyNameDef, imageName, moduleParameters);
                resolver.Register(assemblyDefinition);
                Assemblies.Add(assemblyDefinition);
                var moduleDefinition = assemblyDefinition.MainModule;
                moduleDefinition.Types.Clear();//清除自动创建的<Module>类
                var typeEnd = imageDef.typeStart + imageDef.typeCount;
                for (var index = imageDef.typeStart; index < typeEnd; ++index)
                {
                    var typeDef        = metadata.typeDefs[index];
                    var namespaceName  = metadata.GetStringFromIndex(typeDef.namespaceIndex);
                    var typeName       = metadata.GetStringFromIndex(typeDef.nameIndex);
                    var typeDefinition = new TypeDefinition(namespaceName, typeName, (TypeAttributes)typeDef.flags);
                    typeDefinitionDic.Add(typeDef, typeDefinition);
                    if (typeDef.declaringTypeIndex == -1)
                    {
                        moduleDefinition.Types.Add(typeDefinition);
                    }
                }
            }
            foreach (var imageDef in metadata.imageDefs)
            {
                var typeEnd = imageDef.typeStart + imageDef.typeCount;
                for (var index = imageDef.typeStart; index < typeEnd; ++index)
                {
                    var typeDef        = metadata.typeDefs[index];
                    var typeDefinition = typeDefinitionDic[typeDef];

                    //nestedtype
                    for (int i = 0; i < typeDef.nested_type_count; i++)
                    {
                        var nestedIndex          = metadata.nestedTypeIndices[typeDef.nestedTypesStart + i];
                        var nestedTypeDef        = metadata.typeDefs[nestedIndex];
                        var nestedTypeDefinition = typeDefinitionDic[nestedTypeDef];
                        typeDefinition.NestedTypes.Add(nestedTypeDefinition);
                    }
                }
            }
            //提前处理
            foreach (var imageDef in metadata.imageDefs)
            {
                var typeEnd = imageDef.typeStart + imageDef.typeCount;
                for (var index = imageDef.typeStart; index < typeEnd; ++index)
                {
                    var typeDef        = metadata.typeDefs[index];
                    var typeDefinition = typeDefinitionDic[typeDef];

                    if (addToken)
                    {
                        var customTokenAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(tokenAttribute));
                        customTokenAttribute.Fields.Add(new CustomAttributeNamedArgument("Token", new CustomAttributeArgument(stringType, $"0x{typeDef.token:X}")));
                        typeDefinition.CustomAttributes.Add(customTokenAttribute);
                    }

                    //genericParameter
                    if (typeDef.genericContainerIndex >= 0)
                    {
                        var genericContainer = metadata.genericContainers[typeDef.genericContainerIndex];
                        for (int i = 0; i < genericContainer.type_argc; i++)
                        {
                            var genericParameterIndex = genericContainer.genericParameterStart + i;
                            var param            = metadata.genericParameters[genericParameterIndex];
                            var genericParameter = CreateGenericParameter(param, typeDefinition);
                            typeDefinition.GenericParameters.Add(genericParameter);
                        }
                    }

                    //parent
                    if (typeDef.parentIndex >= 0)
                    {
                        var parentType    = il2Cpp.types[typeDef.parentIndex];
                        var parentTypeRef = GetTypeReference(typeDefinition, parentType);
                        typeDefinition.BaseType = parentTypeRef;
                    }

                    //interfaces
                    for (int i = 0; i < typeDef.interfaces_count; i++)
                    {
                        var interfaceType    = il2Cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]];
                        var interfaceTypeRef = GetTypeReference(typeDefinition, interfaceType);
                        typeDefinition.Interfaces.Add(new InterfaceImplementation(interfaceTypeRef));
                    }
                }
            }
            //处理field, method, property等等
            foreach (var imageDef in metadata.imageDefs)
            {
                var imageName = metadata.GetStringFromIndex(imageDef.nameIndex);
                var typeEnd   = imageDef.typeStart + imageDef.typeCount;
                for (int index = imageDef.typeStart; index < typeEnd; index++)
                {
                    var typeDef        = metadata.typeDefs[index];
                    var typeDefinition = typeDefinitionDic[typeDef];

                    //field
                    var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                    for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                    {
                        var fieldDef        = metadata.fieldDefs[i];
                        var fieldType       = il2Cpp.types[fieldDef.typeIndex];
                        var fieldName       = metadata.GetStringFromIndex(fieldDef.nameIndex);
                        var fieldTypeRef    = GetTypeReference(typeDefinition, fieldType);
                        var fieldDefinition = new FieldDefinition(fieldName, (FieldAttributes)fieldType.attrs, fieldTypeRef);
                        typeDefinition.Fields.Add(fieldDefinition);
                        fieldDefinitionDic.Add(i, fieldDefinition);

                        if (addToken)
                        {
                            var customTokenAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(tokenAttribute));
                            customTokenAttribute.Fields.Add(new CustomAttributeNamedArgument("Token", new CustomAttributeArgument(stringType, $"0x{fieldDef.token:X}")));
                            fieldDefinition.CustomAttributes.Add(customTokenAttribute);
                        }

                        //fieldDefault
                        if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefault) && fieldDefault.dataIndex != -1)
                        {
                            if (executor.TryGetDefaultValue(fieldDefault.typeIndex, fieldDefault.dataIndex, out var value))
                            {
                                fieldDefinition.Constant = value;
                            }
                            else
                            {
                                var customAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(metadataOffsetAttribute));
                                var offset          = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{value:X}"));
                                customAttribute.Fields.Add(offset);
                                fieldDefinition.CustomAttributes.Add(customAttribute);
                            }
                        }
                        //fieldOffset
                        if (!fieldDefinition.IsLiteral)
                        {
                            var fieldOffset = il2Cpp.GetFieldOffsetFromIndex(index, i - typeDef.fieldStart, i, typeDefinition.IsValueType, fieldDefinition.IsStatic);
                            if (fieldOffset >= 0)
                            {
                                var customAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(fieldOffsetAttribute));
                                var offset          = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{fieldOffset:X}"));
                                customAttribute.Fields.Add(offset);
                                fieldDefinition.CustomAttributes.Add(customAttribute);
                            }
                        }
                    }
                    //method
                    var methodEnd = typeDef.methodStart + typeDef.method_count;
                    for (var i = typeDef.methodStart; i < methodEnd; ++i)
                    {
                        var methodDef        = metadata.methodDefs[i];
                        var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                        var methodDefinition = new MethodDefinition(methodName, (MethodAttributes)methodDef.flags, typeDefinition.Module.ImportReference(typeof(void)));
                        methodDefinition.ImplAttributes = (MethodImplAttributes)methodDef.iflags;
                        typeDefinition.Methods.Add(methodDefinition);
                        //genericParameter
                        if (methodDef.genericContainerIndex >= 0)
                        {
                            var genericContainer = metadata.genericContainers[methodDef.genericContainerIndex];
                            for (int j = 0; j < genericContainer.type_argc; j++)
                            {
                                var genericParameterIndex = genericContainer.genericParameterStart + j;
                                var param            = metadata.genericParameters[genericParameterIndex];
                                var genericParameter = CreateGenericParameter(param, methodDefinition);
                                methodDefinition.GenericParameters.Add(genericParameter);
                            }
                        }
                        var methodReturnType = il2Cpp.types[methodDef.returnType];
                        var returnType       = GetTypeReferenceWithByRef(methodDefinition, methodReturnType);
                        methodDefinition.ReturnType = returnType;

                        if (addToken)
                        {
                            var customTokenAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(tokenAttribute));
                            customTokenAttribute.Fields.Add(new CustomAttributeNamedArgument("Token", new CustomAttributeArgument(stringType, $"0x{methodDef.token:X}")));
                            methodDefinition.CustomAttributes.Add(customTokenAttribute);
                        }

                        if (methodDefinition.HasBody && typeDefinition.BaseType?.FullName != "System.MulticastDelegate")
                        {
                            var ilprocessor = methodDefinition.Body.GetILProcessor();
                            if (returnType.FullName == "System.Void")
                            {
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
                            }
                            else if (returnType.IsValueType)
                            {
                                var variable = new VariableDefinition(returnType);
                                methodDefinition.Body.Variables.Add(variable);
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloca_S, variable));
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Initobj, returnType));
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0));
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
                            }
                            else
                            {
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ldnull));
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
                            }
                        }
                        methodDefinitionDic.Add(i, methodDefinition);
                        //method parameter
                        for (var j = 0; j < methodDef.parameterCount; ++j)
                        {
                            var parameterDef        = metadata.parameterDefs[methodDef.parameterStart + j];
                            var parameterName       = metadata.GetStringFromIndex(parameterDef.nameIndex);
                            var parameterType       = il2Cpp.types[parameterDef.typeIndex];
                            var parameterTypeRef    = GetTypeReferenceWithByRef(methodDefinition, parameterType);
                            var parameterDefinition = new ParameterDefinition(parameterName, (ParameterAttributes)parameterType.attrs, parameterTypeRef);
                            methodDefinition.Parameters.Add(parameterDefinition);
                            parameterDefinitionDic.Add(methodDef.parameterStart + j, parameterDefinition);
                            //ParameterDefault
                            if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1)
                            {
                                if (executor.TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value))
                                {
                                    parameterDefinition.Constant = value;
                                }
                                else
                                {
                                    var customAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(metadataOffsetAttribute));
                                    var offset          = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{value:X}"));
                                    customAttribute.Fields.Add(offset);
                                    parameterDefinition.CustomAttributes.Add(customAttribute);
                                }
                            }
                        }
                        //methodAddress
                        if (!methodDefinition.IsAbstract)
                        {
                            var methodPointer = il2Cpp.GetMethodPointer(imageName, methodDef);
                            if (methodPointer > 0)
                            {
                                var customAttribute    = new CustomAttribute(typeDefinition.Module.ImportReference(addressAttribute));
                                var fixedMethodPointer = il2Cpp.GetRVA(methodPointer);
                                var rva    = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{fixedMethodPointer:X}"));
                                var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2Cpp.MapVATR(methodPointer):X}"));
                                var va     = new CustomAttributeNamedArgument("VA", new CustomAttributeArgument(stringType, $"0x{methodPointer:X}"));
                                customAttribute.Fields.Add(rva);
                                customAttribute.Fields.Add(offset);
                                customAttribute.Fields.Add(va);
                                if (methodDef.slot != ushort.MaxValue)
                                {
                                    var slot = new CustomAttributeNamedArgument("Slot", new CustomAttributeArgument(stringType, methodDef.slot.ToString()));
                                    customAttribute.Fields.Add(slot);
                                }
                                methodDefinition.CustomAttributes.Add(customAttribute);
                            }
                        }
                    }
                    //property
                    var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                    for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                    {
                        var              propertyDef  = metadata.propertyDefs[i];
                        var              propertyName = metadata.GetStringFromIndex(propertyDef.nameIndex);
                        TypeReference    propertyType = null;
                        MethodDefinition GetMethod    = null;
                        MethodDefinition SetMethod    = null;
                        if (propertyDef.get >= 0)
                        {
                            GetMethod    = methodDefinitionDic[typeDef.methodStart + propertyDef.get];
                            propertyType = GetMethod.ReturnType;
                        }
                        if (propertyDef.set >= 0)
                        {
                            SetMethod = methodDefinitionDic[typeDef.methodStart + propertyDef.set];
                            if (propertyType == null)
                            {
                                propertyType = SetMethod.Parameters[0].ParameterType;
                            }
                        }
                        var propertyDefinition = new PropertyDefinition(propertyName, (PropertyAttributes)propertyDef.attrs, propertyType)
                        {
                            GetMethod = GetMethod,
                            SetMethod = SetMethod
                        };
                        typeDefinition.Properties.Add(propertyDefinition);
                        propertyDefinitionDic.Add(i, propertyDefinition);

                        if (addToken)
                        {
                            var customTokenAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(tokenAttribute));
                            customTokenAttribute.Fields.Add(new CustomAttributeNamedArgument("Token", new CustomAttributeArgument(stringType, $"0x{propertyDef.token:X}")));
                            propertyDefinition.CustomAttributes.Add(customTokenAttribute);
                        }
                    }
                    //event
                    var eventEnd = typeDef.eventStart + typeDef.event_count;
                    for (var i = typeDef.eventStart; i < eventEnd; ++i)
                    {
                        var eventDef        = metadata.eventDefs[i];
                        var eventName       = metadata.GetStringFromIndex(eventDef.nameIndex);
                        var eventType       = il2Cpp.types[eventDef.typeIndex];
                        var eventTypeRef    = GetTypeReference(typeDefinition, eventType);
                        var eventDefinition = new EventDefinition(eventName, (EventAttributes)eventType.attrs, eventTypeRef);
                        if (eventDef.add >= 0)
                        {
                            eventDefinition.AddMethod = methodDefinitionDic[typeDef.methodStart + eventDef.add];
                        }
                        if (eventDef.remove >= 0)
                        {
                            eventDefinition.RemoveMethod = methodDefinitionDic[typeDef.methodStart + eventDef.remove];
                        }
                        if (eventDef.raise >= 0)
                        {
                            eventDefinition.InvokeMethod = methodDefinitionDic[typeDef.methodStart + eventDef.raise];
                        }
                        typeDefinition.Events.Add(eventDefinition);
                        eventDefinitionDic.Add(i, eventDefinition);

                        if (addToken)
                        {
                            var customTokenAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(tokenAttribute));
                            customTokenAttribute.Fields.Add(new CustomAttributeNamedArgument("Token", new CustomAttributeArgument(stringType, $"0x{eventDef.token:X}")));
                            eventDefinition.CustomAttributes.Add(customTokenAttribute);
                        }
                    }
                }
            }
            //第三遍,添加CustomAttribute
            if (il2Cpp.Version > 20)
            {
                foreach (var imageDef in metadata.imageDefs)
                {
                    var typeEnd = imageDef.typeStart + imageDef.typeCount;
                    for (int index = imageDef.typeStart; index < typeEnd; index++)
                    {
                        var typeDef        = metadata.typeDefs[index];
                        var typeDefinition = typeDefinitionDic[typeDef];
                        //typeAttribute
                        CreateCustomAttribute(imageDef, typeDef.customAttributeIndex, typeDef.token, typeDefinition.Module, typeDefinition.CustomAttributes);

                        //field
                        var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                        for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                        {
                            var fieldDef        = metadata.fieldDefs[i];
                            var fieldDefinition = fieldDefinitionDic[i];
                            //fieldAttribute
                            CreateCustomAttribute(imageDef, fieldDef.customAttributeIndex, fieldDef.token, typeDefinition.Module, fieldDefinition.CustomAttributes);
                        }

                        //method
                        var methodEnd = typeDef.methodStart + typeDef.method_count;
                        for (var i = typeDef.methodStart; i < methodEnd; ++i)
                        {
                            var methodDef        = metadata.methodDefs[i];
                            var methodDefinition = methodDefinitionDic[i];
                            //methodAttribute
                            CreateCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, typeDefinition.Module, methodDefinition.CustomAttributes);

                            //method parameter
                            for (var j = 0; j < methodDef.parameterCount; ++j)
                            {
                                var parameterDef        = metadata.parameterDefs[methodDef.parameterStart + j];
                                var parameterDefinition = parameterDefinitionDic[methodDef.parameterStart + j];
                                //parameterAttribute
                                CreateCustomAttribute(imageDef, parameterDef.customAttributeIndex, parameterDef.token, typeDefinition.Module, parameterDefinition.CustomAttributes);
                            }
                        }

                        //property
                        var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                        for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                        {
                            var propertyDef        = metadata.propertyDefs[i];
                            var propertyDefinition = propertyDefinitionDic[i];
                            //propertyAttribute
                            CreateCustomAttribute(imageDef, propertyDef.customAttributeIndex, propertyDef.token, typeDefinition.Module, propertyDefinition.CustomAttributes);
                        }

                        //event
                        var eventEnd = typeDef.eventStart + typeDef.event_count;
                        for (var i = typeDef.eventStart; i < eventEnd; ++i)
                        {
                            var eventDef        = metadata.eventDefs[i];
                            var eventDefinition = eventDefinitionDic[i];
                            //eventAttribute
                            CreateCustomAttribute(imageDef, eventDef.customAttributeIndex, eventDef.token, typeDefinition.Module, eventDefinition.CustomAttributes);
                        }
                    }
                }
            }
        }
 public Module([Import("ModuleParameters")] ModuleParameters moduleParameters) : base(moduleParameters)
 {
 }
Exemple #13
0
 /// <summary>
 /// Get all of the default properties from the model
 /// </summary>
 /// <param name="modelType">The model that we want all of the properties from</param>
 /// <returns>A set of parameters with their default values</returns>
 public static IModuleParameters GetParameters(Type modelType)
 {
     if (modelType == null) return null;
     ModuleParameters parameters = new ModuleParameters();
     foreach (var property in modelType.GetProperties())
     {
         AddProperties(parameters, property.GetCustomAttributes(true), property.Name, false, property.PropertyType);
     }
     foreach (var field in modelType.GetFields())
     {
         AddProperties(parameters, field.GetCustomAttributes(true), field.Name, true, field.FieldType);
     }
     return parameters;
 }
Exemple #14
0
 /// <summary>
 /// Build up the model parameters
 /// </summary>
 /// <param name="parameters">The parameter structure we are building</param>
 /// <param name="attributes">The attributes that we have found</param>
 private static void AddProperties(ModuleParameters parameters, object[] attributes, string fieldName, bool field, Type t)
 {
     foreach (var attribute in attributes)
     {
         if (attribute is ParameterAttribute)
         {
             var temp = attribute as ParameterAttribute;
             temp.AttachedToField = field;
             temp.VariableName = fieldName;
             parameters.Add(temp, t);
         }
     }
 }
Exemple #15
0
        public InteropAssemblyBuilder(AssemblyNameDefinition assemblyName, ModuleParameters moduleParams = null, string targetFramework = null)
        {
            Name       = assemblyName;
            Namespace  = assemblyName.Name;
            Statistics = new ReadOnlyDictionary <string, long>(_statistics);
            if (moduleParams == null)
            {
                moduleParams = DefaultModuleParameters;
            }

            // ReSharper disable once UnusedVariable
            var forceUnsafeToLoad = Unsafe.AreSame(ref assemblyName, ref assemblyName);

            //var loadedAsms = AppDomain.CurrentDomain.GetAssemblies();
            //var loadedAsms = AssemblyResolver.KnownAssemblies;

            var asmResolver = new AssemblyResolver();

            //var mdResolver = new MetadataResolver(asmResolver);

            var shadowAsmFilePath = Path.Combine(Directory.GetCurrentDirectory(), $"{BaseInteropAsmName}.dll");

            File.Copy(BaseInteropAsmPath, shadowAsmFilePath);

            Assembly = AssemblyDefinition.ReadAssembly(shadowAsmFilePath, new ReaderParameters {
                InMemory         = true,
                ReadWrite        = true,
                ReadingMode      = ReadingMode.Immediate,
                AssemblyResolver = asmResolver,

                //MetadataResolver = mdResolver,
                ReadSymbols = false,
                ApplyWindowsRuntimeProjections = false,

                //SymbolReaderProvider = null,
                //MetadataImporterProvider = null,
                //ReflectionImporterProvider = null,
            });

            Assembly.Name = assemblyName;
            Module        = Assembly.MainModule;
            ModuleName    = $"{Name.Name}.dll";
            Module.Name   = ModuleName;

            if (EmitBoundsChecks)
            {
                ArgumentOutOfRangeCtor = ArgumentOutOfRangeCtorInfo.Import(Module);
            }
            if (EmitNullChecks)
            {
                ArgumentNullCtor = ArgumentNullCtorInfo.Import(Module);
            }

            NonVersionableAttribute = NonVersionableAttributeInfo?
                                      .GetCecilCustomAttribute(Module);
            FlagsAttribute = FlagsAttributeInfo
                             .GetCecilCustomAttribute(Module);

            VoidPointerType = Module.TypeSystem.Void.MakePointerType();

            MulticastDelegateType = typeof(MulticastDelegate).Import(Module);

            //var interopAsm = typeof(IHandle<>).Assembly;
            //var interopAsmName = interopAsm.GetName();
            //var interopMod = interopAsm.ManifestModule;

            //Module.AssemblyReferences.Add(new AssemblyNameReference(interopAsmName.Name, interopAsmName.Version));
            //Module.ModuleReferences.Add(new ModuleReference(interopAsmName.Name));


            ITypedHandleType             = typeof(ITypedHandle).Import(Module);
            IHandleGtd                   = typeof(IHandle <>).Import(Module);
            ITypedHandleGtd              = typeof(ITypedHandle <>).Import(Module);
            HandleInt32Gtd               = typeof(HandleInt32 <>).Import(Module);
            HandleUInt32Gtd              = typeof(HandleUInt32 <>).Import(Module);
            HandleInt64Gtd               = typeof(HandleInt64 <>).Import(Module);
            HandleUInt64Gtd              = typeof(HandleUInt64 <>).Import(Module);
            HandleIntPtrGtd              = typeof(HandleIntPtr <>).Import(Module);
            HandleUIntPtrGtd             = typeof(HandleUIntPtr <>).Import(Module);
            SplitPointerGtd              = typeof(SplitPointer <, ,>).Import(Module);
            BinderGeneratedAttributeType = typeof(BinderGeneratedAttribute).Import(Module);
            IUnmanagedFunctionPointerGtd = typeof(IUnmanagedFunctionPointer <>).Import(Module);

            TypeArrayOfSingularVoidPointer = new[] { VoidPointerType };
            TypeArrayOfSingularUInt        = new[] { Module.TypeSystem.UInt32 };
            TypeArrayOfSingularULong       = new[] { Module.TypeSystem.UInt64 };

            IntegrateInteropTypes(Module.Types);

            if (targetFramework == null)
            {
                targetFramework = DefaultTargetFramework;
            }

            var asmCustAttrs = new[] {
                AttributeInfo.Create
                    (() => new CompilationRelaxationsAttribute(8)),
                AttributeInfo.Create
                    (() => new RuntimeCompatibilityAttribute {
                    WrapNonExceptionThrows = true
                }),
                AttributeInfo.Create
                    (() => new DebuggableAttribute(DebuggableAttribute.DebuggingModes.None)),
                AttributeInfo.Create
                    (() => new TargetFrameworkAttribute(targetFramework)
                {
                    FrameworkDisplayName = ""
                }),
                AttributeInfo.Create
                    (() => new AssemblyCompanyAttribute("")),
                AttributeInfo.Create
                    (() => new AssemblyConfigurationAttribute("Release")),
                AttributeInfo.Create
                    (() => new AssemblyDescriptionAttribute($"Generated {Name.Name} Library")),
                AttributeInfo.Create
                    (() => new AssemblyFileVersionAttribute(Name.Version.ToString())),
                AttributeInfo.Create
                    (() => new AssemblyInformationalVersionAttribute(Name.Version.ToString())),
                AttributeInfo.Create
                    (() => new AssemblyProductAttribute(Name.Name)),
                AttributeInfo.Create
                    (() => new AssemblyTitleAttribute(Name.Name)),
            }.Select(ca => ca.GetCecilCustomAttribute(Module));

            /* where the hell did this go...
             * var unverifiableCodeAttributeTypeRef = new TypeReference("System.Security", "UnverifiableCodeAttribute",
             *      Module.TypeSystem.IntPtr.Resolve().Module,
             *      Module.TypeSystem.CoreLibrary, false);
             * var unverifiableCodeAttributeTypeDef = unverifiableCodeAttributeTypeRef.Resolve();
             * var unverifiableCodeAttributeCtor = unverifiableCodeAttributeTypeDef.GetConstructors().Single();
             *
             * var unverifiableCodeAttribute = new CustomAttribute(unverifiableCodeAttributeCtor);
             */
            while (Assembly.HasCustomAttributes)
            {
                Assembly.CustomAttributes.RemoveAt(0);
            }

            Assembly.CustomAttributes.Clear();
            while (Module.HasCustomAttributes)
            {
                Module.CustomAttributes.RemoveAt(0);
            }

            Module.CustomAttributes.Clear();

            foreach (var custAttr in asmCustAttrs)
            {
                Assembly.CustomAttributes.Add(custAttr);
            }

            //Module.CustomAttributes.Add(unverifiableCodeAttribute);

            /*
             * Assembly.SecurityDeclarations.Add(new SecurityDeclaration(SecurityAction.RequestMinimum) {
             *      SecurityAttributes = {
             *              // ...
             *      }
             * });
             * Module.CustomAttributes.Add(
             *      AttributeInfo.Create(() => new UnverifiableCodeAttribute())
             *      .GetCecilCustomAttribute(Module));
             */
            MarshalTypeRef            = typeof(Marshal).Import(Module);
            GetDelegateForFpMethodGtd = MarshalTypeRef.Resolve().GetMethods()
                                        .First(md => md.Name == "GetDelegateForFunctionPointer" && md.HasGenericParameters)
                                        .Import(Module);
            GetFpForDelegateMethodGtd = MarshalTypeRef.Resolve().GetMethods()
                                        .First(md => md.Name == "GetFunctionPointerForDelegate" && md.HasGenericParameters)
                                        .Import(Module);
        }
Exemple #16
0
        /// <summary>
        /// Creates all the Assemblies defined in the provided metadata, along with (stub) definitions of all the types contained therein, and registers them with the resolver.
        /// </summary>
        /// <param name="metadata">The Il2Cpp metadata to extract assemblies from</param>
        /// <param name="resolver">The Assembly Resolver that assemblies are registered with, used to ensure assemblies can cross reference.</param>
        /// <param name="moduleParams">Configuration for the module creation.</param>
        /// <returns>A list of Mono.Cecil Assemblies, containing empty type definitions for each defined type.</returns>
        internal static List <AssemblyDefinition> CreateAssemblies(Il2CppMetadata metadata, RegistryAssemblyResolver resolver, ModuleParameters moduleParams)
        {
            var assemblies = new List <AssemblyDefinition>();

            foreach (var assemblyDefinition in metadata.imageDefinitions)
            {
                //Get the name of the assembly (= the name of the DLL without the file extension)
                var assemblyNameString = metadata.GetStringFromIndex(assemblyDefinition.nameIndex).Replace(".dll", "");

                //Build a Mono.Cecil assembly name from this name
                var asmName = new AssemblyNameDefinition(assemblyNameString, new Version("0.0.0.0"));
                Console.Write($"\t\t{assemblyNameString}...");

                //Create an empty assembly and register it
                var assembly = AssemblyDefinition.CreateAssembly(asmName, metadata.GetStringFromIndex(assemblyDefinition.nameIndex), moduleParams);
                resolver.Register(assembly);
                assemblies.Add(assembly);

                //Ensure it really _is_ empty
                var mainModule = assembly.MainModule;
                mainModule.Types.Clear();

                //Find the end index of the types belonging to this assembly (as they're all in one huge list in the metadata)
                var end = assemblyDefinition.firstTypeIndex + assemblyDefinition.typeCount;

                for (var defNumber = assemblyDefinition.firstTypeIndex; defNumber < end; defNumber++)
                {
                    //Get the metadata type info, its namespace, and name.
                    var type = metadata.typeDefs[defNumber];
                    var ns   = metadata.GetStringFromIndex(type.namespaceIndex);
                    var name = metadata.GetStringFromIndex(type.nameIndex);

                    TypeDefinition?definition = null;
                    if (type.declaringTypeIndex != -1)
                    {
                        //This is a type declared within another (inner class/type)

                        //Have we already declared this type due to handling its parent?
                        SharedState.TypeDefsByIndex.TryGetValue(defNumber, out definition);
                    }

                    if (definition == null)
                    {
                        //This is a new type (including nested type with parent not defined yet) so ensure it's registered
                        definition = new TypeDefinition(ns, name, (TypeAttributes)type.flags);
                        if (ns == "System" && name == "String")
                        {
                            typeof(TypeReference).GetField("etype", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(definition, (byte)0x0e);  //mark as string
                        }

                        mainModule.Types.Add(definition);
                        SharedState.AllTypeDefinitions.Add(definition);
                        SharedState.TypeDefsByIndex.Add(defNumber, definition);
                    }

                    //Ensure we include all inner types within this type.
                    for (var nestedNumber = 0; nestedNumber < type.nested_type_count; nestedNumber++)
                    {
                        //These are stored in a separate field in the metadata.
                        var nestedIndex = metadata.nestedTypeIndices[type.nestedTypesStart + nestedNumber];
                        var nested      = metadata.typeDefs[nestedIndex];


                        if (SharedState.TypeDefsByIndex.TryGetValue(nestedIndex, out var alreadyMadeNestedType))
                        {
                            //Type has already been defined (can be out-of-order in v27+) so we just add it.
                            definition.NestedTypes.Add(alreadyMadeNestedType);
                        }
                        else
                        {
                            //Create it and register.
                            var nestedDef = new TypeDefinition(metadata.GetStringFromIndex(nested.namespaceIndex),
                                                               metadata.GetStringFromIndex(nested.nameIndex), (TypeAttributes)nested.flags);

                            definition.NestedTypes.Add(nestedDef);
                            SharedState.AllTypeDefinitions.Add(nestedDef);
                            SharedState.TypeDefsByIndex.Add(nestedIndex, nestedDef);
                        }
                    }
                }

                Console.WriteLine("OK");
            }

            return(assemblies);
        }
        public static IEnumerable <EcsFile> Run(MethodReference entryPoint)
        {
            var usedTypes = GetUsedTypesOrdered(entryPoint).ToList();

            var moduleParameter = new ModuleParameters {
                Kind = ModuleKind.Dll, AssemblyResolver = entryPoint.Module.AssemblyResolver
            };
            var mod = ModuleDefinition.CreateModule("test", moduleParameter);

            // copy search path from old assembly

            // todo move to new transform, discovery transform?
            foreach (var t in usedTypes)
            {
                t.IsNestedPrivate = false;
            }

            foreach (var t in usedTypes)
            {
                mod.Types.Add(t);
            }

            (new NewobjTransform()).TransformIL(usedTypes);
            //(new ArrayTransform()).TransformIL(usedTypes);
            (new FinalizerOptimization()).TransformIL(usedTypes);
            (new VirtualCallOptimization()).TransformIL(usedTypes);
            (new MainNoReturnCodeTransform()).TransformIL(usedTypes);
            RenameTransform.Rename(usedTypes);
            (new ThisParameterTransform()).TransformIL(usedTypes);
            (new DelegateTransform()).TransformIL(usedTypes);
            (new StringLiteralOptimization()).GlobalOptimization(usedTypes);
            (new ValueTypeOptimization()).TransformIL(usedTypes);
            (new IsInstanceOptimization()).TransformIL(usedTypes); // has to be before Interface Optimization (IsInterface is set to false there)
            (new InterfaceOptimization()).TransformIL(usedTypes);
            (new FinalizerImplementationOptimization()).TransformIL(usedTypes);
            (new ExceptionTransform()).TransformIL(usedTypes);
            (new StripExternalAnnotations()).TransformIL(usedTypes);
            //(new StripTryCatch()).TransformIL(usedTypes);

            // do this after ExceptionTransform as it will create default values.
            (new PrimitiveDefaultValues()).TransformIL(usedTypes);



            ILAstDebugPrinter.ClearLogs();

            ReferenceImportHelper.ImportReferences(mod);
            mod.Write(@"logs\compacted.dll");

            File.Copy("ESharpCore.dll", @"logs\ESharpCore.dll");

            // todo, just disabled temporarly because of poiter types resolving to null?? Should this happen?
            ReferenceChecker.CheckReferences(mod);

            var files = (new DecompilerService()).Generate(usedTypes, @"logs\compacted.dll").ToList();

            // file optimization
            var fileOptimizationContext = new FileOptimizationContext {
                UsedTypes = usedTypes
            };

            TypeEnumGenerator.FileOptimization(files, fileOptimizationContext);

            IncludeCFiles.Run(files);

            var mergedFiles = CMerger.MergeIntoSingleFile(files);

            return(mergedFiles);
        }
Exemple #18
0
 public Module([Import("ModuleParameters")] ModuleParameters moduleParameters) : base(moduleParameters)
 {
     ModuleInstance = this;
 }
        public DummyAssemblyGenerator(Metadata metadata, Il2Cpp il2Cpp)
        {
            this.metadata = metadata;
            this.il2Cpp   = il2Cpp;

            //Il2CppDummyDll
            var il2CppDummyDll = Il2CppDummyDll.Create();

            Assemblies.Add(il2CppDummyDll);
            var addressAttribute     = il2CppDummyDll.MainModule.Types.First(x => x.Name == "AddressAttribute").Methods[0];
            var fieldOffsetAttribute = il2CppDummyDll.MainModule.Types.First(x => x.Name == "FieldOffsetAttribute").Methods[0];

            attributeAttribute = il2CppDummyDll.MainModule.Types.First(x => x.Name == "AttributeAttribute").Methods[0];
            var metadataOffsetAttribute = il2CppDummyDll.MainModule.Types.First(x => x.Name == "MetadataOffsetAttribute").Methods[0];

            stringType = il2CppDummyDll.MainModule.TypeSystem.String;

            var resolver         = new MyAssemblyResolver();
            var moduleParameters = new ModuleParameters
            {
                Kind             = ModuleKind.Dll,
                AssemblyResolver = resolver
            };

            resolver.Register(il2CppDummyDll);

            var fieldDefinitionDic     = new Dictionary <int, FieldDefinition>();
            var methodDefinitionDic    = new Dictionary <int, MethodDefinition>();
            var parameterDefinitionDic = new Dictionary <int, ParameterDefinition>();
            var propertyDefinitionDic  = new Dictionary <int, PropertyDefinition>();
            var eventDefinitionDic     = new Dictionary <int, EventDefinition>();

            //创建程序集,同时创建所有类
            foreach (var imageDef in metadata.imageDefs)
            {
                var imageName          = metadata.GetStringFromIndex(imageDef.nameIndex);
                var assemblyName       = new AssemblyNameDefinition(imageName.Replace(".dll", ""), new Version("3.7.1.6"));
                var assemblyDefinition = AssemblyDefinition.CreateAssembly(assemblyName, imageName, moduleParameters);
                resolver.Register(assemblyDefinition);
                Assemblies.Add(assemblyDefinition);
                var moduleDefinition = assemblyDefinition.MainModule;
                moduleDefinition.Types.Clear();//清除自动创建的<Module>类
                var typeEnd = imageDef.typeStart + imageDef.typeCount;
                for (var index = imageDef.typeStart; index < typeEnd; ++index)
                {
                    var            typeDef       = metadata.typeDefs[index];
                    var            namespaceName = metadata.GetStringFromIndex(typeDef.namespaceIndex);
                    var            typeName      = metadata.GetStringFromIndex(typeDef.nameIndex);
                    TypeDefinition typeDefinition;
                    if (typeDef.declaringTypeIndex != -1)//nested types
                    {
                        typeDefinition = typeDefinitionDic[index];
                    }
                    else
                    {
                        typeDefinition = new TypeDefinition(namespaceName, typeName, (TypeAttributes)typeDef.flags);
                        moduleDefinition.Types.Add(typeDefinition);
                        typeDefinitionDic.Add(index, typeDefinition);
                    }
                    //nestedtype
                    for (int i = 0; i < typeDef.nested_type_count; i++)
                    {
                        var nestedIndex          = metadata.nestedTypeIndices[typeDef.nestedTypesStart + i];
                        var nestedTypeDef        = metadata.typeDefs[nestedIndex];
                        var nestedTypeDefinition = new TypeDefinition(metadata.GetStringFromIndex(nestedTypeDef.namespaceIndex), metadata.GetStringFromIndex(nestedTypeDef.nameIndex), (TypeAttributes)nestedTypeDef.flags);
                        typeDefinition.NestedTypes.Add(nestedTypeDefinition);
                        typeDefinitionDic.Add(nestedIndex, nestedTypeDefinition);
                    }
                }
            }
            //先单独处理,因为不知道会不会有问题
            for (var index = 0; index < metadata.typeDefs.Length; ++index)
            {
                var typeDef        = metadata.typeDefs[index];
                var typeDefinition = typeDefinitionDic[index];
                //parent
                if (typeDef.parentIndex >= 0)
                {
                    var parentType    = il2Cpp.types[typeDef.parentIndex];
                    var parentTypeRef = GetTypeReference(typeDefinition, parentType);
                    typeDefinition.BaseType = parentTypeRef;
                }
                //interfaces
                for (int i = 0; i < typeDef.interfaces_count; i++)
                {
                    var interfaceType    = il2Cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]];
                    var interfaceTypeRef = GetTypeReference(typeDefinition, interfaceType);
                    typeDefinition.Interfaces.Add(new InterfaceImplementation(interfaceTypeRef));
                }
            }
            //处理field, method, property等等
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                for (int index = imageDef.typeStart; index < typeEnd; index++)
                {
                    var typeDef        = metadata.typeDefs[index];
                    var typeDefinition = typeDefinitionDic[index];

                    //field
                    var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                    for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                    {
                        var fieldDef        = metadata.fieldDefs[i];
                        var fieldType       = il2Cpp.types[fieldDef.typeIndex];
                        var fieldName       = metadata.GetStringFromIndex(fieldDef.nameIndex);
                        var fieldTypeRef    = GetTypeReference(typeDefinition, fieldType);
                        var fieldDefinition = new FieldDefinition(fieldName, (FieldAttributes)fieldType.attrs, fieldTypeRef);
                        typeDefinition.Fields.Add(fieldDefinition);
                        fieldDefinitionDic.Add(i, fieldDefinition);
                        //fieldDefault
                        if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefault) && fieldDefault.dataIndex != -1)
                        {
                            if (TryGetDefaultValue(fieldDefault.typeIndex, fieldDefault.dataIndex, out var value))
                            {
                                fieldDefinition.Constant = value;
                            }
                            else
                            {
                                var customAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(metadataOffsetAttribute));
                                var offset          = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{value:X}"));
                                customAttribute.Fields.Add(offset);
                                fieldDefinition.CustomAttributes.Add(customAttribute);
                            }
                        }
                        //fieldOffset
                        if (!fieldDefinition.IsLiteral)
                        {
                            var fieldOffset = il2Cpp.GetFieldOffsetFromIndex(index, i - typeDef.fieldStart, i, typeDefinition.IsValueType, fieldDefinition.IsStatic);
                            if (fieldOffset >= 0)
                            {
                                var customAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(fieldOffsetAttribute));
                                var offset          = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{fieldOffset:X}"));
                                customAttribute.Fields.Add(offset);
                                fieldDefinition.CustomAttributes.Add(customAttribute);
                            }
                        }
                    }
                    //method
                    var methodEnd = typeDef.methodStart + typeDef.method_count;
                    for (var i = typeDef.methodStart; i < methodEnd; ++i)
                    {
                        var methodDef        = metadata.methodDefs[i];
                        var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                        var methodDefinition = new MethodDefinition(methodName, (MethodAttributes)methodDef.flags, typeDefinition.Module.ImportReference(typeof(void)));
                        methodDefinition.ImplAttributes = (MethodImplAttributes)methodDef.iflags;
                        typeDefinition.Methods.Add(methodDefinition);
                        var methodReturnType = il2Cpp.types[methodDef.returnType];
                        var returnType       = GetTypeReferenceWithByRef(methodDefinition, methodReturnType);
                        methodDefinition.ReturnType = returnType;
                        if (methodDefinition.HasBody && typeDefinition.BaseType?.FullName != "System.MulticastDelegate")
                        {
                            var ilprocessor = methodDefinition.Body.GetILProcessor();
                            if (returnType.FullName == "System.Void")
                            {
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
                            }
                            else if (returnType.IsValueType)
                            {
                                var variable = new VariableDefinition(returnType);
                                methodDefinition.Body.Variables.Add(variable);
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloca_S, variable));
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Initobj, returnType));
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0));
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
                            }
                            else
                            {
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ldnull));
                                ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
                            }
                        }
                        methodDefinitionDic.Add(i, methodDefinition);
                        //method parameter
                        for (var j = 0; j < methodDef.parameterCount; ++j)
                        {
                            var parameterDef        = metadata.parameterDefs[methodDef.parameterStart + j];
                            var parameterName       = metadata.GetStringFromIndex(parameterDef.nameIndex);
                            var parameterType       = il2Cpp.types[parameterDef.typeIndex];
                            var parameterTypeRef    = GetTypeReferenceWithByRef(methodDefinition, parameterType);
                            var parameterDefinition = new ParameterDefinition(parameterName, (ParameterAttributes)parameterType.attrs, parameterTypeRef);
                            methodDefinition.Parameters.Add(parameterDefinition);
                            parameterDefinitionDic.Add(methodDef.parameterStart + j, parameterDefinition);
                            //ParameterDefault
                            if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1)
                            {
                                if (TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value))
                                {
                                    parameterDefinition.Constant = value;
                                }
                                else
                                {
                                    var customAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(metadataOffsetAttribute));
                                    var offset          = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{value:X}"));
                                    customAttribute.Fields.Add(offset);
                                    parameterDefinition.CustomAttributes.Add(customAttribute);
                                }
                            }
                        }
                        //补充泛型参数
                        if (methodDef.genericContainerIndex >= 0)
                        {
                            var genericContainer = metadata.genericContainers[methodDef.genericContainerIndex];
                            if (genericContainer.type_argc > methodDefinition.GenericParameters.Count)
                            {
                                for (int j = 0; j < genericContainer.type_argc; j++)
                                {
                                    var genericParameterIndex = genericContainer.genericParameterStart + j;
                                    if (!genericParameterDic.TryGetValue(genericParameterIndex, out var genericParameter))
                                    {
                                        CreateGenericParameter(genericParameterIndex, methodDefinition);
                                    }
                                    else
                                    {
                                        if (!methodDefinition.GenericParameters.Contains(genericParameter))
                                        {
                                            methodDefinition.GenericParameters.Add(genericParameter);
                                        }
                                    }
                                }
                            }
                        }
                        //methodAddress
                        var methodPointer = il2Cpp.GetMethodPointer(methodDef, imageIndex);
                        if (methodPointer > 0)
                        {
                            var customAttribute    = new CustomAttribute(typeDefinition.Module.ImportReference(addressAttribute));
                            var fixedMethodPointer = il2Cpp.GetRVA(methodPointer);
                            var rva    = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{fixedMethodPointer:X}"));
                            var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2Cpp.MapVATR(methodPointer):X}"));
                            var va     = new CustomAttributeNamedArgument("VA", new CustomAttributeArgument(stringType, $"0x{methodPointer:X}"));
                            customAttribute.Fields.Add(rva);
                            customAttribute.Fields.Add(offset);
                            customAttribute.Fields.Add(va);
                            if (methodDef.slot != ushort.MaxValue)
                            {
                                var slot = new CustomAttributeNamedArgument("Slot", new CustomAttributeArgument(stringType, methodDef.slot.ToString()));
                                customAttribute.Fields.Add(slot);
                            }
                            methodDefinition.CustomAttributes.Add(customAttribute);
                        }
                    }
                    //property
                    var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                    for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                    {
                        var              propertyDef  = metadata.propertyDefs[i];
                        var              propertyName = metadata.GetStringFromIndex(propertyDef.nameIndex);
                        TypeReference    propertyType = null;
                        MethodDefinition GetMethod    = null;
                        MethodDefinition SetMethod    = null;
                        if (propertyDef.get >= 0)
                        {
                            GetMethod    = methodDefinitionDic[typeDef.methodStart + propertyDef.get];
                            propertyType = GetMethod.ReturnType;
                        }
                        if (propertyDef.set >= 0)
                        {
                            SetMethod = methodDefinitionDic[typeDef.methodStart + propertyDef.set];
                            if (propertyType == null)
                            {
                                propertyType = SetMethod.Parameters[0].ParameterType;
                            }
                        }
                        var propertyDefinition = new PropertyDefinition(propertyName, (PropertyAttributes)propertyDef.attrs, propertyType)
                        {
                            GetMethod = GetMethod,
                            SetMethod = SetMethod
                        };
                        typeDefinition.Properties.Add(propertyDefinition);
                        propertyDefinitionDic.Add(i, propertyDefinition);
                    }
                    //event
                    var eventEnd = typeDef.eventStart + typeDef.event_count;
                    for (var i = typeDef.eventStart; i < eventEnd; ++i)
                    {
                        var eventDef        = metadata.eventDefs[i];
                        var eventName       = metadata.GetStringFromIndex(eventDef.nameIndex);
                        var eventType       = il2Cpp.types[eventDef.typeIndex];
                        var eventTypeRef    = GetTypeReference(typeDefinition, eventType);
                        var eventDefinition = new EventDefinition(eventName, (EventAttributes)eventType.attrs, eventTypeRef);
                        if (eventDef.add >= 0)
                        {
                            eventDefinition.AddMethod = methodDefinitionDic[typeDef.methodStart + eventDef.add];
                        }
                        if (eventDef.remove >= 0)
                        {
                            eventDefinition.RemoveMethod = methodDefinitionDic[typeDef.methodStart + eventDef.remove];
                        }
                        if (eventDef.raise >= 0)
                        {
                            eventDefinition.InvokeMethod = methodDefinitionDic[typeDef.methodStart + eventDef.raise];
                        }
                        typeDefinition.Events.Add(eventDefinition);
                        eventDefinitionDic.Add(i, eventDefinition);
                    }
                    //补充泛型参数
                    if (typeDef.genericContainerIndex >= 0)
                    {
                        var genericContainer = metadata.genericContainers[typeDef.genericContainerIndex];
                        if (genericContainer.type_argc > typeDefinition.GenericParameters.Count)
                        {
                            for (int i = 0; i < genericContainer.type_argc; i++)
                            {
                                var genericParameterIndex = genericContainer.genericParameterStart + i;
                                if (!genericParameterDic.TryGetValue(genericParameterIndex, out var genericParameter))
                                {
                                    CreateGenericParameter(genericParameterIndex, typeDefinition);
                                }
                                else
                                {
                                    if (!typeDefinition.GenericParameters.Contains(genericParameter))
                                    {
                                        typeDefinition.GenericParameters.Add(genericParameter);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //第三遍,添加CustomAttribute
            if (il2Cpp.Version > 20)
            {
                PrepareCustomAttribute();
                foreach (var imageDef in metadata.imageDefs)
                {
                    var typeEnd = imageDef.typeStart + imageDef.typeCount;
                    for (int index = imageDef.typeStart; index < typeEnd; index++)
                    {
                        var typeDef        = metadata.typeDefs[index];
                        var typeDefinition = typeDefinitionDic[index];
                        //typeAttribute
                        CreateCustomAttribute(imageDef, typeDef.customAttributeIndex, typeDef.token, typeDefinition.Module, typeDefinition.CustomAttributes);

                        //field
                        var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                        for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                        {
                            var fieldDef        = metadata.fieldDefs[i];
                            var fieldDefinition = fieldDefinitionDic[i];
                            //fieldAttribute
                            CreateCustomAttribute(imageDef, fieldDef.customAttributeIndex, fieldDef.token, typeDefinition.Module, fieldDefinition.CustomAttributes);
                        }

                        //method
                        var methodEnd = typeDef.methodStart + typeDef.method_count;
                        for (var i = typeDef.methodStart; i < methodEnd; ++i)
                        {
                            var methodDef        = metadata.methodDefs[i];
                            var methodDefinition = methodDefinitionDic[i];
                            //methodAttribute
                            CreateCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, typeDefinition.Module, methodDefinition.CustomAttributes);

                            //method parameter
                            for (var j = 0; j < methodDef.parameterCount; ++j)
                            {
                                var parameterDef        = metadata.parameterDefs[methodDef.parameterStart + j];
                                var parameterDefinition = parameterDefinitionDic[methodDef.parameterStart + j];
                                //parameterAttribute
                                CreateCustomAttribute(imageDef, parameterDef.customAttributeIndex, parameterDef.token, typeDefinition.Module, parameterDefinition.CustomAttributes);
                            }
                        }

                        //property
                        var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                        for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                        {
                            var propertyDef        = metadata.propertyDefs[i];
                            var propertyDefinition = propertyDefinitionDic[i];
                            //propertyAttribute
                            CreateCustomAttribute(imageDef, propertyDef.customAttributeIndex, propertyDef.token, typeDefinition.Module, propertyDefinition.CustomAttributes);
                        }

                        //event
                        var eventEnd = typeDef.eventStart + typeDef.event_count;
                        for (var i = typeDef.eventStart; i < eventEnd; ++i)
                        {
                            var eventDef        = metadata.eventDefs[i];
                            var eventDefinition = eventDefinitionDic[i];
                            //eventAttribute
                            CreateCustomAttribute(imageDef, eventDef.customAttributeIndex, eventDef.token, typeDefinition.Module, eventDefinition.CustomAttributes);
                        }
                    }
                }
            }
        }
Exemple #20
0
        public static void Main(string[] args)
        {
            Console.WriteLine("===Cpp2IL by Samboy063===");
            Console.WriteLine("A Tool to Reverse Unity's \"il2cpp\" Build Process.");
            Console.WriteLine("Running on " + Environment.OSVersion.Platform);

            #region Command Line Parsing

            CommandLineOptions = null;
            Parser.Default.ParseArguments <Options>(args).WithParsed(options => { CommandLineOptions = options; });

            if (CommandLineOptions == null)
            {
                Console.WriteLine("Invalid command line. Exiting.");
                return;
            }

            var baseGamePath = CommandLineOptions.GamePath;

            Console.WriteLine("Using path: " + baseGamePath);

            if (!Directory.Exists(baseGamePath))
            {
                Console.WriteLine("Specified game-path does not exist: " + baseGamePath);
                return;
            }

            var assemblyPath = Path.Combine(baseGamePath, "GameAssembly.dll");
            var exeName      = Path.GetFileNameWithoutExtension(Directory.GetFiles(baseGamePath)
                                                                .First(f => f.EndsWith(".exe") && !BlacklistedExecutableFilenames.Any(bl => f.EndsWith(bl))));

            if (CommandLineOptions.ExeName != null)
            {
                exeName = CommandLineOptions.ExeName;
                Console.WriteLine($"Using OVERRIDDEN game name: {exeName}");
            }
            else
            {
                Console.WriteLine($"Auto-detected game name: {exeName}");
            }

            var unityPlayerPath = Path.Combine(baseGamePath, $"{exeName}.exe");
            var metadataPath    = Path.Combine(baseGamePath, $"{exeName}_Data", "il2cpp_data", "Metadata", "global-metadata.dat");

            if (!File.Exists(assemblyPath) || !File.Exists(unityPlayerPath) || !File.Exists(metadataPath))
            {
                Console.WriteLine("Invalid game-path or exe-name specified. Failed to find one of the following:\n" +
                                  $"\t{assemblyPath}\n" +
                                  $"\t{unityPlayerPath}\n" +
                                  $"\t{metadataPath}\n");
                return;
            }

            #endregion

            Console.WriteLine($"Located game EXE: {unityPlayerPath}");
            Console.WriteLine($"Located global-metadata: {metadataPath}");

            #region Unity Version Determination

            Console.WriteLine("\nAttempting to determine Unity version...");

            int[] unityVerUseful;
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                var unityVer = FileVersionInfo.GetVersionInfo(unityPlayerPath);

                unityVerUseful = new[] { unityVer.FileMajorPart, unityVer.FileMinorPart, unityVer.FileBuildPart };
            }
            else
            {
                //Globalgamemanagers
                var globalgamemanagersPath = Path.Combine(baseGamePath, $"{exeName}_Data", "globalgamemanagers");
                var ggmBytes  = File.ReadAllBytes(globalgamemanagersPath);
                var verString = new StringBuilder();
                var idx       = 0x14;
                while (ggmBytes[idx] != 0)
                {
                    verString.Append(Convert.ToChar(ggmBytes[idx]));
                    idx++;
                }

                var unityVer = verString.ToString();
                unityVer = unityVer.Substring(0, unityVer.IndexOf("f", StringComparison.Ordinal));
                Console.WriteLine("Read version string from globalgamemanagers: " + unityVer);
                unityVerUseful = unityVer.Split(".").Select(int.Parse).ToArray();
            }

            Console.WriteLine("This game is built with Unity version " + string.Join(".", unityVerUseful));

            if (unityVerUseful[0] <= 4)
            {
                Console.WriteLine("Unable to determine a valid unity version. Aborting.");
                return;
            }

            #endregion

            LibCpp2IlMain.Settings.AllowManualMetadataAndCodeRegInput = true;

            if (!LibCpp2IlMain.LoadFromFile(assemblyPath, metadataPath, unityVerUseful))
            {
                Console.WriteLine("Initialization with LibCpp2IL failed.");
                return;
            }

            Console.WriteLine(LibCpp2IlReflection.GetType("String", "System").DeclaringAssembly.Name);

            //Dump DLLs

            #region Assembly Generation

            var resolver     = new RegistryAssemblyResolver();
            var moduleParams = new ModuleParameters
            {
                Kind             = ModuleKind.Dll,
                AssemblyResolver = resolver,
                MetadataResolver = new MetadataResolver(resolver)
            };


            Console.WriteLine("Building assemblies...");
            Console.WriteLine("\tPass 1: Creating empty types...");

            Assemblies = AssemblyBuilder.CreateAssemblies(LibCpp2IlMain.TheMetadata !, resolver, moduleParams);

            Utils.BuildPrimitiveMappings();

            Console.WriteLine("\tPass 2: Setting parents and handling inheritance...");

            //Stateful method, no return value
            AssemblyBuilder.ConfigureHierarchy(LibCpp2IlMain.TheMetadata, LibCpp2IlMain.ThePe !);

            Console.WriteLine("\tPass 3: Populating types...");

            var methods = new List <(TypeDefinition type, List <CppMethodData> methods)>();

            //Create out dirs if needed
            var outputPath = Path.GetFullPath("cpp2il_out");
            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }

            var methodOutputDir = Path.Combine(outputPath, "types");
            if (!(CommandLineOptions.SkipAnalysis && CommandLineOptions.SkipMetadataTextFiles) && !Directory.Exists(methodOutputDir))
            {
                Directory.CreateDirectory(methodOutputDir);
            }

            for (var imageIndex = 0; imageIndex < LibCpp2IlMain.TheMetadata.assemblyDefinitions.Length; imageIndex++)
            {
                var imageDef = LibCpp2IlMain.TheMetadata.assemblyDefinitions[imageIndex];

                Console.WriteLine($"\t\tPopulating {imageDef.typeCount} types in assembly {imageIndex + 1} of {LibCpp2IlMain.TheMetadata.assemblyDefinitions.Length}: {imageDef.Name}...");

                var assemblySpecificPath = Path.Combine(methodOutputDir, imageDef.Name.Replace(".dll", ""));
                if (!(CommandLineOptions.SkipMetadataTextFiles && CommandLineOptions.SkipAnalysis) && !Directory.Exists(assemblySpecificPath))
                {
                    Directory.CreateDirectory(assemblySpecificPath);
                }

                methods.AddRange(AssemblyBuilder.ProcessAssemblyTypes(LibCpp2IlMain.TheMetadata, LibCpp2IlMain.ThePe, imageDef));
            }

            //Invert dict for CppToMono
            SharedState.CppToMonoTypeDefs = SharedState.MonoToCppTypeDefs.ToDictionary(i => i.Value, i => i.Key);

            Console.WriteLine("\tPass 4: Handling SerializeFields...");
            //Add serializefield to monobehaviors

            #region SerializeFields

            var unityEngineAssembly = Assemblies.Find(x => x.MainModule.Types.Any(t => t.Namespace == "UnityEngine" && t.Name == "SerializeField"));
            if (unityEngineAssembly != null)
            {
                var serializeFieldMethod = unityEngineAssembly.MainModule.Types.First(x => x.Name == "SerializeField").Methods.First();
                foreach (var imageDef in LibCpp2IlMain.TheMetadata.assemblyDefinitions)
                {
                    var lastTypeIndex = imageDef.firstTypeIndex + imageDef.typeCount;
                    for (var typeIndex = imageDef.firstTypeIndex; typeIndex < lastTypeIndex; typeIndex++)
                    {
                        var typeDef        = LibCpp2IlMain.TheMetadata.typeDefs[typeIndex];
                        var typeDefinition = SharedState.TypeDefsByIndex[typeIndex];

                        //Fields
                        var lastFieldIdx = typeDef.firstFieldIdx + typeDef.field_count;
                        for (var fieldIdx = typeDef.firstFieldIdx; fieldIdx < lastFieldIdx; ++fieldIdx)
                        {
                            var fieldDef        = LibCpp2IlMain.TheMetadata.fieldDefs[fieldIdx];
                            var fieldName       = LibCpp2IlMain.TheMetadata.GetStringFromIndex(fieldDef.nameIndex);
                            var fieldDefinition = typeDefinition.Fields.First(x => x.Name == fieldName);

                            //Get attributes and look for the serialize field attribute.
                            var attributeIndex = LibCpp2IlMain.TheMetadata.GetCustomAttributeIndex(imageDef, fieldDef.customAttributeIndex, fieldDef.token);
                            if (attributeIndex < 0)
                            {
                                continue;
                            }
                            var attributeTypeRange = LibCpp2IlMain.TheMetadata.attributeTypeRanges[attributeIndex];
                            for (var attributeIdxIdx = 0; attributeIdxIdx < attributeTypeRange.count; attributeIdxIdx++)
                            {
                                var attributeTypeIndex = LibCpp2IlMain.TheMetadata.attributeTypes[attributeTypeRange.start + attributeIdxIdx];
                                var attributeType      = LibCpp2IlMain.ThePe.types[attributeTypeIndex];
                                if (attributeType.type != Il2CppTypeEnum.IL2CPP_TYPE_CLASS)
                                {
                                    continue;
                                }
                                var cppAttribType = LibCpp2IlMain.TheMetadata.typeDefs[attributeType.data.classIndex];
                                var attributeName = LibCpp2IlMain.TheMetadata.GetStringFromIndex(cppAttribType.nameIndex);
                                if (attributeName != "SerializeField")
                                {
                                    continue;
                                }
                                var customAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(serializeFieldMethod));
                                fieldDefinition.CustomAttributes.Add(customAttribute);
                            }
                        }
                    }
                }
            }

            #endregion

            KeyFunctionAddresses keyFunctionAddresses = null;
            if (!CommandLineOptions.SkipAnalysis)
            {
                Console.WriteLine("\tPass 5: Locating Globals...");

                Console.WriteLine($"\t\tFound {LibCpp2IlGlobalMapper.TypeRefs.Count} type globals");
                Console.WriteLine($"\t\tFound {LibCpp2IlGlobalMapper.MethodRefs.Count} method globals");
                Console.WriteLine($"\t\tFound {LibCpp2IlGlobalMapper.FieldRefs.Count} field globals");
                Console.WriteLine($"\t\tFound {LibCpp2IlGlobalMapper.Literals.Count} string literals");

                //TODO: Don't do this. Rework everything to use the API surface.
                SharedState.Globals.AddRange(LibCpp2IlGlobalMapper.TypeRefs);
                SharedState.Globals.AddRange(LibCpp2IlGlobalMapper.MethodRefs);
                SharedState.Globals.AddRange(LibCpp2IlGlobalMapper.FieldRefs);
                SharedState.Globals.AddRange(LibCpp2IlGlobalMapper.Literals);

                foreach (var globalIdentifier in SharedState.Globals)
                {
                    SharedState.GlobalsByOffset[globalIdentifier.Offset] = globalIdentifier;
                }

                Console.WriteLine("\tPass 6: Looking for key functions...");

                //This part involves decompiling known functions to search for other function calls

                Disassembler.Translator.IncludeAddress = true;
                Disassembler.Translator.IncludeBinary  = true;

                keyFunctionAddresses = KeyFunctionAddresses.Find(methods, LibCpp2IlMain.ThePe);
            }

            #endregion

            Console.WriteLine("Saving Header DLLs to " + outputPath + "...");

            GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency;

            foreach (var assembly in Assemblies)
            {
                var dllPath = Path.Combine(outputPath, assembly.MainModule.Name);

                var reference = assembly.MainModule.AssemblyReferences.FirstOrDefault(a => a.Name == "System.Private.CoreLib");
                if (reference != null)
                {
                    assembly.MainModule.AssemblyReferences.Remove(reference);
                }

                assembly.Write(dllPath);

                if (assembly.Name.Name != "Assembly-CSharp" || CommandLineOptions.SkipAnalysis)
                {
                    continue;
                }

                Console.WriteLine("Dumping method bytes to " + methodOutputDir);
                Directory.CreateDirectory(Path.Combine(methodOutputDir, assembly.Name.Name));
                //Write methods

                var allUsedMnemonics = new List <ud_mnemonic_code>();

                var counter   = 0;
                var toProcess = methods.Where(tuple => tuple.type.Module.Assembly == assembly).ToList();

                //Sort alphabetically by type.
                toProcess.Sort((a, b) => String.Compare(a.type.FullName, b.type.FullName, StringComparison.Ordinal));
                var thresholds = new[] { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }.ToList();
                var nextThreshold = thresholds.First();

                var successfullyProcessed = 0;
                var failedProcess         = 0;

                var startTime = DateTime.Now;

                var methodTaintDict = new ConcurrentDictionary <string, AsmDumper.TaintReason>();

                thresholds.RemoveAt(0);


                Action <(TypeDefinition type, List <CppMethodData> methods)> action = tuple =>
                {
                    var(type, methodData) = tuple;
                    counter++;
                    var pct = 100 * ((decimal)counter / toProcess.Count);
                    if (pct > nextThreshold)
                    {
                        lock (thresholds)
                        {
                            //Check again to prevent races
                            if (pct > nextThreshold)
                            {
                                var elapsedSoFar = DateTime.Now - startTime;
                                var rate         = counter / elapsedSoFar.TotalSeconds;
                                var remaining    = toProcess.Count - counter;
                                Console.WriteLine($"{nextThreshold}% ({counter} classes in {Math.Round(elapsedSoFar.TotalSeconds)} sec, ~{Math.Round(rate)} classes / sec, {remaining} classes remaining, approx {Math.Round(remaining / rate + 5)} sec remaining)");
                                nextThreshold = thresholds.First();
                                thresholds.RemoveAt(0);
                            }
                        }
                    }

                    // Console.WriteLine($"\t-Dumping methods in type {counter}/{methodBytes.Count}: {type.Key}");
                    try
                    {
                        var filename = Path.Combine(methodOutputDir, assembly.Name.Name, type.Name.Replace("<", "_").Replace(">", "_").Replace("|", "_") + "_methods.txt");
                        var typeDump = new StringBuilder("Type: " + type.Name + "\n\n");

                        foreach (var method in methodData)
                        {
                            var methodStart = method.MethodOffsetRam;

                            if (methodStart == 0)
                            {
                                continue;
                            }

                            var methodDefinition = SharedState.MethodsByIndex[method.MethodId];

                            var taintResult = new AsmDumper(methodDefinition, method, methodStart, keyFunctionAddresses !, LibCpp2IlMain.ThePe)
                                              .AnalyzeMethod(typeDump, ref allUsedMnemonics);

                            var key = new StringBuilder();

                            key.Append(methodDefinition.DeclaringType.FullName).Append("::").Append(methodDefinition.Name);

                            methodDefinition.MethodSignatureFullName(key);

                            methodTaintDict[key.ToString()] = taintResult;

                            if (taintResult != AsmDumper.TaintReason.UNTAINTED)
                            {
                                Interlocked.Increment(ref failedProcess);
                            }
                            else
                            {
                                Interlocked.Increment(ref successfullyProcessed);
                            }
                        }

                        lock (type)
                            File.WriteAllText(filename, typeDump.ToString());
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Failed to dump methods for type " + type.Name + " " + e);
                    }
                };


                var parallel = false;

                if (parallel)
                {
                    toProcess.AsParallel().ForAll(action);
                }
                else
                {
                    toProcess.ForEach(action);
                }


                var total = successfullyProcessed + failedProcess;

                var elapsed = DateTime.Now - startTime;
                Console.WriteLine($"Finished method processing in {elapsed.Ticks} ticks (about {Math.Round(elapsed.TotalSeconds, 1)} seconds), at an overall rate of about {Math.Round(toProcess.Count / elapsed.TotalSeconds)} methods/sec");
                Console.WriteLine($"Processed {total} methods, {successfullyProcessed} ({Math.Round(successfullyProcessed * 100.0 / total, 2)}%) successfully, {failedProcess} ({Math.Round(failedProcess * 100.0 / total, 2)}%) with errors.");

                Console.WriteLine("Breakdown By Taint Reason:");
                foreach (var reason in Enum.GetValues(typeof(AsmDumper.TaintReason)))
                {
                    var count = (decimal)methodTaintDict.Values.Count(v => v == (AsmDumper.TaintReason)reason);
                    Console.WriteLine($"{reason}: {count} (about {Math.Round(count * 100 / total, 1)}%)");
                }

                var summary = new StringBuilder();
                foreach (var keyValuePair in methodTaintDict)
                {
                    summary.Append("\t")
                    .Append(keyValuePair.Key)
                    .Append(Utils.Repeat(" ", 250 - keyValuePair.Key.Length))
                    .Append(keyValuePair.Value)
                    .Append(" (")
                    .Append((int)keyValuePair.Value)
                    .Append(")")
                    .Append("\n");
                }

#if DUMP_PACKAGE_SUCCESS_DATA
                Console.WriteLine("By Package:");
                var keys = methodTaintDict
                           .Select(kvp => kvp.Key)
                           .GroupBy(
                    GetPackageName,
                    className => className,
                    (packageName, classEnumerable) => new
                {
                    package = packageName,
                    classes = classEnumerable.ToList()
                })
                           .ToList();

                foreach (var key in keys)
                {
                    var resultLine      = new StringBuilder();
                    var totalClassCount = key.classes.Count;
                    resultLine.Append($"\tIn package {key.package} ({totalClassCount} classes):   ");

                    foreach (var reason in Enum.GetValues(typeof(AsmDumper.TaintReason)))
                    {
                        var count = (decimal)methodTaintDict.Where(kvp => key.classes.Contains(kvp.Key)).Count(v => v.Value == (AsmDumper.TaintReason)reason);
                        resultLine.Append(reason).Append(":").Append(count).Append($" ({Math.Round(count * 100 / totalClassCount, 1)}%)   ");
                    }

                    Console.WriteLine(resultLine.ToString());
                }
#endif


                File.WriteAllText(Path.Combine(outputPath, "method_statuses.txt"), summary.ToString());
                Console.WriteLine($"Wrote file: {Path.Combine(outputPath, "method_statuses.txt")}");

                // Console.WriteLine("Assembly uses " + allUsedMnemonics.Count + " mnemonics");
            }

            // Console.WriteLine("[Finished. Press enter to exit]");
            // Console.ReadLine();
        }
Exemple #21
0
        public static void Main(string[] args)
        {
            Console.WriteLine("===Cpp2IL by Samboy063===");
            Console.WriteLine("A Tool to Reverse Unity's \"il2cpp\" Build Process.");
            Console.WriteLine("Running on " + Environment.OSVersion.Platform);

            Options commandLineOptions = null;

            Parser.Default.ParseArguments <Options>(args).WithParsed(options =>
            {
                commandLineOptions = options;
            });

            if (commandLineOptions == null)
            {
                return;
            }

            string loc;

            //TODO: No longer needed
            // if (Environment.OSVersion.Platform == PlatformID.Win32Windows || Environment.OSVersion.Platform == PlatformID.Win32NT)
            // {
            //     loc = Registry.GetValue(
            //         "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 1020340",
            //         "InstallLocation", null) as string;
            // }
            // else if (Environment.OSVersion.Platform == PlatformID.Unix)
            // {
            //     // $HOME/.local/share/Steam/steamapps/common/Audica
            //     loc = Environment.GetEnvironmentVariable("HOME") + "/.local/share/Steam/steamapps/common/Audica";
            // }
            // else
            // {
            //     loc = null;
            // }
            //
            // if (args.Length != 1 && loc == null)
            // {
            //     Console.WriteLine(
            //         "Couldn't auto-detect Audica installation folder (via steam), and you didn't tell me where it is.");
            //     PrintUsage();
            //     return;
            // }

            var baseGamePath = commandLineOptions.GamePath;

            Console.WriteLine("Using path: " + baseGamePath);

            if (!Directory.Exists(baseGamePath))
            {
                Console.WriteLine("Specified path does not exist: " + baseGamePath);
                PrintUsage();
                return;
            }

            var assemblyPath = Path.Combine(baseGamePath, "GameAssembly.dll");
            var exeName      = Path.GetFileNameWithoutExtension(Directory.GetFiles(baseGamePath).First(f => f.EndsWith(".exe") && !blacklistedExecutableFilenames.Contains(f)));

            if (commandLineOptions.ExeName != null)
            {
                exeName = commandLineOptions.ExeName;
                Console.WriteLine($"Using OVERRIDDEN game name: {exeName}");
            }
            else
            {
                Console.WriteLine($"Auto-detected game name: {exeName}");
            }

            var unityPlayerPath = Path.Combine(baseGamePath, $"{exeName}.exe");
            var metadataPath    = Path.Combine(baseGamePath, $"{exeName}_Data", "il2cpp_data", "Metadata",
                                               "global-metadata.dat");

            if (!File.Exists(assemblyPath) || !File.Exists(unityPlayerPath) || !File.Exists(metadataPath))
            {
                Console.WriteLine("Invalid path specified. Failed to find one of the following:\n" +
                                  $"\t{assemblyPath}\n" +
                                  $"\t{unityPlayerPath}\n" +
                                  $"\t{metadataPath}\n");
                PrintUsage();
                return;
            }

            Console.WriteLine($"Located game EXE: {unityPlayerPath}");
            Console.WriteLine($"Located global-metadata: {metadataPath}");

            Console.WriteLine("\nAttempting to determine Unity version...");

            var unityVer = FileVersionInfo.GetVersionInfo(unityPlayerPath);

            var unityVerUseful = new[] { unityVer.FileMajorPart, unityVer.FileMinorPart, unityVer.FileBuildPart };

            Console.WriteLine("This game is built with Unity version " + string.Join(".", unityVerUseful));

            if (unityVerUseful[0] <= 4)
            {
                Console.WriteLine("Unable to determine a valid unity version. Aborting.");
                return;
            }

            Console.WriteLine("Reading metadata...");
            Metadata = Il2CppMetadata.ReadFrom(metadataPath, unityVerUseful);

            Console.WriteLine("Reading binary / game assembly...");
            var PEBytes = File.ReadAllBytes(assemblyPath);

            Console.WriteLine($"\t-Initializing MemoryStream of {PEBytes.Length} bytes, parsing sections, and initializing with auto+ mode.");

            ThePE = new PE.PE(new MemoryStream(PEBytes, 0, PEBytes.Length, false, true), Metadata.maxMetadataUsages);
            if (!ThePE.PlusSearch(Metadata.methodDefs.Count(x => x.methodIndex >= 0), Metadata.typeDefs.Length))
            {
                Console.WriteLine("Initialize failed. Aborting.");
                return;
            }

            //Dump DLLs

            #region Assembly Generation

            var resolver     = new RegistryAssemblyResolver();
            var moduleParams = new ModuleParameters
            {
                Kind             = ModuleKind.Dll,
                AssemblyResolver = resolver,
                MetadataResolver = new MetadataResolver(resolver)
            };


            Console.WriteLine("Building assemblies...");
            Console.WriteLine("\tPass 1: Creating types...");

            Assemblies = AssemblyBuilder.CreateAssemblies(Metadata, resolver, moduleParams);

            Console.WriteLine("\tPass 2: Setting parents and handling inheritance...");

            //Stateful method, no return value
            AssemblyBuilder.ConfigureHierarchy(Metadata, ThePE);

            Console.WriteLine("\tPass 3: Handling Fields, methods, and properties (THIS MAY TAKE A WHILE)...");

            var methods = new List <(TypeDefinition type, List <CppMethodData> methods)>();
            for (var imageIndex = 0; imageIndex < Metadata.assemblyDefinitions.Length; imageIndex++)
            {
                Console.WriteLine($"\t\tProcessing DLL {imageIndex + 1} of {Metadata.assemblyDefinitions.Length}...");
                methods.AddRange(AssemblyBuilder.ProcessAssemblyTypes(Metadata, ThePE, Metadata.assemblyDefinitions[imageIndex]));
            }

            //Invert dict for CppToMono
            SharedState.CppToMonoTypeDefs = SharedState.MonoToCppTypeDefs.ToDictionary(i => i.Value, i => i.Key);

            Console.WriteLine("\tPass 4: Handling SerializeFields...");
            //Add serializefield to monobehaviors

            #region SerializeFields

            var unityEngineAssembly = Assemblies.Find(x => x.MainModule.Types.Any(t => t.Namespace == "UnityEngine" && t.Name == "SerializeField"));
            if (unityEngineAssembly != null)
            {
                var serializeFieldMethod = unityEngineAssembly.MainModule.Types.First(x => x.Name == "SerializeField").Methods.First();
                foreach (var imageDef in Metadata.assemblyDefinitions)
                {
                    var lastTypeIndex = imageDef.firstTypeIndex + imageDef.typeCount;
                    for (var typeIndex = imageDef.firstTypeIndex; typeIndex < lastTypeIndex; typeIndex++)
                    {
                        var typeDef        = Metadata.typeDefs[typeIndex];
                        var typeDefinition = SharedState.TypeDefsByIndex[typeIndex];

                        //Fields
                        var lastFieldIdx = typeDef.firstFieldIdx + typeDef.field_count;
                        for (var fieldIdx = typeDef.firstFieldIdx; fieldIdx < lastFieldIdx; ++fieldIdx)
                        {
                            var fieldDef        = Metadata.fieldDefs[fieldIdx];
                            var fieldName       = Metadata.GetStringFromIndex(fieldDef.nameIndex);
                            var fieldDefinition = typeDefinition.Fields.First(x => x.Name == fieldName);

                            //Get attributes and look for the serialize field attribute.
                            var attributeIndex = Metadata.GetCustomAttributeIndex(imageDef, fieldDef.customAttributeIndex, fieldDef.token);
                            if (attributeIndex < 0)
                            {
                                continue;
                            }
                            var attributeTypeRange = Metadata.attributeTypeRanges[attributeIndex];
                            for (var attributeIdxIdx = 0; attributeIdxIdx < attributeTypeRange.count; attributeIdxIdx++)
                            {
                                var attributeTypeIndex = Metadata.attributeTypes[attributeTypeRange.start + attributeIdxIdx];
                                var attributeType      = ThePE.types[attributeTypeIndex];
                                if (attributeType.type != Il2CppTypeEnum.IL2CPP_TYPE_CLASS)
                                {
                                    continue;
                                }
                                var cppAttribType = Metadata.typeDefs[attributeType.data.classIndex];
                                var attributeName = Metadata.GetStringFromIndex(cppAttribType.nameIndex);
                                if (attributeName != "SerializeField")
                                {
                                    continue;
                                }
                                var customAttribute = new CustomAttribute(typeDefinition.Module.ImportReference(serializeFieldMethod));
                                fieldDefinition.CustomAttributes.Add(customAttribute);
                            }
                        }
                    }
                }
            }

            #endregion

            KeyFunctionAddresses keyFunctionAddresses = null;
            if (!commandLineOptions.SkipAnalysis)
            {
                Console.WriteLine("\tPass 5: Locating Globals...");

                var globals = AssemblyBuilder.MapGlobalIdentifiers(Metadata, ThePE);

                Console.WriteLine($"\t\tFound {globals.Count(g => g.IdentifierType == GlobalIdentifier.Type.TYPE)} type globals");
                Console.WriteLine($"\t\tFound {globals.Count(g => g.IdentifierType == GlobalIdentifier.Type.METHOD)} method globals");
                Console.WriteLine($"\t\tFound {globals.Count(g => g.IdentifierType == GlobalIdentifier.Type.FIELD)} field globals");
                Console.WriteLine($"\t\tFound {globals.Count(g => g.IdentifierType == GlobalIdentifier.Type.LITERAL)} string literals");

                SharedState.Globals.AddRange(globals);

                foreach (var globalIdentifier in globals)
                {
                    SharedState.GlobalsDict[globalIdentifier.Offset] = globalIdentifier;
                }

                Console.WriteLine("\tPass 6: Looking for key functions...");

                //This part involves decompiling known functions to search for other function calls

                Disassembler.Translator.IncludeAddress = true;
                Disassembler.Translator.IncludeBinary  = true;

                keyFunctionAddresses = KeyFunctionAddresses.Find(methods, ThePE);
            }

            #endregion

            Utils.BuildPrimitiveMappings();

            var outputPath = Path.GetFullPath("cpp2il_out");
            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }

            var methodOutputDir = Path.Combine(outputPath, "types");
            if (!Directory.Exists(methodOutputDir))
            {
                Directory.CreateDirectory(methodOutputDir);
            }

            Console.WriteLine("Saving Header DLLs to " + outputPath + "...");

            GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency;

            foreach (var assembly in Assemblies)
            {
                var dllPath = Path.Combine(outputPath, assembly.MainModule.Name);

                assembly.Write(dllPath);

                if (assembly.Name.Name != "Assembly-CSharp" || commandLineOptions.SkipAnalysis)
                {
                    continue;
                }

                Console.WriteLine("Dumping method bytes to " + methodOutputDir);
                Directory.CreateDirectory(Path.Combine(methodOutputDir, assembly.Name.Name));
                //Write methods

                var imageIndex       = Assemblies.IndexOf(assembly);
                var allUsedMnemonics = new List <ud_mnemonic_code>();

                var counter   = 0;
                var toProcess = methods.Where(tuple => tuple.type.Module.Assembly == assembly).ToList();

                //Sort alphabetically by type.
                toProcess.Sort((a, b) => String.Compare(a.type.FullName, b.type.FullName, StringComparison.Ordinal));
                var thresholds = new[] { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }.ToList();
                var nextThreshold = thresholds.First();

                var successfullyProcessed = 0;
                var failedProcess         = 0;

                var startTime = DateTime.Now;

                var methodTaintDict = new ConcurrentDictionary <string, AsmDumper.TaintReason>();

                thresholds.RemoveAt(0);
                toProcess
                .AsParallel()
                .ForAll(tuple =>
                {
                    var(type, methodData) = tuple;
                    counter++;
                    var pct = 100 * ((decimal)counter / toProcess.Count);
                    if (pct > nextThreshold)
                    {
                        lock (thresholds)
                        {
                            //Check again to prevent races
                            if (pct > nextThreshold)
                            {
                                var elapsedSoFar = DateTime.Now - startTime;
                                var rate         = counter / elapsedSoFar.TotalSeconds;
                                var remaining    = toProcess.Count - counter;
                                Console.WriteLine($"{nextThreshold}% ({counter} classes in {Math.Round(elapsedSoFar.TotalSeconds)} sec, ~{Math.Round(rate)} classes / sec, {remaining} classes remaining, approx {Math.Round(remaining / rate + 5)} sec remaining)");
                                nextThreshold = thresholds.First();
                                thresholds.RemoveAt(0);
                            }
                        }
                    }

                    // Console.WriteLine($"\t-Dumping methods in type {counter}/{methodBytes.Count}: {type.Key}");
                    try
                    {
                        var filename = Path.Combine(methodOutputDir, assembly.Name.Name, type.Name.Replace("<", "_").Replace(">", "_") + "_methods.txt");
                        var typeDump = new StringBuilder("Type: " + type.Name + "\n\n");

                        foreach (var method in methodData)
                        {
                            var methodDef        = Metadata.methodDefs[method.MethodId];
                            var methodStart      = method.MethodOffsetRam;
                            var methodDefinition = SharedState.MethodsByIndex[method.MethodId];

                            var taintResult = new AsmDumper(methodDefinition, method, methodStart, keyFunctionAddresses, ThePE)
                                              .AnalyzeMethod(typeDump, ref allUsedMnemonics);

                            var key = new StringBuilder();

                            key.Append(methodDefinition.DeclaringType.FullName).Append("::").Append(methodDefinition.Name);

                            methodDefinition.MethodSignatureFullName(key);

                            methodTaintDict[key.ToString()] = taintResult;

                            if (taintResult != AsmDumper.TaintReason.UNTAINTED)
                            {
                                Interlocked.Increment(ref failedProcess);
                            }
                            else
                            {
                                Interlocked.Increment(ref successfullyProcessed);
                            }
                        }

                        lock (type)
                            File.WriteAllText(filename, typeDump.ToString());
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Failed to dump methods for type " + type.Name + " " + e);
                    }
                });

                var total = successfullyProcessed + failedProcess;

                var elapsed = DateTime.Now - startTime;
                Console.WriteLine($"Finished method processing in {elapsed.Ticks} ticks (about {Math.Round(elapsed.TotalSeconds, 1)} seconds), at an overall rate of about {Math.Round(toProcess.Count / elapsed.TotalSeconds)} methods/sec");
                Console.WriteLine($"Processed {total} methods, {successfullyProcessed} ({Math.Round(successfullyProcessed * 100.0 / total, 2)}%) successfully, {failedProcess} ({Math.Round(failedProcess * 100.0 / total, 2)}%) with errors.");

                Console.WriteLine("Breakdown By Taint Reason:");
                foreach (var reason in Enum.GetValues(typeof(AsmDumper.TaintReason)))
                {
                    var count = (decimal)methodTaintDict.Values.Count(v => v == (AsmDumper.TaintReason)reason);
                    Console.WriteLine($"{reason}: {count} (about {Math.Round(count * 100 / total, 1)}%)");
                }

                var summary = new StringBuilder();
                foreach (var keyValuePair in methodTaintDict)
                {
                    summary.Append("\t")
                    .Append(keyValuePair.Key)
                    .Append(Utils.Repeat(" ", 250 - keyValuePair.Key.Length))
                    .Append(keyValuePair.Value)
                    .Append(" (")
                    .Append((int)keyValuePair.Value)
                    .Append(")")
                    .Append("\n");
                }

                if (false)
                {
                    Console.WriteLine("By Package:");
                    var keys = methodTaintDict
                               .Select(kvp => kvp.Key)
                               .GroupBy(
                        GetPackageName,
                        className => className,
                        (packageName, keys) => new
                    {
                        package = packageName,
                        classes = keys.ToList()
                    })
                               .ToList();

                    foreach (var key in keys)
                    {
                        var resultLine      = new StringBuilder();
                        var totalClassCount = key.classes.Count;
                        resultLine.Append($"\tIn package {key.package} ({totalClassCount} classes):   ");

                        foreach (var reason in Enum.GetValues(typeof(AsmDumper.TaintReason)))
                        {
                            var count = (decimal)methodTaintDict.Where(kvp => key.classes.Contains(kvp.Key)).Count(v => v.Value == (AsmDumper.TaintReason)reason);
                            resultLine.Append(reason).Append(":").Append(count).Append($" ({Math.Round(count * 100 / totalClassCount, 1)}%)   ");
                        }

                        Console.WriteLine(resultLine.ToString());
                    }
                }


                File.WriteAllText(Path.Combine(outputPath, "method_statuses.txt"), summary.ToString());
                Console.WriteLine($"Wrote file: {Path.Combine(outputPath, "method_statuses.txt")}");

                // Console.WriteLine("Assembly uses " + allUsedMnemonics.Count + " mnemonics");
            }

            // Console.WriteLine("[Finished. Press enter to exit]");
            // Console.ReadLine();
        }
        public void CreateClientDll(Stream stream)
        {
            var transformedTypes = this.typeMapper.TransformedTypes.ToList();

            // Use Pomona.Client lib as starting point!
            AssemblyDefinition assembly;

            this.assemblyName = this.typeMapper.Filter.GetClientAssemblyName();

            var assemblyResolver = GetAssemblyResolver();

            var version = new Version(string.Join(".", this.typeMapper.Filter.ApiVersion.Split('.').Pad(4, "0").Take(4)));
            if (PomonaClientEmbeddingEnabled)
            {
                var readerParameters = new ReaderParameters { AssemblyResolver = assemblyResolver };
                assembly = AssemblyDefinition.ReadAssembly(typeof(ResourceBase).Assembly.Location, readerParameters);
                assembly.CustomAttributes.Clear();
            }
            else
            {
                var moduleParameters = new ModuleParameters
                {
                    Kind = ModuleKind.Dll,
                    AssemblyResolver = assemblyResolver
                };
                assembly =
                    AssemblyDefinition.CreateAssembly(
                        new AssemblyNameDefinition(this.assemblyName, version),
                        this.assemblyName,
                        moduleParameters);
            }

            assembly.Name = new AssemblyNameDefinition(this.assemblyName, version);

            //var assembly =
            //    AssemblyDefinition.CreateAssembly(
            //        new AssemblyNameDefinition("Critter", new Version(1, 0, 0, 134)), "Critter", ModuleKind.Dll);

            this.module = assembly.MainModule;
            this.module.Name = this.assemblyName + ".dll";
            this.module.Mvid = Guid.NewGuid();

            this.clientTypeInfoDict = new Dictionary<TypeSpec, TypeCodeGenInfo>();
            this.enumClientTypeDict = new Dictionary<EnumTypeSpec, TypeReference>();

            BuildEnumTypes();

            BuildInterfacesAndPocoTypes(transformedTypes);

            CreateProxies(
                new WrappedPropertyProxyBuilder(
                    this.module,
                    GetProxyType("LazyProxyBase"),
                    Import(typeof(PropertyWrapper<,>)).Resolve()),
                (info, def) => { info.LazyProxyType = def; });

            CreateProxies(
                new PatchFormProxyBuilder(this, MakeProxyTypesPublic),
                (info, def) => { info.PatchFormType = def; },
                typeIsGeneratedPredicate : x => x.TransformedType.PatchAllowed);

            CreateProxies(
                new PostFormProxyBuilder(this),
                (info, def) => { info.PostFormType = def; },
                typeIsGeneratedPredicate : x => x.TransformedType.PostAllowed);

            CreateClientInterface("IClient");
            CreateClientType("Client");

            foreach (var typeInfo in this.clientTypeInfoDict.Values)
                AddResourceInfoAttribute(typeInfo);

            foreach (var typeInfo in this.clientTypeInfoDict.Values.Where(x => x.CustomRepositoryInterface != null))
                CreateRepositoryInterfaceAndImplementation(typeInfo);

            //AddRepositoryPostExtensionMethods();

            // Copy types from running assembly

            if (PomonaClientEmbeddingEnabled)
            {
                foreach (
                    var clientHelperType in
                        this.module.Types.Where(
                            methodDefinition =>
                                !methodDefinition.Namespace.StartsWith(this.assemblyName)
                                && !string.IsNullOrEmpty(methodDefinition.Namespace)))
                    clientHelperType.Namespace = this.assemblyName + "." + clientHelperType.Namespace;
            }

            AddAssemblyAttributes();

            var memstream = new MemoryStream();
            assembly.Write(memstream);

            var array = memstream.ToArray();

            stream.Write(array, 0, array.Length);

            //assembly.Write(stream);
        }
        public DummyAssemblyCreator(Metadata metadata, Il2Cpp il2cpp)
        {
            this.metadata = metadata;
            this.il2cpp   = il2cpp;
            //Il2CppDummyDll
            var il2CppDummyDll       = AssemblyDefinition.ReadAssembly(new MemoryStream(Resource1.Il2CppDummyDll));
            var addressAttribute     = il2CppDummyDll.MainModule.Types.First(x => x.Name == "AddressAttribute").Methods.First();
            var fieldOffsetAttribute = il2CppDummyDll.MainModule.Types.First(x => x.Name == "FieldOffsetAttribute").Methods.First();
            var stringType           = il2CppDummyDll.MainModule.TypeSystem.String;
            var resolver             = new MyAssemblyResolver();
            var moduleParameters     = new ModuleParameters
            {
                Kind             = ModuleKind.Dll,
                AssemblyResolver = resolver
            };

            //创建程序集,同时创建所有类
            foreach (var imageDef in metadata.imageDefs)
            {
                var assemblyName       = new AssemblyNameDefinition(metadata.GetStringFromIndex(imageDef.nameIndex).Replace(".dll", ""), new Version("3.7.1.6"));
                var assemblyDefinition = AssemblyDefinition.CreateAssembly(assemblyName, metadata.GetStringFromIndex(imageDef.nameIndex), moduleParameters);
                resolver.Register(assemblyDefinition);
                Assemblies.Add(assemblyDefinition);
                var moduleDefinition = assemblyDefinition.MainModule;
                moduleDefinition.Types.Clear();//清除自动创建的<Module>类
                var typeEnd = imageDef.typeStart + imageDef.typeCount;
                for (var index = imageDef.typeStart; index < typeEnd; ++index)
                {
                    var            typeDef       = metadata.typeDefs[index];
                    var            namespaceName = metadata.GetStringFromIndex(typeDef.namespaceIndex);
                    var            typeName      = metadata.GetStringFromIndex(typeDef.nameIndex);
                    TypeDefinition typeDefinition;
                    if (typeDef.declaringTypeIndex != -1)//nested types
                    {
                        typeDefinition = typeDefinitionDic[index];
                    }
                    else
                    {
                        typeDefinition = new TypeDefinition(namespaceName, typeName, (TypeAttributes)typeDef.flags);
                        moduleDefinition.Types.Add(typeDefinition);
                        typeDefinitionDic.Add(index, typeDefinition);
                    }
                    //nestedtype
                    for (int i = 0; i < typeDef.nested_type_count; i++)
                    {
                        var nestedIndex          = metadata.nestedTypeIndices[typeDef.nestedTypesStart + i];
                        var nestedTypeDef        = metadata.typeDefs[nestedIndex];
                        var nestedTypeDefinition = new TypeDefinition(metadata.GetStringFromIndex(nestedTypeDef.namespaceIndex), metadata.GetStringFromIndex(nestedTypeDef.nameIndex), (TypeAttributes)nestedTypeDef.flags);
                        typeDefinition.NestedTypes.Add(nestedTypeDefinition);
                        typeDefinitionDic.Add(nestedIndex, nestedTypeDefinition);
                    }
                }
            }
            //先单独处理,因为不知道会不会有问题
            for (var index = 0; index < metadata.uiNumTypes; ++index)
            {
                var typeDef        = metadata.typeDefs[index];
                var typeDefinition = typeDefinitionDic[index];
                //parent
                if (typeDef.parentIndex >= 0)
                {
                    var parentType    = il2cpp.types[typeDef.parentIndex];
                    var parentTypeRef = GetTypeReference(typeDefinition, parentType);
                    typeDefinition.BaseType = parentTypeRef;
                }
                //interfaces
                for (int i = 0; i < typeDef.interfaces_count; i++)
                {
                    var interfaceType    = il2cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]];
                    var interfaceTypeRef = GetTypeReference(typeDefinition, interfaceType);
                    typeDefinition.Interfaces.Add(interfaceTypeRef);
                }
            }
            //处理field, method, property等等
            for (var index = 0; index < metadata.uiNumTypes; ++index)
            {
                var typeDef        = metadata.typeDefs[index];
                var typeDefinition = typeDefinitionDic[index];
                //field
                var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                {
                    var fieldDef        = metadata.fieldDefs[i];
                    var fieldType       = il2cpp.types[fieldDef.typeIndex];
                    var fieldName       = metadata.GetStringFromIndex(fieldDef.nameIndex);
                    var fieldTypeRef    = GetTypeReference(typeDefinition, fieldType);
                    var fieldDefinition = new FieldDefinition(fieldName, (FieldAttributes)fieldType.attrs, fieldTypeRef);
                    typeDefinition.Fields.Add(fieldDefinition);
                    //fieldDefault
                    if (fieldDefinition.HasDefault)
                    {
                        var fieldDefault = metadata.GetFieldDefaultValueFromIndex(i);
                        if (fieldDefault != null && fieldDefault.dataIndex != -1)
                        {
                            fieldDefinition.Constant = GetDefaultValue(fieldDefault.dataIndex, fieldDefault.typeIndex);
                        }
                    }
                    //fieldOffset
                    var fieldOffset = il2cpp.GetFieldOffsetFromIndex(index, i - typeDef.fieldStart, i);
                    if (fieldOffset > 0)
                    {
                        var customAttribute = new CustomAttribute(typeDefinition.Module.Import(fieldOffsetAttribute));
                        var offset          = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{fieldOffset:X}"));
                        customAttribute.Fields.Add(offset);
                        fieldDefinition.CustomAttributes.Add(customAttribute);
                    }
                }
                //method
                var methodEnd = typeDef.methodStart + typeDef.method_count;
                for (var i = typeDef.methodStart; i < methodEnd; ++i)
                {
                    var methodDef        = metadata.methodDefs[i];
                    var methodReturnType = il2cpp.types[methodDef.returnType];
                    var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                    var methodDefinition = new MethodDefinition(methodName, (MethodAttributes)methodDef.flags, typeDefinition.Module.Import(typeof(void)));
                    typeDefinition.Methods.Add(methodDefinition);
                    methodDefinition.ReturnType = GetTypeReference(methodDefinition, methodReturnType);
                    if (methodDefinition.HasBody && typeDefinition.BaseType?.FullName != "System.MulticastDelegate")
                    {
                        var ilprocessor = methodDefinition.Body.GetILProcessor();
                        ilprocessor.Append(ilprocessor.Create(OpCodes.Nop));
                    }
                    methodDefinitionDic.Add(i, methodDefinition);
                    //method parameter
                    for (var j = 0; j < methodDef.parameterCount; ++j)
                    {
                        var parameterDef        = metadata.parameterDefs[methodDef.parameterStart + j];
                        var parameterName       = metadata.GetStringFromIndex(parameterDef.nameIndex);
                        var parameterType       = il2cpp.types[parameterDef.typeIndex];
                        var parameterTypeRef    = GetTypeReference(methodDefinition, parameterType);
                        var parameterDefinition = new ParameterDefinition(parameterName, (ParameterAttributes)parameterType.attrs, parameterTypeRef);
                        methodDefinition.Parameters.Add(parameterDefinition);
                        //ParameterDefault
                        if (parameterDefinition.HasDefault)
                        {
                            var parameterDefault = metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j);
                            if (parameterDefault != null && parameterDefault.dataIndex != -1)
                            {
                                parameterDefinition.Constant = GetDefaultValue(parameterDefault.dataIndex, parameterDefault.typeIndex);
                            }
                        }
                    }
                    //补充泛型参数
                    if (methodDef.genericContainerIndex >= 0)
                    {
                        var genericContainer = metadata.genericContainers[methodDef.genericContainerIndex];
                        if (genericContainer.type_argc > methodDefinition.GenericParameters.Count)
                        {
                            for (int j = methodDefinition.GenericParameters.Count + 1; j <= genericContainer.type_argc; j++)
                            {
                                var genericParameter = new GenericParameter("T" + j, methodDefinition);
                                methodDefinition.GenericParameters.Add(genericParameter);
                            }
                        }
                    }
                    //address
                    ulong methodPointer;
                    if (methodDef.methodIndex >= 0)
                    {
                        methodPointer = il2cpp.methodPointers[methodDef.methodIndex];
                    }
                    else
                    {
                        il2cpp.genericMethoddDictionary.TryGetValue(i, out methodPointer);
                    }
                    if (methodPointer > 0)
                    {
                        var customAttribute = new CustomAttribute(typeDefinition.Module.Import(addressAttribute));
                        var rva             = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{methodPointer:X}"));
                        var offset          = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2cpp.MapVATR(methodPointer):X}"));
                        customAttribute.Fields.Add(rva);
                        customAttribute.Fields.Add(offset);
                        methodDefinition.CustomAttributes.Add(customAttribute);
                    }
                }
                //property
                var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                {
                    var              propertyDef  = metadata.propertyDefs[i];
                    var              propertyName = metadata.GetStringFromIndex(propertyDef.nameIndex);
                    TypeReference    propertyType = null;
                    MethodDefinition GetMethod    = null;
                    MethodDefinition SetMethod    = null;
                    if (propertyDef.get >= 0)
                    {
                        GetMethod    = methodDefinitionDic[typeDef.methodStart + propertyDef.get];
                        propertyType = GetMethod.ReturnType;
                    }
                    if (propertyDef.set >= 0)
                    {
                        SetMethod = methodDefinitionDic[typeDef.methodStart + propertyDef.set];
                        if (propertyType == null)
                        {
                            propertyType = SetMethod.Parameters[0].ParameterType;
                        }
                    }
                    var propertyDefinition = new PropertyDefinition(propertyName, (PropertyAttributes)propertyDef.attrs, propertyType)
                    {
                        GetMethod = GetMethod,
                        SetMethod = SetMethod
                    };
                    typeDefinition.Properties.Add(propertyDefinition);
                }
                //event
                var eventEnd = typeDef.eventStart + typeDef.event_count;
                for (var i = typeDef.eventStart; i < eventEnd; ++i)
                {
                    var eventDef        = metadata.eventDefs[i];
                    var eventName       = metadata.GetStringFromIndex(eventDef.nameIndex);
                    var eventType       = il2cpp.types[eventDef.typeIndex];
                    var eventTypeRef    = GetTypeReference(typeDefinition, eventType);
                    var eventDefinition = new EventDefinition(eventName, (EventAttributes)eventType.attrs, eventTypeRef);
                    if (eventDef.add >= 0)
                    {
                        eventDefinition.AddMethod = methodDefinitionDic[typeDef.methodStart + eventDef.add];
                    }
                    if (eventDef.remove >= 0)
                    {
                        eventDefinition.RemoveMethod = methodDefinitionDic[typeDef.methodStart + eventDef.remove];
                    }
                    if (eventDef.raise >= 0)
                    {
                        eventDefinition.InvokeMethod = methodDefinitionDic[typeDef.methodStart + eventDef.raise];
                    }
                    typeDefinition.Events.Add(eventDefinition);
                }
                //补充泛型参数
                if (typeDef.genericContainerIndex >= 0)
                {
                    var genericContainer = metadata.genericContainers[typeDef.genericContainerIndex];
                    if (genericContainer.type_argc > typeDefinition.GenericParameters.Count)
                    {
                        for (int j = typeDefinition.GenericParameters.Count + 1; j <= genericContainer.type_argc; j++)
                        {
                            var genericParameter = new GenericParameter("T" + j, typeDefinition);
                            typeDefinition.GenericParameters.Add(genericParameter);
                        }
                    }
                }
            }
            //第三遍,添加CustomAttribute。只添加SerializeField用于MonoBehaviour的反序列化
            if (il2cpp.version > 20)
            {
                var engine         = Assemblies.Find(x => x.MainModule.Types.Any(t => t.Namespace == "UnityEngine" && t.Name == "SerializeField"));
                var serializeField = engine.MainModule.Types.First(x => x.Name == "SerializeField").Methods.First();
                foreach (var imageDef in metadata.imageDefs)
                {
                    var typeEnd = imageDef.typeStart + imageDef.typeCount;
                    for (int index = imageDef.typeStart; index < typeEnd; index++)
                    {
                        var typeDef        = metadata.typeDefs[index];
                        var typeDefinition = typeDefinitionDic[index];
                        //field
                        var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                        for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                        {
                            var fieldDef        = metadata.fieldDefs[i];
                            var fieldName       = metadata.GetStringFromIndex(fieldDef.nameIndex);
                            var fieldDefinition = typeDefinition.Fields.First(x => x.Name == fieldName);
                            //fieldAttribute
                            var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, fieldDef.customAttributeIndex, fieldDef.token);
                            if (attributeIndex >= 0)
                            {
                                var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex];
                                for (int j = 0; j < attributeTypeRange.count; j++)
                                {
                                    var attributeTypeIndex = metadata.attributeTypes[attributeTypeRange.start + j];
                                    var attributeType      = il2cpp.types[attributeTypeIndex];
                                    if (attributeType.type == Il2CppTypeEnum.IL2CPP_TYPE_CLASS)
                                    {
                                        var klass         = metadata.typeDefs[attributeType.data.klassIndex];
                                        var attributeName = metadata.GetStringFromIndex(klass.nameIndex);
                                        if (attributeName == "SerializeField")
                                        {
                                            var customAttribute = new CustomAttribute(typeDefinition.Module.Import(serializeField));
                                            fieldDefinition.CustomAttributes.Add(customAttribute);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
 public LoadingScreenHintsModule([Import("ModuleParameters")] ModuleParameters moduleParameters) : base(moduleParameters)
 {
     ModuleInstance = this;
 }
 public ScreenshotManagerModule([Import("ModuleParameters")] ModuleParameters moduleParameters) : base(
         moduleParameters)
 {
     ModuleInstance             = this;
     _invalidFileNameCharacters = Path.GetInvalidFileNameChars().Union(Path.GetInvalidPathChars());
 }
        public static AssemblyDefinition CreateAssembly(AssemblyNameDefinition assemblyName, string moduleName, ModuleParameters parameters)
        {
            if (assemblyName == null)
                throw new ArgumentNullException("assemblyName");
            if (moduleName == null)
                throw new ArgumentNullException("moduleName");
            Mixin.CheckParameters(parameters);
            if (parameters.Kind == ModuleKind.NetModule)
                throw new ArgumentException("kind");

            var assembly = ModuleDefinition.CreateModule(moduleName, parameters).Assembly;
            assembly.Name = assemblyName;

            return assembly;
        }
Exemple #27
0
        /// <summary>
        /// Creates all the Assemblies defined in the provided metadata, along with (stub) definitions of all the types contained therein, and registers them with the resolver.
        /// </summary>
        /// <param name="metadata">The Il2Cpp metadata to extract assemblies from</param>
        /// <param name="resolver">The Assembly Resolver that assemblies are registered with, used to ensure assemblies can cross reference.</param>
        /// <param name="moduleParams">Configuration for the module creation.</param>
        /// <returns>A list of Mono.Cecil Assemblies, containing empty type definitions for each defined type.</returns>
        internal static List <AssemblyDefinition> CreateAssemblies(Il2CppMetadata metadata, RegistryAssemblyResolver resolver, ModuleParameters moduleParams)
        {
            var assemblies = new List <AssemblyDefinition>();

            foreach (var assemblyDefinition in metadata.assemblyDefinitions)
            {
                //Get the name of the assembly (= the name of the DLL without the file extension)
                var assemblyNameString = metadata.GetStringFromIndex(assemblyDefinition.nameIndex).Replace(".dll", "");

                //Build a Mono.Cecil assembly name from this name
                var asmName = new AssemblyNameDefinition(assemblyNameString, new Version("0.0.0.0"));
                Console.Write($"\t\t{assemblyNameString}...");

                //Create an empty assembly and register it
                var assembly = AssemblyDefinition.CreateAssembly(asmName, metadata.GetStringFromIndex(assemblyDefinition.nameIndex), moduleParams);
                resolver.Register(assembly);
                assemblies.Add(assembly);

                //Ensure it really _is_ empty
                var mainModule = assembly.MainModule;
                mainModule.Types.Clear();

                //Find the end index of the types belonging to this assembly (as they're all in one huge list in the metadata)
                var end = assemblyDefinition.firstTypeIndex + assemblyDefinition.typeCount;

                for (var defNumber = assemblyDefinition.firstTypeIndex; defNumber < end; defNumber++)
                {
                    //Get the metadata type info, its namespace, and name.
                    var type = metadata.typeDefs[defNumber];
                    var ns   = metadata.GetStringFromIndex(type.namespaceIndex);
                    var name = metadata.GetStringFromIndex(type.nameIndex);

                    TypeDefinition definition;
                    if (type.declaringTypeIndex != -1)
                    {
                        //This is a type declared within another (inner class/type)
                        definition = SharedState.TypeDefsByIndex[defNumber];
                    }
                    else
                    {
                        //This is a new type so ensure it's registered
                        definition = new TypeDefinition(ns, name, (TypeAttributes)type.flags);
                        mainModule.Types.Add(definition);
                        SharedState.TypeDefsByIndex.Add(defNumber, definition);
                    }

                    //Ensure we include all inner types within this type.
                    for (var nestedNumber = 0; nestedNumber < type.nested_type_count; nestedNumber++)
                    {
                        //These are stored in a separate field in the metadata.
                        var nestedIndex = metadata.nestedTypeIndices[type.nestedTypesStart + nestedNumber];
                        var nested      = metadata.typeDefs[nestedIndex];

                        //Create it and register.
                        var nestedDef = new TypeDefinition(metadata.GetStringFromIndex(nested.namespaceIndex),
                                                           metadata.GetStringFromIndex(nested.nameIndex), (TypeAttributes)nested.flags);

                        definition.NestedTypes.Add(nestedDef);
                        SharedState.TypeDefsByIndex.Add(nestedIndex, nestedDef);
                    }
                }

                Console.WriteLine("OK");
            }

            return(assemblies);
        }