Example #1
0
        public void Decompile(Config config)
        {
            var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create), new UTF8Encoding(false));

            //dump image
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                writer.Write($"// Image {imageIndex}: {metadata.GetStringFromIndex(imageDef.nameIndex)} - {imageDef.typeStart}\n");
            }
            //dump type
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                try
                {
                    var imageDef = metadata.imageDefs[imageIndex];
                    var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                    for (int typeDefIndex = imageDef.typeStart; typeDefIndex < typeEnd; typeDefIndex++)
                    {
                        var typeDef = metadata.typeDefs[typeDefIndex];
                        var extends = new List <string>();
                        if (typeDef.parentIndex >= 0)
                        {
                            var parent     = il2Cpp.types[typeDef.parentIndex];
                            var parentName = executor.GetTypeName(parent, false, false);
                            if (!typeDef.IsValueType && !typeDef.IsEnum && parentName != "object")
                            {
                                extends.Add(parentName);
                            }
                        }
                        if (typeDef.interfaces_count > 0)
                        {
                            for (int i = 0; i < typeDef.interfaces_count; i++)
                            {
                                var @interface = il2Cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]];
                                extends.Add(executor.GetTypeName(@interface, false, false));
                            }
                        }
                        writer.Write($"\n// Namespace: {metadata.GetStringFromIndex(typeDef.namespaceIndex)}\n");
                        if (config.DumpAttribute)
                        {
                            writer.Write(GetCustomAttribute(imageDef, typeDef.customAttributeIndex, typeDef.token));
                        }
                        if (config.DumpAttribute && (typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
                        {
                            writer.Write("[Serializable]\n");
                        }
                        var visibility = typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
                        switch (visibility)
                        {
                        case TYPE_ATTRIBUTE_PUBLIC:
                        case TYPE_ATTRIBUTE_NESTED_PUBLIC:
                            writer.Write("public ");
                            break;

                        case TYPE_ATTRIBUTE_NOT_PUBLIC:
                        case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
                        case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
                            writer.Write("internal ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_PRIVATE:
                            writer.Write("private ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_FAMILY:
                            writer.Write("protected ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
                            writer.Write("protected internal ");
                            break;
                        }
                        if ((typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0 && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                        {
                            writer.Write("static ");
                        }
                        else if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) == 0 && (typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0)
                        {
                            writer.Write("abstract ");
                        }
                        else if (!typeDef.IsValueType && !typeDef.IsEnum && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                        {
                            writer.Write("sealed ");
                        }
                        if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0)
                        {
                            writer.Write("interface ");
                        }
                        else if (typeDef.IsEnum)
                        {
                            writer.Write("enum ");
                        }
                        else if (typeDef.IsValueType)
                        {
                            writer.Write("struct ");
                        }
                        else
                        {
                            writer.Write("class ");
                        }
                        var typeName = executor.GetTypeDefName(typeDef, false, true);
                        writer.Write($"{typeName}");
                        if (extends.Count > 0)
                        {
                            writer.Write($" : {string.Join(", ", extends)}");
                        }
                        if (config.DumpTypeDefIndex)
                        {
                            writer.Write($" // TypeDefIndex: {typeDefIndex}\n{{");
                        }
                        else
                        {
                            writer.Write("\n{");
                        }
                        //dump field
                        if (config.DumpField && typeDef.field_count > 0)
                        {
                            writer.Write("\n\t// Fields\n");
                            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 isStatic  = false;
                                if (config.DumpAttribute)
                                {
                                    writer.Write(GetCustomAttribute(imageDef, fieldDef.customAttributeIndex, fieldDef.token, "\t"));
                                }
                                writer.Write("\t");
                                var access = fieldType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
                                switch (access)
                                {
                                case FIELD_ATTRIBUTE_PRIVATE:
                                    writer.Write("private ");
                                    break;

                                case FIELD_ATTRIBUTE_PUBLIC:
                                    writer.Write("public ");
                                    break;

                                case FIELD_ATTRIBUTE_FAMILY:
                                    writer.Write("protected ");
                                    break;

                                case FIELD_ATTRIBUTE_ASSEMBLY:
                                case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
                                    writer.Write("internal ");
                                    break;

                                case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
                                    writer.Write("protected internal ");
                                    break;
                                }
                                if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
                                {
                                    writer.Write("const ");
                                }
                                else
                                {
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                                    {
                                        isStatic = true;
                                        writer.Write("static ");
                                    }
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                                    {
                                        writer.Write("readonly ");
                                    }
                                }
                                writer.Write($"{executor.GetTypeName(fieldType, false, false)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}");
                                if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefaultValue) && fieldDefaultValue.dataIndex != -1)
                                {
                                    if (TryGetDefaultValue(fieldDefaultValue.typeIndex, fieldDefaultValue.dataIndex, out var value))
                                    {
                                        writer.Write($" = ");
                                        if (value is string str)
                                        {
                                            writer.Write($"\"{str.ToEscapedString()}\"");
                                        }
                                        else if (value is char c)
                                        {
                                            var v = (int)c;
                                            writer.Write($"'\\x{v:x}'");
                                        }
                                        else if (value != null)
                                        {
                                            writer.Write($"{value}");
                                        }
                                    }
                                    else
                                    {
                                        writer.Write($" /*Metadata offset 0x{value:X}*/");
                                    }
                                }
                                if (config.DumpFieldOffset)
                                {
                                    writer.Write("; // 0x{0:X}\n", il2Cpp.GetFieldOffsetFromIndex(typeDefIndex, i - typeDef.fieldStart, i, typeDef.IsValueType, isStatic));
                                }
                                else
                                {
                                    writer.Write(";\n");
                                }
                            }
                        }
                        //dump property
                        if (config.DumpProperty && typeDef.property_count > 0)
                        {
                            writer.Write("\n\t// Properties\n");
                            var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                            for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                            {
                                var propertyDef = metadata.propertyDefs[i];
                                if (config.DumpAttribute)
                                {
                                    writer.Write(GetCustomAttribute(imageDef, propertyDef.customAttributeIndex, propertyDef.token, "\t"));
                                }
                                writer.Write("\t");
                                if (propertyDef.get >= 0)
                                {
                                    var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.get];
                                    writer.Write(GetModifiers(methodDef));
                                    var propertyType = il2Cpp.types[methodDef.returnType];
                                    writer.Write($"{executor.GetTypeName(propertyType, false, false)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                }
                                else if (propertyDef.set > 0)
                                {
                                    var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.set];
                                    writer.Write(GetModifiers(methodDef));
                                    var parameterDef = metadata.parameterDefs[methodDef.parameterStart];
                                    var propertyType = il2Cpp.types[parameterDef.typeIndex];
                                    writer.Write($"{executor.GetTypeName(propertyType, false, false)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                }
                                if (propertyDef.get >= 0)
                                {
                                    writer.Write("get; ");
                                }
                                if (propertyDef.set >= 0)
                                {
                                    writer.Write("set; ");
                                }
                                writer.Write("}");
                                writer.Write("\n");
                            }
                        }
                        //dump method
                        if (config.DumpMethod && typeDef.method_count > 0)
                        {
                            writer.Write("\n\t// Methods\n");
                            var methodEnd = typeDef.methodStart + typeDef.method_count;
                            for (var i = typeDef.methodStart; i < methodEnd; ++i)
                            {
                                var methodDef = metadata.methodDefs[i];
                                if (config.DumpAttribute)
                                {
                                    writer.Write(GetCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, "\t"));
                                }
                                if (config.DumpMethodOffset)
                                {
                                    var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
                                    if (methodPointer > 0)
                                    {
                                        var fixedMethodPointer = il2Cpp.GetRVA(methodPointer);
                                        writer.Write("\t// RVA: 0x{0:X} Offset: 0x{1:X} VA: 0x{2:X}", fixedMethodPointer, il2Cpp.MapVATR(methodPointer), methodPointer);
                                    }
                                    else
                                    {
                                        writer.Write("\t// RVA: -1 Offset: -1");
                                    }
                                    if (methodDef.slot != ushort.MaxValue)
                                    {
                                        writer.Write(" Slot: {0}", methodDef.slot);
                                    }
                                    writer.Write("\n");
                                }
                                writer.Write("\t");
                                writer.Write(GetModifiers(methodDef));
                                var methodReturnType = il2Cpp.types[methodDef.returnType];
                                var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                                if (methodReturnType.byref == 1)
                                {
                                    writer.Write("ref ");
                                }
                                writer.Write($"{executor.GetTypeName(methodReturnType, false, false)} {methodName}(");
                                var parameterStrs = new List <string>();
                                for (var j = 0; j < methodDef.parameterCount; ++j)
                                {
                                    var parameterStr      = "";
                                    var parameterDef      = metadata.parameterDefs[methodDef.parameterStart + j];
                                    var parameterName     = metadata.GetStringFromIndex(parameterDef.nameIndex);
                                    var parameterType     = il2Cpp.types[parameterDef.typeIndex];
                                    var parameterTypeName = executor.GetTypeName(parameterType, false, false);
                                    if (parameterType.byref == 1)
                                    {
                                        if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0 && (parameterType.attrs & PARAM_ATTRIBUTE_IN) == 0)
                                        {
                                            parameterStr += "out ";
                                        }
                                        else if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) == 0 && (parameterType.attrs & PARAM_ATTRIBUTE_IN) != 0)
                                        {
                                            parameterStr += "in ";
                                        }
                                        else
                                        {
                                            parameterStr += "ref ";
                                        }
                                    }
                                    else
                                    {
                                        if ((parameterType.attrs & PARAM_ATTRIBUTE_IN) != 0)
                                        {
                                            parameterStr += "[In] ";
                                        }
                                        if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
                                        {
                                            parameterStr += "[Out] ";
                                        }
                                    }
                                    parameterStr += $"{parameterTypeName} {parameterName}";
                                    if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1)
                                    {
                                        if (TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value))
                                        {
                                            parameterStr += " = ";
                                            if (value is string str)
                                            {
                                                parameterStr += $"\"{str.ToEscapedString()}\"";
                                            }
                                            else if (value is char c)
                                            {
                                                var v = (int)c;
                                                parameterStr += $"'\\x{v:x}'";
                                            }
                                            else if (value != null)
                                            {
                                                parameterStr += $"{value}";
                                            }
                                        }
                                        else
                                        {
                                            parameterStr += $" /*Metadata offset 0x{value:X}*/";
                                        }
                                    }
                                    parameterStrs.Add(parameterStr);
                                }
                                writer.Write(string.Join(", ", parameterStrs));
                                writer.Write(") { }\n");
                            }
                        }
                        writer.Write("}\n");
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("ERROR: Some errors in dumping");
                    writer.Write("/*");
                    writer.Write(e);
                    writer.Write("*/\n}\n");
                }
            }
            writer.Close();
        }
Example #2
0
 public DummyAssemblyCreator(Metadata metadata, Il2Cpp il2cpp)
 {
     this.metadata = metadata;
     this.il2cpp   = il2cpp;
     //创建程序集,同时创建所有类
     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), ModuleKind.Dll);
         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);
                 }
             }
         }
         //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 pParam              = metadata.parameterDefs[methodDef.parameterStart + j];
                 var parameterName       = metadata.GetStringFromIndex(pParam.nameIndex);
                 var parameterType       = il2cpp.types[pParam.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);
                     }
                 }
             }
         }
         //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);
                 }
             }
         }
     }
 }
