Ejemplo n.º 1
0
 private void CreateCustomAttribute(Il2CppImageDefinition imageDef, int customAttributeIndex, uint token, ModuleDefinition moduleDefinition, Collection <CustomAttribute> customAttributes)
 {
     if (il2cpp.version > 20)
     {
         var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, 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];
                 var attributeName      = GetTypeName(attributeType);
                 if (attributeName == "CompilerGeneratedAttribute" ||
                     attributeName == "DebuggerBrowsableAttribute" ||
                     attributeName == "SerializeField")
                 {
                     continue;
                 }
                 var methodPointer      = il2cpp.customAttributeGenerators[attributeIndex];
                 var fixedMethodPointer = il2cpp.FixPointer(methodPointer);
                 var customAttribute    = new CustomAttribute(moduleDefinition.ImportReference(attributeAttribute));
                 var name   = new CustomAttributeNamedArgument("Name", new CustomAttributeArgument(stringType, attributeName));
                 var rva    = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{fixedMethodPointer:X}"));
                 var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2cpp.MapVATR(methodPointer):X}"));
                 customAttribute.Fields.Add(name);
                 customAttribute.Fields.Add(rva);
                 customAttribute.Fields.Add(offset);
                 customAttributes.Add(customAttribute);
             }
         }
     }
 }
