diff --git a/ReCodeItCLI/Commands/BuildCommand.cs b/ReCodeItCLI/Commands/Build.cs similarity index 99% rename from ReCodeItCLI/Commands/BuildCommand.cs rename to ReCodeItCLI/Commands/Build.cs index 01eab8d..1233834 100644 --- a/ReCodeItCLI/Commands/BuildCommand.cs +++ b/ReCodeItCLI/Commands/Build.cs @@ -8,7 +8,7 @@ using ReCodeItLib.Utils; namespace ReCodeIt.Commands; [Command("Build", Description = "(Compile Time Reflection) Build your project and get a dll output for the original assembly.")] -public class BuildCommand : ICommand +public class Build : ICommand { private ReCodeItCrossCompiler CrossCompiler { get; set; } diff --git a/ReCodeItCLI/Commands/DeObfuscate.cs b/ReCodeItCLI/Commands/DeObfuscate.cs new file mode 100644 index 0000000..a4d5714 --- /dev/null +++ b/ReCodeItCLI/Commands/DeObfuscate.cs @@ -0,0 +1,28 @@ +using CliFx; +using CliFx.Attributes; +using CliFx.Infrastructure; +using ReCodeIt.Utils; +using ReCodeItLib.Remapper; + +namespace ReCodeIt.Commands; + +[Command("DeObfuscate", Description = "Generates a de-obfuscated -cleaned dll in the folder your assembly is in")] +public class DeObfuscate : ICommand +{ + [CommandParameter(0, IsRequired = true, Description = "The absolute path to your obfuscated assembly file, folder must contain all references to be resolved.")] + public string AssemblyPath { get; init; } + + public ValueTask ExecuteAsync(IConsole console) + { + DataProvider.LoadAppSettings(); + DataProvider.IsCli = true; + + Logger.Log("Deobfuscating assembly..."); + + Deobfuscator.Deobfuscate(AssemblyPath); + + Logger.Log("Complete", ConsoleColor.Green); + + return default; + } +} \ No newline at end of file diff --git a/ReCodeItCLI/Commands/ReMapCommand.cs b/ReCodeItCLI/Commands/ReMap.cs similarity index 97% rename from ReCodeItCLI/Commands/ReMapCommand.cs rename to ReCodeItCLI/Commands/ReMap.cs index 2a3c854..64494d6 100644 --- a/ReCodeItCLI/Commands/ReMapCommand.cs +++ b/ReCodeItCLI/Commands/ReMap.cs @@ -7,7 +7,7 @@ using ReCodeIt.Utils; namespace ReCodeIt.Commands; [Command("ReMap", Description = "Generates a re-mapped dll provided a mapping file and de-obfuscated dll")] -public class ReMapCommand : ICommand +public class ReMap : ICommand { private ReCodeItRemapper _remapper { get; set; } = new(); diff --git a/RecodeItGUI/GUI/Main.Designer.cs b/RecodeItGUI/GUI/Main.Designer.cs index 64066fa..779c17f 100644 --- a/RecodeItGUI/GUI/Main.Designer.cs +++ b/RecodeItGUI/GUI/Main.Designer.cs @@ -1742,7 +1742,7 @@ partial class ReCodeItForm Controls.Add(TabControlMain); FormBorderStyle = FormBorderStyle.FixedSingle; Name = "ReCodeItForm"; - Text = "ReCodeIt V0.1.0 - RC1"; + Text = "ReCodeIt V0.1.0"; RemapperTabPage.ResumeLayout(false); groupBox1.ResumeLayout(false); groupBox1.PerformLayout(); diff --git a/RecodeItGUI/GUI/Main.resx b/RecodeItGUI/GUI/Main.resx index ba46472..2704a16 100644 --- a/RecodeItGUI/GUI/Main.resx +++ b/RecodeItGUI/GUI/Main.resx @@ -120,13 +120,4 @@ 17, 17 - - 17, 17 - - - 17, 17 - - - 17, 17 - \ No newline at end of file diff --git a/RecodeItLib/DeMangler/ReCodeItDeMangler.cs b/RecodeItLib/DeMangler/ReCodeItDeMangler.cs deleted file mode 100644 index 85d1b5a..0000000 --- a/RecodeItLib/DeMangler/ReCodeItDeMangler.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace ReCodeIt.DeMangler; - -internal class ReCodeItDeMangler -{ -} \ No newline at end of file diff --git a/RecodeItLib/ReCodeItLib.csproj b/RecodeItLib/ReCodeItLib.csproj index b16bb33..6fef663 100644 --- a/RecodeItLib/ReCodeItLib.csproj +++ b/RecodeItLib/ReCodeItLib.csproj @@ -19,4 +19,8 @@ + + + + diff --git a/RecodeItLib/Remapper/DeObfuscator.cs b/RecodeItLib/Remapper/DeObfuscator.cs new file mode 100644 index 0000000..a2c6bec --- /dev/null +++ b/RecodeItLib/Remapper/DeObfuscator.cs @@ -0,0 +1,76 @@ +using Mono.Cecil; +using Mono.Cecil.Cil; +using ReCodeIt.Utils; +using System.Diagnostics; + +namespace ReCodeItLib.Remapper; + +public static class Deobfuscator +{ + public static void Deobfuscate(string assemblyPath) + { + var executablePath = Path.Combine(DataProvider.DataPath, "De4dot", "de4dot.exe"); + + string token; + + using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyPath)) + { + var potentialStringDelegates = new List(); + + foreach (var type in assemblyDefinition.MainModule.Types) + { + foreach (var method in type.Methods) + { + if (method.ReturnType.FullName != "System.String" + || method.Parameters.Count != 1 + || method.Parameters[0].ParameterType.FullName != "System.Int32" + || method.Body == null + || !method.IsStatic) + { + continue; + } + + if (!method.Body.Instructions.Any(x => + x.OpCode.Code == Code.Callvirt && + ((MethodReference)x.Operand).FullName == "System.Object System.AppDomain::GetData(System.String)")) + { + continue; + } + + potentialStringDelegates.Add(method); + } + } + + if (potentialStringDelegates.Count != 1) + { + Logger.Log($"Expected to find 1 potential string delegate method; found {potentialStringDelegates.Count}. Candidates: {string.Join("\r\n", potentialStringDelegates.Select(x => x.FullName))}"); + } + + var deobfRid = potentialStringDelegates[0].MetadataToken; + + token = $"0x{((uint)deobfRid.TokenType | deobfRid.RID):x4}"; + + Console.WriteLine($"Deobfuscation token: {token}"); + } + + var process = Process.Start(executablePath, + $"--un-name \"!^<>[a-z0-9]$&!^<>[a-z0-9]__.*$&![A-Z][A-Z]\\$<>.*$&^[a-zA-Z_<{{$][a-zA-Z_0-9<>{{}}$.`-]*$\" \"{assemblyPath}\" --strtyp delegate --strtok \"{token}\""); + + process.WaitForExit(); + + // Fixes "ResolutionScope is null" by rewriting the assembly + var cleanedDllPath = Path.Combine(Path.GetDirectoryName(assemblyPath), Path.GetFileNameWithoutExtension(assemblyPath) + "-cleaned.dll"); + + var resolver = new DefaultAssemblyResolver(); + resolver.AddSearchDirectory(Path.GetDirectoryName(assemblyPath)); + + using (var memoryStream = new MemoryStream(File.ReadAllBytes(cleanedDllPath))) + using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(memoryStream, new ReaderParameters() + { + AssemblyResolver = resolver + })) + { + assemblyDefinition.Write(cleanedDllPath); + } + } +} \ No newline at end of file