private string AttributeDataToString(BlobValue blobValue)
        {
            //TODO enum
            if (blobValue.Value == null)
            {
                return("null");
            }
            switch (blobValue.il2CppTypeEnum)
            {
            case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
                return($"\"{blobValue.Value}\"");

            case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY:
                var array = (BlobValue[])blobValue.Value;
                var list  = new List <string>();
                foreach (var item in array)
                {
                    list.Add(AttributeDataToString(item));
                }
                return($"new[] {{ {string.Join(", ", list)} }}");

            case Il2CppTypeEnum.IL2CPP_TYPE_IL2CPP_TYPE_INDEX:
                var il2CppType = (Il2CppType)blobValue.Value;
                return($"typeof({executor.GetTypeName(il2CppType, false, false)})");

            default:
                return(blobValue.Value.ToString());
            }
        }
Exemplo n.º 2
0
 // requires TypeMetadata
 private void IndexGenerics()
 {
     // build type -> generic instance lookup
     foreach (var il2CppType in il2Cpp.types.Where(x => x.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST))
     {
         var genericClass = il2Cpp.MapVATR <Il2CppGenericClass>(il2CppType.data.generic_class);
         var baseTypeDef  = executor.GetGenericClassTypeDefinition(genericClass);
         if (baseTypeDef == null)
         {
             continue;
         }
         TypeDefinitionMetadata baseTypeMetadata = TypeMetadata[baseTypeDef];
         var typeBaseName      = TypeMetadata[baseTypeDef].UniqueName;
         var typeToReplaceName = executor.GetTypeDefName(baseTypeDef, true, true);
         var typeReplaceName   = executor.GetTypeName(il2CppType, true, false);
         var typeStructName    = typeBaseName.Replace(typeToReplaceName, typeReplaceName);
         genericClassList.Add(il2CppType.data.generic_class);
         lookupGenericType[typeStructName] = il2CppType;
         lookupGenericClassName[il2CppType.data.generic_class] = typeStructName;
     }
 }
