Esempio n. 1
0
 public StructJsonGenerator(Il2CppExecutor il2CppExecutor, Config config)
 {
     executor = il2CppExecutor;
     metadata = il2CppExecutor.metadata;
     il2Cpp   = il2CppExecutor.il2Cpp;
     index    = new Il2CppIndex(il2CppExecutor, config);
 }
Esempio n. 2
0
        public static bool PerformDump(string gameAssemblyPath, string metadataDatPath, string outputDirectoryPath,
                                       Config config, Action <string> reportProgressAction)
        {
            Init(gameAssemblyPath, metadataDatPath, config, reportProgressAction, out var metadata, out var il2Cpp);

            reportProgressAction("Dumping...");
            var executor   = new Il2CppExecutor(metadata, il2Cpp);
            var decompiler = new Il2CppDecompiler(executor);

            reportProgressAction("Done!");
            if (config.GenerateStruct)
            {
                decompiler.Decompile(config, outputDirectoryPath, reportProgressAction);
                reportProgressAction("Generate struct...");
                var scriptGenerator = new StructGenerator(executor);
                scriptGenerator.WriteScript(outputDirectoryPath);
                reportProgressAction("Done!");
            }
            if (config.GenerateDummyDll)
            {
                reportProgressAction("Generate dummy dll...");
                DummyAssemblyExporter.Export(executor, outputDirectoryPath, config.DummyDllAddToken);
                reportProgressAction("Done!");
            }

            return(true);
        }
Esempio n. 3
0
        private void Dump(Metadata metadata, Il2Cpp il2Cpp, string outputDir)
        {
            Log("Dumping...");
            var executor   = new Il2CppExecutor(metadata, il2Cpp);
            var decompiler = new Il2CppDecompiler(executor);

            decompiler.Decompile(config, outputDir);
            Log("Done!");
            if (config.GenerateStruct)
            {
                Log("Generate struct...");
                try
                {
                    var scriptGenerator = new StructGenerator(executor);
                    scriptGenerator.WriteScript(outputDir);
                    Log("Done!");
                }
                catch
                {
                    Log("There was an error trying to generate struct. Skipped", Color.Orange);
                }
            }
            if (config.GenerateDummyDll)
            {
                Log("Generate dummy dll...");
                DummyAssemblyExporter.Export(executor, outputDir, config.DummyDllAddToken);
                Log("Done!");
                Directory.SetCurrentDirectory(realPath); //Fix read-only directory permission
            }
        }
Esempio n. 4
0
        private static void Dump(Metadata metadata, Il2Cpp il2Cpp, string outputDir)
        {
            Console.WriteLine("Dumping...");
            var executor   = new Il2CppExecutor(metadata, il2Cpp);
            var structJson = new StructJsonGenerator(executor, config);

            structJson.WriteJson(outputDir);
        }
Esempio n. 5
0
 public Il2CppIndex(Il2CppExecutor il2CppExecutor, Config config)
 {
     this.config = config;
     executor    = il2CppExecutor;
     metadata    = il2CppExecutor.metadata;
     il2Cpp      = il2CppExecutor.il2Cpp;
     BuildIndex();
 }
 public CustomAttributeDataReader(Il2CppExecutor executor, byte[] buff) : base(new MemoryStream(buff))
 {
     this.executor = executor;
     metadata      = executor.metadata;
     il2Cpp        = executor.il2Cpp;
     Count         = this.ReadCompressedUInt32();
     ctorBuffer    = BaseStream.Position;
     dataBuffer    = BaseStream.Position + Count * 4;
 }
Esempio n. 7
0
        private static void Dump(Metadata metadata, Il2Cpp il2Cpp, string outputDir)
        {
            Console.WriteLine("Dumping...");
            var executor   = new Il2CppExecutor(metadata, il2Cpp);
            var decompiler = new Il2CppDecompiler(executor);

            decompiler.Decompile(config, outputDir);
            Console.WriteLine("Done!");
        }
Esempio n. 8
0
        private string GetName(Il2CppExecutor executor, Il2CppTypeDefinition typeDef, Il2CppType il2CppType, string originalName)
        {
            if (_typeDefToName.ContainsKey(il2CppType))
            {
                return(_typeDefToName[il2CppType].Split('|')[1]);
            }

            var uniqueTypeNamePair = $"{typeDef.namespaceIndex}|{originalName}";
            int n = 0;

            while (_uniqueNames.Contains(uniqueTypeNamePair))
            {
                uniqueTypeNamePair = $"{typeDef.namespaceIndex}|_{++n}_{originalName}";
            }
            _uniqueNames.Add(uniqueTypeNamePair);
            _typeDefToName[il2CppType] = uniqueTypeNamePair;
            return(uniqueTypeNamePair.Split('|')[1]);
        }
