Exemple #1
0
        private object GetDefaultValue(int dataIndex, int typeIndex)
        {
            var pointer = metadata.GetDefaultValueFromIndex(dataIndex);

            if (pointer > 0)
            {
                var pTypeToUse = il2cpp.types[typeIndex];
                metadata.Position = pointer;
                switch (pTypeToUse.type)
                {
                case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
                    return(metadata.ReadBoolean());

                case Il2CppTypeEnum.IL2CPP_TYPE_U1:
                    return(metadata.ReadByte());

                case Il2CppTypeEnum.IL2CPP_TYPE_I1:
                    return(metadata.ReadSByte());

                case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
                    return(BitConverter.ToChar(metadata.ReadBytes(2), 0));

                case Il2CppTypeEnum.IL2CPP_TYPE_U2:
                    return(metadata.ReadUInt16());

                case Il2CppTypeEnum.IL2CPP_TYPE_I2:
                    return(metadata.ReadInt16());

                case Il2CppTypeEnum.IL2CPP_TYPE_U4:
                    return(metadata.ReadUInt32());

                case Il2CppTypeEnum.IL2CPP_TYPE_I4:
                    return(metadata.ReadInt32());

                case Il2CppTypeEnum.IL2CPP_TYPE_U8:
                    return(metadata.ReadUInt64());

                case Il2CppTypeEnum.IL2CPP_TYPE_I8:
                    return(metadata.ReadInt64());

                case Il2CppTypeEnum.IL2CPP_TYPE_R4:
                    return(metadata.ReadSingle());

                case Il2CppTypeEnum.IL2CPP_TYPE_R8:
                    return(metadata.ReadDouble());

                case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                    var uiLen = metadata.ReadInt32();
                    return(Encoding.UTF8.GetString(metadata.ReadBytes(uiLen)));
                }
            }
            return(null);
        }
Exemple #2
0
        static void Main(string[] args)
        {
            config = File.Exists("config.json") ? new JavaScriptSerializer().Deserialize <Config>(File.ReadAllText("config.json")) : new Config();
            var ofd = new OpenFileDialog();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            metadata.Position = pointer;
            switch (defaultValueType.type)
            {
            case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
                value = metadata.ReadBoolean();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_U1:
                value = metadata.ReadByte();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_I1:
                value = metadata.ReadSByte();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
                value = BitConverter.ToChar(metadata.ReadBytes(2), 0);
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_U2:
                value = metadata.ReadUInt16();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_I2:
                value = metadata.ReadInt16();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_U4:
                value = metadata.ReadUInt32();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_I4:
                value = metadata.ReadInt32();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_U8:
                value = metadata.ReadUInt64();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_I8:
                value = metadata.ReadInt64();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_R4:
                value = metadata.ReadSingle();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_R8:
                value = metadata.ReadDouble();
                return(true);

            case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                var len = metadata.ReadInt32();
                value = Encoding.UTF8.GetString(metadata.ReadBytes(len));
                return(true);

            default:
                value = pointer;
                return(false);
            }
        }