Exemplo n.º 3
0
        public void WriteScript(Config config)
        {
            var json = new ScriptJson();

            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
                {
                    var typeDef = metadata.typeDefs[typeIndex];
                    CreateStructNameDic(typeDef);
                }
            }
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
                {
                    var typeDef = metadata.typeDefs[typeIndex];
                    AddStruct(typeDef);
                    var typeName = executor.GetTypeDefName(typeDef, true, true);
                    typeDefImageIndices.Add(typeDef, imageIndex);
                    var methodEnd = typeDef.methodStart + typeDef.method_count;
                    for (var i = typeDef.methodStart; i < methodEnd; ++i)
                    {
                        var methodDef     = metadata.methodDefs[i];
                        var methodName    = metadata.GetStringFromIndex(methodDef.nameIndex);
                        var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
                        if (methodPointer > 0)
                        {
                            var scriptMethod = new ScriptMethod();
                            json.ScriptMethod.Add(scriptMethod);
                            scriptMethod.Address = il2Cpp.GetRVA(methodPointer);
                            var methodFullName = typeName + "$$" + methodName;
                            scriptMethod.Name = methodFullName;

                            var methodReturnType = il2Cpp.types[methodDef.returnType];
                            var returnType       = ParseType(methodReturnType);
                            var signature        = $"{returnType} {FixName(methodFullName)} (";
                            var parameterStrs    = new List <string>();
                            if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) == 0)
                            {
                                var thisType = ParseType(il2Cpp.types[typeDef.byrefTypeIndex]);
                                parameterStrs.Add($"{thisType} this");
                            }
                            for (var j = 0; j < methodDef.parameterCount; j++)
                            {
                                var parameterDef  = metadata.parameterDefs[methodDef.parameterStart + j];
                                var parameterName = metadata.GetStringFromIndex(parameterDef.nameIndex);
                                var parameterType = il2Cpp.types[parameterDef.typeIndex];
                                parameterStrs.Add($"{ParseType(parameterType)} {FixName(parameterName)}");
                            }
                            signature += string.Join(", ", parameterStrs);
                            signature += ");";
                            scriptMethod.Signature = signature;
                        }
                    }
                }
            }
            if (il2Cpp.Version > 16)
            {
                foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo
                {
                    var type           = il2Cpp.types[i.Value];
                    var typeName       = executor.GetTypeName(type, true, false);
                    var scriptMetadata = new ScriptMetadata();
                    json.ScriptMetadata.Add(scriptMetadata);
                    scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadata.Name    = "Class$" + typeName;
                    var signature = GetIl2CppStructName(type);
                    if (signature.EndsWith("_array"))
                    {
                        scriptMetadata.Signature = signature + "*";
                    }
                    else
                    {
                        scriptMetadata.Signature = FixName(signature) + "_c*";
                    }
                }
                foreach (var i in metadata.metadataUsageDic[2]) //kIl2CppMetadataUsageIl2CppType
                {
                    var type           = il2Cpp.types[i.Value];
                    var typeName       = executor.GetTypeName(type, true, false);
                    var scriptMetadata = new ScriptMetadata();
                    json.ScriptMetadata.Add(scriptMetadata);
                    scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadata.Name    = "Object$" + typeName;
                    var signature = GetIl2CppStructName(type);
                    if (signature.EndsWith("_array"))
                    {
                        scriptMetadata.Signature = signature + "*";
                    }
                    else
                    {
                        scriptMetadata.Signature = FixName(signature) + "_o*";
                    }
                }
                foreach (var i in metadata.metadataUsageDic[3]) //kIl2CppMetadataUsageMethodDef
                {
                    var methodDef            = metadata.methodDefs[i.Value];
                    var typeDef              = metadata.typeDefs[methodDef.declaringType];
                    var typeName             = executor.GetTypeDefName(typeDef, true, true);
                    var methodName           = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex) + "()";
                    var scriptMetadataMethod = new ScriptMetadataMethod();
                    json.ScriptMetadataMethod.Add(scriptMetadataMethod);
                    scriptMetadataMethod.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadataMethod.Name    = "Method$" + methodName;
                    var imageIndex    = typeDefImageIndices[typeDef];
                    var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, (int)i.Value, imageIndex, methodDef.token);
                    if (methodPointer > 0)
                    {
                        scriptMetadataMethod.MethodAddress = il2Cpp.GetRVA(methodPointer);
                    }
                }
                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      = executor.GetTypeName(type, true, false) + "." + metadata.GetStringFromIndex(fieldDef.nameIndex);
                    var scriptMetadata = new ScriptMetadata();
                    json.ScriptMetadata.Add(scriptMetadata);
                    scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadata.Name    = "Field$" + fieldName;
                }
                foreach (var i in metadata.metadataUsageDic[5]) //kIl2CppMetadataUsageStringLiteral
                {
                    var scriptString = new ScriptString();
                    json.ScriptString.Add(scriptString);
                    scriptString.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptString.Value   = metadata.GetStringLiteralFromIndex(i.Value);
                }
                var stringLiterals = json.ScriptString.Select(x => new
                {
                    value   = x.Value,
                    address = $"0x{x.Address:X}"
                }).ToArray();
                File.WriteAllText("stringliteral.json", JsonConvert.SerializeObject(stringLiterals, Formatting.Indented), new UTF8Encoding(false));
                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   = executor.GetTypeDefName(typeDef, true, false);
                    if (methodSpec.classIndexIndex != -1)
                    {
                        var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex];
                        typeName += executor.GetGenericInstParams(classInst);
                    }
                    var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex);
                    if (methodSpec.methodIndexIndex != -1)
                    {
                        var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex];
                        methodName += executor.GetGenericInstParams(methodInst);
                    }
                    methodName += "()";
                    var scriptMetadataMethod = new ScriptMetadataMethod();
                    json.ScriptMetadataMethod.Add(scriptMetadataMethod);
                    scriptMetadataMethod.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadataMethod.Name    = "Method$" + methodName;
                    var imageIndex    = typeDefImageIndices[typeDef];
                    var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, methodSpec.methodDefinitionIndex, imageIndex, methodDef.token);
                    if (methodPointer > 0)
                    {
                        scriptMetadataMethod.MethodAddress = il2Cpp.GetRVA(methodPointer);
                    }
                }
            }
            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);
                for (int i = 0; i < orderedPointers.Count; i++)
                {
                    orderedPointers[i] = il2Cpp.GetRVA(orderedPointers[i]);
                }
                json.Addresses = orderedPointers;
            }
            File.WriteAllText("script.json", JsonConvert.SerializeObject(json, Formatting.Indented));
            //il2cpp.h
            for (int i = 0; i < genericClassList.Count; i++)
            {
                var pointer = genericClassList[i];
                AddGenericClassStruct(pointer);
            }
            var preHeader    = new StringBuilder();
            var headerStruct = new StringBuilder();
            var headerClass  = new StringBuilder();

            foreach (var info in structInfoList)
            {
                structInfoWithStructName.Add(info.TypeName + "_o", info);
            }
            foreach (var info in structInfoList)
            {
                preHeader.Append($"struct {info.TypeName}_o;\n");

                if (info.IsValueType)
                {
                    headerStruct.Append(RecursionStructInfo(info));
                }
                else
                {
                    headerClass.Append($"struct {info.TypeName}_StaticFields {{\n");
                    foreach (var field in info.StaticFields)
                    {
                        headerClass.Append($"\t{field.FieldTypeName} {field.FieldName};\n");
                    }
                    headerClass.Append("};\n");

                    headerClass.Append($"struct {info.TypeName}_VTable {{\n");
                    foreach (var method in info.VTableMethod)
                    {
                        headerClass.Append($"\tVirtualInvokeData {method.MethodName};\n");
                    }
                    headerClass.Append("};\n");

                    headerClass.Append($"struct {info.TypeName}_c {{\n" +
                                       $"\tIl2CppClass_1 _1;\n" +
                                       $"\t{info.TypeName}_StaticFields* static_fields;\n" +
                                       $"\tIl2CppClass_2 _2;\n" +
                                       $"\t{info.TypeName}_VTable vtable;\n" +
                                       $"}};\n");
                    headerClass.Append($"struct {info.TypeName}_o {{\n" +
                                       $"\t{info.TypeName}_c *klass;\n" +
                                       $"\tvoid *monitor;\n");

                    foreach (var field in info.Fields)
                    {
                        headerClass.Append($"\t{field.FieldTypeName} {field.FieldName};\n");
                    }
                    headerClass.Append("};\n");
                }
            }
            var sb = new StringBuilder();

            if (il2Cpp is PE)
            {
                sb.Append(HeaderConstants.TypedefHeader);
            }
            sb.Append(HeaderConstants.GenericHeader);
            switch (il2Cpp.Version)
            {
            case 22f:
                sb.Append(HeaderConstants.HeaderV22);
                break;

            case 23f:
                sb.Append(HeaderConstants.HeaderV240);
                break;

            case 24f:
                sb.Append(HeaderConstants.HeaderV240);
                break;

            case 24.1f:
                sb.Append(HeaderConstants.HeaderV241);
                break;

            case 24.2f:
                sb.Append(HeaderConstants.HeaderV242);
                break;

            //TODO
            default:
                Console.WriteLine($"WARNING: This il2cpp version [{il2Cpp.Version}] does not support generating .h files");
                return;
            }
            sb.Append(preHeader);
            sb.Append(arrayClassPreHeader);
            sb.Append(headerStruct);
            sb.Append(headerClass);
            sb.Append(arrayClassHeader);
            File.WriteAllText("il2cpp.h", sb.ToString());
        }