Ejemplo n.º 2
0
        private void CreateCustomAttribute(Il2CppImageDefinition imageDef, int customAttributeIndex, uint token, ModuleDefinition moduleDefinition, Collection <CustomAttribute> customAttributes)
        {
            var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, token);

            if (attributeIndex >= 0)
            {
                var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex];
                for (int i = 0; i < attributeTypeRange.count; i++)
                {
                    var attributeTypeIndex = metadata.attributeTypes[attributeTypeRange.start + i];
                    var attributeType      = il2Cpp.types[attributeTypeIndex];
                    var typeDefinition     = typeDefinitionDic[attributeType.data.klassIndex];
                    if (knownAttributes.TryGetValue(typeDefinition.FullName, out var methodDefinition))
                    {
                        var customAttribute = new CustomAttribute(moduleDefinition.ImportReference(methodDefinition));
                        customAttributes.Add(customAttribute);
                    }
                    else
                    {
                        var methodPointer      = il2Cpp.customAttributeGenerators[attributeIndex];
                        var fixedMethodPointer = il2Cpp.FixPointer(methodPointer);
                        var customAttribute    = new CustomAttribute(moduleDefinition.ImportReference(attributeAttribute));
                        var name   = new CustomAttributeNamedArgument("Name", new CustomAttributeArgument(stringType, typeDefinition.Name));
                        var rva    = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{fixedMethodPointer:X}"));
                        var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2Cpp.MapVATR(methodPointer):X}"));
                        customAttribute.Fields.Add(name);
                        customAttribute.Fields.Add(rva);
                        customAttribute.Fields.Add(offset);
                        customAttributes.Add(customAttribute);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        public void WriteScript(Config config)
        {
            var writer = new StreamWriter(new FileStream("ida.py", FileMode.Create), new UTF8Encoding(false));

            writer.WriteLine("# -*- coding: utf-8 -*-");
            writer.WriteLine("import idaapi");
            writer.WriteLine();
            writer.WriteLine("def SetString(addr, comm):");
            writer.WriteLine("\tglobal index");
            writer.WriteLine("\tname = \"StringLiteral_\" + str(index)");
            writer.WriteLine("\tret = idc.set_name(addr, name, SN_NOWARN)");
            writer.WriteLine("\tidc.set_cmt(addr, comm, 1)");
            writer.WriteLine("\tindex += 1");
            writer.WriteLine();
            writer.WriteLine("def SetName(addr, name):");
            writer.WriteLine("\tret = idc.set_name(addr, name, SN_NOWARN | SN_NOCHECK)");
            writer.WriteLine("\tif ret == 0:");
            writer.WriteLine("\t\tnew_name = name + '_' + str(addr)");
            writer.WriteLine("\t\tret = idc.set_name(addr, new_name, SN_NOWARN | SN_NOCHECK)");
            writer.WriteLine();
            writer.WriteLine("def MakeFunction(start, end):");
            writer.WriteLine("\tnext_func = idc.get_next_func(start)");
            writer.WriteLine("\tif next_func < end:");
            writer.WriteLine("\t\tend = next_func");
            writer.WriteLine("\tif idc.get_func_attr(start, FUNCATTR_START) == start:");
            writer.WriteLine("\t\tida_funcs.del_func(start)");
            writer.WriteLine("\tida_funcs.add_func(start, end)");
            writer.WriteLine();
            writer.WriteLine("index = 1");
            writer.WriteLine("print('Making method name...')");
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
                {
                    var typeDef  = metadata.typeDefs[typeIndex];
                    var typeName = GetTypeDefName(typeDef);
                    typeDefImageIndices.Add(typeDef, imageIndex);
                    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 methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
                        if (methodPointer > 0)
                        {
                            var fixedMethodPointer = il2Cpp.FixPointer(methodPointer);
                            if (il2Cpp is PE)
                            {
                                writer.WriteLine($"SetName(0x{methodPointer:X}, '{typeName + "$$" + methodName}')");
                            }
                            else
                            {
                                writer.WriteLine($"SetName(0x{fixedMethodPointer:X}, '{typeName + "$$" + methodName}')");
                            }
                        }
                    }
                }
            }
            writer.WriteLine("print('Make method name done')");
            if (il2Cpp.version > 16)
            {
                writer.WriteLine("print('Setting MetadataUsage...')");
                foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo
                {
                    var type     = il2Cpp.types[i.Value];
                    var typeName = GetTypeName(type, true);
                    writer.WriteLine($"SetName(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Class$" + typeName}')");
                    writer.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);
                    writer.WriteLine($"SetName(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Class$" + typeName}')");
                    writer.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   = GetTypeDefName(typeDef);
                    var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex) + "()";
                    writer.WriteLine($"SetName(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Method$" + methodName}')");
                    writer.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);
                    writer.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);
                    writer.WriteLine($"SetName(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Field$" + fieldName}')");
                    writer.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)); //TODO
                foreach (var stringLiteral in stringLiterals)
                {
                    writer.WriteLine($"SetString({stringLiteral.address}, r'{stringLiteral.value.ToEscapedString()}')");
                }
                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   = GetTypeDefName(typeDef, false);
                    if (methodSpec.classIndexIndex != -1)
                    {
                        var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex];
                        typeName += GetGenericTypeParams(classInst);
                    }
                    var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex);
                    if (methodSpec.methodIndexIndex != -1)
                    {
                        var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex];
                        methodName += GetGenericTypeParams(methodInst);
                    }
                    methodName += "()";
                    writer.WriteLine($"SetName(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Method$" + methodName}')");
                    writer.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);
                    writer.WriteLine($"idc.set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, '0x{methodPointer:X}', 0)");
                }
                writer.WriteLine("print('Set MetadataUsage done')");
            }
            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);
                writer.WriteLine("print('Making function...')");
                for (int i = 0; i < orderedPointers.Count - 1; i++)
                {
                    writer.WriteLine($"MakeFunction(0x{orderedPointers[i]:X}, 0x{orderedPointers[i + 1]:X})");
                }
                writer.WriteLine("print('Make function done, please wait for IDA to complete the analysis')");
            }
            writer.WriteLine("print('Script finished!')");
            writer.Close();
        }
Ejemplo n.º 4
0
        public void Decompile(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 = GetTypeDefName(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)
                                {
                                    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(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)
                                    {
                                        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(") { }");
                                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();
        }
Ejemplo n.º 5
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 !");
            }
        }