Exemple #4
0
        static void Main(string[] args)
        {
            Console.WriteLine("Select Mode: 1. Manual 2.Auto");
            var key = Console.ReadKey(true);

            try
            {
                if (key.KeyChar == '2')
                {
                    metadata = new Metadata(new MemoryStream(File.ReadAllBytes("global-metadata.dat")));
                    il2cpp   = new Il2Cpp(new MemoryStream(File.ReadAllBytes("libil2cpp.so")));
                }
                else if (key.KeyChar == '1')
                {
                    Console.Write("Input CodeRegistration(R0): ");
                    var codeRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
                    Console.Write("Input MetadataRegistration(R1): ");
                    var metadataRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
                    metadata = new Metadata(new MemoryStream(File.ReadAllBytes("global-metadata.dat")));
                    il2cpp   = new Il2Cpp(new MemoryStream(File.ReadAllBytes("libil2cpp.so")), codeRegistration, metadataRegistration);
                }
                else
                {
                    return;
                }
                var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create));
                Console.WriteLine("Dumping...");
                //dump_image();
                for (int imageIndex = 0; imageIndex < metadata.uiImageCount; imageIndex++)
                {
                    var imageDef = metadata.imageDefs[imageIndex];
                    writer.Write($"// Image {imageIndex}: {metadata.GetString(imageDef.nameIndex)} - {imageDef.typeStart}\n");
                }
                for (int idx = 0; idx < metadata.uiNumTypes; ++idx)
                {
                    //dump_class(i);
                    var typeDef = metadata.typeDefs[idx];
                    writer.Write($"// Namespace: {metadata.GetString(typeDef.namespaceIndex)}\n");
                    if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
                    {
                        writer.Write("[Serializable]\n");
                    }
                    if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_VISIBILITY_MASK) == DefineConstants.TYPE_ATTRIBUTE_PUBLIC)
                    {
                        writer.Write("public ");
                    }
                    if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_ABSTRACT) != 0)
                    {
                        writer.Write("abstract ");
                    }
                    if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_SEALED) != 0)
                    {
                        writer.Write("sealed ");
                    }
                    if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_INTERFACE) != 0)
                    {
                        writer.Write("interface ");
                    }
                    else
                    {
                        writer.Write("class ");
                    }
                    writer.Write($"{metadata.GetString(typeDef.nameIndex)} // TypeDefIndex: {idx}\n{{\n");
                    writer.Write("\t// Fields\n");
                    var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                    for (int i = typeDef.fieldStart; i < fieldEnd; ++i)
                    {
                        //dump_field(i, idx, i - typeDef.fieldStart);
                        var pField   = metadata.fieldDefs[i];
                        var pType    = il2cpp.GetTypeFromTypeIndex(pField.typeIndex);
                        var pDefault = metadata.GetFieldDefaultFromIndex(i);
                        writer.Write("\t");
                        if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_PRIVATE) == DefineConstants.FIELD_ATTRIBUTE_PRIVATE)
                        {
                            writer.Write("private ");
                        }
                        if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_PUBLIC) == DefineConstants.FIELD_ATTRIBUTE_PUBLIC)
                        {
                            writer.Write("public ");
                        }
                        if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_STATIC) != 0)
                        {
                            writer.Write("static ");
                        }
                        if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                        {
                            writer.Write("readonly ");
                        }
                        writer.Write($"{get_type_name(pType)} {metadata.GetString(pField.nameIndex)}");
                        if (pDefault != null && pDefault.dataIndex != -1)
                        {
                            var        pointer    = metadata.GetDefaultValueFromIndex(pDefault.dataIndex);
                            Il2CppType pTypeToUse = il2cpp.GetTypeFromTypeIndex(pDefault.typeIndex);
                            if (pointer > 0)
                            {
                                metadata.Position = pointer;
                                object multi = null;
                                switch (pTypeToUse.type)
                                {
                                case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
                                    multi = metadata.ReadBoolean();
                                    break;

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

                                case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
                                    multi = metadata.ReadChar();
                                    break;

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

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

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

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

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

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

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

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

                                case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                                    var uiLen = metadata.ReadInt32();
                                    multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
                                    break;
                                }
                                if (multi is string)
                                {
                                    writer.Write($" = \"{multi}\"");
                                }
                                else if (multi != null)
                                {
                                    writer.Write($" = {multi}");
                                }
                            }
                        }
                        writer.Write("; // 0x{0:x}\n", il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart));
                    }
                    writer.Write("\t// Methods\n");
                    var methodEnd = typeDef.methodStart + typeDef.method_count;
                    for (int i = typeDef.methodStart; i < methodEnd; ++i)
                    {
                        //dump_method(i);
                        var methodDef = metadata.methodDefs[i];
                        writer.Write("\t");
                        Il2CppType pReturnType = il2cpp.GetTypeFromTypeIndex(methodDef.returnType);
                        if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == DefineConstants.METHOD_ATTRIBUTE_PRIVATE)
                        {
                            writer.Write("private ");
                        }
                        if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == DefineConstants.METHOD_ATTRIBUTE_PUBLIC)
                        {
                            writer.Write("public ");
                        }
                        if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_VIRTUAL) != 0)
                        {
                            writer.Write("virtual ");
                        }
                        if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_STATIC) != 0)
                        {
                            writer.Write("static ");
                        }

                        writer.Write($"{get_type_name(pReturnType)} {metadata.GetString(methodDef.nameIndex)}(");
                        for (int j = 0; j < methodDef.parameterCount; ++j)
                        {
                            Il2CppParameterDefinition pParam = metadata.parameterDefs[methodDef.parameterStart + j];
                            string     szParamName           = metadata.GetString(pParam.nameIndex);
                            Il2CppType pType      = il2cpp.GetTypeFromTypeIndex(pParam.typeIndex);
                            string     szTypeName = get_type_name(pType);
                            if ((pType.attrs & DefineConstants.PARAM_ATTRIBUTE_OPTIONAL) != 0)
                            {
                                writer.Write("optional ");
                            }
                            if ((pType.attrs & DefineConstants.PARAM_ATTRIBUTE_OUT) != 0)
                            {
                                writer.Write("out ");
                            }
                            if (j != methodDef.parameterCount - 1)
                            {
                                writer.Write($"{szTypeName} {szParamName}, ");
                            }
                            else
                            {
                                writer.Write($"{szTypeName} {szParamName}");
                            }
                        }
                        if (methodDef.methodIndex >= 0)
                        {
                            writer.Write("); // {0:x} - {1}\n", il2cpp.pCodeRegistration.methodPointers[methodDef.methodIndex], methodDef.methodIndex);
                        }
                        else
                        {
                            writer.Write("); // 0 - -1\n");
                        }
                    }
                    writer.Write("}\n");
                }
                writer.Close();
                Console.WriteLine("Done !");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey(true);
        }