Exemplo n.º 4
0
        public void Decompile(Config config)
        {
            var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create), new UTF8Encoding(false));

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

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

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

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

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

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

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

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

                                case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
                                    writer.Write("protected internal ");
                                    break;
                                }
                                if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
                                {
                                    writer.Write("const ");
                                }
                                else
                                {
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                                    {
                                        isStatic = true;
                                        writer.Write("static ");
                                    }
                                    if ((fieldType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                                    {
                                        writer.Write("readonly ");
                                    }
                                }
                                writer.Write($"{executor.GetTypeName(fieldType, false, false)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}");
                                if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefaultValue) && fieldDefaultValue.dataIndex != -1)
                                {
                                    if (TryGetDefaultValue(fieldDefaultValue.typeIndex, fieldDefaultValue.dataIndex, out var value))
                                    {
                                        writer.Write($" = ");
                                        if (value is string str)
                                        {
                                            writer.Write($"\"{str.ToEscapedString()}\"");
                                        }
                                        else if (value is char c)
                                        {
                                            var v = (int)c;
                                            writer.Write($"'\\x{v:x}'");
                                        }
                                        else if (value != null)
                                        {
                                            writer.Write($"{value}");
                                        }
                                    }
                                    else
                                    {
                                        writer.Write($" /*Metadata offset 0x{value:X}*/");
                                    }
                                }
                                if (config.DumpFieldOffset)
                                {
                                    writer.Write("; // 0x{0:X}\n", il2Cpp.GetFieldOffsetFromIndex(typeDefIndex, i - typeDef.fieldStart, i, typeDef.IsValueType, isStatic));
                                }
                                else
                                {
                                    writer.Write(";\n");
                                }
                            }
                        }
                        //dump property
                        if (config.DumpProperty && typeDef.property_count > 0)
                        {
                            writer.Write("\n\t// Properties\n");
                            var propertyEnd = typeDef.propertyStart + typeDef.property_count;
                            for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
                            {
                                var propertyDef = metadata.propertyDefs[i];
                                if (config.DumpAttribute)
                                {
                                    writer.Write(GetCustomAttribute(imageDef, propertyDef.customAttributeIndex, propertyDef.token, "\t"));
                                }
                                writer.Write("\t");
                                if (propertyDef.get >= 0)
                                {
                                    var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.get];
                                    writer.Write(GetModifiers(methodDef));
                                    var propertyType = il2Cpp.types[methodDef.returnType];
                                    writer.Write($"{executor.GetTypeName(propertyType, false, false)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                }
                                else if (propertyDef.set > 0)
                                {
                                    var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.set];
                                    writer.Write(GetModifiers(methodDef));
                                    var parameterDef = metadata.parameterDefs[methodDef.parameterStart];
                                    var propertyType = il2Cpp.types[parameterDef.typeIndex];
                                    writer.Write($"{executor.GetTypeName(propertyType, false, false)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ ");
                                }
                                if (propertyDef.get >= 0)
                                {
                                    writer.Write("get; ");
                                }
                                if (propertyDef.set >= 0)
                                {
                                    writer.Write("set; ");
                                }
                                writer.Write("}");
                                writer.Write("\n");
                            }
                        }
                        //dump method
                        if (config.DumpMethod && typeDef.method_count > 0)
                        {
                            writer.Write("\n\t// Methods\n");
                            var methodEnd = typeDef.methodStart + typeDef.method_count;
                            for (var i = typeDef.methodStart; i < methodEnd; ++i)
                            {
                                var methodDef = metadata.methodDefs[i];
                                if (config.DumpAttribute)
                                {
                                    writer.Write(GetCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, "\t"));
                                }
                                if (config.DumpMethodOffset)
                                {
                                    var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
                                    if (methodPointer > 0)
                                    {
                                        var fixedMethodPointer = il2Cpp.GetRVA(methodPointer);
                                        writer.Write("\t// RVA: 0x{0:X} Offset: 0x{1:X} VA: 0x{2:X}", fixedMethodPointer, il2Cpp.MapVATR(methodPointer), methodPointer);
                                    }
                                    else
                                    {
                                        writer.Write("\t// RVA: -1 Offset: -1");
                                    }
                                    if (methodDef.slot != ushort.MaxValue)
                                    {
                                        writer.Write(" Slot: {0}", methodDef.slot);
                                    }
                                    writer.Write("\n");
                                }
                                writer.Write("\t");
                                writer.Write(GetModifiers(methodDef));
                                var methodReturnType = il2Cpp.types[methodDef.returnType];
                                var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                                if (methodReturnType.byref == 1)
                                {
                                    writer.Write("ref ");
                                }
                                writer.Write($"{executor.GetTypeName(methodReturnType, false, false)} {methodName}(");
                                var parameterStrs = new List <string>();
                                for (var j = 0; j < methodDef.parameterCount; ++j)
                                {
                                    var parameterStr      = "";
                                    var parameterDef      = metadata.parameterDefs[methodDef.parameterStart + j];
                                    var parameterName     = metadata.GetStringFromIndex(parameterDef.nameIndex);
                                    var parameterType     = il2Cpp.types[parameterDef.typeIndex];
                                    var parameterTypeName = executor.GetTypeName(parameterType, false, false);
                                    if (parameterType.byref == 1)
                                    {
                                        if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0 && (parameterType.attrs & PARAM_ATTRIBUTE_IN) == 0)
                                        {
                                            parameterStr += "out ";
                                        }
                                        else if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) == 0 && (parameterType.attrs & PARAM_ATTRIBUTE_IN) != 0)
                                        {
                                            parameterStr += "in ";
                                        }
                                        else
                                        {
                                            parameterStr += "ref ";
                                        }
                                    }
                                    else
                                    {
                                        if ((parameterType.attrs & PARAM_ATTRIBUTE_IN) != 0)
                                        {
                                            parameterStr += "[In] ";
                                        }
                                        if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
                                        {
                                            parameterStr += "[Out] ";
                                        }
                                    }
                                    parameterStr += $"{parameterTypeName} {parameterName}";
                                    if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1)
                                    {
                                        if (TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value))
                                        {
                                            parameterStr += " = ";
                                            if (value is string str)
                                            {
                                                parameterStr += $"\"{str.ToEscapedString()}\"";
                                            }
                                            else if (value is char c)
                                            {
                                                var v = (int)c;
                                                parameterStr += $"'\\x{v:x}'";
                                            }
                                            else if (value != null)
                                            {
                                                parameterStr += $"{value}";
                                            }
                                        }
                                        else
                                        {
                                            parameterStr += $" /*Metadata offset 0x{value:X}*/";
                                        }
                                    }
                                    parameterStrs.Add(parameterStr);
                                }
                                writer.Write(string.Join(", ", parameterStrs));
                                writer.Write(") { }\n");
                            }
                        }
                        writer.Write("}\n");
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("ERROR: Some errors in dumping");
                    writer.Write("/*");
                    writer.Write(e);
                    writer.Write("*/\n}\n");
                }
            }
            writer.Close();
        }