Example #3
0
        static void Main(string[] args)
        {
            config = File.Exists("config.json") ? new JavaScriptSerializer().Deserialize <Config>(File.ReadAllText("config.json")) : new Config();
            var ofd = new OpenFileDialog();

            ofd.Filter = "Il2Cpp binary file|*.*";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                var il2cppfile = File.ReadAllBytes(ofd.FileName);
                ofd.Filter = "global-metadata|global-metadata.dat";
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        Console.WriteLine("Initializing metadata...");
                        metadata = new Metadata(new MemoryStream(File.ReadAllBytes(ofd.FileName)));
                        Console.Clear();
                        //判断il2cpp的magic
                        var il2cppMagic = BitConverter.ToUInt32(il2cppfile, 0);
                        var isElf       = false;
                        var isPE        = false;
                        var is64bit     = false;
                        switch (il2cppMagic)
                        {
                        default:
                            throw new Exception("ERROR: il2cpp file not supported.");

                        case 0x905A4D:     //PE
                            isPE = true;
                            break;

                        case 0x464c457f:     //ELF
                            isElf = true;
                            if (il2cppfile[4] == 2)
                            {
                                goto case 0xFEEDFACF;     //ELF64
                            }
                            break;

                        case 0xCAFEBABE:     //FAT header
                        case 0xBEBAFECA:
                            var machofat = new MachoFat(new MemoryStream(il2cppfile));
                            Console.Write("Select Platform: ");
                            for (var i = 0; i < machofat.fats.Length; i++)
                            {
                                var fat = machofat.fats[i];
                                Console.Write(fat.magic == 0xFEEDFACF ? $"{i + 1}.64bit " : $"{i + 1}.32bit ");
                            }
                            Console.WriteLine();
                            var key   = Console.ReadKey(true);
                            var index = int.Parse(key.KeyChar.ToString()) - 1;
                            var magic = machofat.fats[index % 2].magic;
                            il2cppfile = machofat.GetMacho(index % 2);
                            if (magic == 0xFEEDFACF)     // 64-bit mach object file
                            {
                                goto case 0xFEEDFACF;
                            }
                            else
                            {
                                goto case 0xFEEDFACE;
                            }

                        case 0xFEEDFACF:     // 64-bit mach object file
                            is64bit = true;
                            break;

                        case 0xFEEDFACE:     // 32-bit mach object file
                            break;
                        }

                        Console.WriteLine("Select Mode: 1.Manual 2.Auto 3.Auto(Advanced) 4.Auto(Plus) 5.Auto(Symbol)");
                        var modeKey = Console.ReadKey(true);
                        var version = config.ForceIl2CppVersion ? config.ForceVersion : metadata.version;
                        Console.WriteLine("Initializing il2cpp file...");
                        if (isPE)
                        {
                            il2cpp = new PE(new MemoryStream(il2cppfile), version, metadata.maxMetadataUsages);
                        }
                        else if (isElf)
                        {
                            if (is64bit)
                            {
                                il2cpp = new Elf64(new MemoryStream(il2cppfile), version, metadata.maxMetadataUsages);
                            }
                            else
                            {
                                il2cpp = new Elf(new MemoryStream(il2cppfile), version, metadata.maxMetadataUsages);
                            }
                        }
                        else if (is64bit)
                        {
                            il2cpp = new Macho64(new MemoryStream(il2cppfile), version, metadata.maxMetadataUsages);
                        }
                        else
                        {
                            il2cpp = new Macho(new MemoryStream(il2cppfile), version, metadata.maxMetadataUsages);
                        }

                        try
                        {
                            bool flag;
                            switch (modeKey.KeyChar)
                            {
                            case '1':     //Manual
                                Console.Write("Input CodeRegistration: ");
                                var codeRegistration = Convert.ToUInt64(Console.ReadLine(), 16);
                                Console.Write("Input MetadataRegistration: ");
                                var metadataRegistration = Convert.ToUInt64(Console.ReadLine(), 16);
                                il2cpp.Init(codeRegistration, metadataRegistration);
                                flag = true;
                                break;

                            case '2':     //Auto
                                flag = il2cpp.Search();
                                break;

                            case '3':     //Auto(Advanced)
                                flag = il2cpp.AdvancedSearch(metadata.methodDefs.Count(x => x.methodIndex >= 0));
                                break;

                            case '4':     //Auto(Plus)
                                flag = il2cpp.PlusSearch(metadata.methodDefs.Count(x => x.methodIndex >= 0), metadata.typeDefs.Length);
                                break;

                            case '5':     //Auto(Symbol)
                                flag = il2cpp.SymbolSearch();
                                break;

                            default:
                                return;
                            }
                            if (!flag)
                            {
                                throw new Exception();
                            }
                        }
                        catch
                        {
                            throw new Exception("ERROR: Can't use this mode to process file, try another mode.");
                        }
                        var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create), new UTF8Encoding(false));
                        Console.WriteLine("Dumping...");
                        //Script
                        var scriptwriter = new StreamWriter(new FileStream("script.py", FileMode.Create), new UTF8Encoding(false));
                        scriptwriter.WriteLine(Resource1.ida);
                        //dump image;
                        for (var imageIndex = 0; imageIndex < metadata.uiImageCount; imageIndex++)
                        {
                            var imageDef = metadata.imageDefs[imageIndex];
                            writer.Write($"// Image {imageIndex}: {metadata.GetStringFromIndex(imageDef.nameIndex)} - {imageDef.typeStart}\n");
                        }
                        //dump type;
                        for (var idx = 0; idx < metadata.uiNumTypes; ++idx)
                        {
                            try
                            {
                                var typeDef  = metadata.typeDefs[idx];
                                var isStruct = false;
                                var isEnum   = false;
                                var extends  = new List <string>();
                                if (typeDef.parentIndex >= 0)
                                {
                                    var parent     = il2cpp.types[typeDef.parentIndex];
                                    var parentName = GetTypeName(parent);
                                    if (parentName == "ValueType")
                                    {
                                        isStruct = true;
                                    }
                                    else if (parentName == "Enum")
                                    {
                                        isEnum = true;
                                    }
                                    else if (parentName != "object")
                                    {
                                        extends.Add(parentName);
                                    }
                                }
                                //implementedInterfaces
                                if (typeDef.interfaces_count > 0)
                                {
                                    for (int i = 0; i < typeDef.interfaces_count; i++)
                                    {
                                        var @interface = il2cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]];
                                        extends.Add(GetTypeName(@interface));
                                    }
                                }
                                writer.Write($"\n// Namespace: {metadata.GetStringFromIndex(typeDef.namespaceIndex)}\n");
                                writer.Write(GetCustomAttribute(typeDef.customAttributeIndex));
                                if (config.DumpAttribute && (typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
                                {
                                    writer.Write("[Serializable]\n");
                                }
                                var visibility = typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
                                switch (visibility)
                                {
                                case TYPE_ATTRIBUTE_PUBLIC:
                                case TYPE_ATTRIBUTE_NESTED_PUBLIC:
                                    writer.Write("public ");
                                    break;

                                case TYPE_ATTRIBUTE_NOT_PUBLIC:
                                case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
                                case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
                                    writer.Write("internal ");
                                    break;

                                case TYPE_ATTRIBUTE_NESTED_PRIVATE:
                                    writer.Write("private ");
                                    break;

                                case TYPE_ATTRIBUTE_NESTED_FAMILY:
                                    writer.Write("protected ");
                                    break;

                                case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
                                    writer.Write("protected internal ");
                                    break;
                                }
                                if ((typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0 && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                                {
                                    writer.Write("static ");
                                }
                                else if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) == 0 && (typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0)
                                {
                                    writer.Write("abstract ");
                                }
                                else if (!isStruct && !isEnum && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                                {
                                    writer.Write("sealed ");
                                }
                                if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0)
                                {
                                    writer.Write("interface ");
                                }
                                else if (isStruct)
                                {
                                    writer.Write("struct ");
                                }
                                else if (isEnum)
                                {
                                    writer.Write("enum ");
                                }
                                else
                                {
                                    writer.Write("class ");
                                }
                                var typeName = metadata.GetStringFromIndex(typeDef.nameIndex);
                                writer.Write($"{typeName}");
                                if (extends.Count > 0)
                                {
                                    writer.Write($" : {string.Join(", ", extends)}");
                                }
                                if (config.DumpTypeDefIndex)
                                {
                                    writer.Write($" // TypeDefIndex: {idx}\n{{\n");
                                }
                                else
                                {
                                    writer.Write("\n{\n");
                                }
                                //dump field
                                if (config.DumpField && typeDef.field_count > 0)
                                {
                                    writer.Write("\t// Fields\n");
                                    var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                                    for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                                    {
                                        //dump_field(i, idx, i - typeDef.fieldStart);
                                        var fieldDef     = metadata.fieldDefs[i];
                                        var fieldType    = il2cpp.types[fieldDef.typeIndex];
                                        var fieldDefault = metadata.GetFieldDefaultValueFromIndex(i);
                                        writer.Write(GetCustomAttribute(fieldDef.customAttributeIndex, "\t"));
                                        writer.Write("\t");
                                        var access = fieldType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
                                        switch (access)
                                        {
                                        case FIELD_ATTRIBUTE_PRIVATE:
                                            writer.Write("private ");
                                            break;

                                        case FIELD_ATTRIBUTE_PUBLIC:
                                            writer.Write("public ");
                                            break;

                                        case FIELD_ATTRIBUTE_FAMILY:
                                            writer.Write("protected ");
                                            break;

                                        case FIELD_ATTRIBUTE_ASSEMBLY:
                                        case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
                                            writer.Write("internal ");
                                            break;

                                        case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
                                            writer.Write("protected internal ");
                                            break;
                                        }
                                        if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
                                        {
                                            writer.Write("const ");
                                        }
                                        else
                                        {
                                            if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                                            {
                                                writer.Write("static ");
                                            }
                                            if ((fieldType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                                            {
                                                writer.Write("readonly ");
                                            }
                                        }
                                        writer.Write($"{GetTypeName(fieldType)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}");
                                        if (fieldDefault != null && fieldDefault.dataIndex != -1)
                                        {
                                            var pointer = metadata.GetDefaultValueFromIndex(fieldDefault.dataIndex);
                                            if (pointer > 0)
                                            {
                                                var pTypeToUse = il2cpp.types[fieldDefault.typeIndex];
                                                metadata.Position = pointer;
                                                object multi = null;
                                                switch (pTypeToUse.type)
                                                {
                                                case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
                                                    multi = metadata.ReadBoolean();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_U1:
                                                    multi = metadata.ReadByte();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_I1:
                                                    multi = metadata.ReadSByte();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
                                                    multi = BitConverter.ToChar(metadata.ReadBytes(2), 0);
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_U2:
                                                    multi = metadata.ReadUInt16();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_I2:
                                                    multi = metadata.ReadInt16();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_U4:
                                                    multi = metadata.ReadUInt32();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_I4:
                                                    multi = metadata.ReadInt32();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_U8:
                                                    multi = metadata.ReadUInt64();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_I8:
                                                    multi = metadata.ReadInt64();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_R4:
                                                    multi = metadata.ReadSingle();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_R8:
                                                    multi = metadata.ReadDouble();
                                                    break;

                                                case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                                                    var uiLen = metadata.ReadInt32();
                                                    multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
                                                    break;
                                                }
                                                if (multi is string str)
                                                {
                                                    writer.Write($" = \"{ToEscapedString(str)}\"");
                                                }
                                                else if (multi is char c)
                                                {
                                                    var v = (int)c;
                                                    writer.Write($" = '\\x{v:x}'");
                                                }
                                                else if (multi != null)
                                                {
                                                    writer.Write($" = {multi}");
                                                }
                                            }
                                        }
                                        if (config.DumpFieldOffset)
                                        {
                                            writer.Write("; // 0x{0:X}\n", il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart, i));
                                        }
                                        else
                                        {
                                            writer.Write(";\n");
                                        }
                                    }
                                    writer.Write("\n");
                                }
                                //dump property
                                if (config.DumpProperty && typeDef.property_count > 0)
                                {
                                    writer.Write("\t// Properties\n");
                                    var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                                    for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                                    {
                                        var propertyDef = metadata.propertyDefs[i];
                                        writer.Write(GetCustomAttribute(propertyDef.customAttributeIndex, "\t"));
                                        writer.Write("\t");
                                        if (propertyDef.get >= 0)
                                        {
                                            var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.get];
                                            writer.Write(GetModifiers(methodDef));
                                            var propertyType = il2cpp.types[methodDef.returnType];
                                            writer.Write($"{GetTypeName(propertyType)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                        }
                                        else if (propertyDef.set > 0)
                                        {
                                            var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.set];
                                            writer.Write(GetModifiers(methodDef));
                                            var parameterDef = metadata.parameterDefs[methodDef.parameterStart];
                                            var propertyType = il2cpp.types[parameterDef.typeIndex];
                                            writer.Write($"{GetTypeName(propertyType)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                        }
                                        if (propertyDef.get >= 0)
                                        {
                                            writer.Write("get; ");
                                        }
                                        if (propertyDef.set >= 0)
                                        {
                                            writer.Write("set; ");
                                        }
                                        writer.Write("}");
                                        writer.Write("\n");
                                    }
                                    writer.Write("\n");
                                }
                                //dump method
                                if (config.DumpMethod && typeDef.method_count > 0)
                                {
                                    writer.Write("\t// Methods\n");
                                    var methodEnd = typeDef.methodStart + typeDef.method_count;
                                    for (var i = typeDef.methodStart; i < methodEnd; ++i)
                                    {
                                        var methodDef = metadata.methodDefs[i];
                                        writer.Write(GetCustomAttribute(methodDef.customAttributeIndex, "\t"));
                                        writer.Write("\t");
                                        writer.Write(GetModifiers(methodDef));
                                        var methodReturnType = il2cpp.types[methodDef.returnType];
                                        var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                                        writer.Write($"{GetTypeName(methodReturnType)} {methodName}(");
                                        var parameterStrs = new List <string>();
                                        for (var j = 0; j < methodDef.parameterCount; ++j)
                                        {
                                            var parameterStr      = "";
                                            var parameterDef      = metadata.parameterDefs[methodDef.parameterStart + j];
                                            var parameterName     = metadata.GetStringFromIndex(parameterDef.nameIndex);
                                            var parameterType     = il2cpp.types[parameterDef.typeIndex];
                                            var parameterTypeName = GetTypeName(parameterType);
                                            if ((parameterType.attrs & PARAM_ATTRIBUTE_OPTIONAL) != 0)
                                            {
                                                parameterStr += "optional ";
                                            }
                                            if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
                                            {
                                                parameterStr += "out ";
                                            }
                                            parameterStr += $"{parameterTypeName} {parameterName}";
                                            parameterStrs.Add(parameterStr);
                                        }
                                        writer.Write(string.Join(", ", parameterStrs));
                                        if (config.DumpMethodOffset)
                                        {
                                            ulong methodPointer;
                                            if (methodDef.methodIndex >= 0)
                                            {
                                                methodPointer = il2cpp.methodPointers[methodDef.methodIndex];
                                            }
                                            else
                                            {
                                                il2cpp.genericMethoddDictionary.TryGetValue(i, out methodPointer);
                                            }
                                            if (methodPointer > 0)
                                            {
                                                writer.Write("); // RVA: 0x{0:X} Offset: 0x{1:X}\n", methodPointer, il2cpp.MapVATR(methodPointer));
                                                //Script - method
                                                var name = ToEscapedString(HandleSpecialCharacters(typeName + "$$" + methodName));
                                                scriptwriter.WriteLine($"SetMethod(0x{methodPointer:X}, '{name}')");
                                            }
                                            else
                                            {
                                                writer.Write("); // -1\n");
                                            }
                                        }
                                        else
                                        {
                                            writer.Write("); \n");
                                        }
                                    }
                                }
                                writer.Write("}\n");
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine("ERROR: Some errors in dumping");
                                writer.Write("/*");
                                writer.Write($"{e.Message}\n{e.StackTrace}\n");
                                writer.Write("*/\n}\n");
                            }
                        }
                        //Script - stringLiteral
                        scriptwriter.WriteLine("print('Make method name done')");
                        scriptwriter.WriteLine("print('Setting String...')");
                        if (il2cpp.version > 16)
                        {
                            foreach (var i in metadata.stringLiteralsdic)
                            {
                                scriptwriter.WriteLine($"SetString(0x{il2cpp.metadataUsages[i.Key]:X}, r'{ToEscapedString(i.Value)}')");
                            }
                        }
                        scriptwriter.WriteLine("print('Set string done')");
                        //Script - MakeFunction
                        if (config.MakeFunction)
                        {
                            var orderedPointers = il2cpp.methodPointers.ToList();
                            orderedPointers.AddRange(il2cpp.genericMethodPointers.Where(x => x > 0));
                            orderedPointers.AddRange(il2cpp.invokerPointers);
                            orderedPointers.AddRange(il2cpp.customAttributeGenerators);
                            orderedPointers = orderedPointers.OrderBy(x => x).ToList();
                            scriptwriter.WriteLine("print('Making function...')");
                            for (int i = 0; i < orderedPointers.Count - 1; i++)
                            {
                                scriptwriter.WriteLine($"MakeFunction(0x{orderedPointers[i]:X}, 0x{orderedPointers[i + 1]:X})");
                            }
                            scriptwriter.WriteLine("print('Make function done, please wait for IDA to complete the analysis')");
                        }
                        scriptwriter.WriteLine("print('Script finish !')");
                        //writer close
                        writer.Close();
                        scriptwriter.Close();
                        Console.WriteLine("Done !");
                        //DummyDll
                        if (config.DummyDll)
                        {
                            Console.WriteLine("Create DummyDll...");
                            if (Directory.Exists("DummyDll"))
                            {
                                Directory.Delete("DummyDll", true);
                            }
                            Directory.CreateDirectory("DummyDll");
                            Directory.SetCurrentDirectory("DummyDll");
                            File.WriteAllBytes("Il2CppDummyDll.dll", Resource1.Il2CppDummyDll);
                            var dummy = new DummyAssemblyCreator(metadata, il2cpp);
                            foreach (var assembly in dummy.Assemblies)
                            {
                                var stream = new MemoryStream();
                                assembly.Write(stream);
                                File.WriteAllBytes(assembly.MainModule.Name, stream.ToArray());
                            }
                            Console.WriteLine("Done !");
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                    Console.WriteLine("Press any key to exit...");
                    Console.ReadKey(true);
                }
            }
        }
        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);
                        }
                    }
                }
            }
        }
        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);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Example #6