Ejemplo n.º 6
0
        public DummyAssemblyCreator(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];
            stringType         = il2CppDummyDll.MainModule.TypeSystem.String;

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

            resolver.Register(il2CppDummyDll);
            //创建程序集,同时创建所有类
            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];
                    //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 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.ImportReference(fieldOffsetAttribute));
                            var offset          = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{fieldOffset:X}"));
                            customAttribute.Fields.Add(offset);
                            fieldDefinition.CustomAttributes.Add(customAttribute);
                        }
                        //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 methodReturnType = il2cpp.types[methodDef.returnType];
                        var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                        var methodDefinition = new MethodDefinition(methodName, (MethodAttributes)methodDef.flags, typeDefinition.Module.ImportReference(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 = 0; j < genericContainer.type_argc; j++)
                                {
                                    var genericParameterIndex = genericContainer.genericParameterStart + j;
                                    var param       = metadata.genericParameters[genericParameterIndex];
                                    var genericName = metadata.GetStringFromIndex(param.nameIndex);
                                    if (!genericParameterDic.TryGetValue(genericParameterIndex, out var genericParameter))
                                    {
                                        genericParameter = new GenericParameter(genericName, methodDefinition);
                                        methodDefinition.GenericParameters.Add(genericParameter);
                                        genericParameterDic.Add(genericParameterIndex, genericParameter);
                                    }
                                    else
                                    {
                                        if (!methodDefinition.GenericParameters.Contains(genericParameter))
                                        {
                                            methodDefinition.GenericParameters.Add(genericParameter);
                                        }
                                    }
                                }
                            }
                        }
                        //methodAddress
                        var methodPointer = il2cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
                        if (methodPointer > 0)
                        {
                            var customAttribute    = new CustomAttribute(typeDefinition.Module.ImportReference(addressAttribute));
                            var fixedMethodPointer = il2cpp.FixPointer(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}"));
                            customAttribute.Fields.Add(rva);
                            customAttribute.Fields.Add(offset);
                            methodDefinition.CustomAttributes.Add(customAttribute);
                        }
                        //methodAttribute
                        CreateCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, typeDefinition.Module, methodDefinition.CustomAttributes);
                    }
                    //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);

                        //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 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);
                        //eventAttribute
                        CreateCustomAttribute(imageDef, eventDef.customAttributeIndex, eventDef.token, typeDefinition.Module, eventDefinition.CustomAttributes);
                    }
                    //补充泛型参数
                    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;
                                var param       = metadata.genericParameters[genericParameterIndex];
                                var genericName = metadata.GetStringFromIndex(param.nameIndex);
                                if (!genericParameterDic.TryGetValue(genericParameterIndex, out var genericParameter))
                                {
                                    genericParameter = new GenericParameter(genericName, typeDefinition);
                                    typeDefinition.GenericParameters.Add(genericParameter);
                                    genericParameterDic.Add(genericParameterIndex, genericParameter);
                                }
                                else
                                {
                                    if (!typeDefinition.GenericParameters.Contains(genericParameter))
                                    {
                                        typeDefinition.GenericParameters.Add(genericParameter);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //第三遍,添加SerializeField用于MonoBehaviour的反序列化
            if (il2cpp.version > 20)
            {
                var engine = Assemblies.Find(x => x.MainModule.Types.Any(t => t.Namespace == "UnityEngine" && t.Name == "SerializeField"));
                if (engine != null)
                {
                    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.ImportReference(serializeField));
                                                fieldDefinition.CustomAttributes.Add(customAttribute);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 7
0
 public void WriteScript(StreamWriter writer, Config config)
 {
     writer.WriteLine("#include <idc.idc>");
     writer.WriteLine();
     writer.WriteLine("static MySetString(addr, comm) {");
     writer.WriteLine("\textern index;");
     writer.WriteLine("\tauto name = sprintf(\"StringLiteral_%d\", index);");
     writer.WriteLine("\tcreate_data(addr, FF_QWORD, 8, BADADDR);");
     writer.WriteLine("\tset_name(addr, name, SN_NOWARN);");
     writer.WriteLine("\tset_cmt(addr, comm, 1);");
     writer.WriteLine("\tindex = index + 1;");
     writer.WriteLine("}");
     writer.WriteLine();
     writer.WriteLine("static MySetName(addr, name) {");
     writer.WriteLine("\tauto ret = set_name(addr, name, SN_NOWARN | SN_NOCHECK);");
     writer.WriteLine("\tif (ret == 0) {");
     writer.WriteLine("\t\tauto new_name = sprintf(\"%s_%x\", name, addr);");
     writer.WriteLine("\t\tset_name(addr, new_name, SN_NOWARN | SN_NOCHECK);");
     writer.WriteLine("\t}");
     writer.WriteLine("}");
     writer.WriteLine();
     writer.WriteLine("static MyMakeFunction(start, end) {");
     writer.WriteLine("\tauto next_func = get_next_func(start);");
     writer.WriteLine("\tif (next_func < end)");
     writer.WriteLine("\t\tend = next_func;");
     writer.WriteLine("\tif (get_func_attr(start, FUNCATTR_START) == start)");
     writer.WriteLine("\t\tdel_func(start);");
     writer.WriteLine("\tadd_func(start, end);");
     writer.WriteLine("}");
     writer.WriteLine();
     writer.WriteLine("static main(void) {");
     writer.WriteLine("extern index;");
     writer.WriteLine("index = 1;");
     writer.WriteLine("msg(\"Making method name...\\n\");");
     for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
     {
         var imageDef = metadata.imageDefs[imageIndex];
         var typeEnd  = imageDef.typeStart + imageDef.typeCount;
         for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
         {
             var typeDef  = metadata.typeDefs[typeIndex];
             var typeName = GetTypeName(typeDef);
             typeDefImageIndices.Add(typeDef, imageIndex);
             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 methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
                 if (methodPointer > 0)
                 {
                     var fixedMethodPointer = il2Cpp.FixPointer(methodPointer);
                     if (il2Cpp is PE)
                     {
                         writer.WriteLine($"MySetName(0x{methodPointer:X}, \"{typeName + "$$" + methodName}\");");
                     }
                     else
                     {
                         writer.WriteLine($"MySetName(0x{fixedMethodPointer:X}, \"{typeName + "$$" + methodName}\");");
                     }
                 }
             }
         }
     }
     writer.WriteLine("msg(\"Make method name done\\n\");");
     if (il2Cpp.version > 16)
     {
         writer.WriteLine("msg(\"Setting MetadataUsage...\\n\");");
         foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo
         {
             var type     = il2Cpp.types[i.Value];
             var typeName = GetTypeName(type, true);
             writer.WriteLine($"MySetName(0x{il2Cpp.metadataUsages[i.Key]:X}, \"{"Class$" + typeName}\");");
             writer.WriteLine($"set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, \"{typeName}\", 1);");
         }
         foreach (var i in metadata.metadataUsageDic[2]) //kIl2CppMetadataUsageIl2CppType
         {
             var type     = il2Cpp.types[i.Value];
             var typeName = GetTypeName(type, true);
             writer.WriteLine($"MySetName(0x{il2Cpp.metadataUsages[i.Key]:X}, \"{"Class$" + typeName}\");");
             writer.WriteLine($"set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, \"{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) + "()";
             writer.WriteLine($"MySetName(0x{il2Cpp.metadataUsages[i.Key]:X}, \"{"Method$" + methodName}\");");
             writer.WriteLine($"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);
             writer.WriteLine($"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);
             writer.WriteLine($"MySetName(0x{il2Cpp.metadataUsages[i.Key]:X}, \"{"Field$" + fieldName}\");");
             writer.WriteLine($"set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, \"{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)); //TODO
         foreach (var stringLiteral in stringLiterals)
         {
             writer.WriteLine($"MySetString({stringLiteral.address}, \"{stringLiteral.value.ToEscapedString()}\");");
         }
         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);
             if (methodSpec.classIndexIndex != -1)
             {
                 var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex];
                 typeName += GetGenericTypeParams(classInst);
             }
             var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex) + "()";
             if (methodSpec.methodIndexIndex != -1)
             {
                 var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex];
                 methodName += GetGenericTypeParams(methodInst);
             }
             writer.WriteLine($"MySetName(0x{il2Cpp.metadataUsages[i.Key]:X}, \"{"Method$" + methodName}\");");
             writer.WriteLine($"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);
             writer.WriteLine($"set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, \"0x{methodPointer:X}\", 0);");
         }
         writer.WriteLine("msg(\"Set MetadataUsage done\\n\");");
     }
     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);
         writer.WriteLine("msg(\"Making function...\\n\");");
         for (int i = 0; i < orderedPointers.Count - 1; i++)
         {
             writer.WriteLine($"MyMakeFunction(0x{orderedPointers[i]:X}, 0x{orderedPointers[i + 1]:X});");
         }
         writer.WriteLine("msg(\"Make function done, please wait for IDA to complete the analysis\\n\");");
     }
     writer.WriteLine("msg(\"Script finished!\\n\");");
     writer.WriteLine("}");
     writer.Close();
 }