diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..15ed876 --- /dev/null +++ b/Program.cs @@ -0,0 +1,160 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using dnlib.DotNet; +using dnlib.DotNet.Emit; +using dnlib.DotNet.Writer; + +namespace SinUnfuscator +{ + class Program + { + public static ModuleDefMD asm; + public static string path; + + static void fixLengthCalls() + { + foreach (TypeDef type in asm.Types) + { + foreach (MethodDef methods in type.Methods) + { + if (!methods.HasBody) { continue; } + for (int x = 0; x < methods.Body.Instructions.Count; x++) + { + Instruction inst = methods.Body.Instructions[x]; + if (inst.OpCode.Equals(OpCodes.Call)) + { + if (inst.Operand.ToString().Contains("System.String::get_Length")) + { + int newLen = inst.Operand.ToString().Length; + methods.Body.Instructions[x - 1].OpCode = OpCodes.Ldc_I4; + methods.Body.Instructions[x - 1].Operand = newLen; + methods.Body.Instructions.Remove(inst); + } + } + } + } + } + } + + static void removeJunk() + { + asm.EntryPoint.DeclaringType.Name = "Entrypoint"; + for (int x_type = 0; x_type < asm.Types.Count; x_type++) + { + TypeDef type = asm.Types[x_type]; + if (type.IsGlobalModuleType) { type.Name = ""; } + if (type.HasInterfaces) + { + bool wasInterfaceObf = false; + foreach (InterfaceImpl intrface in type.Interfaces) + { + if (intrface.Interface == type) + { + asm.Types.RemoveAt(x_type); + x_type--; + wasInterfaceObf = true; + break; + } + } + if (wasInterfaceObf) { continue; } + } + for (int x_methods = 0; x_methods < type.Methods.Count; x_methods++) + { + MethodDef methods = type.Methods[x_methods]; + if (!methods.HasBody) { continue; } + methods.Body.KeepOldMaxStack = true; + for (int x_inst = 0; x_inst < methods.Body.Instructions.Count; x_inst++) + { + Instruction inst = methods.Body.Instructions[x_inst]; + switch (inst.OpCode.Code) + { + case Code.Ret: + if (methods.Body.Instructions[x_inst - 1].OpCode.Equals(OpCodes.Ldc_I4) && methods.Body.Instructions[x_inst - 2].OpCode.Equals(OpCodes.Ldc_I4)) + { + type.Methods.RemoveAt(x_methods); + x_methods--; + } + break; + case Code.Call: + if (inst.Operand.ToString().Contains("System.Convert::FromBase64String")) { methods.Name = "StringDecoder"; } + if (inst.Operand.ToString().Contains("::Initialize")) { methods.Name = ".cctor"; } + break; + } + } + } + if (!type.HasMethods) { asm.Types.RemoveAt(x_type); x_type--; } + } + } + + static void fixStrings() + { + foreach (TypeDef type in asm.Types) + { + foreach (MethodDef methods in type.Methods) + { + if (!methods.HasBody) { continue; } + for (int x = 0; x < methods.Body.Instructions.Count; x++) + { + if (x + 1 >= methods.Body.Instructions.Count) { continue; } + Instruction inst = methods.Body.Instructions[x]; + if (inst.OpCode.Equals(OpCodes.Ldstr) && methods.Body.Instructions[x + 1].OpCode.Equals(OpCodes.Call)) + { + if (methods.Body.Instructions[x + 1].Operand.ToString().Contains("::StringDecoder")) + { + inst.Operand = Encoding.UTF8.GetString(Convert.FromBase64String(inst.Operand.ToString())); + methods.Body.Instructions.RemoveAt(x + 1); + } + } + } + } + } + } + + static void disableProtections() + { + foreach (TypeDef type in asm.Types) + { + if (type.IsGlobalModuleType) + { + type.Methods.Clear(); + } + } + } + + static void Main(string[] args) + { + Console.Title = "SinUnfuscator"; + Console.WriteLine(); + Console.WriteLine(" SinUnfuscator by misonothx - SaintFuscator Deobfuscator"); + Console.WriteLine(" |- https://github.com/miso-xyz/SinUnfuscator/"); + Console.WriteLine(); + path = args[0]; + asm = ModuleDefMD.Load(args[0]); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine(" Removing Junk..."); + removeJunk(); + Console.WriteLine(" Decoding Strings..."); + fixStrings(); + Console.WriteLine(" Simplifying Length Calls..."); + fixLengthCalls(); + Console.WriteLine(" Removing Protections..."); + disableProtections(); + ModuleWriterOptions moduleWriterOptions = new ModuleWriterOptions(asm); + moduleWriterOptions.MetadataOptions.Flags |= MetadataFlags.PreserveAll; + moduleWriterOptions.Logger = DummyLogger.NoThrowInstance; + NativeModuleWriterOptions nativeModuleWriterOptions = new NativeModuleWriterOptions(asm, true); + nativeModuleWriterOptions.MetadataOptions.Flags |= MetadataFlags.PreserveAll; + nativeModuleWriterOptions.Logger = DummyLogger.NoThrowInstance; + if (asm.IsILOnly) { asm.Write(Path.GetFileNameWithoutExtension(path) + "-SinUnfuscator" + Path.GetExtension(path)); } + else { asm.NativeWrite(Path.GetFileNameWithoutExtension(path) + "-SinUnfuscator" + Path.GetExtension(path)); } + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(" Successfully cleaned! (saved as '" + Path.GetFileNameWithoutExtension(path) + "-SinUnfuscator" + Path.GetExtension(path) + "')"); + Console.ResetColor(); + Console.WriteLine(" Press any key to exit..."); + Console.ReadKey(); + } + } +} \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1527c1d --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SinUnfuscator")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SinUnfuscator")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9025aba8-60df-40d4-804f-6538880714fe")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SinUnfuscator.csproj b/SinUnfuscator.csproj new file mode 100644 index 0000000..384e92b --- /dev/null +++ b/SinUnfuscator.csproj @@ -0,0 +1,67 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {BDA5D9C2-E6B1-44CC-B143-FB921188A13B} + Exe + Properties + SinUnfuscator + SinUnfuscator + v4.0 + Client + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + ax_chara.ico + + + + False + bin\Debug\dnlib.dll + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SinUnfuscator.csproj.user b/SinUnfuscator.csproj.user new file mode 100644 index 0000000..b979fd9 --- /dev/null +++ b/SinUnfuscator.csproj.user @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/ax_chara.ico b/ax_chara.ico new file mode 100644 index 0000000..87736e4 Binary files /dev/null and b/ax_chara.ico differ