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);
        }
Exemplo n.º 2
0
        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();
        }