Exemplo n.º 5
0
        public void WriteScript(string outputDir)
        {
            var json = new ScriptJson();

            // 生成唯一名称
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
                {
                    var typeDef = metadata.typeDefs[typeIndex];
                    typeDefImageIndices.Add(typeDef, imageIndex);
                    CreateStructNameDic(typeDef);
                }
            }
            // 生成后面处理泛型实例要用到的字典
            foreach (var il2CppType in il2Cpp.types.Where(x => x.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST))
            {
                var genericClass = il2Cpp.MapVATR <Il2CppGenericClass>(il2CppType.data.generic_class);
                if (genericClass.typeDefinitionIndex == 4294967295 || genericClass.typeDefinitionIndex == -1)
                {
                    continue;
                }
                var typeDef           = metadata.typeDefs[genericClass.typeDefinitionIndex];
                var typeBaseName      = structNameDic[typeDef];
                var typeToReplaceName = FixName(executor.GetTypeDefName(typeDef, true, true));
                var typeReplaceName   = FixName(executor.GetTypeName(il2CppType, true, false));
                var typeStructName    = typeBaseName.Replace(typeToReplaceName, typeReplaceName);
                nameGenericClassDic[typeStructName] = il2CppType;
                genericClassStructNameDic[il2CppType.data.generic_class] = typeStructName;
            }
            // 处理函数
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
                {
                    var typeDef = metadata.typeDefs[typeIndex];
                    AddStruct(typeDef);
                    var methodInfoName = $"MethodInfo_{typeIndex}";
                    var structTypeName = structNameDic[typeDef];
                    GenerateMethodInfo(structTypeName, methodInfoName);
                    var typeName  = executor.GetTypeDefName(typeDef, true, true);
                    var methodEnd = typeDef.methodStart + typeDef.method_count;
                    for (var i = typeDef.methodStart; i < methodEnd; ++i)
                    {
                        var methodDef     = metadata.methodDefs[i];
                        var methodName    = metadata.GetStringFromIndex(methodDef.nameIndex);
                        var methodPointer = il2Cpp.GetMethodPointer(methodDef, imageIndex);
                        if (methodPointer > 0)
                        {
                            var scriptMethod = new ScriptMethod();
                            json.ScriptMethod.Add(scriptMethod);
                            scriptMethod.Address = il2Cpp.GetRVA(methodPointer);
                            var methodFullName = typeName + "$$" + methodName;
                            scriptMethod.Name = methodFullName;

                            var methodReturnType = il2Cpp.types[methodDef.returnType];
                            var returnType       = ParseType(methodReturnType);
                            if (methodReturnType.byref == 1)
                            {
                                returnType += "*";
                            }
                            var signature     = $"{returnType} {FixName(methodFullName)} (";
                            var parameterStrs = new List <string>();
                            if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) == 0)
                            {
                                var thisType = ParseType(il2Cpp.types[typeDef.byrefTypeIndex]);
                                parameterStrs.Add($"{thisType} __this");
                            }
                            else if (il2Cpp.Version <= 24f)
                            {
                                parameterStrs.Add($"Il2CppObject* __this");
                            }
                            for (var j = 0; j < methodDef.parameterCount; j++)
                            {
                                var parameterDef   = metadata.parameterDefs[methodDef.parameterStart + j];
                                var parameterName  = metadata.GetStringFromIndex(parameterDef.nameIndex);
                                var parameterType  = il2Cpp.types[parameterDef.typeIndex];
                                var parameterCType = ParseType(parameterType);
                                if (parameterType.byref == 1)
                                {
                                    parameterCType += "*";
                                }
                                parameterStrs.Add($"{parameterCType} {FixName(parameterName)}");
                            }
                            parameterStrs.Add("const MethodInfo* method");
                            signature += string.Join(", ", parameterStrs);
                            signature += ");";
                            scriptMethod.Signature = signature;
                        }
                        //泛型实例函数
                        if (il2Cpp.methodDefinitionMethodSpecs.TryGetValue(i, out var methodSpecs))
                        {
                            foreach (var methodSpec in methodSpecs)
                            {
                                var genericMethodPointer = il2Cpp.methodSpecGenericMethodPointers[methodSpec];
                                if (genericMethodPointer > 0)
                                {
                                    var scriptMethod = new ScriptMethod();
                                    json.ScriptMethod.Add(scriptMethod);
                                    scriptMethod.Address = il2Cpp.GetRVA(genericMethodPointer);
                                    (var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec, true);
                                    var methodFullName = methodSpecTypeName + "$$" + methodSpecMethodName;
                                    scriptMethod.Name = methodFullName;

                                    var genericContext   = executor.GetMethodSpecGenericContext(methodSpec);
                                    var methodReturnType = il2Cpp.types[methodDef.returnType];
                                    var returnType       = ParseType(methodReturnType, genericContext);
                                    if (methodReturnType.byref == 1)
                                    {
                                        returnType += "*";
                                    }
                                    var signature     = $"{returnType} {FixName(methodFullName)} (";
                                    var parameterStrs = new List <string>();
                                    if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) == 0)
                                    {
                                        string thisType;
                                        if (methodSpec.classIndexIndex != -1)
                                        {
                                            var typeBaseName      = structNameDic[typeDef];
                                            var typeToReplaceName = FixName(typeName);
                                            var typeReplaceName   = FixName(methodSpecTypeName);
                                            var typeStructName    = typeBaseName.Replace(typeToReplaceName, typeReplaceName);
                                            if (nameGenericClassDic.TryGetValue(typeStructName, out var il2CppType))
                                            {
                                                thisType = ParseType(il2CppType);
                                            }
                                            else
                                            {
                                                //没有单独的泛型实例类
                                                thisType = ParseType(il2Cpp.types[typeDef.byrefTypeIndex]);
                                            }
                                        }
                                        else
                                        {
                                            thisType = ParseType(il2Cpp.types[typeDef.byrefTypeIndex]);
                                        }
                                        parameterStrs.Add($"{thisType} __this");
                                    }
                                    else if (il2Cpp.Version <= 24f)
                                    {
                                        parameterStrs.Add($"Il2CppObject* __this");
                                    }
                                    for (var j = 0; j < methodDef.parameterCount; j++)
                                    {
                                        var parameterDef   = metadata.parameterDefs[methodDef.parameterStart + j];
                                        var parameterName  = metadata.GetStringFromIndex(parameterDef.nameIndex);
                                        var parameterType  = il2Cpp.types[parameterDef.typeIndex];
                                        var parameterCType = ParseType(parameterType, genericContext);
                                        if (parameterType.byref == 1)
                                        {
                                            parameterCType += "*";
                                        }
                                        parameterStrs.Add($"{parameterCType} {FixName(parameterName)}");
                                    }
                                    parameterStrs.Add($"const {methodInfoName}* method");
                                    signature += string.Join(", ", parameterStrs);
                                    signature += ");";
                                    scriptMethod.Signature = signature;
                                }
                            }
                        }
                    }
                }
            }
            // 处理MetadataUsage
            if (il2Cpp.Version > 16)
            {
                foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo
                {
                    var type           = il2Cpp.types[i.Value];
                    var typeName       = executor.GetTypeName(type, true, false);
                    var scriptMetadata = new ScriptMetadata();
                    json.ScriptMetadata.Add(scriptMetadata);
                    scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadata.Name    = "Class$" + typeName;
                    var signature = GetIl2CppStructName(type);
                    if (signature.EndsWith("_array"))
                    {
                        scriptMetadata.Signature = signature + "*";
                    }
                    else
                    {
                        scriptMetadata.Signature = FixName(signature) + "_c*";
                    }
                }
                foreach (var i in metadata.metadataUsageDic[2]) //kIl2CppMetadataUsageIl2CppType
                {
                    var type           = il2Cpp.types[i.Value];
                    var typeName       = executor.GetTypeName(type, true, false);
                    var scriptMetadata = new ScriptMetadata();
                    json.ScriptMetadata.Add(scriptMetadata);
                    scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadata.Name    = "Object$" + typeName;
                    var signature = GetIl2CppStructName(type);
                    if (signature.EndsWith("_array"))
                    {
                        scriptMetadata.Signature = signature + "*";
                    }
                    else
                    {
                        scriptMetadata.Signature = FixName(signature) + "_o*";
                    }
                }
                foreach (var i in metadata.metadataUsageDic[3]) //kIl2CppMetadataUsageMethodDef
                {
                    var methodDef            = metadata.methodDefs[i.Value];
                    var typeDef              = metadata.typeDefs[methodDef.declaringType];
                    var typeName             = executor.GetTypeDefName(typeDef, true, true);
                    var methodName           = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex) + "()";
                    var scriptMetadataMethod = new ScriptMetadataMethod();
                    json.ScriptMetadataMethod.Add(scriptMetadataMethod);
                    scriptMetadataMethod.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadataMethod.Name    = "Method$" + methodName;
                    var imageIndex    = typeDefImageIndices[typeDef];
                    var methodPointer = il2Cpp.GetMethodPointer(methodDef, imageIndex);
                    if (methodPointer > 0)
                    {
                        scriptMetadataMethod.MethodAddress = il2Cpp.GetRVA(methodPointer);
                    }
                }
                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      = executor.GetTypeName(type, true, false) + "." + metadata.GetStringFromIndex(fieldDef.nameIndex);
                    var scriptMetadata = new ScriptMetadata();
                    json.ScriptMetadata.Add(scriptMetadata);
                    scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadata.Name    = "Field$" + fieldName;
                }
                foreach (var i in metadata.metadataUsageDic[5]) //kIl2CppMetadataUsageStringLiteral
                {
                    var scriptString = new ScriptString();
                    json.ScriptString.Add(scriptString);
                    scriptString.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptString.Value   = metadata.GetStringLiteralFromIndex(i.Value);
                }
                var stringLiterals = json.ScriptString.Select(x => new
                {
                    value   = x.Value,
                    address = $"0x{x.Address:X}"
                }).ToArray();
                File.WriteAllText(outputDir + "stringliteral.json", JsonConvert.SerializeObject(stringLiterals, Formatting.Indented), new UTF8Encoding(false));
                foreach (var i in metadata.metadataUsageDic[6]) //kIl2CppMetadataUsageMethodRef
                {
                    var methodSpec           = il2Cpp.methodSpecs[i.Value];
                    var scriptMetadataMethod = new ScriptMetadataMethod();
                    json.ScriptMetadataMethod.Add(scriptMetadataMethod);
                    scriptMetadataMethod.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    (var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec, true);
                    scriptMetadataMethod.Name = "Method$" + methodSpecTypeName + "." + methodSpecMethodName + "()";
                    var genericMethodPointer = il2Cpp.methodSpecGenericMethodPointers[methodSpec];
                    if (genericMethodPointer > 0)
                    {
                        scriptMetadataMethod.MethodAddress = il2Cpp.GetRVA(genericMethodPointer);
                    }
                }
            }
            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)
            {
                if (il2Cpp.reversePInvokeWrappers != null)
                {
                    orderedPointers.AddRange(il2Cpp.reversePInvokeWrappers);
                }
                if (il2Cpp.unresolvedVirtualCallPointers != null)
                {
                    orderedPointers.AddRange(il2Cpp.unresolvedVirtualCallPointers);
                }
            }
            //TODO interopData内也包含函数
            orderedPointers = orderedPointers.Distinct().OrderBy(x => x).ToList();
            orderedPointers.Remove(0);
            for (int i = 0; i < orderedPointers.Count; i++)
            {
                orderedPointers[i] = il2Cpp.GetRVA(orderedPointers[i]);
            }
            json.Addresses = orderedPointers;
            File.WriteAllText(outputDir + "script.json", JsonConvert.SerializeObject(json, Formatting.Indented));
            //il2cpp.h
            for (int i = 0; i < genericClassList.Count; i++)
            {
                var pointer = genericClassList[i];
                AddGenericClassStruct(pointer);
            }
            var preHeader    = new StringBuilder();
            var headerStruct = new StringBuilder();
            var headerClass  = new StringBuilder();

            foreach (var info in structInfoList)
            {
                structInfoWithStructName.Add(info.TypeName + "_o", info);
            }
            foreach (var info in structInfoList)
            {
                preHeader.Append($"struct {info.TypeName}_o;\n");
                headerStruct.Append(RecursionStructInfo(info));
            }
            var sb = new StringBuilder();

            sb.Append(HeaderConstants.GenericHeader);
            switch (il2Cpp.Version)
            {
            case 22f:
                sb.Append(HeaderConstants.HeaderV22);
                break;

            case 23f:
            case 24f:
                sb.Append(HeaderConstants.HeaderV240);
                break;

            case 24.1f:
                sb.Append(HeaderConstants.HeaderV241);
                break;

            case 24.2f:
            case 24.3f:
                sb.Append(HeaderConstants.HeaderV242);
                break;

            //TODO
            default:
                Console.WriteLine($"WARNING: This il2cpp version [{il2Cpp.Version}] does not support generating .h files");
                return;
            }
            sb.Append(preHeader);
            sb.Append(arrayClassPreHeader);
            sb.Append(headerStruct);
            sb.Append(headerClass);
            sb.Append(arrayClassHeader);
            sb.Append(methodInfoHeader);
            File.WriteAllText(outputDir + "il2cpp.h", sb.ToString());
        }