Exemple #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 = new StreamWriter(new FileStream("script.py", FileMode.Create), new UTF8Encoding(false));

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            ofd.Filter = "ELF file or Mach-O file|*.*";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                var il2cppfile = File.ReadAllBytes(ofd.FileName);
                ofd.Filter = "global-metadata|global-metadata.dat";
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        metadata = new Metadata(new MemoryStream(File.ReadAllBytes(ofd.FileName)));
                        //判断il2cpp的magic
                        var il2cppmagic = BitConverter.ToUInt32(il2cppfile, 0);
                        var isElf       = false;
                        var is64bit     = false;
                        switch (il2cppmagic)
                        {
                        default:
                            throw new Exception("ERROR: il2cpp file not supported.");

                        case 0x464c457f:    //ELF
                            isElf = true;
                            goto case 0xFEEDFACE;

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

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

                        case 0xFEEDFACE:    // 32-bit mach object file
                            Console.WriteLine("Select Mode: 1.Manual 2.Auto 3.Auto(Advanced)");
                            key = Console.ReadKey(true);
                            var version = config.forceil2cppversion ? config.forceversion : metadata.version;
                            switch (key.KeyChar)
                            {
                            case '2':
                            case '3':
                                if (isElf)
                                {
                                    il2cpp = new Elf(new MemoryStream(il2cppfile), version, metadata.maxmetadataUsages);
                                }
                                else if (is64bit)
                                {
                                    il2cpp = new Macho64(new MemoryStream(il2cppfile), version, metadata.maxmetadataUsages);
                                }
                                else
                                {
                                    il2cpp = new Macho(new MemoryStream(il2cppfile), version, metadata.maxmetadataUsages);
                                }
                                try
                                {
                                    if (key.KeyChar == '2' ?
                                        !il2cpp.Search() :
                                        !il2cpp.AdvancedSearch(metadata.methodDefs.Count(x => x.methodIndex >= 0)))
                                    {
                                        throw new Exception();
                                    }
                                }
                                catch
                                {
                                    throw new Exception("ERROR: Unable to process file automatically, try to use other mode.");
                                }
                                break;

                            case '1':
                            {
                                Console.Write("Input CodeRegistration(Parameter 0): ");
                                var codeRegistration = Convert.ToUInt64(Console.ReadLine(), 16);
                                Console.Write("Input MetadataRegistration(Parameter 1): ");
                                var metadataRegistration = Convert.ToUInt64(Console.ReadLine(), 16);
                                if (isElf)
                                {
                                    il2cpp = new Elf(new MemoryStream(il2cppfile), codeRegistration, metadataRegistration, version, metadata.maxmetadataUsages);
                                }
                                else if (is64bit)
                                {
                                    il2cpp = new Macho64(new MemoryStream(il2cppfile), codeRegistration, metadataRegistration, version, metadata.maxmetadataUsages);
                                }
                                else
                                {
                                    il2cpp = new Macho(new MemoryStream(il2cppfile), codeRegistration, metadataRegistration, version, metadata.maxmetadataUsages);
                                }
                                break;
                            }

                            default:
                                return;
                            }
                            var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create), Encoding.UTF8);
                            Console.WriteLine("Dumping...");
                            //Script
                            var scriptwriter = new StreamWriter(new FileStream("script.py", FileMode.Create), Encoding.UTF8);
                            scriptwriter.WriteLine(Resource1.ida);
                            //
                            //dump image;
                            for (var imageIndex = 0; imageIndex < metadata.uiImageCount; imageIndex++)
                            {
                                var imageDef = metadata.imageDefs[imageIndex];
                                writer.Write($"// Image {imageIndex}: {metadata.GetString(imageDef.nameIndex)} - {imageDef.typeStart}\n");
                            }
                            //dump type;
                            for (var idx = 0; idx < metadata.uiNumTypes; ++idx)
                            {
                                try
                                {
                                    var typeDef  = metadata.typeDefs[idx];
                                    var isStruct = false;
                                    var 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 != "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.GetString(typeDef.namespaceIndex)}\n");
                                    writer.Write(GetCustomAttribute(typeDef.customAttributeIndex));
                                    if (config.dumpattribute && (typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
                                    {
                                        writer.Write("[Serializable]\n");
                                    }
                                    var visibility = typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
                                    if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
                                    {
                                        writer.Write("public ");
                                    }
                                    else if (visibility == TYPE_ATTRIBUTE_NOT_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM || visibility == TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
                                    {
                                        writer.Write("internal ");
                                    }
                                    else if (visibility == TYPE_ATTRIBUTE_NESTED_PRIVATE)
                                    {
                                        writer.Write("private ");
                                    }
                                    else if (visibility == TYPE_ATTRIBUTE_NESTED_FAMILY)
                                    {
                                        writer.Write("protected ");
                                    }
                                    else if (visibility == TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
                                    {
                                        writer.Write("protected internal ");
                                    }
                                    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 && (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
                                    {
                                        writer.Write("class ");
                                    }
                                    writer.Write($"{metadata.GetString(typeDef.nameIndex)}");
                                    if (extends.Count > 0)
                                    {
                                        writer.Write($" : {string.Join(", ", extends)}");
                                    }
                                    writer.Write($" // TypeDefIndex: {idx}\n{{\n");
                                    //dump field
                                    if (config.dumpfield && typeDef.field_count > 0)
                                    {
                                        writer.Write("\t// Fields\n");
                                        var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                                        for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                                        {
                                            //dump_field(i, idx, i - typeDef.fieldStart);
                                            var pField   = metadata.fieldDefs[i];
                                            var pType    = il2cpp.types[pField.typeIndex];
                                            var pDefault = metadata.GetFieldDefaultFromIndex(i);
                                            writer.Write(GetCustomAttribute(pField.customAttributeIndex, "\t"));
                                            writer.Write("\t");
                                            var access = pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
                                            if (access == FIELD_ATTRIBUTE_PRIVATE)
                                            {
                                                writer.Write("private ");
                                            }
                                            else if (access == FIELD_ATTRIBUTE_PUBLIC)
                                            {
                                                writer.Write("public ");
                                            }
                                            else if (access == FIELD_ATTRIBUTE_FAMILY)
                                            {
                                                writer.Write("protected ");
                                            }
                                            else if (access == FIELD_ATTRIBUTE_ASSEMBLY || access == FIELD_ATTRIBUTE_FAM_AND_ASSEM)
                                            {
                                                writer.Write("internal ");
                                            }
                                            else if (access == FIELD_ATTRIBUTE_FAM_OR_ASSEM)
                                            {
                                                writer.Write("protected internal ");
                                            }
                                            if ((pType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
                                            {
                                                writer.Write("const ");
                                            }
                                            else
                                            {
                                                if ((pType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                                                {
                                                    writer.Write("static ");
                                                }
                                                if ((pType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                                                {
                                                    writer.Write("readonly ");
                                                }
                                            }
                                            writer.Write($"{GetTypeName(pType)} {metadata.GetString(pField.nameIndex)}");
                                            if (pDefault != null && pDefault.dataIndex != -1)
                                            {
                                                var pointer = metadata.GetDefaultValueFromIndex(pDefault.dataIndex);
                                                if (pointer > 0)
                                                {
                                                    var pTypeToUse = il2cpp.types[pDefault.typeIndex];
                                                    metadata.Position = pointer;
                                                    object multi = null;
                                                    switch (pTypeToUse.type)
                                                    {
                                                    case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
                                                        multi = metadata.ReadBoolean();
                                                        break;

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

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

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

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

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

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

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

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

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

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

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

                                                    case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                                                        var uiLen = metadata.ReadInt32();
                                                        multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
                                                        break;
                                                    }
                                                    if (multi is string)
                                                    {
                                                        writer.Write($" = \"{multi}\"");
                                                    }
                                                    else if (multi != null)
                                                    {
                                                        writer.Write($" = {multi}");
                                                    }
                                                }
                                            }
                                            if (config.dumpfieldoffset)
                                            {
                                                writer.Write("; // 0x{0:X}\n", il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart, i));
                                            }
                                            else
                                            {
                                                writer.Write(";\n");
                                            }
                                        }
                                        writer.Write("\n");
                                    }
                                    //dump property
                                    if (config.dumpproperty && typeDef.property_count > 0)
                                    {
                                        writer.Write("\t// Properties\n");
                                        var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                                        for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                                        {
                                            var propertydef = metadata.propertyDefs[i];
                                            writer.Write(GetCustomAttribute(propertydef.customAttributeIndex, "\t"));
                                            writer.Write("\t");
                                            if (propertydef.get >= 0)
                                            {
                                                var methodDef = metadata.methodDefs[typeDef.methodStart + propertydef.get];
                                                writer.Write(GetModifiers(methodDef));
                                                var pReturnType = il2cpp.types[methodDef.returnType];
                                                writer.Write($"{GetTypeName(pReturnType)} {metadata.GetString(propertydef.nameIndex)} {{ ");
                                            }
                                            else if (propertydef.set > 0)
                                            {
                                                var methodDef = metadata.methodDefs[typeDef.methodStart + propertydef.set];
                                                writer.Write(GetModifiers(methodDef));
                                                var pParam = metadata.parameterDefs[methodDef.parameterStart];
                                                var pType  = il2cpp.types[pParam.typeIndex];
                                                writer.Write($"{GetTypeName(pType)} {metadata.GetString(propertydef.nameIndex)} {{ ");
                                            }
                                            if (propertydef.get >= 0)
                                            {
                                                writer.Write("get; ");
                                            }
                                            if (propertydef.set >= 0)
                                            {
                                                writer.Write("set; ");
                                            }
                                            writer.Write("}");
                                            writer.Write("\n");
                                        }
                                        writer.Write("\n");
                                    }
                                    //dump method
                                    if (config.dumpmethod && typeDef.method_count > 0)
                                    {
                                        writer.Write("\t// Methods\n");
                                        var methodEnd = typeDef.methodStart + typeDef.method_count;
                                        for (var i = typeDef.methodStart; i < methodEnd; ++i)
                                        {
                                            var methodDef = metadata.methodDefs[i];
                                            writer.Write(GetCustomAttribute(methodDef.customAttributeIndex, "\t"));
                                            writer.Write("\t");
                                            writer.Write(GetModifiers(methodDef));
                                            var pReturnType = il2cpp.types[methodDef.returnType];
                                            writer.Write($"{GetTypeName(pReturnType)} {metadata.GetString(methodDef.nameIndex)}(");
                                            for (var j = 0; j < methodDef.parameterCount; ++j)
                                            {
                                                var pParam      = metadata.parameterDefs[methodDef.parameterStart + j];
                                                var szParamName = metadata.GetString(pParam.nameIndex);
                                                var pType       = il2cpp.types[pParam.typeIndex];
                                                var szTypeName  = GetTypeName(pType);
                                                if ((pType.attrs & PARAM_ATTRIBUTE_OPTIONAL) != 0)
                                                {
                                                    writer.Write("optional ");
                                                }
                                                if ((pType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
                                                {
                                                    writer.Write("out ");
                                                }
                                                if (j != methodDef.parameterCount - 1)
                                                {
                                                    writer.Write($"{szTypeName} {szParamName}, ");
                                                }
                                                else
                                                {
                                                    writer.Write($"{szTypeName} {szParamName}");
                                                }
                                            }
                                            if (methodDef.methodIndex >= 0)
                                            {
                                                writer.Write("); // 0x{0:X}\n", il2cpp.methodPointers[methodDef.methodIndex]);
                                                //Script
                                                var name = ToUnicodeString(metadata.GetString(typeDef.nameIndex) + "$$" + metadata.GetString(methodDef.nameIndex));
                                                scriptwriter.WriteLine($"SetMethod(0x{il2cpp.methodPointers[methodDef.methodIndex]:x}, '{name}')");
                                                //
                                            }
                                            else
                                            {
                                                writer.Write("); // 0\n");
                                            }
                                        }
                                    }
                                    writer.Write("}\n");
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine("ERROR: Some errors in dumping");
                                    writer.Write("/*");
                                    writer.Write($"{e.Message}\n{e.StackTrace}\n");
                                    writer.Write("*/\n}\n");
                                }
                            }
                            //Script
                            if (il2cpp.version > 16)
                            {
                                foreach (var i in metadata.stringLiteralsdic)
                                {
                                    scriptwriter.WriteLine($"SetString(0x{il2cpp.metadataUsages[i.Key]:x}, '{ToUnicodeString(i.Value)}')");
                                }
                            }
                            //
                            writer.Close();
                            scriptwriter.Close();
                            Console.WriteLine("Done !");
                            break;
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"{e.Message}\r\n{e.StackTrace}");
                    }
                    Console.WriteLine("Press any key to exit...");
                    Console.ReadKey(true);
                }
            }
        }
Exemple #7
0
        private static void Dump()
        {
            var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create), new UTF8Encoding(false));

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            ofd.Filter = "ELF file or Mach-O file|*.*";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                var il2cppfile = File.ReadAllBytes(ofd.FileName);
                ofd.Filter = "global-metadata|global-metadata.dat";
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        var metadatafile = File.ReadAllBytes(ofd.FileName);
                        //判断Metadata的magic和version
                        var metadatamagic = BitConverter.ToUInt32(metadatafile, 0);
                        if (metadatamagic != 0xFAB11BAF)
                        {
                            throw new Exception("ERROR: Metadata file supplied is not valid metadata file.");
                        }
                        var metadataversion = BitConverter.ToUInt32(metadatafile, 4);
                        switch (metadataversion)
                        {
                        default:
                            throw new Exception($"ERROR: Metadata file supplied is not a supported version[{metadataversion}].");

                        case 23:
                            v23.Dump.Dumpv23(il2cppfile, metadatafile);
                            break;

                        case 21:
                        case 22:
                            //判断il2cpp的magic
                            var il2cppmagic = BitConverter.ToUInt32(il2cppfile, 0);
                            var isElf       = false;
                            switch (il2cppmagic)
                            {
                            default:
                                throw new Exception("ERROR: il2cpp file not supported.");

                            case 0x464c457f:
                                isElf = true;
                                goto case 0xFEEDFACE;

                            case 0xCAFEBABE:
                            case 0xBEBAFECA:
                                Console.Write("WARNING: fat macho will only dump the first object file.");
                                var fat = new MachoFat(new MemoryStream(il2cppfile));
                                il2cppfile = fat.GetFirstMacho();
                                var magic = fat.GetFirstMachoMagic();
                                if (magic == 0xFEEDFACF)        // 64-bit mach object file
                                {
                                    goto case 0xFEEDFACF;
                                }
                                else
                                {
                                    goto case 0xFEEDFACE;
                                }

                            case 0xFEEDFACF:        // 64-bit mach object file
                                _64bit.Dump.Dump64bit(il2cppfile, metadatafile);
                                break;

                            case 0xFEEDFACE:        // 32-bit mach object file
                                Console.WriteLine("Select Mode: 1. Manual 2.Auto");
                                var key = Console.ReadKey(true);
                                if (key.KeyChar == '2')
                                {
                                    metadata = new Metadata(new MemoryStream(metadatafile));
                                    if (isElf)
                                    {
                                        il2cpp = new Elf(new MemoryStream(il2cppfile));
                                    }
                                    else
                                    {
                                        il2cpp = new Macho(new MemoryStream(il2cppfile));
                                    }
                                    if (!il2cpp.Auto())
                                    {
                                        throw new Exception(
                                                  "ERROR: Unable to process file automatically, try to use manual mode.");
                                    }
                                }
                                else if (key.KeyChar == '1')
                                {
                                    Console.Write("Input CodeRegistration(R0): ");
                                    var codeRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
                                    Console.Write("Input MetadataRegistration(R1): ");
                                    var metadataRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
                                    metadata = new Metadata(new MemoryStream(metadatafile));
                                    if (isElf)
                                    {
                                        il2cpp = new Elf(new MemoryStream(il2cppfile), codeRegistration,
                                                         metadataRegistration);
                                    }
                                    else
                                    {
                                        il2cpp = new Macho(new MemoryStream(il2cppfile), codeRegistration,
                                                           metadataRegistration);
                                    }
                                }
                                else
                                {
                                    return;
                                }
                                var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create));
                                Console.WriteLine("Dumping...");
                                //dump_image();
                                for (var imageIndex = 0; imageIndex < metadata.uiImageCount; imageIndex++)
                                {
                                    var imageDef = metadata.imageDefs[imageIndex];
                                    writer.Write(
                                        $"// Image {imageIndex}: {metadata.GetString(imageDef.nameIndex)} - {imageDef.typeStart}\n");
                                }
                                for (var idx = 0; idx < metadata.uiNumTypes; ++idx)
                                {
                                    try
                                    {
                                        //dump_class(i);
                                        var typeDef = metadata.typeDefs[idx];
                                        writer.Write($"\n// Namespace: {metadata.GetString(typeDef.namespaceIndex)}\n");
                                        writer.Write(GetCustomAttribute(typeDef.customAttributeIndex));
                                        if ((typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
                                        {
                                            writer.Write("[Serializable]\n");
                                        }
                                        if ((typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_PUBLIC)
                                        {
                                            writer.Write("public ");
                                        }
                                        else if ((typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) ==
                                                 TYPE_ATTRIBUTE_NOT_PUBLIC)
                                        {
                                            writer.Write("internal ");
                                        }
                                        if ((typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0)
                                        {
                                            writer.Write("abstract ");
                                        }
                                        if ((typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
                                        {
                                            writer.Write("sealed ");
                                        }
                                        if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0)
                                        {
                                            writer.Write("interface ");
                                        }
                                        else
                                        {
                                            writer.Write("class ");
                                        }
                                        writer.Write($"{metadata.GetString(typeDef.nameIndex)}");
                                        if (typeDef.parentIndex >= 0)
                                        {
                                            var parent     = il2cpp.types[typeDef.parentIndex];
                                            var parentname = get_type_name(parent);
                                            if (parentname != "object")
                                            {
                                                writer.Write($" : {parentname}");
                                            }
                                        }
                                        writer.Write($" // TypeDefIndex: {idx}\n{{\n");
                                        if (typeDef.field_count > 0)
                                        {
                                            writer.Write("\t// Fields\n");
                                            var fieldEnd = typeDef.fieldStart + typeDef.field_count;
                                            for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
                                            {
                                                //dump_field(i, idx, i - typeDef.fieldStart);
                                                var pField   = metadata.fieldDefs[i];
                                                var pType    = il2cpp.types[pField.typeIndex];
                                                var pDefault = metadata.GetFieldDefaultFromIndex(i);
                                                writer.Write(GetCustomAttribute(pField.customAttributeIndex, "\t"));
                                                writer.Write("\t");
                                                if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) ==
                                                    FIELD_ATTRIBUTE_PRIVATE)
                                                {
                                                    writer.Write("private ");
                                                }
                                                else if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) ==
                                                         FIELD_ATTRIBUTE_PUBLIC)
                                                {
                                                    writer.Write("public ");
                                                }
                                                else if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) ==
                                                         FIELD_ATTRIBUTE_FAMILY)
                                                {
                                                    writer.Write("protected ");
                                                }
                                                if ((pType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                                                {
                                                    writer.Write("static ");
                                                }
                                                if ((pType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                                                {
                                                    writer.Write("readonly ");
                                                }
                                                writer.Write(
                                                    $"{get_type_name(pType)} {metadata.GetString(pField.nameIndex)}");
                                                if (pDefault != null && pDefault.dataIndex != -1)
                                                {
                                                    var pointer = metadata.GetDefaultValueFromIndex(pDefault.dataIndex);
                                                    if (pointer > 0)
                                                    {
                                                        var pTypeToUse = il2cpp.types[pDefault.typeIndex];
                                                        metadata.Position = pointer;
                                                        object multi = null;
                                                        switch (pTypeToUse.type)
                                                        {
                                                        case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
                                                            multi = metadata.ReadBoolean();
                                                            break;

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

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

                                                        case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
                                                            multi = metadata.ReadChar();
                                                            break;

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

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

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

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

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

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

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

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

                                                        case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                                                            var uiLen = metadata.ReadInt32();
                                                            multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
                                                            break;
                                                        }
                                                        if (multi is string)
                                                        {
                                                            writer.Write($" = \"{multi}\"");
                                                        }
                                                        else if (multi != null)
                                                        {
                                                            writer.Write($" = {multi}");
                                                        }
                                                    }
                                                }
                                                writer.Write("; // 0x{0:x}\n",
                                                             il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart));
                                            }
                                            writer.Write("\n");
                                        }
                                        if (typeDef.property_count > 0)
                                        {
                                            //dump_property(i);
                                            writer.Write("\t// Properties\n");
                                            var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                                            for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                                            {
                                                var propertydef = metadata.propertyDefs[i];
                                                writer.Write(GetCustomAttribute(propertydef.customAttributeIndex, "\t"));
                                                writer.Write("\t");
                                                if (propertydef.get >= 0)
                                                {
                                                    var methodDef =
                                                        metadata.methodDefs[typeDef.methodStart + propertydef.get];
                                                    var pReturnType = il2cpp.types[methodDef.returnType];
                                                    if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                                                        METHOD_ATTRIBUTE_PRIVATE)
                                                    {
                                                        writer.Write("private ");
                                                    }
                                                    else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                                                             METHOD_ATTRIBUTE_PUBLIC)
                                                    {
                                                        writer.Write("public ");
                                                    }
                                                    else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                                                             METHOD_ATTRIBUTE_FAMILY)
                                                    {
                                                        writer.Write("protected ");
                                                    }
                                                    if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
                                                    {
                                                        writer.Write("abstract ");
                                                    }
                                                    else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
                                                    {
                                                        writer.Write("virtual ");
                                                    }
                                                    if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
                                                    {
                                                        writer.Write("static ");
                                                    }
                                                    writer.Write(
                                                        $"{get_type_name(pReturnType)} {metadata.GetString(propertydef.nameIndex)} {{ ");
                                                }
                                                else if (propertydef.set > 0)
                                                {
                                                    var methodDef =
                                                        metadata.methodDefs[typeDef.methodStart + propertydef.set];
                                                    if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                                                        METHOD_ATTRIBUTE_PRIVATE)
                                                    {
                                                        writer.Write("private ");
                                                    }
                                                    else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                                                             METHOD_ATTRIBUTE_PUBLIC)
                                                    {
                                                        writer.Write("public ");
                                                    }
                                                    else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                                                             METHOD_ATTRIBUTE_FAMILY)
                                                    {
                                                        writer.Write("protected ");
                                                    }
                                                    if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
                                                    {
                                                        writer.Write("abstract ");
                                                    }
                                                    else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
                                                    {
                                                        writer.Write("virtual ");
                                                    }
                                                    if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
                                                    {
                                                        writer.Write("static ");
                                                    }
                                                    var pParam = metadata.parameterDefs[methodDef.parameterStart];
                                                    var pType  = il2cpp.types[pParam.typeIndex];
                                                    writer.Write(
                                                        $"{get_type_name(pType)} {metadata.GetString(propertydef.nameIndex)} {{ ");
                                                }
                                                if (propertydef.get >= 0)
                                                {
                                                    writer.Write("get; ");
                                                }
                                                if (propertydef.set >= 0)
                                                {
                                                    writer.Write("set; ");
                                                }
                                                writer.Write("}");
                                                writer.Write("\n");
                                            }
                                            writer.Write("\n");
                                        }
                                        if (typeDef.method_count > 0)
                                        {
                                            writer.Write("\t// Methods\n");
                                            var methodEnd = typeDef.methodStart + typeDef.method_count;
                                            for (var i = typeDef.methodStart; i < methodEnd; ++i)
                                            {
                                                //dump_method(i);
                                                var methodDef = metadata.methodDefs[i];
                                                writer.Write(GetCustomAttribute(methodDef.customAttributeIndex, "\t"));
                                                writer.Write("\t");
                                                var pReturnType = il2cpp.types[methodDef.returnType];
                                                if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                                                    METHOD_ATTRIBUTE_PRIVATE)
                                                {
                                                    writer.Write("private ");
                                                }
                                                else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                                                         METHOD_ATTRIBUTE_PUBLIC)
                                                {
                                                    writer.Write("public ");
                                                }
                                                else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                                                         METHOD_ATTRIBUTE_FAMILY)
                                                {
                                                    writer.Write("protected ");
                                                }
                                                if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
                                                {
                                                    writer.Write("abstract ");
                                                }
                                                else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
                                                {
                                                    writer.Write("virtual ");
                                                }
                                                if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
                                                {
                                                    writer.Write("static ");
                                                }
                                                writer.Write(
                                                    $"{get_type_name(pReturnType)} {metadata.GetString(methodDef.nameIndex)}(");
                                                for (var j = 0; j < methodDef.parameterCount; ++j)
                                                {
                                                    var pParam      = metadata.parameterDefs[methodDef.parameterStart + j];
                                                    var szParamName = metadata.GetString(pParam.nameIndex);
                                                    var pType       = il2cpp.types[pParam.typeIndex];
                                                    var szTypeName  = get_type_name(pType);
                                                    if ((pType.attrs & PARAM_ATTRIBUTE_OPTIONAL) != 0)
                                                    {
                                                        writer.Write("optional ");
                                                    }
                                                    if ((pType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
                                                    {
                                                        writer.Write("out ");
                                                    }
                                                    if (j != methodDef.parameterCount - 1)
                                                    {
                                                        writer.Write($"{szTypeName} {szParamName}, ");
                                                    }
                                                    else
                                                    {
                                                        writer.Write($"{szTypeName} {szParamName}");
                                                    }
                                                }
                                                if (methodDef.methodIndex >= 0)
                                                {
                                                    writer.Write("); // {0:x}\n",
                                                                 il2cpp.methodPointers[methodDef.methodIndex]);
                                                }
                                                else
                                                {
                                                    writer.Write("); // 0\n");
                                                }
                                            }
                                        }
                                        writer.Write("}\n");
                                    }
                                    catch (Exception e)
                                    {
                                        Console.WriteLine("ERROR: Some errors in dumping");
                                        writer.Write("/*");
                                        writer.Write($"{e.Message}\n{e.StackTrace}\n");
                                        writer.Write("*/\n}\n");
                                    }
                                }
                                writer.Close();
                                Console.WriteLine("Done !");
                                break;
                            }
                            break;
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"{e.Message}\r\n{e.StackTrace}");
                    }
                    Console.WriteLine("Press any key to exit...");
                    Console.ReadKey(true);
                }
            }
        }
Exemple #10
0
        private void DumpField(StreamWriter writer, Il2CppTypeDefinition typeDef, int idx)
        {
            writer.Write("\t// Fields\n");
            var fieldEnd = typeDef.fieldStart + typeDef.field_count;

            for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
            {
                var fieldDef     = metadata.fieldDefs[i];
                var fieldType    = il2cpp.types[fieldDef.typeIndex];
                var fieldDefault = metadata.GetFieldDefaultValueFromIndex(i);
                writer.Write(GetCustomAttribute(fieldDef.customAttributeIndex, "\t"));
                writer.Write("\t");
                var access = fieldType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
                switch (access)
                {
                case FIELD_ATTRIBUTE_PRIVATE:
                    writer.Write("private ");
                    break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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