0
        private static void Dump()
        {
            var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create), new UTF8Encoding(false));

            Console.WriteLine("Dumping...");
            //Script
            var scriptwriter = new StreamWriter(new FileStream("script.py", FileMode.Create), new UTF8Encoding(false));

            scriptwriter.WriteLine(Resource1.ida);
            //dump image
            for (var imageIndex = 0; imageIndex < metadata.uiImageCount; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                writer.Write($"// Image {imageIndex}: {metadata.GetStringFromIndex(imageDef.nameIndex)} - {imageDef.typeStart}\n");
            }
            //dump type
            foreach (var imageDef in metadata.imageDefs)
            {
                try
                {
                    var typeEnd = imageDef.typeStart + imageDef.typeCount;
                    for (int idx = imageDef.typeStart; idx < typeEnd; idx++)
                    {
                        var typeDef  = metadata.typeDefs[idx];
                        var isStruct = false;
                        var isEnum   = false;
                        var extends  = new List <string>();
                        if (typeDef.parentIndex >= 0)
                        {
                            var parent     = il2cpp.types[typeDef.parentIndex];
                            var parentName = GetTypeName(parent);
                            if (parentName == "ValueType")
                            {
                                isStruct = true;
                            }
                            else if (parentName == "Enum")
                            {
                                isEnum = true;
                            }
                            else if (parentName != "object")
                            {
                                extends.Add(parentName);
                            }
                        }
                        //implementedInterfaces
                        if (typeDef.interfaces_count > 0)
                        {
                            for (int i = 0; i < typeDef.interfaces_count; i++)
                            {
                                var @interface = il2cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]];
                                extends.Add(GetTypeName(@interface));
                            }
                        }
                        writer.Write($"\n// Namespace: {metadata.GetStringFromIndex(typeDef.namespaceIndex)}\n");
                        writer.Write(GetCustomAttribute(imageDef, typeDef.customAttributeIndex, typeDef.token));
                        if (config.DumpAttribute && (typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
                        {
                            writer.Write("[Serializable]\n");
                        }
                        var visibility = typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
                        switch (visibility)
                        {
                        case TYPE_ATTRIBUTE_PUBLIC:
                        case TYPE_ATTRIBUTE_NESTED_PUBLIC:
                            writer.Write("public ");
                            break;

                        case TYPE_ATTRIBUTE_NOT_PUBLIC:
                        case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
                        case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
                            writer.Write("internal ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_PRIVATE:
                            writer.Write("private ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_FAMILY:
                            writer.Write("protected ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
                            writer.Write("protected internal ");
                            break;
                        }
                        if ((typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0 && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                        {
                            writer.Write("static ");
                        }
                        else if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) == 0 && (typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0)
                        {
                            writer.Write("abstract ");
                        }
                        else if (!isStruct && !isEnum && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                        {
                            writer.Write("sealed ");
                        }
                        if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0)
                        {
                            writer.Write("interface ");
                        }
                        else if (isStruct)
                        {
                            writer.Write("struct ");
                        }
                        else if (isEnum)
                        {
                            writer.Write("enum ");
                        }
                        else
                        {
                            writer.Write("class ");
                        }
                        var typeName = metadata.GetStringFromIndex(typeDef.nameIndex);
                        writer.Write($"{typeName}");
                        if (extends.Count > 0)
                        {
                            writer.Write($" : {string.Join(", ", extends)}");
                        }
                        if (config.DumpTypeDefIndex)
                        {
                            writer.Write($" // TypeDefIndex: {idx}\n{{");
                        }
                        else
                        {
                            writer.Write("\n{");
                        }
                        //dump field
                        if (config.DumpField && typeDef.field_count > 0)
                        {
                            writer.Write("\n\t// Fields\n");
                            var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                            for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                            {
                                //dump_field(i, idx, i - typeDef.fieldStart);
                                var fieldDef     = metadata.fieldDefs[i];
                                var fieldType    = il2cpp.types[fieldDef.typeIndex];
                                var fieldDefault = metadata.GetFieldDefaultValueFromIndex(i);
                                writer.Write(GetCustomAttribute(imageDef, fieldDef.customAttributeIndex, fieldDef.token, "\t"));
                                writer.Write("\t");
                                var access = fieldType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
                                switch (access)
                                {
                                case FIELD_ATTRIBUTE_PRIVATE:
                                    writer.Write("private ");
                                    break;

                                case FIELD_ATTRIBUTE_PUBLIC:
                                    writer.Write("public ");
                                    break;

                                case FIELD_ATTRIBUTE_FAMILY:
                                    writer.Write("protected ");
                                    break;

                                case FIELD_ATTRIBUTE_ASSEMBLY:
                                case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
                                    writer.Write("internal ");
                                    break;

                                case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
                                    writer.Write("protected internal ");
                                    break;
                                }
                                if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
                                {
                                    writer.Write("const ");
                                }
                                else
                                {
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                                    {
                                        writer.Write("static ");
                                    }
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                                    {
                                        writer.Write("readonly ");
                                    }
                                }
                                writer.Write($"{GetTypeName(fieldType)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}");
                                if (fieldDefault != null && fieldDefault.dataIndex != -1)
                                {
                                    var pointer = metadata.GetDefaultValueFromIndex(fieldDefault.dataIndex);
                                    if (pointer > 0)
                                    {
                                        var pTypeToUse = il2cpp.types[fieldDefault.typeIndex];
                                        metadata.Position = pointer;
                                        object multi = null;
                                        switch (pTypeToUse.type)
                                        {
                                        case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
                                            multi = metadata.ReadBoolean();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_U1:
                                            multi = metadata.ReadByte();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_I1:
                                            multi = metadata.ReadSByte();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
                                            multi = BitConverter.ToChar(metadata.ReadBytes(2), 0);
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_U2:
                                            multi = metadata.ReadUInt16();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_I2:
                                            multi = metadata.ReadInt16();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_U4:
                                            multi = metadata.ReadUInt32();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_I4:
                                            multi = metadata.ReadInt32();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_U8:
                                            multi = metadata.ReadUInt64();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_I8:
                                            multi = metadata.ReadInt64();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_R4:
                                            multi = metadata.ReadSingle();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_R8:
                                            multi = metadata.ReadDouble();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                                            var uiLen = metadata.ReadInt32();
                                            multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
                                            break;
                                        }
                                        if (multi is string str)
                                        {
                                            writer.Write($" = \"{ToEscapedString(str)}\"");
                                        }
                                        else if (multi is char c)
                                        {
                                            var v = (int)c;
                                            writer.Write($" = '\\x{v:x}'");
                                        }
                                        else if (multi != null)
                                        {
                                            writer.Write($" = {multi}");
                                        }
                                    }
                                }
                                if (config.DumpFieldOffset)
                                {
                                    writer.Write("; // 0x{0:X}\n", il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart, i));
                                }
                                else
                                {
                                    writer.Write(";\n");
                                }
                            }
                        }
                        //dump property
                        if (config.DumpProperty && typeDef.property_count > 0)
                        {
                            writer.Write("\n\t// Properties\n");
                            var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                            for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                            {
                                var propertyDef = metadata.propertyDefs[i];
                                writer.Write(GetCustomAttribute(imageDef, propertyDef.customAttributeIndex, propertyDef.token, "\t"));
                                writer.Write("\t");
                                if (propertyDef.get >= 0)
                                {
                                    var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.get];
                                    writer.Write(GetModifiers(methodDef));
                                    var propertyType = il2cpp.types[methodDef.returnType];
                                    writer.Write($"{GetTypeName(propertyType)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                }
                                else if (propertyDef.set > 0)
                                {
                                    var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.set];
                                    writer.Write(GetModifiers(methodDef));
                                    var parameterDef = metadata.parameterDefs[methodDef.parameterStart];
                                    var propertyType = il2cpp.types[parameterDef.typeIndex];
                                    writer.Write($"{GetTypeName(propertyType)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                }
                                if (propertyDef.get >= 0)
                                {
                                    writer.Write("get; ");
                                }
                                if (propertyDef.set >= 0)
                                {
                                    writer.Write("set; ");
                                }
                                writer.Write("}");
                                writer.Write("\n");
                            }
                        }
                        //dump method
                        if (config.DumpMethod && typeDef.method_count > 0)
                        {
                            writer.Write("\n\t// Methods\n");
                            var methodEnd = typeDef.methodStart + typeDef.method_count;
                            for (var i = typeDef.methodStart; i < methodEnd; ++i)
                            {
                                var methodDef = metadata.methodDefs[i];
                                writer.Write(GetCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, "\t"));
                                writer.Write("\t");
                                writer.Write(GetModifiers(methodDef));
                                var methodReturnType = il2cpp.types[methodDef.returnType];
                                var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                                writer.Write($"{GetTypeName(methodReturnType)} {methodName}(");
                                var parameterStrs = new List <string>();
                                for (var j = 0; j < methodDef.parameterCount; ++j)
                                {
                                    var parameterStr      = "";
                                    var parameterDef      = metadata.parameterDefs[methodDef.parameterStart + j];
                                    var parameterName     = metadata.GetStringFromIndex(parameterDef.nameIndex);
                                    var parameterType     = il2cpp.types[parameterDef.typeIndex];
                                    var parameterTypeName = GetTypeName(parameterType);
                                    if ((parameterType.attrs & PARAM_ATTRIBUTE_OPTIONAL) != 0)
                                    {
                                        parameterStr += "optional ";
                                    }
                                    if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
                                    {
                                        parameterStr += "out ";
                                    }
                                    parameterStr += $"{parameterTypeName} {parameterName}";
                                    parameterStrs.Add(parameterStr);
                                }
                                writer.Write(string.Join(", ", parameterStrs));
                                if (config.DumpMethodOffset)
                                {
                                    ulong methodPointer;
                                    if (methodDef.methodIndex >= 0)
                                    {
                                        methodPointer = il2cpp.methodPointers[methodDef.methodIndex];
                                    }
                                    else
                                    {
                                        il2cpp.genericMethoddDictionary.TryGetValue(i, out methodPointer);
                                    }
                                    if (methodPointer > 0)
                                    {
                                        writer.Write("); // RVA: 0x{0:X} Offset: 0x{1:X}\n", methodPointer, il2cpp.MapVATR(methodPointer));
                                        //Script - method
                                        var name = ToEscapedString(HandleSpecialCharacters(typeName + "$$" + methodName));
                                        scriptwriter.WriteLine($"SetMethod(0x{methodPointer:X}, '{name}')");
                                    }
                                    else
                                    {
                                        writer.Write("); // -1\n");
                                    }
                                }
                                else
                                {
                                    writer.Write("); \n");
                                }
                            }
                        }
                        writer.Write("}\n");
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("ERROR: Some errors in dumping");
                    writer.Write("/*");
                    writer.Write(e);
                    writer.Write("*/\n}\n");
                }
            }
            //Script - stringLiteral
            scriptwriter.WriteLine("print('Make method name done')");
            scriptwriter.WriteLine("print('Setting String...')");
            if (il2cpp.version > 16)
            {
                foreach (var i in metadata.stringLiteralsdic)
                {
                    scriptwriter.WriteLine($"SetString(0x{il2cpp.metadataUsages[i.Key]:X}, r'{ToEscapedString(i.Value)}')");
                }
            }
            scriptwriter.WriteLine("print('Set string done')");
            //Script - MakeFunction
            if (config.MakeFunction)
            {
                var orderedPointers = il2cpp.methodPointers.ToList();
                orderedPointers.AddRange(il2cpp.genericMethodPointers.Where(x => x > 0));
                orderedPointers.AddRange(il2cpp.invokerPointers);
                orderedPointers.AddRange(il2cpp.customAttributeGenerators);
                orderedPointers = orderedPointers.OrderBy(x => x).ToList();
                scriptwriter.WriteLine("print('Making function...')");
                for (int i = 0; i < orderedPointers.Count - 1; i++)
                {
                    scriptwriter.WriteLine($"MakeFunction(0x{orderedPointers[i]:X}, 0x{orderedPointers[i + 1]:X})");
                }
                scriptwriter.WriteLine("print('Make function done, please wait for IDA to complete the analysis')");
            }
            scriptwriter.WriteLine("print('Script finish !')");
            //writer close
            writer.Close();
            scriptwriter.Close();
            Console.WriteLine("Done !");
            //DummyDll
            if (config.DummyDll)
            {
                Console.WriteLine("Create DummyDll...");
                if (Directory.Exists("DummyDll"))
                {
                    Directory.Delete("DummyDll", true);
                }
                Directory.CreateDirectory("DummyDll");
                Directory.SetCurrentDirectory("DummyDll");
                File.WriteAllBytes("Il2CppDummyDll.dll", Resource1.Il2CppDummyDll);
                var dummy = new DummyAssemblyCreator(metadata, il2cpp);
                foreach (var assembly in dummy.Assemblies)
                {
                    var stream = new MemoryStream();
                    assembly.Write(stream);
                    File.WriteAllBytes(assembly.MainModule.Name, stream.ToArray());
                }
                Console.WriteLine("Done !");
            }
        }
Example #7
0
        private static void Dump()
        {
            var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create), new UTF8Encoding(false));

            Console.WriteLine("Dumping...");
            //Script
            var scriptwriter = CreateScriptWriter();

            //dump image
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                writer.Write($"// Image {imageIndex}: {metadata.GetStringFromIndex(imageDef.nameIndex)} - {imageDef.typeStart}\n");
            }
            //dump type
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                try
                {
                    var imageDef = metadata.imageDefs[imageIndex];
                    var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                    for (int idx = imageDef.typeStart; idx < typeEnd; idx++)
                    {
                        var typeDef = metadata.typeDefs[idx];
                        typeDefImageIndices.Add(typeDef, imageIndex);
                        var isStruct = false;
                        var isEnum   = false;
                        var extends  = new List <string>();
                        if (typeDef.parentIndex >= 0)
                        {
                            var parent     = il2cpp.types[typeDef.parentIndex];
                            var parentName = GetTypeName(parent);
                            if (parentName == "ValueType")
                            {
                                isStruct = true;
                            }
                            else if (parentName == "Enum")
                            {
                                isEnum = true;
                            }
                            else if (parentName != "object")
                            {
                                extends.Add(parentName);
                            }
                        }
                        //implementedInterfaces
                        if (typeDef.interfaces_count > 0)
                        {
                            for (int i = 0; i < typeDef.interfaces_count; i++)
                            {
                                var @interface = il2cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]];
                                extends.Add(GetTypeName(@interface));
                            }
                        }
                        writer.Write($"\n// Namespace: {metadata.GetStringFromIndex(typeDef.namespaceIndex)}\n");
                        writer.Write(GetCustomAttribute(imageDef, typeDef.customAttributeIndex, typeDef.token));
                        if (config.DumpAttribute && (typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
                        {
                            writer.Write("[Serializable]\n");
                        }
                        var visibility = typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
                        switch (visibility)
                        {
                        case TYPE_ATTRIBUTE_PUBLIC:
                        case TYPE_ATTRIBUTE_NESTED_PUBLIC:
                            writer.Write("public ");
                            break;

                        case TYPE_ATTRIBUTE_NOT_PUBLIC:
                        case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
                        case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
                            writer.Write("internal ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_PRIVATE:
                            writer.Write("private ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_FAMILY:
                            writer.Write("protected ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
                            writer.Write("protected internal ");
                            break;
                        }
                        if ((typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0 && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                        {
                            writer.Write("static ");
                        }
                        else if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) == 0 && (typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0)
                        {
                            writer.Write("abstract ");
                        }
                        else if (!isStruct && !isEnum && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                        {
                            writer.Write("sealed ");
                        }
                        if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0)
                        {
                            writer.Write("interface ");
                        }
                        else if (isStruct)
                        {
                            writer.Write("struct ");
                        }
                        else if (isEnum)
                        {
                            writer.Write("enum ");
                        }
                        else
                        {
                            writer.Write("class ");
                        }
                        var typeName = GetTypeName(typeDef);
                        writer.Write($"{typeName}");
                        if (extends.Count > 0)
                        {
                            writer.Write($" : {string.Join(", ", extends)}");
                        }
                        if (config.DumpTypeDefIndex)
                        {
                            writer.Write($" // TypeDefIndex: {idx}\n{{");
                        }
                        else
                        {
                            writer.Write("\n{");
                        }
                        //dump field
                        if (config.DumpField && typeDef.field_count > 0)
                        {
                            writer.Write("\n\t// Fields\n");
                            var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                            for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                            {
                                //dump_field(i, idx, i - typeDef.fieldStart);
                                var fieldDef          = metadata.fieldDefs[i];
                                var fieldType         = il2cpp.types[fieldDef.typeIndex];
                                var fieldDefaultValue = metadata.GetFieldDefaultValueFromIndex(i);
                                writer.Write(GetCustomAttribute(imageDef, fieldDef.customAttributeIndex, fieldDef.token, "\t"));
                                writer.Write("\t");
                                var access = fieldType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
                                switch (access)
                                {
                                case FIELD_ATTRIBUTE_PRIVATE:
                                    writer.Write("private ");
                                    break;

                                case FIELD_ATTRIBUTE_PUBLIC:
                                    writer.Write("public ");
                                    break;

                                case FIELD_ATTRIBUTE_FAMILY:
                                    writer.Write("protected ");
                                    break;

                                case FIELD_ATTRIBUTE_ASSEMBLY:
                                case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
                                    writer.Write("internal ");
                                    break;

                                case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
                                    writer.Write("protected internal ");
                                    break;
                                }
                                if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
                                {
                                    writer.Write("const ");
                                }
                                else
                                {
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                                    {
                                        writer.Write("static ");
                                    }
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                                    {
                                        writer.Write("readonly ");
                                    }
                                }
                                writer.Write($"{GetTypeName(fieldType)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}");
                                if (fieldDefaultValue != null && fieldDefaultValue.dataIndex != -1)
                                {
                                    var pointer = metadata.GetDefaultValueFromIndex(fieldDefaultValue.dataIndex);
                                    if (pointer > 0)
                                    {
                                        var fieldDefaultValueType = il2cpp.types[fieldDefaultValue.typeIndex];
                                        metadata.Position = pointer;
                                        object val = null;
                                        switch (fieldDefaultValueType.type)
                                        {
                                        case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
                                            val = metadata.ReadBoolean();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_U1:
                                            val = metadata.ReadByte();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_I1:
                                            val = metadata.ReadSByte();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
                                            val = BitConverter.ToChar(metadata.ReadBytes(2), 0);
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_U2:
                                            val = metadata.ReadUInt16();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_I2:
                                            val = metadata.ReadInt16();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_U4:
                                            val = metadata.ReadUInt32();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_I4:
                                            val = metadata.ReadInt32();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_U8:
                                            val = metadata.ReadUInt64();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_I8:
                                            val = metadata.ReadInt64();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_R4:
                                            val = metadata.ReadSingle();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_R8:
                                            val = metadata.ReadDouble();
                                            break;

                                        case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                                            var len = metadata.ReadInt32();
                                            val = Encoding.UTF8.GetString(metadata.ReadBytes(len));
                                            break;

                                        //case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
                                        default:
                                            writer.Write($" /*Default value offset 0x{pointer:X}*/");
                                            break;
                                        }
                                        if (val is string str)
                                        {
                                            writer.Write($" = \"{ToEscapedString(str)}\"");
                                        }
                                        else if (val is char c)
                                        {
                                            var v = (int)c;
                                            writer.Write($" = '\\x{v:x}'");
                                        }
                                        else if (val != null)
                                        {
                                            writer.Write($" = {val}");
                                        }
                                    }
                                }
                                if (config.DumpFieldOffset)
                                {
                                    writer.Write("; // 0x{0:X}\n", il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart, i));
                                }
                                else
                                {
                                    writer.Write(";\n");
                                }
                            }
                        }
                        //dump property
                        if (config.DumpProperty && typeDef.property_count > 0)
                        {
                            writer.Write("\n\t// Properties\n");
                            var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                            for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                            {
                                var propertyDef = metadata.propertyDefs[i];
                                writer.Write(GetCustomAttribute(imageDef, propertyDef.customAttributeIndex, propertyDef.token, "\t"));
                                writer.Write("\t");
                                if (propertyDef.get >= 0)
                                {
                                    var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.get];
                                    writer.Write(GetModifiers(methodDef));
                                    var propertyType = il2cpp.types[methodDef.returnType];
                                    writer.Write($"{GetTypeName(propertyType)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                }
                                else if (propertyDef.set > 0)
                                {
                                    var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.set];
                                    writer.Write(GetModifiers(methodDef));
                                    var parameterDef = metadata.parameterDefs[methodDef.parameterStart];
                                    var propertyType = il2cpp.types[parameterDef.typeIndex];
                                    writer.Write($"{GetTypeName(propertyType)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                }
                                if (propertyDef.get >= 0)
                                {
                                    writer.Write("get; ");
                                }
                                if (propertyDef.set >= 0)
                                {
                                    writer.Write("set; ");
                                }
                                writer.Write("}");
                                writer.Write("\n");
                            }
                        }
                        //dump method
                        if (config.DumpMethod && typeDef.method_count > 0)
                        {
                            writer.Write("\n\t// Methods\n");
                            var methodEnd = typeDef.methodStart + typeDef.method_count;
                            for (var i = typeDef.methodStart; i < methodEnd; ++i)
                            {
                                var methodDef = metadata.methodDefs[i];
                                writer.Write(GetCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, "\t"));
                                writer.Write("\t");
                                writer.Write(GetModifiers(methodDef));
                                var methodReturnType = il2cpp.types[methodDef.returnType];
                                var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                                writer.Write($"{GetTypeName(methodReturnType)} {methodName}(");
                                var parameterStrs = new List <string>();
                                for (var j = 0; j < methodDef.parameterCount; ++j)
                                {
                                    var parameterStr      = "";
                                    var parameterDef      = metadata.parameterDefs[methodDef.parameterStart + j];
                                    var parameterName     = metadata.GetStringFromIndex(parameterDef.nameIndex);
                                    var parameterType     = il2cpp.types[parameterDef.typeIndex];
                                    var parameterTypeName = GetTypeName(parameterType);
                                    if ((parameterType.attrs & PARAM_ATTRIBUTE_OPTIONAL) != 0)
                                    {
                                        parameterStr += "optional ";
                                    }
                                    if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
                                    {
                                        parameterStr += "out ";
                                    }
                                    parameterStr += $"{parameterTypeName} {parameterName}";
                                    parameterStrs.Add(parameterStr);
                                }
                                writer.Write(string.Join(", ", parameterStrs));
                                if (config.DumpMethodOffset)
                                {
                                    var methodPointer = il2cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
                                    if (methodPointer > 0)
                                    {
                                        var fixedMethodPointer = il2cpp.FixPointer(methodPointer);
                                        writer.Write("); // RVA: 0x{0:X} Offset: 0x{1:X}\n", fixedMethodPointer, il2cpp.MapVATR(methodPointer));
                                        //Script - methodPointer
                                        if (il2cpp is PE)
                                        {
                                            scriptwriter.WriteLine($"SetName(0x{methodPointer:X}, '{typeName + "$$" + methodName}')");
                                        }
                                        else
                                        {
                                            scriptwriter.WriteLine($"SetName(0x{fixedMethodPointer:X}, '{typeName + "$$" + methodName}')");
                                        }
                                    }
                                    else
                                    {
                                        writer.Write("); // -1\n");
                                    }
                                }
                                else
                                {
                                    writer.Write("); \n");
                                }
                            }
                        }
                        writer.Write("}\n");
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("ERROR: Some errors in dumping");
                    writer.Write("/*");
                    writer.Write(e);
                    writer.Write("*/\n}\n");
                }
            }
            scriptwriter.WriteLine("print('Make method name done')");
            //Script - MetadataUsage
            if (il2cpp.version > 16)
            {
                scriptwriter.WriteLine("print('Setting MetadataUsage...')");
                foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo
                {
                    var type     = il2cpp.types[i.Value];
                    var typeName = GetTypeName(type, true);
                    scriptwriter.WriteLine($"SetName(0x{il2cpp.metadataUsages[i.Key]:X}, '{"Class$" + typeName}')");
                    scriptwriter.WriteLine($"idc.set_cmt(0x{il2cpp.metadataUsages[i.Key]:X}, r'{typeName}', 1)");
                }
                foreach (var i in metadata.metadataUsageDic[2]) //kIl2CppMetadataUsageIl2CppType
                {
                    var type     = il2cpp.types[i.Value];
                    var typeName = GetTypeName(type, true);
                    scriptwriter.WriteLine($"SetName(0x{il2cpp.metadataUsages[i.Key]:X}, '{"Class$" + typeName}')");
                    scriptwriter.WriteLine($"idc.set_cmt(0x{il2cpp.metadataUsages[i.Key]:X}, r'{typeName}', 1)");
                }
                foreach (var i in metadata.metadataUsageDic[3]) //kIl2CppMetadataUsageMethodDef
                {
                    var methodDef  = metadata.methodDefs[i.Value];
                    var typeDef    = metadata.typeDefs[methodDef.declaringType];
                    var typeName   = GetTypeName(typeDef);
                    var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex) + "()";
                    scriptwriter.WriteLine($"SetName(0x{il2cpp.metadataUsages[i.Key]:X}, '{"Method$" + methodName}')");
                    scriptwriter.WriteLine($"idc.set_cmt(0x{il2cpp.metadataUsages[i.Key]:X}, '{"Method$" + methodName}', 1)");
                    var imageIndex    = typeDefImageIndices[typeDef];
                    var methodPointer = il2cpp.GetMethodPointer(methodDef.methodIndex, (int)i.Value, imageIndex, methodDef.token);
                    scriptwriter.WriteLine($"idc.set_cmt(0x{il2cpp.metadataUsages[i.Key]:X}, '0x{methodPointer:X}', 0)");
                }
                foreach (var i in metadata.metadataUsageDic[4]) //kIl2CppMetadataUsageFieldInfo
                {
                    var fieldRef  = metadata.fieldRefs[i.Value];
                    var type      = il2cpp.types[fieldRef.typeIndex];
                    var typeDef   = metadata.typeDefs[type.data.klassIndex];
                    var fieldDef  = metadata.fieldDefs[typeDef.fieldStart + fieldRef.fieldIndex];
                    var fieldName = GetTypeName(type, true) + "." + metadata.GetStringFromIndex(fieldDef.nameIndex);
                    scriptwriter.WriteLine($"SetName(0x{il2cpp.metadataUsages[i.Key]:X}, '{"Field$" + fieldName}')");
                    scriptwriter.WriteLine($"idc.set_cmt(0x{il2cpp.metadataUsages[i.Key]:X}, r'{fieldName}', 1)");
                }
                var stringLiterals = metadata.metadataUsageDic[5].Select(x => new //kIl2CppMetadataUsageStringLiteral
                {
                    value   = metadata.GetStringLiteralFromIndex(x.Value),
                    address = $"0x{il2cpp.metadataUsages[x.Key]:X}"
                }).ToArray();
                File.WriteAllText("stringliteral.json", JsonConvert.SerializeObject(stringLiterals, Formatting.Indented), new UTF8Encoding(false));
                foreach (var stringLiteral in stringLiterals)
                {
                    scriptwriter.WriteLine($"SetString({stringLiteral.address}, r'{ToEscapedString(stringLiteral.value)}')");
                }
                foreach (var i in metadata.metadataUsageDic[6]) //kIl2CppMetadataUsageMethodRef
                {
                    var methodSpec = il2cpp.methodSpecs[i.Value];
                    var methodDef  = metadata.methodDefs[methodSpec.methodDefinitionIndex];
                    var typeDef    = metadata.typeDefs[methodDef.declaringType];
                    var typeName   = GetTypeName(typeDef);
                    // Class of the method is generic
                    if (methodSpec.classIndexIndex != -1)
                    {
                        var classInst = il2cpp.genericInsts[methodSpec.classIndexIndex];
                        typeName += GetGenericTypeParams(classInst);
                    }

                    var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex) + "()";
                    // Method itself is generic
                    if (methodSpec.methodIndexIndex != -1)
                    {
                        var methodInst = il2cpp.genericInsts[methodSpec.methodIndexIndex];
                        methodName += GetGenericTypeParams(methodInst);
                    }

                    scriptwriter.WriteLine($"SetName(0x{il2cpp.metadataUsages[i.Key]:X}, '{"Method$" + methodName}')");
                    scriptwriter.WriteLine($"idc.set_cmt(0x{il2cpp.metadataUsages[i.Key]:X}, '{"Method$" + methodName}', 1)");
                    var imageIndex    = typeDefImageIndices[typeDef];
                    var methodPointer = il2cpp.GetMethodPointer(methodDef.methodIndex, methodSpec.methodDefinitionIndex, imageIndex, methodDef.token);
                    scriptwriter.WriteLine($"idc.set_cmt(0x{il2cpp.metadataUsages[i.Key]:X}, '0x{methodPointer:X}', 0)");
                }
                scriptwriter.WriteLine("print('Set MetadataUsage done')");
            }
            //Script - MakeFunction
            if (config.MakeFunction)
            {
                List <ulong> orderedPointers;
                if (il2cpp.version >= 24.2f)
                {
                    orderedPointers = new List <ulong>();
                    foreach (var methodPointers in il2cpp.codeGenModuleMethodPointers)
                    {
                        orderedPointers.AddRange(methodPointers);
                    }
                }
                else
                {
                    orderedPointers = il2cpp.methodPointers.ToList();
                }
                orderedPointers.AddRange(il2cpp.genericMethodPointers);
                orderedPointers.AddRange(il2cpp.invokerPointers);
                orderedPointers.AddRange(il2cpp.customAttributeGenerators);
                if (il2cpp.version >= 22)
                {
                    orderedPointers.AddRange(il2cpp.reversePInvokeWrappers);
                    orderedPointers.AddRange(il2cpp.unresolvedVirtualCallPointers);
                }
                //TODO interopData内也包含函数
                orderedPointers = orderedPointers.Distinct().OrderBy(x => x).ToList();
                orderedPointers.Remove(0);
                scriptwriter.WriteLine("print('Making function...')");
                for (int i = 0; i < orderedPointers.Count - 1; i++)
                {
                    scriptwriter.WriteLine($"MakeFunction(0x{orderedPointers[i]:X}, 0x{orderedPointers[i + 1]:X})");
                }
                scriptwriter.WriteLine("print('Make function done, please wait for IDA to complete the analysis')");
            }
            scriptwriter.WriteLine("print('Script finish !')");
            //writer close
            writer.Close();
            scriptwriter.Close();
            Console.WriteLine("Done !");
            //DummyDll
            if (config.DummyDll)
            {
                Console.WriteLine("Create DummyDll...");
                if (Directory.Exists("DummyDll"))
                {
                    Directory.Delete("DummyDll", true);
                }
                Directory.CreateDirectory("DummyDll");
                Directory.SetCurrentDirectory("DummyDll");
                var dummy = new DummyAssemblyCreator(metadata, il2cpp);
                foreach (var assembly in dummy.Assemblies)
                {
                    var stream = new MemoryStream();
                    assembly.Write(stream);
                    File.WriteAllBytes(assembly.MainModule.Name, stream.ToArray());
                }
                Console.WriteLine("Done !");
            }
        }
Example #8
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);
                        }
                    }
                }
            }
        }