Exemplo n.º 6
0
        public void WriteScript(Config config)
        {
            var writer = new StreamWriter(new FileStream("ida.py", FileMode.Create), new UTF8Encoding(false));

            writer.WriteLine("# -*- coding: utf-8 -*-");
            writer.WriteLine("import idaapi");
            writer.WriteLine();
            writer.WriteLine("def SetString(addr, comm):");
            writer.WriteLine("\tglobal index");
            writer.WriteLine("\tname = \"StringLiteral_\" + str(index)");
            writer.WriteLine("\tret = idc.set_name(addr, name, SN_NOWARN)");
            writer.WriteLine("\tidc.set_cmt(addr, comm, 1)");
            writer.WriteLine("\tindex += 1");
            writer.WriteLine();
            writer.WriteLine("def SetName(addr, name):");
            writer.WriteLine("\tret = idc.set_name(addr, name, SN_NOWARN | SN_NOCHECK)");
            writer.WriteLine("\tif ret == 0:");
            writer.WriteLine("\t\tnew_name = name + '_' + str(addr)");
            writer.WriteLine("\t\tret = idc.set_name(addr, new_name, SN_NOWARN | SN_NOCHECK)");
            writer.WriteLine();
            writer.WriteLine("def MakeFunction(start, end):");
            writer.WriteLine("\tnext_func = idc.get_next_func(start)");
            writer.WriteLine("\tif next_func < end:");
            writer.WriteLine("\t\tend = next_func");
            writer.WriteLine("\tif idc.get_func_attr(start, FUNCATTR_START) == start:");
            writer.WriteLine("\t\tida_funcs.del_func(start)");
            writer.WriteLine("\tida_funcs.add_func(start, end)");
            writer.WriteLine();
            writer.WriteLine("index = 1");
            writer.WriteLine("print('Making method name...')");
            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
                {
                    var typeDef  = metadata.typeDefs[typeIndex];
                    var typeName = executor.GetTypeDefName(typeDef, false, true);
                    typeDefImageIndices.Add(typeDef, imageIndex);
                    var methodEnd = typeDef.methodStart + typeDef.method_count;
                    for (var i = typeDef.methodStart; i < methodEnd; ++i)
                    {
                        var methodDef     = metadata.methodDefs[i];
                        var methodName    = metadata.GetStringFromIndex(methodDef.nameIndex);
                        var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
                        if (methodPointer > 0)
                        {
                            var fixedMethodPointer = il2Cpp.FixPointer(methodPointer);
                            if (il2Cpp is PE)
                            {
                                writer.WriteLine($"SetName(0x{methodPointer:X}, '{typeName + "$$" + methodName}')");
                            }
                            else
                            {
                                writer.WriteLine($"SetName(0x{fixedMethodPointer:X}, '{typeName + "$$" + methodName}')");
                            }
                        }
                    }
                }
            }
            writer.WriteLine("print('Make method name done')");
            if (il2Cpp.Version > 16)
            {
                writer.WriteLine("print('Setting MetadataUsage...')");
                foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo
                {
                    var type     = il2Cpp.types[i.Value];
                    var typeName = executor.GetTypeName(type, true, true);
                    writer.WriteLine($"SetName(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Class$" + typeName}')");
                    writer.WriteLine($"idc.set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, r'{typeName}', 1)");
                }
                foreach (var i in metadata.metadataUsageDic[2]) //kIl2CppMetadataUsageIl2CppType
                {
                    var type     = il2Cpp.types[i.Value];
                    var typeName = executor.GetTypeName(type, true, true);
                    writer.WriteLine($"SetName(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Class$" + typeName}')");
                    writer.WriteLine($"idc.set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, r'{typeName}', 1)");
                }
                foreach (var i in metadata.metadataUsageDic[3]) //kIl2CppMetadataUsageMethodDef
                {
                    var methodDef  = metadata.methodDefs[i.Value];
                    var typeDef    = metadata.typeDefs[methodDef.declaringType];
                    var typeName   = executor.GetTypeDefName(typeDef, true, true);
                    var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex) + "()";
                    writer.WriteLine($"SetName(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Method$" + methodName}')");
                    writer.WriteLine($"idc.set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Method$" + methodName}', 1)");
                    var imageIndex    = typeDefImageIndices[typeDef];
                    var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, (int)i.Value, imageIndex, methodDef.token);
                    writer.WriteLine($"idc.set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, '0x{methodPointer:X}', 0)");
                }
                foreach (var i in metadata.metadataUsageDic[4]) //kIl2CppMetadataUsageFieldInfo
                {
                    var fieldRef  = metadata.fieldRefs[i.Value];
                    var type      = il2Cpp.types[fieldRef.typeIndex];
                    var typeDef   = metadata.typeDefs[type.data.klassIndex];
                    var fieldDef  = metadata.fieldDefs[typeDef.fieldStart + fieldRef.fieldIndex];
                    var fieldName = executor.GetTypeName(type, true, true) + "." + metadata.GetStringFromIndex(fieldDef.nameIndex);
                    writer.WriteLine($"SetName(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Field$" + fieldName}')");
                    writer.WriteLine($"idc.set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, r'{fieldName}', 1)");
                }
                var stringLiterals = metadata.metadataUsageDic[5].Select(x => new //kIl2CppMetadataUsageStringLiteral
                {
                    value   = metadata.GetStringLiteralFromIndex(x.Value),
                    address = $"0x{il2Cpp.metadataUsages[x.Key]:X}"
                }).ToArray();
                File.WriteAllText("stringliteral.json", JsonConvert.SerializeObject(stringLiterals, Formatting.Indented), new UTF8Encoding(false)); //TODO
                foreach (var stringLiteral in stringLiterals)
                {
                    writer.WriteLine($"SetString({stringLiteral.address}, r'{stringLiteral.value.ToEscapedString()}')");
                }
                foreach (var i in metadata.metadataUsageDic[6]) //kIl2CppMetadataUsageMethodRef
                {
                    var methodSpec = il2Cpp.methodSpecs[i.Value];
                    var methodDef  = metadata.methodDefs[methodSpec.methodDefinitionIndex];
                    var typeDef    = metadata.typeDefs[methodDef.declaringType];
                    var typeName   = executor.GetTypeDefName(typeDef, true, false);
                    if (methodSpec.classIndexIndex != -1)
                    {
                        var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex];
                        typeName += executor.GetGenericInstParams(classInst);
                    }
                    var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex);
                    if (methodSpec.methodIndexIndex != -1)
                    {
                        var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex];
                        methodName += executor.GetGenericInstParams(methodInst);
                    }
                    methodName += "()";
                    writer.WriteLine($"SetName(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Method$" + methodName}')");
                    writer.WriteLine($"idc.set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, '{"Method$" + methodName}', 1)");
                    var imageIndex    = typeDefImageIndices[typeDef];
                    var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, methodSpec.methodDefinitionIndex, imageIndex, methodDef.token);
                    writer.WriteLine($"idc.set_cmt(0x{il2Cpp.metadataUsages[i.Key]:X}, '0x{methodPointer:X}', 0)");
                }
                writer.WriteLine("print('Set MetadataUsage done')");
            }
            if (config.MakeFunction)
            {
                List <ulong> orderedPointers;
                if (il2Cpp.Version >= 24.2f)
                {
                    orderedPointers = new List <ulong>();
                    foreach (var methodPointers in il2Cpp.codeGenModuleMethodPointers)
                    {
                        orderedPointers.AddRange(methodPointers);
                    }
                }
                else
                {
                    orderedPointers = il2Cpp.methodPointers.ToList();
                }
                orderedPointers.AddRange(il2Cpp.genericMethodPointers);
                orderedPointers.AddRange(il2Cpp.invokerPointers);
                orderedPointers.AddRange(il2Cpp.customAttributeGenerators);
                if (il2Cpp.Version >= 22)
                {
                    orderedPointers.AddRange(il2Cpp.reversePInvokeWrappers);
                    orderedPointers.AddRange(il2Cpp.unresolvedVirtualCallPointers);
                }
                //TODO interopData内也包含函数
                orderedPointers = orderedPointers.Distinct().OrderBy(x => x).ToList();
                orderedPointers.Remove(0);
                writer.WriteLine("print('Making function...')");
                for (int i = 0; i < orderedPointers.Count - 1; i++)
                {
                    writer.WriteLine($"MakeFunction(0x{orderedPointers[i]:X}, 0x{orderedPointers[i + 1]:X})");
                }
                writer.WriteLine("print('Make function done, please wait for IDA to complete the analysis')");
            }
            writer.WriteLine("print('Script finished!')");
            writer.Close();
        }
