public static void AnalyzeDeobfuscationParams(UnhollowerOptions options) { RewriteGlobalContext rewriteContext; using (new TimingCookie("Reading assemblies")) rewriteContext = new RewriteGlobalContext(options, Directory.EnumerateFiles(options.SourceDir, "*.dll")); for (var chars = 1; chars <= 3; chars++) { for (var uniq = 3; uniq <= 15; uniq++) { options.TypeDeobfuscationCharsPerUniquifier = chars; options.TypeDeobfuscationMaxUniquifiers = uniq; rewriteContext.RenamedTypes.Clear(); rewriteContext.RenameGroups.Clear(); Pass05CreateRenameGroups.DoPass(rewriteContext); var uniqueTypes = rewriteContext.RenameGroups.Values.Count(it => it.Count == 1); var nonUniqueTypes = rewriteContext.RenameGroups.Values.Count(it => it.Count > 1); Console.WriteLine($"Chars=\t{chars}\tMaxU=\t{uniq}\tUniq=\t{uniqueTypes}\tNonUniq=\t{nonUniqueTypes}"); } } }
public static void AnalyzeDeobfuscationParams(UnhollowerOptions options) { RewriteGlobalContext rewriteContext; IIl2CppMetadataAccess inputAssemblies; using (new TimingCookie("Reading assemblies")) inputAssemblies = new CecilMetadataAccess(options.Source); using (new TimingCookie("Creating assembly contexts")) rewriteContext = new RewriteGlobalContext(options, inputAssemblies, NullMetadataAccess.Instance, NullMetadataAccess.Instance); for (var chars = 1; chars <= 3; chars++) { for (var uniq = 3; uniq <= 15; uniq++) { options.TypeDeobfuscationCharsPerUniquifier = chars; options.TypeDeobfuscationMaxUniquifiers = uniq; rewriteContext.RenamedTypes.Clear(); rewriteContext.RenameGroups.Clear(); Pass05CreateRenameGroups.DoPass(rewriteContext); var uniqueTypes = rewriteContext.RenameGroups.Values.Count(it => it.Count == 1); var nonUniqueTypes = rewriteContext.RenameGroups.Values.Count(it => it.Count > 1); Console.WriteLine($"Chars=\t{chars}\tMaxU=\t{uniq}\tUniq=\t{uniqueTypes}\tNonUniq=\t{nonUniqueTypes}"); } } }
public static void Main(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.MscorlibPath)) { Console.WriteLine("No mscorlib specified; use -h for help"); return; } if (!Directory.Exists(options.OutputDir)) { Directory.CreateDirectory(options.OutputDir); } RewriteGlobalContext rewriteContext; using (new TimingCookie("Reading assemblies")) rewriteContext = new RewriteGlobalContext(options, Directory.EnumerateFiles(options.SourceDir, "*.dll")); 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); using (new TimingCookie("Scanning method cross-references")) Pass16ScanMethodRefs.DoPass(rewriteContext, options); using (new TimingCookie("Finalizing method declarations")) Pass18FinalizeMethodContexts.DoPass(rewriteContext); LogSupport.Info($"{Pass18FinalizeMethodContexts.TotalPotentiallyDeadMethods} total potentially dead methods"); using (new TimingCookie("Filling method parameters")) Pass19CopyMethodParameters.DoPass(rewriteContext); using (new TimingCookie("Creating static constructors")) Pass20GenerateStaticConstructors.DoPass(rewriteContext); using (new TimingCookie("Creating value type fields")) Pass21GenerateValueTypeFields.DoPass(rewriteContext); using (new TimingCookie("Creating enums")) Pass22GenerateEnums.DoPass(rewriteContext); using (new TimingCookie("Creating IntPtr constructors")) Pass23GeneratePointerConstructors.DoPass(rewriteContext); using (new TimingCookie("Creating type getters")) Pass24GenerateTypeStaticGetters.DoPass(rewriteContext); using (new TimingCookie("Creating non-blittable struct constructors")) Pass25GenerateNonBlittableValueTypeDefaultCtors.DoPass(rewriteContext); using (new TimingCookie("Creating generic method static constructors")) Pass30GenerateGenericMethodStoreConstructors.DoPass(rewriteContext); using (new TimingCookie("Creating field accessors")) Pass40GenerateFieldAccessors.DoPass(rewriteContext); using (new TimingCookie("Filling methods")) Pass50GenerateMethods.DoPass(rewriteContext); using (new TimingCookie("Generating implicit conversions")) Pass60AddImplicitConversions.DoPass(rewriteContext); using (new TimingCookie("Creating properties")) Pass70GenerateProperties.DoPass(rewriteContext); if (options.UnityBaseLibsDir != null) { using (new TimingCookie("Unstripping types")) Pass79UnstripTypes.DoPass(rewriteContext); using (new TimingCookie("Unstripping fields")) Pass80UnstripFields.DoPass(rewriteContext); using (new TimingCookie("Unstripping methods")) Pass80UnstripMethods.DoPass(rewriteContext); using (new TimingCookie("Unstripping method bodies")) Pass81FillUnstrippedMethodBodies.DoPass(rewriteContext); } else { LogSupport.Warning("Not performing unstripping as unity libs are not specified"); } using (new TimingCookie("Generating forwarded types")) Pass89GenerateForwarders.DoPass(rewriteContext); using (new TimingCookie("Writing xref cache")) Pass89GenerateMethodXrefCache.DoPass(rewriteContext, options); using (new TimingCookie("Writing assemblies")) Pass90WriteToDisk.DoPass(rewriteContext, options); using (new TimingCookie("Writing method pointer map")) Pass91GenerateMethodPointerMap.DoPass(rewriteContext, options); if (!options.NoCopyUnhollowerLibs) { File.Copy(typeof(IL2CPP).Assembly.Location, Path.Combine(options.OutputDir, typeof(IL2CPP).Assembly.GetName().Name + ".dll"), true); File.Copy(typeof(RuntimeLibMarker).Assembly.Location, Path.Combine(options.OutputDir, typeof(RuntimeLibMarker).Assembly.GetName().Name + ".dll"), true); File.Copy(typeof(Decoder).Assembly.Location, Path.Combine(options.OutputDir, typeof(Decoder).Assembly.GetName().Name + ".dll"), true); } LogSupport.Info("Done!"); rewriteContext.Dispose(); }
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(); }
public static void Main(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.MscorlibPath)) { Console.WriteLine("No mscorlib specified; use -h for help"); return; } if (!Directory.Exists(options.OutputDir)) { Directory.CreateDirectory(options.OutputDir); } RewriteGlobalContext rewriteContext; using (new TimingCookie("Reading assemblies")) rewriteContext = new RewriteGlobalContext(options, Directory.EnumerateFiles(options.SourceDir, "*.dll")); 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); using (new TimingCookie("Creating static constructors")) Pass20GenerateStaticConstructors.DoPass(rewriteContext); using (new TimingCookie("Creating value type fields")) Pass21GenerateValueTypeFields.DoPass(rewriteContext); using (new TimingCookie("Creating enums")) Pass22GenerateEnums.DoPass(rewriteContext); using (new TimingCookie("Creating IntPtr constructors")) Pass23GeneratePointerConstructors.DoPass(rewriteContext); using (new TimingCookie("Creating type getters")) Pass24GenerateTypeStaticGetters.DoPass(rewriteContext); using (new TimingCookie("Creating non-blittable struct constructors")) Pass25GenerateNonBlittableValueTypeDefaultCtors.DoPass(rewriteContext); using (new TimingCookie("Creating generic method static constructors")) Pass30GenerateGenericMethodStoreConstructors.DoPass(rewriteContext); using (new TimingCookie("Creating field accessors")) Pass40GenerateFieldAccessors.DoPass(rewriteContext); using (new TimingCookie("Filling methods")) Pass50GenerateMethods.DoPass(rewriteContext); using (new TimingCookie("Generating implicit conversions")) Pass60AddImplicitConversions.DoPass(rewriteContext); using (new TimingCookie("Creating properties")) Pass70GenerateProperties.DoPass(rewriteContext); if (options.UnityBaseLibsDir != null) { using (new TimingCookie("Unstripping types")) Pass79UnstripTypes.DoPass(rewriteContext); using (new TimingCookie("Unstripping methods")) Pass80UnstripMethods.DoPass(rewriteContext); } else { Console.WriteLine("Not performing unstripping as unity libs are not specified"); } using (new TimingCookie("Writing assemblies")) Pass99WriteToDisk.DoPass(rewriteContext, options); File.Copy(typeof(IL2CPP).Assembly.Location, Path.Combine(options.OutputDir, typeof(IL2CPP).Assembly.GetName().Name + ".dll"), true); File.Copy(typeof(DelegateSupport).Assembly.Location, Path.Combine(options.OutputDir, typeof(DelegateSupport).Assembly.GetName().Name + ".dll"), true); File.Copy(typeof(Decoder).Assembly.Location, Path.Combine(options.OutputDir, typeof(Decoder).Assembly.GetName().Name + ".dll"), true); Console.WriteLine("Done!"); }