Example #9
0
        public void Decompile(StreamWriter writer, Config config)
        {
            //dump image
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                writer.Write($"// Image {imageIndex}: {metadata.GetStringFromIndex(imageDef.nameIndex)} - {imageDef.typeStart}\n");
            }
            //dump type
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                try
                {
                    var imageDef = metadata.imageDefs[imageIndex];
                    var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                    for (int idx = imageDef.typeStart; idx < typeEnd; idx++)
                    {
                        var typeDef  = metadata.typeDefs[idx];
                        var isStruct = false;
                        var isEnum   = false;
                        var extends  = new List <string>();
                        if (typeDef.parentIndex >= 0)
                        {
                            var parent     = il2Cpp.types[typeDef.parentIndex];
                            var parentName = GetTypeName(parent);
                            if (parentName == "ValueType")
                            {
                                isStruct = true;
                            }
                            else if (parentName == "Enum")
                            {
                                isEnum = true;
                            }
                            else if (parentName != "object")
                            {
                                extends.Add(parentName);
                            }
                        }
                        if (typeDef.interfaces_count > 0)
                        {
                            for (int i = 0; i < typeDef.interfaces_count; i++)
                            {
                                var @interface = il2Cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]];
                                extends.Add(GetTypeName(@interface));
                            }
                        }
                        writer.Write($"\n// Namespace: {metadata.GetStringFromIndex(typeDef.namespaceIndex)}\n");
                        if (config.DumpAttribute)
                        {
                            writer.Write(GetCustomAttribute(imageDef, typeDef.customAttributeIndex, typeDef.token));
                        }
                        if (config.DumpAttribute && (typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
                        {
                            writer.Write("[Serializable]\n");
                        }
                        var visibility = typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
                        switch (visibility)
                        {
                        case TYPE_ATTRIBUTE_PUBLIC:
                        case TYPE_ATTRIBUTE_NESTED_PUBLIC:
                            writer.Write("public ");
                            break;

                        case TYPE_ATTRIBUTE_NOT_PUBLIC:
                        case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
                        case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
                            writer.Write("internal ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_PRIVATE:
                            writer.Write("private ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_FAMILY:
                            writer.Write("protected ");
                            break;

                        case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
                            writer.Write("protected internal ");
                            break;
                        }
                        if ((typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0 && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                        {
                            writer.Write("static ");
                        }
                        else if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) == 0 && (typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0)
                        {
                            writer.Write("abstract ");
                        }
                        else if (!isStruct && !isEnum && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                        {
                            writer.Write("sealed ");
                        }
                        if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0)
                        {
                            writer.Write("interface ");
                        }
                        else if (isStruct)
                        {
                            writer.Write("struct ");
                        }
                        else if (isEnum)
                        {
                            writer.Write("enum ");
                        }
                        else
                        {
                            writer.Write("class ");
                        }
                        var typeName = GetTypeName(typeDef);
                        writer.Write($"{typeName}");
                        if (extends.Count > 0)
                        {
                            writer.Write($" : {string.Join(", ", extends)}");
                        }
                        if (config.DumpTypeDefIndex)
                        {
                            writer.Write($" // TypeDefIndex: {idx}\n{{");
                        }
                        else
                        {
                            writer.Write("\n{");
                        }
                        //dump field
                        if (config.DumpField && typeDef.field_count > 0)
                        {
                            writer.Write("\n\t// Fields\n");
                            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 fieldDefaultValue = metadata.GetFieldDefaultValueFromIndex(i);
                                if (config.DumpAttribute)
                                {
                                    writer.Write(GetCustomAttribute(imageDef, fieldDef.customAttributeIndex, fieldDef.token, "\t"));
                                }
                                writer.Write("\t");
                                var access = fieldType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
                                switch (access)
                                {
                                case FIELD_ATTRIBUTE_PRIVATE:
                                    writer.Write("private ");
                                    break;

                                case FIELD_ATTRIBUTE_PUBLIC:
                                    writer.Write("public ");
                                    break;

                                case FIELD_ATTRIBUTE_FAMILY:
                                    writer.Write("protected ");
                                    break;

                                case FIELD_ATTRIBUTE_ASSEMBLY:
                                case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
                                    writer.Write("internal ");
                                    break;

                                case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
                                    writer.Write("protected internal ");
                                    break;
                                }
                                if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
                                {
                                    writer.Write("const ");
                                }
                                else
                                {
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                                    {
                                        writer.Write("static ");
                                    }
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                                    {
                                        writer.Write("readonly ");
                                    }
                                }
                                writer.Write($"{GetTypeName(fieldType)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}");
                                if (fieldDefaultValue != null && fieldDefaultValue.dataIndex != -1)
                                {
                                    var pointer = metadata.GetDefaultValueFromIndex(fieldDefaultValue.dataIndex);
                                    var fieldDefaultValueType = il2Cpp.types[fieldDefaultValue.typeIndex];
                                    metadata.Position = pointer;
                                    object val = null;
                                    switch (fieldDefaultValueType.type)
                                    {
                                    case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
                                        val = metadata.ReadBoolean();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_U1:
                                        val = metadata.ReadByte();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_I1:
                                        val = metadata.ReadSByte();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
                                        val = BitConverter.ToChar(metadata.ReadBytes(2), 0);
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_U2:
                                        val = metadata.ReadUInt16();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_I2:
                                        val = metadata.ReadInt16();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_U4:
                                        val = metadata.ReadUInt32();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_I4:
                                        val = metadata.ReadInt32();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_U8:
                                        val = metadata.ReadUInt64();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_I8:
                                        val = metadata.ReadInt64();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_R4:
                                        val = metadata.ReadSingle();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_R8:
                                        val = metadata.ReadDouble();
                                        break;

                                    case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                                        var len = metadata.ReadInt32();
                                        val = Encoding.UTF8.GetString(metadata.ReadBytes(len));
                                        break;

                                    default:
                                        writer.Write($" /*Metadata offset 0x{pointer:X}*/");
                                        break;
                                    }
                                    if (val is string str)
                                    {
                                        writer.Write($" = \"{ToEscapedString(str)}\"");
                                    }
                                    else if (val is char c)
                                    {
                                        var v = (int)c;
                                        writer.Write($" = '\\x{v:x}'");
                                    }
                                    else if (val != null)
                                    {
                                        writer.Write($" = {val}");
                                    }
                                }
                                if (config.DumpFieldOffset)
                                {
                                    writer.Write("; // 0x{0:X}\n", il2Cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart, i));
                                }
                                else
                                {
                                    writer.Write(";\n");
                                }
                            }
                        }
                        //dump property
                        if (config.DumpProperty && typeDef.property_count > 0)
                        {
                            writer.Write("\n\t// Properties\n");
                            var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                            for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                            {
                                var propertyDef = metadata.propertyDefs[i];
                                if (config.DumpAttribute)
                                {
                                    writer.Write(GetCustomAttribute(imageDef, propertyDef.customAttributeIndex, propertyDef.token, "\t"));
                                }
                                writer.Write("\t");
                                if (propertyDef.get >= 0)
                                {
                                    var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.get];
                                    writer.Write(GetModifiers(methodDef));
                                    var propertyType = il2Cpp.types[methodDef.returnType];
                                    writer.Write($"{GetTypeName(propertyType)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                }
                                else if (propertyDef.set > 0)
                                {
                                    var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.set];
                                    writer.Write(GetModifiers(methodDef));
                                    var parameterDef = metadata.parameterDefs[methodDef.parameterStart];
                                    var propertyType = il2Cpp.types[parameterDef.typeIndex];
                                    writer.Write($"{GetTypeName(propertyType)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                }
                                if (propertyDef.get >= 0)
                                {
                                    writer.Write("get; ");
                                }
                                if (propertyDef.set >= 0)
                                {
                                    writer.Write("set; ");
                                }
                                writer.Write("}");
                                writer.Write("\n");
                            }
                        }
                        //dump method
                        if (config.DumpMethod && typeDef.method_count > 0)
                        {
                            writer.Write("\n\t// Methods\n");
                            var methodEnd = typeDef.methodStart + typeDef.method_count;
                            for (var i = typeDef.methodStart; i < methodEnd; ++i)
                            {
                                var methodDef = metadata.methodDefs[i];
                                if (config.DumpAttribute)
                                {
                                    writer.Write(GetCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, "\t"));
                                }
                                writer.Write("\t");
                                writer.Write(GetModifiers(methodDef));
                                var methodReturnType = il2Cpp.types[methodDef.returnType];
                                var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                                if (methodReturnType.byref == 1)
                                {
                                    writer.Write("ref ");
                                }
                                writer.Write($"{GetTypeName(methodReturnType)} {methodName}(");
                                var parameterStrs = new List <string>();
                                for (var j = 0; j < methodDef.parameterCount; ++j)
                                {
                                    var parameterStr      = "";
                                    var parameterDef      = metadata.parameterDefs[methodDef.parameterStart + j];
                                    var parameterName     = metadata.GetStringFromIndex(parameterDef.nameIndex);
                                    var parameterType     = il2Cpp.types[parameterDef.typeIndex];
                                    var parameterTypeName = GetTypeName(parameterType);
                                    if (parameterType.byref == 1)
                                    {
                                        if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0 && (parameterType.attrs & PARAM_ATTRIBUTE_IN) == 0)
                                        {
                                            parameterStr += "out ";
                                        }
                                        else if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) == 0 && (parameterType.attrs & PARAM_ATTRIBUTE_IN) != 0)
                                        {
                                            parameterStr += "in ";
                                        }
                                        else
                                        {
                                            parameterStr += "ref ";
                                        }
                                    }
                                    else
                                    {
                                        if ((parameterType.attrs & PARAM_ATTRIBUTE_IN) != 0)
                                        {
                                            parameterStr += "[In] ";
                                        }
                                        if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
                                        {
                                            parameterStr += "[Out] ";
                                        }
                                    }
                                    parameterStr += $"{parameterTypeName} {parameterName}";
                                    var parameterDefault = metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j);
                                    if (parameterDefault != null && parameterDefault.dataIndex != -1)
                                    {
                                        var value = GetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex);
                                        if (value is string str)
                                        {
                                            parameterStr += $" = \"{ToEscapedString(str)}\"";
                                        }
                                        else if (value is char c)
                                        {
                                            var v = (int)c;
                                            parameterStr += $" = '\\x{v:x}'";
                                        }
                                        else if (value != null)
                                        {
                                            parameterStr += $" = {value}";
                                        }
                                    }
                                    parameterStrs.Add(parameterStr);
                                }
                                writer.Write(string.Join(", ", parameterStrs));
                                writer.Write(") { }");
                                if (config.DumpMethodOffset)
                                {
                                    var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
                                    if (methodPointer > 0)
                                    {
                                        var fixedMethodPointer = il2Cpp.FixPointer(methodPointer);
                                        writer.Write(" // RVA: 0x{0:X} Offset: 0x{1:X}\n", fixedMethodPointer, il2Cpp.MapVATR(methodPointer));
                                    }
                                    else
                                    {
                                        writer.Write(" // -1\n");
                                    }
                                }
                                else
                                {
                                    writer.Write("\n");
                                }
                            }
                        }
                        writer.Write("}\n");
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("ERROR: Some errors in dumping");
                    writer.Write("/*");
                    writer.Write(e);
                    writer.Write("*/\n}\n");
                }
            }
            writer.Close();
        }
