Esempio n. 1
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, 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);
                            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, 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("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, imageIndex);
                    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)
                {
                    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("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:
            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);
            File.WriteAllText("il2cpp.h", sb.ToString());
        }
        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));
        }