Esempio n. 9
0
        private static void Dump(Metadata metadata, Il2Cpp il2Cpp)
        {
            Console.WriteLine("Dumping...");
            var executor   = new Il2CppExecutor(metadata, il2Cpp);
            var decompiler = new Il2CppDecompiler(executor);

            decompiler.Decompile(config);
            Console.WriteLine("Done!");
            Console.WriteLine("Generate script...");
            var scriptGenerator = new ScriptGenerator(executor);

            scriptGenerator.WriteScript(config);
            Console.WriteLine("Done!");
            if (config.DummyDll)
            {
                Console.WriteLine("Generate dummy dll...");
                DummyAssemblyExporter.Export(metadata, il2Cpp);
                Console.WriteLine("Done!");
            }
        }
        public static void Export(Il2CppExecutor il2CppExecutor, string outputDir)
        {
            Directory.SetCurrentDirectory(outputDir);
            if (Directory.Exists("DummyDll"))
            {
                Directory.Delete("DummyDll", true);
            }
            Directory.CreateDirectory("DummyDll");
            Directory.SetCurrentDirectory("DummyDll");
            var dummy = new DummyAssemblyGenerator(il2CppExecutor);

            foreach (var assembly in dummy.Assemblies)
            {
                using (var stream = new MemoryStream())
                {
                    assembly.Write(stream);
                    File.WriteAllBytes(assembly.MainModule.Name, stream.ToArray());
                }
            }
        }
Esempio n. 11
0
        private static void Dump(Metadata metadata, Il2Cpp il2Cpp, string outputDir)
        {
            Console.WriteLine("Dumping...");
            var executor   = new Il2CppExecutor(metadata, il2Cpp);
            var decompiler = new Il2CppDecompiler(executor);

            decompiler.Decompile(config, outputDir);
            Console.WriteLine("Done!");
            if (config.GenerateStruct)
            {
                Console.WriteLine("Generate struct...");
                var scriptGenerator = new StructGenerator(executor);
                scriptGenerator.WriteScript(outputDir);
                Console.WriteLine("Done!");
            }
            if (config.GenerateDummyDll)
            {
                Console.WriteLine("Generate dummy dll...");
                DummyAssemblyExporter.Export(executor, outputDir, config.DummyDllAddToken);
                Console.WriteLine("Done!");
            }
        }
Esempio n. 12
0
        public static void Export(Il2CppExecutor il2CppExecutor, string outputDir)
        {
            string dummyDllPath = Path.Combine(outputDir, "DummyDll");

            if (Directory.Exists(dummyDllPath))
            {
                Directory.Delete(dummyDllPath, true);
            }
            Directory.CreateDirectory(dummyDllPath);

            var dummy = new DummyAssemblyGenerator(il2CppExecutor);

            foreach (var assembly in dummy.Assemblies)
            {
                string path = Path.Combine(dummyDllPath, assembly.MainModule.Name);

                using (var stream = new FileStream(path, FileMode.Create))
                {
                    assembly.Write(stream);
                    assembly.Dispose();
                }
            }
        }
Esempio n. 13
0
        private void Dump(Metadata metadata, Il2Cpp il2Cpp, string outputDir)
        {
            WriteLine("Dumping...");
            var executor   = new Il2CppExecutor(metadata, il2Cpp);
            var decompiler = new Il2CppDecompiler(executor);

            decompiler.Decompile(config, outputDir);
            WriteLine("Done!");
            if (config.GenerateStruct)
            {
                WriteLine("Generate struct...");
                var scriptGenerator = new StructGenerator(executor);
                scriptGenerator.WriteScript(outputDir);
                WriteLine("Done!");
            }
            if (config.GenerateDummyDll)
            {
                WriteLine("Generate dummy dll...");
                DummyAssemblyExporter.Export(executor, outputDir, config.DummyDllAddToken);
                WriteLine("Done!");
                Directory.SetCurrentDirectory(RealPath); //Fix read-only directory permission
            }
        }
Esempio n. 14
0
 public ScriptGenerator(Il2CppExecutor il2CppExecutor)
 {
     executor = il2CppExecutor;
     metadata = il2CppExecutor.metadata;
     il2Cpp   = il2CppExecutor.il2Cpp;
 }
Esempio n. 15
0
 public Il2CppDecompiler(Il2CppExecutor il2CppExecutor)
 {
     executor = il2CppExecutor;
     metadata = il2CppExecutor.metadata;
     il2Cpp   = il2CppExecutor.il2Cpp;
 }
Esempio n. 16
0
        public DummyAssemblyGenerator(Il2CppExecutor il2CppExecutor)
        {
            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 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);
                    var typeDefinition = new TypeDefinition(namespaceName, typeName, (TypeAttributes)typeDef.flags);
                    typeDefinitionDic.Add(typeDef, typeDefinition);
                    if (typeDef.declaringTypeIndex == -1)
                    {
                        moduleDefinition.Types.Add(typeDefinition);
                    }
                }
            }
            for (var index = 0; index < metadata.typeDefs.Length; ++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);
                }
            }
            //提前处理
            for (var index = 0; index < metadata.typeDefs.Length; ++index)
            {
                var typeDef        = metadata.typeDefs[index];
                var typeDefinition = typeDefinitionDic[typeDef];

                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);

                        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 (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;

                        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 (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
                        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);

                        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);

                        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)
            {
                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[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);
                        }
                    }
                }
            }
        }