Exemplo n.º 7
0
        private string header_include(Il2CppType type)
        {
            string output;
            string type_name     = "";
            string namespaze     = "";
            string template_decl = "";

            switch (type.type)
            {
            case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY:
            case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY:
            {
                return("#include <cs/array.hpp>");
            }


            case Il2CppTypeEnum.IL2CPP_TYPE_MVAR: return("");

            case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE: return($"#include <{include_path(type)}.hpp>");

            case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
            {
                return("#include <cs/string.hpp>");
            }

            case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST:
            {
                Il2CppTypeDefinition typeDef;
                Il2CppGenericClass   genericClass = il2Cpp.MapVATR <Il2CppGenericClass>(type.data.generic_class);

                typeDef = executor.GetGenericClassTypeDefinition(genericClass);

                var @namespace = metadata.GetStringFromIndex(typeDef.namespaceIndex);
                if (@namespace != "")
                {
                    type_name += @namespace + ".";
                }

                type_name += metadata.GetStringFromIndex(typeDef.nameIndex);
                var index = type_name.IndexOf("`");
                if (index != -1)
                {
                    type_name = type_name.Substring(0, index);
                }
                template_decl = "template <class...> ";        //Il2CppExecutor.GetGenericContainerParams(genericContainer, generic_decl)

                break;
            }

            default:
            {
                if (type.type > Il2CppTypeEnum.IL2CPP_TYPE_R8)
                {
                    type_name = executor.GetTypeName(type, true, false);
                }
                else
                {
                    return("");
                }
                break;
            }
            }

            type_name = type_name.Replace(".", "::");
            type_name = type_name.Replace("*", "");

            var nsindex = type_name.LastIndexOf("::");

            if (nsindex > 0)
            {
                namespaze = type_name.Substring(0, nsindex);
                type_name = type_name.Substring(nsindex + 2);
                output    = "namespace " + namespaze + "{ " + template_decl + "struct " + deobfu(type_name) + "; }";
            }
            else
            {
                output = "struct " + deobfu(type_name) + ";";
            }

            return(output);
        }
        public void WriteScript(Config config)
        {
            var json = new ScriptJson();

            for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
            {
                var imageDef = metadata.imageDefs[imageIndex];
                var typeEnd  = imageDef.typeStart + imageDef.typeCount;
                for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
                {
                    var typeDef  = metadata.typeDefs[typeIndex];
                    var typeName = executor.GetTypeDefName(typeDef, false, true);
                    typeDefImageIndices.Add(typeDef, imageIndex);
                    var methodEnd = typeDef.methodStart + typeDef.method_count;
                    for (var i = typeDef.methodStart; i < methodEnd; ++i)
                    {
                        var methodDef     = metadata.methodDefs[i];
                        var methodName    = metadata.GetStringFromIndex(methodDef.nameIndex);
                        var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
                        if (methodPointer > 0)
                        {
                            var scriptMethod = new ScriptMethod();
                            json.ScriptMethod.Add(scriptMethod);
                            scriptMethod.Address = il2Cpp.GetRVA(methodPointer);
                            scriptMethod.Name    = typeName + "$$" + methodName;
                        }
                    }
                }
            }
            if (il2Cpp.Version > 16)
            {
                foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo
                {
                    var type           = il2Cpp.types[i.Value];
                    var typeName       = executor.GetTypeName(type, true, true);
                    var scriptMetadata = new ScriptMetadata();
                    json.ScriptMetadata.Add(scriptMetadata);
                    scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadata.Name    = "Class$" + typeName;
                }
                foreach (var i in metadata.metadataUsageDic[2]) //kIl2CppMetadataUsageIl2CppType
                {
                    var type           = il2Cpp.types[i.Value];
                    var typeName       = executor.GetTypeName(type, true, true);
                    var scriptMetadata = new ScriptMetadata();
                    json.ScriptMetadata.Add(scriptMetadata);
                    scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadata.Name    = "Class$" + typeName;
                }
                foreach (var i in metadata.metadataUsageDic[3]) //kIl2CppMetadataUsageMethodDef
                {
                    var methodDef            = metadata.methodDefs[i.Value];
                    var typeDef              = metadata.typeDefs[methodDef.declaringType];
                    var typeName             = executor.GetTypeDefName(typeDef, true, true);
                    var methodName           = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex) + "()";
                    var scriptMetadataMethod = new ScriptMetadataMethod();
                    json.ScriptMetadataMethod.Add(scriptMetadataMethod);
                    scriptMetadataMethod.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadataMethod.Name    = "Method$" + methodName;
                    var imageIndex    = typeDefImageIndices[typeDef];
                    var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, (int)i.Value, imageIndex, methodDef.token);
                    if (methodPointer > 0)
                    {
                        scriptMetadataMethod.MethodAddress = il2Cpp.GetRVA(methodPointer);
                    }
                }
                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      = executor.GetTypeName(type, true, true) + "." + metadata.GetStringFromIndex(fieldDef.nameIndex);
                    var scriptMetadata = new ScriptMetadata();
                    json.ScriptMetadata.Add(scriptMetadata);
                    scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadata.Name    = "Field$" + fieldName;
                }
                foreach (var i in metadata.metadataUsageDic[5]) //kIl2CppMetadataUsageStringLiteral
                {
                    var scriptString = new ScriptString();
                    json.ScriptString.Add(scriptString);
                    scriptString.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptString.Value   = metadata.GetStringLiteralFromIndex(i.Value);
                }
                var stringLiterals = json.ScriptString.Select(x => new
                {
                    value   = x.Value,
                    address = $"0x{x.Address:X}"
                }).ToArray();
                File.WriteAllText("stringliteral.json", JsonConvert.SerializeObject(stringLiterals, Formatting.Indented), new UTF8Encoding(false));
                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   = executor.GetTypeDefName(typeDef, true, false);
                    if (methodSpec.classIndexIndex != -1)
                    {
                        var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex];
                        typeName += executor.GetGenericInstParams(classInst);
                    }
                    var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex);
                    if (methodSpec.methodIndexIndex != -1)
                    {
                        var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex];
                        methodName += executor.GetGenericInstParams(methodInst);
                    }
                    methodName += "()";
                    var scriptMetadataMethod = new ScriptMetadataMethod();
                    json.ScriptMetadataMethod.Add(scriptMetadataMethod);
                    scriptMetadataMethod.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
                    scriptMetadataMethod.Name    = "Method$" + methodName;
                    var imageIndex    = typeDefImageIndices[typeDef];
                    var methodPointer = il2Cpp.GetMethodPointer(methodDef.methodIndex, methodSpec.methodDefinitionIndex, imageIndex, methodDef.token);
                    if (methodPointer > 0)
                    {
                        scriptMetadataMethod.MethodAddress = il2Cpp.GetRVA(methodPointer);
                    }
                }
            }
            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);
                for (int i = 0; i < orderedPointers.Count; i++)
                {
                    orderedPointers[i] = il2Cpp.GetRVA(orderedPointers[i]);
                }
                json.Addresses = orderedPointers;
            }
            File.WriteAllText("script.json", JsonConvert.SerializeObject(json, Formatting.Indented));
        }