private void CreateCustomAttribute(Il2CppImageDefinition imageDef, int customAttributeIndex, uint token, ModuleDefinition moduleDefinition, Collection <CustomAttribute> customAttributes) { if (il2cpp.version > 20) { var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, token); if (attributeIndex >= 0) { var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex]; for (int j = 0; j < attributeTypeRange.count; j++) { var attributeTypeIndex = metadata.attributeTypes[attributeTypeRange.start + j]; var attributeType = il2cpp.types[attributeTypeIndex]; var attributeName = GetTypeName(attributeType); if (attributeName == "CompilerGeneratedAttribute" || attributeName == "DebuggerBrowsableAttribute" || attributeName == "SerializeField") { continue; } var methodPointer = il2cpp.customAttributeGenerators[attributeIndex]; var fixedMethodPointer = il2cpp.FixPointer(methodPointer); var customAttribute = new CustomAttribute(moduleDefinition.ImportReference(attributeAttribute)); var name = new CustomAttributeNamedArgument("Name", new CustomAttributeArgument(stringType, attributeName)); var rva = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{fixedMethodPointer:X}")); var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2cpp.MapVATR(methodPointer):X}")); customAttribute.Fields.Add(name); customAttribute.Fields.Add(rva); customAttribute.Fields.Add(offset); customAttributes.Add(customAttribute); } } } }
public string GetCustomAttribute(Il2CppImageDefinition imageDef, int customAttributeIndex, uint token, string padding = "") { if (il2Cpp.Version < 21) { return(string.Empty); } var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, token); if (attributeIndex >= 0) { var methodPointer = executor.customAttributeGenerators[attributeIndex]; var fixedMethodPointer = il2Cpp.GetRVA(methodPointer); var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex]; var sb = new StringBuilder(); for (var i = 0; i < attributeTypeRange.count; i++) { var typeIndex = metadata.attributeTypes[attributeTypeRange.start + i]; sb.AppendFormat("{0}[{1}] // RVA: 0x{2:X} Offset: 0x{3:X} VA: 0x{4:X}\n", padding, executor.GetTypeName(il2Cpp.types[typeIndex], false, false), fixedMethodPointer, il2Cpp.MapVATR(methodPointer), methodPointer); } return(sb.ToString()); } else { return(string.Empty); } }
private void CreateCustomAttribute(Il2CppImageDefinition imageDef, int customAttributeIndex, uint token, ModuleDefinition moduleDefinition, Collection <CustomAttribute> customAttributes) { var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, token); if (attributeIndex >= 0) { var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex]; for (int i = 0; i < attributeTypeRange.count; i++) { var attributeTypeIndex = metadata.attributeTypes[attributeTypeRange.start + i]; var attributeType = il2Cpp.types[attributeTypeIndex]; var typeDefinition = typeDefinitionDic[attributeType.data.klassIndex]; if (knownAttributes.TryGetValue(typeDefinition.FullName, out var methodDefinition)) { var customAttribute = new CustomAttribute(moduleDefinition.ImportReference(methodDefinition)); customAttributes.Add(customAttribute); } else { var methodPointer = il2Cpp.customAttributeGenerators[attributeIndex]; var fixedMethodPointer = il2Cpp.FixPointer(methodPointer); var customAttribute = new CustomAttribute(moduleDefinition.ImportReference(attributeAttribute)); var name = new CustomAttributeNamedArgument("Name", new CustomAttributeArgument(stringType, typeDefinition.Name)); var rva = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{fixedMethodPointer:X}")); var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2Cpp.MapVATR(methodPointer):X}")); customAttribute.Fields.Add(name); customAttribute.Fields.Add(rva); customAttribute.Fields.Add(offset); customAttributes.Add(customAttribute); } } } }
private static string GetCustomAttribute(Il2CppImageDefinition image, int customAttributeIndex, uint token, string padding = "") { if (!config.DumpAttribute || il2cpp.version < 21) { return(string.Empty); } var index = metadata.GetCustomAttributeIndex(image, customAttributeIndex, token); if (index >= 0) { var attributeTypeRange = metadata.attributeTypeRanges[index]; var sb = new StringBuilder(); for (var i = 0; i < attributeTypeRange.count; i++) { var typeIndex = metadata.attributeTypes[attributeTypeRange.start + i]; var methodPointer = il2cpp.customAttributeGenerators[index]; sb.AppendFormat("{0}[{1}] // RVA: 0x{2:X} Offset: 0x{3:X}\n", padding, GetTypeName(il2cpp.types[typeIndex]), methodPointer, il2cpp.MapVATR(methodPointer)); } return(sb.ToString()); } else { return(string.Empty); } }
public string GetCustomAttribute(Il2CppImageDefinition imageDef, int customAttributeIndex, uint token, string padding = "") { if (il2Cpp.Version < 21) { return(string.Empty); } var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, token); if (attributeIndex >= 0) { if (il2Cpp.Version < 29) { var methodPointer = executor.customAttributeGenerators[attributeIndex]; var fixedMethodPointer = il2Cpp.GetRVA(methodPointer); var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex]; var sb = new StringBuilder(); for (var i = 0; i < attributeTypeRange.count; i++) { var typeIndex = metadata.attributeTypes[attributeTypeRange.start + i]; sb.AppendFormat("{0}[{1}] // RVA: 0x{2:X} Offset: 0x{3:X} VA: 0x{4:X}\n", padding, executor.GetTypeName(il2Cpp.types[typeIndex], false, false), fixedMethodPointer, il2Cpp.MapVATR(methodPointer), methodPointer); } return(sb.ToString()); } else { var startRange = metadata.attributeDataRanges[attributeIndex]; var endRange = metadata.attributeDataRanges[attributeIndex + 1]; metadata.Position = metadata.header.attributeDataOffset + startRange.startOffset; var buff = metadata.ReadBytes((int)(endRange.startOffset - startRange.startOffset)); var reader = new CustomAttributeDataReader(executor, buff); if (reader.Count == 0) { return(string.Empty); } var sb = new StringBuilder(); for (var i = 0; i < reader.Count; i++) { sb.Append(padding); sb.Append(reader.GetStringCustomAttributeData()); sb.Append("\n"); } return(sb.ToString()); } } else { return(string.Empty); } }
public DummyAssemblyCreator(Metadata metadata, Il2Cpp il2cpp) { this.metadata = metadata; this.il2cpp = il2cpp; //Il2CppDummyDll var il2CppDummyDll = AssemblyDefinition.ReadAssembly(new MemoryStream(Resource1.Il2CppDummyDll)); var addressAttribute = il2CppDummyDll.MainModule.Types.First(x => x.Name == "AddressAttribute").Methods.First(); var fieldOffsetAttribute = il2CppDummyDll.MainModule.Types.First(x => x.Name == "FieldOffsetAttribute").Methods.First(); var stringType = il2CppDummyDll.MainModule.TypeSystem.String; var resolver = new MyAssemblyResolver(); var moduleParameters = new ModuleParameters { Kind = ModuleKind.Dll, AssemblyResolver = resolver }; //创建程序集,同时创建所有类 foreach (var imageDef in metadata.imageDefs) { var assemblyName = new AssemblyNameDefinition(metadata.GetStringFromIndex(imageDef.nameIndex).Replace(".dll", ""), new Version("3.7.1.6")); var assemblyDefinition = AssemblyDefinition.CreateAssembly(assemblyName, metadata.GetStringFromIndex(imageDef.nameIndex), moduleParameters); resolver.Register(assemblyDefinition); Assemblies.Add(assemblyDefinition); var moduleDefinition = assemblyDefinition.MainModule; moduleDefinition.Types.Clear();//清除自动创建的<Module>类 var typeEnd = imageDef.typeStart + imageDef.typeCount; for (var index = imageDef.typeStart; index < typeEnd; ++index) { var typeDef = metadata.typeDefs[index]; var namespaceName = metadata.GetStringFromIndex(typeDef.namespaceIndex); var typeName = metadata.GetStringFromIndex(typeDef.nameIndex); TypeDefinition typeDefinition; if (typeDef.declaringTypeIndex != -1)//nested types { typeDefinition = typeDefinitionDic[index]; } else { typeDefinition = new TypeDefinition(namespaceName, typeName, (TypeAttributes)typeDef.flags); moduleDefinition.Types.Add(typeDefinition); typeDefinitionDic.Add(index, typeDefinition); } //nestedtype for (int i = 0; i < typeDef.nested_type_count; i++) { var nestedIndex = metadata.nestedTypeIndices[typeDef.nestedTypesStart + i]; var nestedTypeDef = metadata.typeDefs[nestedIndex]; var nestedTypeDefinition = new TypeDefinition(metadata.GetStringFromIndex(nestedTypeDef.namespaceIndex), metadata.GetStringFromIndex(nestedTypeDef.nameIndex), (TypeAttributes)nestedTypeDef.flags); typeDefinition.NestedTypes.Add(nestedTypeDefinition); typeDefinitionDic.Add(nestedIndex, nestedTypeDefinition); } } } //先单独处理,因为不知道会不会有问题 for (var index = 0; index < metadata.uiNumTypes; ++index) { var typeDef = metadata.typeDefs[index]; var typeDefinition = typeDefinitionDic[index]; //parent if (typeDef.parentIndex >= 0) { var parentType = il2cpp.types[typeDef.parentIndex]; var parentTypeRef = GetTypeReference(typeDefinition, parentType); typeDefinition.BaseType = parentTypeRef; } //interfaces for (int i = 0; i < typeDef.interfaces_count; i++) { var interfaceType = il2cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]]; var interfaceTypeRef = GetTypeReference(typeDefinition, interfaceType); typeDefinition.Interfaces.Add(interfaceTypeRef); } } //处理field, method, property等等 for (var index = 0; index < metadata.uiNumTypes; ++index) { var typeDef = metadata.typeDefs[index]; var typeDefinition = typeDefinitionDic[index]; //field var fieldEnd = typeDef.fieldStart + typeDef.field_count; for (var i = typeDef.fieldStart; i < fieldEnd; ++i) { var fieldDef = metadata.fieldDefs[i]; var fieldType = il2cpp.types[fieldDef.typeIndex]; var fieldName = metadata.GetStringFromIndex(fieldDef.nameIndex); var fieldTypeRef = GetTypeReference(typeDefinition, fieldType); var fieldDefinition = new FieldDefinition(fieldName, (FieldAttributes)fieldType.attrs, fieldTypeRef); typeDefinition.Fields.Add(fieldDefinition); //fieldDefault if (fieldDefinition.HasDefault) { var fieldDefault = metadata.GetFieldDefaultValueFromIndex(i); if (fieldDefault != null && fieldDefault.dataIndex != -1) { fieldDefinition.Constant = GetDefaultValue(fieldDefault.dataIndex, fieldDefault.typeIndex); } } //fieldOffset var fieldOffset = il2cpp.GetFieldOffsetFromIndex(index, i - typeDef.fieldStart, i); if (fieldOffset > 0) { var customAttribute = new CustomAttribute(typeDefinition.Module.Import(fieldOffsetAttribute)); var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{fieldOffset:X}")); customAttribute.Fields.Add(offset); fieldDefinition.CustomAttributes.Add(customAttribute); } } //method var methodEnd = typeDef.methodStart + typeDef.method_count; for (var i = typeDef.methodStart; i < methodEnd; ++i) { var methodDef = metadata.methodDefs[i]; var methodReturnType = il2cpp.types[methodDef.returnType]; var methodName = metadata.GetStringFromIndex(methodDef.nameIndex); var methodDefinition = new MethodDefinition(methodName, (MethodAttributes)methodDef.flags, typeDefinition.Module.Import(typeof(void))); typeDefinition.Methods.Add(methodDefinition); methodDefinition.ReturnType = GetTypeReference(methodDefinition, methodReturnType); if (methodDefinition.HasBody && typeDefinition.BaseType?.FullName != "System.MulticastDelegate") { var ilprocessor = methodDefinition.Body.GetILProcessor(); ilprocessor.Append(ilprocessor.Create(OpCodes.Nop)); } methodDefinitionDic.Add(i, methodDefinition); //method parameter for (var j = 0; j < methodDef.parameterCount; ++j) { var parameterDef = metadata.parameterDefs[methodDef.parameterStart + j]; var parameterName = metadata.GetStringFromIndex(parameterDef.nameIndex); var parameterType = il2cpp.types[parameterDef.typeIndex]; var parameterTypeRef = GetTypeReference(methodDefinition, parameterType); var parameterDefinition = new ParameterDefinition(parameterName, (ParameterAttributes)parameterType.attrs, parameterTypeRef); methodDefinition.Parameters.Add(parameterDefinition); //ParameterDefault if (parameterDefinition.HasDefault) { var parameterDefault = metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j); if (parameterDefault != null && parameterDefault.dataIndex != -1) { parameterDefinition.Constant = GetDefaultValue(parameterDefault.dataIndex, parameterDefault.typeIndex); } } } //补充泛型参数 if (methodDef.genericContainerIndex >= 0) { var genericContainer = metadata.genericContainers[methodDef.genericContainerIndex]; if (genericContainer.type_argc > methodDefinition.GenericParameters.Count) { for (int j = methodDefinition.GenericParameters.Count + 1; j <= genericContainer.type_argc; j++) { var genericParameter = new GenericParameter("T" + j, methodDefinition); methodDefinition.GenericParameters.Add(genericParameter); } } } //address ulong methodPointer; if (methodDef.methodIndex >= 0) { methodPointer = il2cpp.methodPointers[methodDef.methodIndex]; } else { il2cpp.genericMethoddDictionary.TryGetValue(i, out methodPointer); } if (methodPointer > 0) { var customAttribute = new CustomAttribute(typeDefinition.Module.Import(addressAttribute)); var rva = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{methodPointer:X}")); var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2cpp.MapVATR(methodPointer):X}")); customAttribute.Fields.Add(rva); customAttribute.Fields.Add(offset); methodDefinition.CustomAttributes.Add(customAttribute); } } //property var propertyEnd = typeDef.propertyStart + typeDef.property_count; for (var i = typeDef.propertyStart; i < propertyEnd; ++i) { var propertyDef = metadata.propertyDefs[i]; var propertyName = metadata.GetStringFromIndex(propertyDef.nameIndex); TypeReference propertyType = null; MethodDefinition GetMethod = null; MethodDefinition SetMethod = null; if (propertyDef.get >= 0) { GetMethod = methodDefinitionDic[typeDef.methodStart + propertyDef.get]; propertyType = GetMethod.ReturnType; } if (propertyDef.set >= 0) { SetMethod = methodDefinitionDic[typeDef.methodStart + propertyDef.set]; if (propertyType == null) { propertyType = SetMethod.Parameters[0].ParameterType; } } var propertyDefinition = new PropertyDefinition(propertyName, (PropertyAttributes)propertyDef.attrs, propertyType) { GetMethod = GetMethod, SetMethod = SetMethod }; typeDefinition.Properties.Add(propertyDefinition); } //event var eventEnd = typeDef.eventStart + typeDef.event_count; for (var i = typeDef.eventStart; i < eventEnd; ++i) { var eventDef = metadata.eventDefs[i]; var eventName = metadata.GetStringFromIndex(eventDef.nameIndex); var eventType = il2cpp.types[eventDef.typeIndex]; var eventTypeRef = GetTypeReference(typeDefinition, eventType); var eventDefinition = new EventDefinition(eventName, (EventAttributes)eventType.attrs, eventTypeRef); if (eventDef.add >= 0) { eventDefinition.AddMethod = methodDefinitionDic[typeDef.methodStart + eventDef.add]; } if (eventDef.remove >= 0) { eventDefinition.RemoveMethod = methodDefinitionDic[typeDef.methodStart + eventDef.remove]; } if (eventDef.raise >= 0) { eventDefinition.InvokeMethod = methodDefinitionDic[typeDef.methodStart + eventDef.raise]; } typeDefinition.Events.Add(eventDefinition); } //补充泛型参数 if (typeDef.genericContainerIndex >= 0) { var genericContainer = metadata.genericContainers[typeDef.genericContainerIndex]; if (genericContainer.type_argc > typeDefinition.GenericParameters.Count) { for (int j = typeDefinition.GenericParameters.Count + 1; j <= genericContainer.type_argc; j++) { var genericParameter = new GenericParameter("T" + j, typeDefinition); typeDefinition.GenericParameters.Add(genericParameter); } } } } //第三遍,添加CustomAttribute。只添加SerializeField用于MonoBehaviour的反序列化 if (il2cpp.version > 20) { var engine = Assemblies.Find(x => x.MainModule.Types.Any(t => t.Namespace == "UnityEngine" && t.Name == "SerializeField")); var serializeField = engine.MainModule.Types.First(x => x.Name == "SerializeField").Methods.First(); foreach (var imageDef in metadata.imageDefs) { var typeEnd = imageDef.typeStart + imageDef.typeCount; for (int index = imageDef.typeStart; index < typeEnd; index++) { var typeDef = metadata.typeDefs[index]; var typeDefinition = typeDefinitionDic[index]; //field var fieldEnd = typeDef.fieldStart + typeDef.field_count; for (var i = typeDef.fieldStart; i < fieldEnd; ++i) { var fieldDef = metadata.fieldDefs[i]; var fieldName = metadata.GetStringFromIndex(fieldDef.nameIndex); var fieldDefinition = typeDefinition.Fields.First(x => x.Name == fieldName); //fieldAttribute var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, fieldDef.customAttributeIndex, fieldDef.token); if (attributeIndex >= 0) { var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex]; for (int j = 0; j < attributeTypeRange.count; j++) { var attributeTypeIndex = metadata.attributeTypes[attributeTypeRange.start + j]; var attributeType = il2cpp.types[attributeTypeIndex]; if (attributeType.type == Il2CppTypeEnum.IL2CPP_TYPE_CLASS) { var klass = metadata.typeDefs[attributeType.data.klassIndex]; var attributeName = metadata.GetStringFromIndex(klass.nameIndex); if (attributeName == "SerializeField") { var customAttribute = new CustomAttribute(typeDefinition.Module.Import(serializeField)); fieldDefinition.CustomAttributes.Add(customAttribute); } } } } } } } } }
private void CreateCustomAttribute(Il2CppImageDefinition imageDef, int customAttributeIndex, uint token, ModuleDefinition moduleDefinition, Collection <CustomAttribute> customAttributes) { var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, token); if (attributeIndex >= 0) { try { if (il2Cpp.Version < 29) { var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex]; for (int i = 0; i < attributeTypeRange.count; i++) { var attributeTypeIndex = metadata.attributeTypes[attributeTypeRange.start + i]; var attributeType = il2Cpp.types[attributeTypeIndex]; var typeDef = executor.GetTypeDefinitionFromIl2CppType(attributeType); var typeDefinition = typeDefinitionDic[typeDef]; if (!TryRestoreCustomAttribute(typeDefinition, moduleDefinition, customAttributes)) { var methodPointer = executor.customAttributeGenerators[attributeIndex]; var fixedMethodPointer = il2Cpp.GetRVA(methodPointer); var customAttribute = new CustomAttribute(moduleDefinition.ImportReference(attributeAttribute)); var name = new CustomAttributeNamedArgument("Name", new CustomAttributeArgument(stringType, typeDefinition.Name)); var rva = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{fixedMethodPointer:X}")); var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2Cpp.MapVATR(methodPointer):X}")); customAttribute.Fields.Add(name); customAttribute.Fields.Add(rva); customAttribute.Fields.Add(offset); customAttributes.Add(customAttribute); } } } else { var startRange = metadata.attributeDataRanges[attributeIndex]; var endRange = metadata.attributeDataRanges[attributeIndex + 1]; metadata.Position = metadata.header.attributeDataOffset + startRange.startOffset; var buff = metadata.ReadBytes((int)(endRange.startOffset - startRange.startOffset)); var reader = new CustomAttributeDataReader(executor, buff); if (reader.Count != 0) { for (var i = 0; i < reader.Count; i++) { var visitor = reader.VisitCustomAttributeData(); var methodDefinition = methodDefinitionDic[visitor.CtorIndex]; var customAttribute = new CustomAttribute(moduleDefinition.ImportReference(methodDefinition)); foreach (var argument in visitor.Arguments) { var parameterDefinition = methodDefinition.Parameters[argument.Index]; var customAttributeArgument = CreateCustomAttributeArgument(parameterDefinition.ParameterType, argument.Value, methodDefinition); customAttribute.ConstructorArguments.Add(customAttributeArgument); } foreach (var field in visitor.Fields) { var fieldDefinition = fieldDefinitionDic[field.Index]; var customAttributeArgument = CreateCustomAttributeArgument(fieldDefinition.FieldType, field.Value, fieldDefinition); var customAttributeNamedArgument = new CustomAttributeNamedArgument(fieldDefinition.Name, customAttributeArgument); customAttribute.Fields.Add(customAttributeNamedArgument); } foreach (var property in visitor.Properties) { var propertyDefinition = propertyDefinitionDic[property.Index]; var customAttributeArgument = CreateCustomAttributeArgument(propertyDefinition.PropertyType, property.Value, propertyDefinition); var customAttributeNamedArgument = new CustomAttributeNamedArgument(propertyDefinition.Name, customAttributeArgument); customAttribute.Properties.Add(customAttributeNamedArgument); } customAttributes.Add(customAttribute); } } } } catch { Console.WriteLine($"ERROR: Error while restoring attributeIndex {attributeIndex}"); } } }