public static void DoPass(RewriteGlobalContext context) { var assemblyContext = context.GetAssemblyByName("mscorlib"); var typeContext = assemblyContext.GetTypeByName("System.String"); var objectTypeContext = assemblyContext.GetTypeByName("System.Object"); var methodFromMonoString = new MethodDefinition("op_Implicit", MethodAttributes.Static | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, typeContext.NewType); methodFromMonoString.Parameters.Add(new ParameterDefinition(assemblyContext.Imports.String)); typeContext.NewType.Methods.Add(methodFromMonoString); var fromBuilder = methodFromMonoString.Body.GetILProcessor(); var createIl2CppStringNop = fromBuilder.Create(OpCodes.Nop); fromBuilder.Emit(OpCodes.Ldarg_0); fromBuilder.Emit(OpCodes.Dup); fromBuilder.Emit(OpCodes.Brtrue_S, createIl2CppStringNop); fromBuilder.Emit(OpCodes.Ret); fromBuilder.Append(createIl2CppStringNop); fromBuilder.Emit(OpCodes.Call, assemblyContext.Imports.StringToNative); fromBuilder.Emit(OpCodes.Newobj, new MethodReference(".ctor", assemblyContext.Imports.Void, typeContext.NewType) { HasThis = true, Parameters = { new ParameterDefinition(assemblyContext.Imports.IntPtr) } }); fromBuilder.Emit(OpCodes.Ret); var methodToObject = new MethodDefinition("op_Implicit", MethodAttributes.Static | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, objectTypeContext.NewType); methodToObject.Parameters.Add(new ParameterDefinition(assemblyContext.Imports.String)); objectTypeContext.NewType.Methods.Add(methodToObject); var toObjectBuilder = methodToObject.Body.GetILProcessor(); toObjectBuilder.Emit(OpCodes.Ldarg_0); toObjectBuilder.Emit(OpCodes.Call, methodFromMonoString); toObjectBuilder.Emit(OpCodes.Ret); var methodToMonoString = new MethodDefinition("op_Implicit", MethodAttributes.Static | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, assemblyContext.Imports.String); methodToMonoString.Parameters.Add(new ParameterDefinition(typeContext.NewType)); typeContext.NewType.Methods.Add(methodToMonoString); var toBuilder = methodToMonoString.Body.GetILProcessor(); var createStringNop = toBuilder.Create(OpCodes.Nop); toBuilder.Emit(OpCodes.Ldarg_0); toBuilder.Emit(OpCodes.Call, assemblyContext.Imports.Il2CppObjectBaseToPointer); toBuilder.Emit(OpCodes.Dup); toBuilder.Emit(OpCodes.Brtrue_S, createStringNop); toBuilder.Emit(OpCodes.Pop); toBuilder.Emit(OpCodes.Ldnull); toBuilder.Emit(OpCodes.Ret); toBuilder.Append(createStringNop); toBuilder.Emit(OpCodes.Call, assemblyContext.Imports.StringFromNative); toBuilder.Emit(OpCodes.Ret); AddDelegateConversions(context); }
public AssemblyKnownImports(ModuleDefinition module, RewriteGlobalContext context) { Module = module; myContext = context; myVoidReference = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.Void)); myIntPtrReference = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.IntPtr)); myStringReference = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.String)); myIntReference = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.Int)); myLongReference = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.Long)); myTypeReference = new Lazy <TypeDefinition>(() => TargetTypeSystemHandler.Type); myEnumReference = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.Enum)); myDelegateReference = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.Delegate)); myMulticastDelegateReference = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.MulticastDelegate)); myValueTypeReference = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.ValueType)); myObjectReference = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.Object)); myIl2CppClassPointerStoreReference = new Lazy <TypeReference>(() => Module.ImportReference(typeof(Il2CppClassPointerStore <>))); myIl2CppReferenceArray = new Lazy <TypeReference>(() => Module.ImportReference(typeof(Il2CppReferenceArray <>))); myIl2CppStructArray = new Lazy <TypeReference>(() => Module.ImportReference(typeof(Il2CppStructArray <>))); myIl2CppStringArray = new Lazy <TypeReference>(() => Module.ImportReference(typeof(Il2CppStringArray))); myIl2CppArrayBase = new Lazy <TypeReference>(() => Module.ImportReference(typeof(Il2CppArrayBase <>))); myIl2CppArrayBaseSetlfSubst = new Lazy <TypeReference>(() => Module.ImportReference(new GenericInstanceType(Il2CppArrayBase) { GenericArguments = { Il2CppArrayBase.GenericParameters[0] } })); myIl2CppObjectBaseReference = new Lazy <TypeReference>(() => Module.ImportReference(typeof(Il2CppObjectBase))); myDefaultMemberAttribute = new Lazy <TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.DefaultMemberAttribute)); // myIl2CppObjectReference = new Lazy<TypeReference>(() => Module.ImportReference(TargetTypeSystemHandler.Object));// todo! myIl2CppObjectToPointer = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("Il2CppObjectBaseToPtr"))); myIl2CppObjectToPointerNotNull = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("Il2CppObjectBaseToPtrNotNull"))); myStringFromNative = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("Il2CppStringToManaged"))); myStringToNative = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("ManagedStringToIl2Cpp"))); myIl2CppObjectCast = new Lazy <MethodReference>(() => Module.ImportReference(typeof(Il2CppObjectBase).GetMethod("Cast"))); myIl2CppObjectTryCast = new Lazy <MethodReference>(() => Module.ImportReference(typeof(Il2CppObjectBase).GetMethod("TryCast"))); myIl2CppResolveICall = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.ResolveICall)))); myFieldGetOffset = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("il2cpp_field_get_offset"))); myFieldStaticGet = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("il2cpp_field_static_get_value"))); myFieldStaticSet = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("il2cpp_field_static_set_value"))); myRuntimeInvoke = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("il2cpp_runtime_invoke"))); myRuntimeClassInit = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("il2cpp_runtime_class_init"))); myObjectUnbox = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("il2cpp_object_unbox"))); myObjectBox = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.il2cpp_value_box)))); myValueSizeGet = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.il2cpp_class_value_size)))); myObjectGetClass = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.il2cpp_object_get_class)))); myClassIsValueType = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.il2cpp_class_is_valuetype)))); myRaiseExceptionIfNecessary = new Lazy <MethodReference>(() => Module.ImportReference(typeof(Il2CppException).GetMethod("RaiseExceptionIfNecessary"))); myGetVirtualMethod = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("il2cpp_object_get_virtual_method"))); myGetFieldPtr = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("GetIl2CppField"))); myGetIl2CppNestedClass = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("GetIl2CppNestedType"))); myGetIl2CppGlobalClass = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("GetIl2CppClass"))); myGetIl2CppMethod = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod("GetIl2CppMethod"))); myGetIl2CppMethodFromToken = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.GetIl2CppMethodByToken)))); myGetIl2CppTypeFromClass = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.il2cpp_class_get_type)))); myGetIl2CppTypeToClass = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.il2cpp_class_from_type)))); myIl2CppNewObject = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.il2cpp_object_new)))); myIl2CppMethodInfoFromReflection = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.il2cpp_method_get_from_reflection)))); myIl2CppMethodInfoToReflection = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.il2cpp_method_get_object)))); myIl2CppPointerToGeneric = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.PointerToValueGeneric)))); myIl2CppRenderTypeNameGeneric = new Lazy <MethodReference>(() => Module.ImportReference(typeof(IL2CPP).GetMethod(nameof(IL2CPP.RenderTypeName), new [] { typeof(bool) }))); myLdTokUnstrippedImpl = new Lazy <MethodReference>(() => { var declaringTypeRef = Module.ImportReference(typeof(RuntimeReflectionHelper)); var returnTypeRef = Module.ImportReference(myContext.GetAssemblyByName("mscorlib").NewAssembly.MainModule.GetType("Il2CppSystem.RuntimeTypeHandle")); var methodReference = new MethodReference("GetRuntimeTypeHandle", returnTypeRef, declaringTypeRef) { HasThis = false }; methodReference.GenericParameters.Add(new GenericParameter("T", methodReference)); return(Module.ImportReference(methodReference)); }); myFlagsAttributeCtor = new Lazy <MethodReference>(() => new MethodReference(".ctor", Void, Module.ImportReference(TargetTypeSystemHandler.FlagsAttribute)) { HasThis = true }); myObsoleteAttributeCtor = new Lazy <MethodReference>(() => new MethodReference(".ctor", Void, Module.ImportReference(TargetTypeSystemHandler.ObsoleteAttribute)) { HasThis = true, Parameters = { new ParameterDefinition(String) } }); myNotSupportedExceptionCtor = new Lazy <MethodReference>(() => new MethodReference(".ctor", Void, Module.ImportReference(TargetTypeSystemHandler.NotSupportedException)) { HasThis = true, Parameters = { new ParameterDefinition(String) } }); myObfuscatedNameAttributeCtor = new Lazy <MethodReference>(() => new MethodReference(".ctor", Void, Module.ImportReference(typeof(ObfuscatedNameAttribute))) { HasThis = true, Parameters = { new ParameterDefinition(String) } }); myCallerCountAttributeCtor = new Lazy <MethodReference>(() => new MethodReference(".ctor", Void, Module.ImportReference(typeof(CallerCountAttribute))) { HasThis = true, Parameters = { new ParameterDefinition(Int) } }); myCachedScanResultsAttributeCtor = new Lazy <MethodReference>(() => new MethodReference(".ctor", Void, Module.ImportReference(typeof(CachedScanResultsAttribute))) { HasThis = true, Parameters = {} }); }
public static void GenerateDeobfuscationMap(UnhollowerOptions options) { if (string.IsNullOrEmpty(options.SourceDir)) { Console.WriteLine("No input dir specified; use -h for help"); return; } if (string.IsNullOrEmpty(options.OutputDir)) { Console.WriteLine("No target dir specified; use -h for help"); return; } if (string.IsNullOrEmpty(options.DeobfuscationNewAssembliesPath)) { Console.WriteLine("No obfuscated assembly path specified; use -h for help"); return; } if (!Directory.Exists(options.OutputDir)) { Directory.CreateDirectory(options.OutputDir); } RewriteGlobalContext rewriteContext; IIl2CppMetadataAccess inputAssemblies; IIl2CppMetadataAccess systemAssemblies; using (new TimingCookie("Reading assemblies")) inputAssemblies = new CecilMetadataAccess(Directory.EnumerateFiles(options.DeobfuscationNewAssembliesPath, "*.dll")); using (new TimingCookie("Reading system assemblies")) { if (!string.IsNullOrEmpty(options.SystemLibrariesPath)) { systemAssemblies = new CecilMetadataAccess(Directory.EnumerateFiles(options.SystemLibrariesPath, "*.dll") .Where(it => Path.GetFileName(it).StartsWith("System.") || Path.GetFileName(it) == "mscorlib.dll" || Path.GetFileName(it) == "netstandard.dll")); } else { systemAssemblies = new CecilMetadataAccess(new[] { options.MscorlibPath }); } } using (new TimingCookie("Creating rewrite assemblies")) rewriteContext = new RewriteGlobalContext(options, inputAssemblies, systemAssemblies, NullMetadataAccess.Instance); using (new TimingCookie("Computing renames")) Pass05CreateRenameGroups.DoPass(rewriteContext); using (new TimingCookie("Creating typedefs")) Pass10CreateTypedefs.DoPass(rewriteContext); using (new TimingCookie("Computing struct blittability")) Pass11ComputeTypeSpecifics.DoPass(rewriteContext); using (new TimingCookie("Filling typedefs")) Pass12FillTypedefs.DoPass(rewriteContext); using (new TimingCookie("Filling generic constraints")) Pass13FillGenericConstraints.DoPass(rewriteContext); using (new TimingCookie("Creating members")) Pass15GenerateMemberContexts.DoPass(rewriteContext); RewriteGlobalContext cleanContext; IIl2CppMetadataAccess cleanAssemblies; using (new TimingCookie("Reading clean assemblies")) cleanAssemblies = new CecilMetadataAccess(Directory.EnumerateFiles(options.SourceDir, "*.dll")); using (new TimingCookie("Creating clean rewrite assemblies")) cleanContext = new RewriteGlobalContext(options, cleanAssemblies, systemAssemblies, NullMetadataAccess.Instance); using (new TimingCookie("Computing clean assembly renames")) Pass05CreateRenameGroups.DoPass(cleanContext); using (new TimingCookie("Creating clean assembly typedefs")) Pass10CreateTypedefs.DoPass(cleanContext); var usedNames = new Dictionary <TypeDefinition, (string OldName, int Penalty, bool ForceNs)>(); using var fileOutput = new FileStream(options.OutputDir + Path.DirectorySeparatorChar + "RenameMap.csv.gz", FileMode.Create, FileAccess.Write); using var gzipStream = new GZipStream(fileOutput, CompressionLevel.Optimal, true); using var writer = new StreamWriter(gzipStream, Encoding.UTF8, 65536, true); void DoEnum(TypeRewriteContext obfuscatedType, TypeRewriteContext cleanType) { foreach (var originalTypeField in obfuscatedType.OriginalType.Fields) { if (!originalTypeField.Name.IsObfuscated(obfuscatedType.AssemblyContext.GlobalContext.Options)) { continue; } var matchedField = cleanType.OriginalType.Fields[obfuscatedType.OriginalType.Fields.IndexOf(originalTypeField)]; writer.WriteLine(obfuscatedType.NewType.GetNamespacePrefix() + "." + obfuscatedType.NewType.Name + "::" + Pass22GenerateEnums.GetUnmangledName(originalTypeField) + ";" + matchedField.Name + ";0"); } } foreach (var assemblyContext in rewriteContext.Assemblies) { if (options.DeobfuscationGenerationAssemblies.Count > 0 && !options.DeobfuscationGenerationAssemblies.Contains(assemblyContext.NewAssembly.Name.Name)) { continue; } var cleanAssembly = cleanContext.GetAssemblyByName(assemblyContext.OriginalAssembly.Name.Name); void DoType(TypeRewriteContext typeContext, TypeRewriteContext?enclosingType) { if (!typeContext.OriginalNameWasObfuscated) { return; } var cleanType = FindBestMatchType(typeContext, cleanAssembly, enclosingType); if (cleanType.Item1 == null) { return; } if (!usedNames.TryGetValue(cleanType.Item1.NewType, out var existing) || existing.Item2 < cleanType.Item2) { usedNames[cleanType.Item1.NewType] = (typeContext.NewType.GetNamespacePrefix() + "." + typeContext.NewType.Name, cleanType.Item2, typeContext.OriginalType.Namespace != cleanType.Item1.OriginalType.Namespace); } else { return; } if (typeContext.OriginalType.IsEnum) { DoEnum(typeContext, cleanType.Item1); } foreach (var originalTypeNestedType in typeContext.OriginalType.NestedTypes) { DoType(typeContext.AssemblyContext.GetContextForOriginalType(originalTypeNestedType), cleanType.Item1); } } foreach (var typeContext in assemblyContext.Types) { if (typeContext.NewType.DeclaringType != null) { continue; } DoType(typeContext, null); } } foreach (var keyValuePair in usedNames) { writer.WriteLine(keyValuePair.Value.Item1 + ";" + (keyValuePair.Value.ForceNs ? keyValuePair.Key.Namespace + "." : "") + keyValuePair.Key.Name + ";" + keyValuePair.Value.Item2); } LogSupport.Info("Done!"); rewriteContext.Dispose(); }