Example #10
0
        public void Decompile(Config config, string outputDir)
        {
            //var writer = new StreamWriter(new FileStream(outputDir + "dump.cs", FileMode.Create), new UTF8Encoding(false));

            //dump image
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                //var imageDef = metadata.imageDefs[imageIndex];
                //writer.Write($"// Image {imageIndex}: {metadata.GetStringFromIndex(imageDef.nameIndex)} - {imageDef.typeStart}\n");
            }
            //dump type
            foreach (var imageDef in metadata.imageDefs)
            {
                string typeName = "";
                try
                {
                    var imageName = metadata.GetStringFromIndex(imageDef.nameIndex);

                    var typeEnd = imageDef.typeStart + imageDef.typeCount;
                    for (int typeDefIndex = imageDef.typeStart; typeDefIndex < typeEnd; typeDefIndex++)
                    {
                        var types        = new HashSet <Il2CppType>();
                        var hpp_includes = new HashSet <string>();
                        var cpp_includes = new HashSet <string>();

                        bool is_generic   = false;
                        bool is_interface = false;
                        var  typeDef      = metadata.typeDefs[typeDefIndex];
                        typeName = executor.GetTypeDefName(typeDef, false, false);
                        var genericTypeName = executor.GetTypeDefName(typeDef, false, true);
                        var generic_decl    = executor.GetTypeDefName(typeDef, false, true, true);
                        var extends         = new List <string>();
                        var namespaze       = metadata.GetStringFromIndex(typeDef.namespaceIndex);
                        namespaze = namespaze.Replace(".", "::");

                        typeName = clear_name(typeName);
                        typeName = deobfu(typeName);

                        // if (typeName == "Object" && namespaze == "unityEngine") extends.add(il2cppObject);

                        var fullTypeName = typeName;
                        if (namespaze != "")
                        {
                            fullTypeName = namespaze + "::" + typeName;
                        }

                        if (executor.GetTypeDefName(typeDef, false, true).Contains("<"))
                        {
                            is_generic = true;
                        }

                        // skip
                        //if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0) continue;
                        //if ((typeDef.flags & TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) != 0) continue;
                        if (klasses.Count() > 0 && !klasses.Contains(typeName))
                        {
                            continue;
                        }

                        // outputs
                        string hpp_headers   = "";
                        string cpp_headers   = "";
                        string statics_def   = "";
                        string meta_statics  = "";
                        string methods_rva   = "";
                        string fields        = "";
                        string methods       = "";
                        string methods_decl  = "";
                        string methods_def   = "";
                        string klass         = "";
                        string klass_meta    = "";
                        string klass_inerhit = "";

                        // file
                        string file_path = "au/" + namespaze.Replace("::", "/") + "/";
                        file_path += typeName;

                        StreamWriter hpp_writer;
                        StreamWriter cpp_writer;
                        try
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(file_path));

                            hpp_writer = new StreamWriter(new FileStream(outputDir + file_path + ".hpp", FileMode.Create), new UTF8Encoding(false));
                            cpp_writer = new StreamWriter(new FileStream(outputDir + file_path + ".cpp", FileMode.Create), new UTF8Encoding(false));
                        }
                        catch (Exception) { continue; }

                        if (typeDef.parentIndex >= 0)
                        {
                            var parent     = il2Cpp.types[typeDef.parentIndex];
                            var parentName = executor.GetTypeName(parent, true, false, false);
                            if (!typeDef.IsValueType && !typeDef.IsEnum && parentName != "object")
                            {
                                extends.Add(parentName);
                                //types.Add(parent);
                                hpp_includes.Add("#include <" + include_path(parent) + ".hpp>\n");
                            }
                        }
                        if (typeDef.interfaces_count > 0)
                        {
                            for (int i = 0; i < typeDef.interfaces_count; i++)
                            {
                                var @interface = il2Cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]];
                                //extends.Add(executor.GetTypeName(@interface, false, false));
                            }
                        }


                        if (is_generic)
                        {
                            klass += generic_decl + "\n";
                        }



                        if (typeDef.IsEnum)
                        {
                            klass += "enum class ";
                        }
                        else
                        {
                            klass += "struct ";
                        }

                        klass += typeName;

                        genericTypeName = deobfu(genericTypeName.Replace("::", "_"));
                        if (!typeDef.IsEnum)
                        {
                            if (extends.Count > 0)
                            {
                                klass_inerhit = $" : ark::meta<{genericTypeName}, {string.Join(", ", extends)}>";
                            }
                            else
                            {
                                klass_inerhit = $" : ark::meta<{genericTypeName}>";
                            }
                            klass_meta = $"ark_meta(\"{namespaze}\", \"{typeName}\", \"\");";
                        }



                        //dump field
                        if (config.DumpField && typeDef.field_count > 0)
                        {
                            fields += "\n    // Fields\n\n";
                            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 isStatic  = false;
                                var isConst   = false;

                                var field_typename = executor.GetTypeName(fieldType, true, false, true);
                                field_typename = deobfu(field_typename);
                                var field_name = metadata.GetStringFromIndex(fieldDef.nameIndex);
                                field_name = deobfu(field_name);
                                field_name = clear_name(field_name);


                                types.Add(fieldType);

                                fields += "    ";
                                var access = fieldType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;

                                // enum
                                if (typeDef.IsEnum)
                                {
                                    if (i == typeDef.fieldStart)
                                    {
                                        klass_inerhit = " : " + field_typename;
                                    }
                                    else
                                    {
                                        fields += field_name;

                                        if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefaultValue) && fieldDefaultValue.dataIndex != -1)
                                        {
                                            if (TryGetDefaultValue(fieldDefaultValue.typeIndex, fieldDefaultValue.dataIndex, out var value))
                                            {
                                                fields += $" = ";
                                                if (value is string str)
                                                {
                                                    fields += $"\"{str.ToEscapedString()}\"";
                                                }
                                                else if (value is char c)
                                                {
                                                    var v = (int)c;
                                                    fields += $"'\\x{v:x}'";
                                                }
                                                else if (value != null)
                                                {
                                                    fields += $"{value}";
                                                }
                                            }
                                            else
                                            {
                                                fields += $" /*Metadata offset 0x{value:X}*/";
                                            }
                                        }
                                        fields += ",";
                                    }
                                }
                                // class
                                else
                                {
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
                                    {
                                        isConst = true;
                                        fields += "inline static constexpr ";
                                    }
                                    else
                                    {
                                        if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                                        {
                                            isStatic = true;
                                            fields  += "static ";
                                            var return_type = executor.GetTypeName(fieldType, true, false, true);
                                            statics_def  += "\n" + return_type + " " + executor.GetTypeDefName(typeDef, true, true) + "::" + field_name + "() { return statics()->" + field_name + "; }";
                                            meta_statics += "\n    " + return_type + " " + field_name + ";";
                                        }
                                    }

                                    if (field_typename == "object")
                                    {
                                        field_typename = typeName + "*";
                                    }
                                    if (isConst && field_typename == "cs::string*")
                                    {
                                        field_typename = "const char*";
                                    }

                                    fields += $"{field_typename} {field_name}";
                                    if (isStatic)
                                    {
                                        fields += "()";
                                    }

                                    if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefaultValue) && fieldDefaultValue.dataIndex != -1)
                                    {
                                        if (TryGetDefaultValue(fieldDefaultValue.typeIndex, fieldDefaultValue.dataIndex, out var value))
                                        {
                                            fields += $" = ";
                                            if (value is string str)
                                            {
                                                fields += $"\"{str.ToEscapedString()}\"";
                                            }
                                            else if (value is char c)
                                            {
                                                var v = (int)c;
                                                fields += $"'\\x{v:x}'";
                                            }
                                            else if (value != null)
                                            {
                                                fields += cpp_value($"{value}");
                                            }
                                        }
                                        else
                                        {
                                            fields += $" /*Metadata offset 0x{value:X}*/";
                                        }
                                    }
                                    if (config.DumpFieldOffset && !isConst)
                                    {
                                        fields += $"; // 0x{il2Cpp.GetFieldOffsetFromIndex(typeDefIndex, i - typeDef.fieldStart, i, typeDef.IsValueType, isStatic):X}";
                                    }
                                    else
                                    {
                                        fields += ";\n";
                                    }
                                }
                                fields += "\n";
                            }
                        }

                        //dump method
                        if (config.DumpMethod && typeDef.method_count > 0)
                        {
                            methods_decl += "\n    // Methods\n\n";
                            methods_def  += "\n    // Methods\n\n";

                            var           methodEnd    = typeDef.methodStart + typeDef.method_count;
                            List <string> method_names = new List <string>();

                            for (var i = typeDef.methodStart; i < methodEnd; ++i)
                            {
                                var   methodDef          = metadata.methodDefs[i];
                                ulong fixedMethodPointer = 0;

                                var methodPointer = il2Cpp.GetMethodPointer(imageName, methodDef);
                                if (methodPointer > 0)
                                {
                                    fixedMethodPointer = il2Cpp.GetRVA(methodPointer);
                                }

                                methods_decl += "    ";
                                methods_def  += "    ";
                                var methodReturnType = il2Cpp.types[methodDef.returnType];
                                types.Add(methodReturnType);

                                var methodName = metadata.GetStringFromIndex(methodDef.nameIndex);
                                methodName = deobfu(methodName);
                                methodName = methodName.Replace(".", "");
                                methodName = clear_name(methodName);

                                var original_method_name = methodName;
                                int name_count           = method_names.Where(x => x.Equals(original_method_name)).Count();
                                if (name_count > 0)
                                {
                                    methodName += name_count.ToString();
                                }
                                method_names.Add(original_method_name);

                                var is_generic_method = false;
                                var comment           = "";
                                if (methodDef.genericContainerIndex >= 0)
                                {
                                    var genericContainer = metadata.genericContainers[methodDef.genericContainerIndex];
                                    is_generic_method = true;
                                    //methodName = "// " + methodName + executor.GetGenericContainerParams(genericContainer);
                                    comment = "// ";
                                }
                                if (methodReturnType.byref == 1)
                                {
                                    methods_decl += "/*ref*/ ";
                                }

                                var methodReturnTypeName = executor.GetTypeName(methodReturnType, true, false);
                                methods_decl += comment + $"{methodReturnTypeName} {methodName}(";
                                methods_def  += comment + $"{methodReturnTypeName} {typeName}::{methodName}(";

                                // rva
                                //methods_rva += $"\n    method_rva({executor.GetTypeDefName(typeDef, true, true)}::{methodName}, 0x{fixedMethodPointer:X})";

                                var rvamethod_name  = $"{ executor.GetTypeDefName(typeDef, true, true) }::{methodName}";
                                var rvamethd_adress = $"0x{fixedMethodPointer:X}";

                                if (fixedMethodPointer != 0)
                                {
                                    methods_rva += "\n    template<> inline uintptr_t rva<&" + rvamethod_name + "> () { return " + rvamethd_adress + "; }";
                                }

                                var parameters_decl = new List <string>();
                                var parameters_def  = new List <string>();
                                var parameter_names = new List <string>();

                                for (var j = 0; j < methodDef.parameterCount; ++j)
                                {
                                    var parameterStr_decl = "";
                                    var parameterStr_def  = "";
                                    var parameterDef      = metadata.parameterDefs[methodDef.parameterStart + j];
                                    var parameterName     = metadata.GetStringFromIndex(parameterDef.nameIndex);
                                    parameterName = clear_name(parameterName);
                                    parameterName = deobfu(parameterName);
                                    var parameterType = il2Cpp.types[parameterDef.typeIndex];
                                    types.Add(parameterType);
                                    var parameterTypeName = executor.GetTypeName(parameterType, true, false, true);
                                    parameterTypeName = deobfu(parameterTypeName);
                                    if (parameterTypeName == "object")
                                    {
                                        parameterTypeName = typeName + "*";
                                    }

                                    parameter_names.Add(parameterName);

                                    if (parameterType.byref == 1)
                                    {
                                        if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0 && (parameterType.attrs & PARAM_ATTRIBUTE_IN) == 0)
                                        {
                                            parameterStr_decl += "/*out*/ ";
                                        }
                                        else if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) == 0 && (parameterType.attrs & PARAM_ATTRIBUTE_IN) != 0)
                                        {
                                            parameterStr_decl += "/*in*/ ";
                                        }
                                        else
                                        {
                                            parameterStr_decl += "/*ref*/ ";
                                        }
                                    }

                                    parameterStr_decl += $"{parameterTypeName} {parameterName}";
                                    parameterStr_def  += $"{parameterTypeName} {parameterName}";

                                    if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1)
                                    {
                                        if (TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value))
                                        {
                                            parameterStr_decl += " = ";
                                            if (value is string str)
                                            {
                                                parameterStr_decl += $"\"{str.ToEscapedString()}\"";
                                            }
                                            else if (value is char c)
                                            {
                                                var v = (int)c;
                                                parameterStr_decl += $"'\\x{v:x}'";
                                            }
                                            else if (value != null)
                                            {
                                                value              = cpp_value(value.ToString());
                                                parameterStr_decl += $"{parameterTypeName}({value})";
                                            }
                                        }
                                        else
                                        {
                                            parameterStr_decl += $" /*Metadata offset 0x{value:X}*/";
                                        }
                                    }

                                    parameters_decl.Add(parameterStr_decl);
                                    parameters_def.Add(parameterStr_def);
                                }

                                var methodCall = $"return method_call({methodName}, {string.Join(", ", parameter_names)}); ";
                                if (parameter_names.Count() == 0)
                                {
                                    methodCall = $"return method_call({methodName}); ";
                                }


                                methods_decl += string.Join(", ", parameters_decl);
                                methods_decl += ");";
                                methods_decl += $" // 0x{fixedMethodPointer:X} // ";
                                methods_decl += GetModifiers(methodDef);
                                methods_decl += "\n";

                                methods_def += string.Join(", ", parameters_def);
                                methods_def += ") { " + methodCall + "} ";
                                methods_def += $" // 0x{fixedMethodPointer:X} // ";
                                methods_def += "\n";
                            }
                        }

                        // headers
                        foreach (Il2CppType type in types)
                        {
                            if (!((int)type.type < 0x0e ||
                                  type.type == Il2CppTypeEnum.IL2CPP_TYPE_MVAR ||
                                  type.type == Il2CppTypeEnum.IL2CPP_TYPE_VAR ||
                                  type.type == Il2CppTypeEnum.IL2CPP_TYPE_I ||
                                  type.type == Il2CppTypeEnum.IL2CPP_TYPE_U))
                            {
                                if (executor.GetTypeName(type, false, true) != typeName)
                                {
                                    hpp_includes.Add(header_include(type) + "\n");
                                }

                                /*
                                 * if ((int)type.type != 0x1c && (int)type.type != 0x18 && (int)type.type != 0x19 && (int)type.type != 0x1e)
                                 *  cpp_includes.Add($"#include <{include_path(type)}.hpp>\n");
                                 *
                                 * if (is_generic || (type.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST || type.type == Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE))
                                 *  hpp_includes.Add($"\n#include <{include_path(type)}.hpp>\n");
                                 * else if (executor.GetTypeName(type, false, true) != typeName)
                                 * {
                                 *  var fwd = fwd_decl(type);
                                 *  if (fwd != "") hpp_includes.Add(fwd + "\n");
                                 * }*/
                            }
                        }

                        foreach (string include in hpp_includes)
                        {
                            hpp_headers += include;
                        }
                        foreach (string include in cpp_includes)
                        {
                            cpp_headers += include;
                        }

                        meta_statics = "namespace ark\n{\ntemplate<>\nstruct meta_statics<" + fullTypeName + ">\n{" + meta_statics + "\n};\n} // ark\n";

                        if (is_interface || is_generic)
                        {
                            meta_statics = "";
                            statics_def  = "";
                            methods_rva  = "";
                        }

                        // hpp
                        hpp_writer.Write("//" + file_path + "\n#pragma once\n#include <ark/class.hpp>\n");
                        hpp_writer.Write(hpp_headers + "\n");

                        if (namespaze != "")
                        {
                            hpp_writer.Write("\nnamespace " + namespaze + " {\n");
                        }

                        hpp_writer.Write(klass + klass_inerhit + "\n{\n" + klass_meta + "\n");

                        hpp_writer.Write(fields);

                        hpp_writer.Write(methods_decl);

                        hpp_writer.Write("\n};\n");
                        if (namespaze != "")
                        {
                            hpp_writer.Write("\n} // ns");
                        }

                        hpp_writer.Write("\n\n");

                        hpp_writer.Write(meta_statics);

                        hpp_writer.Write("\n\nnamespace ark::method_info \n{");
                        hpp_writer.Write(methods_rva);
                        hpp_writer.Write("\n} // ark::method_info");

                        hpp_writer.Close();

                        if (!is_generic)
                        {
                            cpp_writer.Write("#include <" + file_path + ".hpp>\n");
                            cpp_writer.Write(cpp_headers);
                            if (namespaze != "")
                            {
                                cpp_writer.Write("\nnamespace " + namespaze + " {\n");
                            }
                            cpp_writer.Write(methods_def);
                            if (namespaze != "")
                            {
                                cpp_writer.Write("\n}\n\n");
                            }

                            cpp_writer.Write(statics_def);

                            cpp_writer.Close();
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("ERROR: Some errors in dumping " + e.Message + " (" + typeName + ")");
                }
            }
        }
Example #11
0
        private void DumpField(StreamWriter writer, Il2CppTypeDefinition typeDef, int idx)
        {
            writer.Write("\t// Fields\n");
            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 fieldDefault = metadata.GetFieldDefaultValueFromIndex(i);
                writer.Write(GetCustomAttribute(fieldDef.customAttributeIndex, "\t"));
                writer.Write("\t");
                var access = fieldType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
                switch (access)
                {
                case FIELD_ATTRIBUTE_PRIVATE:
                    writer.Write("private ");
                    break;

                case FIELD_ATTRIBUTE_PUBLIC:
                    writer.Write("public ");
                    break;

                case FIELD_ATTRIBUTE_FAMILY:
                    writer.Write("protected ");
                    break;

                case FIELD_ATTRIBUTE_ASSEMBLY:
                case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
                    writer.Write("internal ");
                    break;

                case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
                    writer.Write("protected internal ");
                    break;
                }
                if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
                {
                    writer.Write("const ");
                }
                else
                {
                    if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                    {
                        writer.Write("static ");
                    }
                    if ((fieldType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                    {
                        writer.Write("readonly ");
                    }
                }
                writer.Write($"{GetTypeName(fieldType)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}");
                if (fieldDefault != null && fieldDefault.dataIndex != -1)
                {
                    var pointer = metadata.GetDefaultValueFromIndex(fieldDefault.dataIndex);
                    if (pointer > 0)
                    {
                        var pTypeToUse = il2cpp.types[fieldDefault.typeIndex];
                        metadata.Position = pointer;
                        object multi = null;
                        switch (pTypeToUse.type)
                        {
                        case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
                            multi = metadata.ReadBoolean();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_U1:
                            multi = metadata.ReadByte();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_I1:
                            multi = metadata.ReadSByte();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
                            multi = BitConverter.ToChar(metadata.ReadBytes(2), 0);
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_U2:
                            multi = metadata.ReadUInt16();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_I2:
                            multi = metadata.ReadInt16();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_U4:
                            multi = metadata.ReadUInt32();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_I4:
                            multi = metadata.ReadInt32();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_U8:
                            multi = metadata.ReadUInt64();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_I8:
                            multi = metadata.ReadInt64();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_R4:
                            multi = metadata.ReadSingle();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_R8:
                            multi = metadata.ReadDouble();
                            break;

                        case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                            var uiLen = metadata.ReadInt32();
                            multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
                            break;
                        }
                        if (multi is string str)
                        {
                            writer.Write($" = \"{ToEscapedString(str)}\"");
                        }
                        else if (multi is char c)
                        {
                            var v = (int)c;
                            writer.Write($" = '\\x{v:x}'");
                        }
                        else if (multi != null)
                        {
                            writer.Write($" = {multi}");
                        }
                    }
                }
                if (config.DumpFieldOffset)
                {
                    writer.Write("; // 0x{0:X}\n", il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart, i));
                }
                else
                {
                    writer.Write(";\n");
                }
            }
            writer.Write("\n");
        }