2024-06-26 14:45:54 -04:00
|
|
|
|
using dnlib.DotNet;
|
|
|
|
|
using dnlib.DotNet.Emit;
|
2024-06-22 12:39:10 -04:00
|
|
|
|
using ReCodeIt.Utils;
|
|
|
|
|
using System.Diagnostics;
|
2024-11-02 21:30:02 -04:00
|
|
|
|
using ReCodeIt.ReMapper;
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
|
|
|
|
namespace ReCodeItLib.Remapper;
|
|
|
|
|
|
|
|
|
|
public static class Deobfuscator
|
|
|
|
|
{
|
2024-11-02 15:58:08 -04:00
|
|
|
|
public static void Deobfuscate(string assemblyPath, bool isLauncher = false)
|
2024-06-22 12:39:10 -04:00
|
|
|
|
{
|
2024-08-09 21:55:31 +01:00
|
|
|
|
var executablePath = Path.Combine(DataProvider.DataPath, "De4dot", "de4dot.exe");
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
|
|
|
|
string token;
|
|
|
|
|
|
2024-06-26 14:45:54 -04:00
|
|
|
|
ModuleContext modCtx = ModuleDef.CreateModuleContext();
|
|
|
|
|
ModuleDefMD module = ModuleDefMD.Load(assemblyPath, modCtx);
|
|
|
|
|
|
|
|
|
|
var potentialStringDelegates = new List<MethodDef>();
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
2024-06-26 14:45:54 -04:00
|
|
|
|
foreach (var type in module.GetTypes())
|
|
|
|
|
{
|
|
|
|
|
foreach (var method in type.Methods)
|
2024-06-22 12:39:10 -04:00
|
|
|
|
{
|
2024-06-26 14:45:54 -04:00
|
|
|
|
if (method.ReturnType.FullName != "System.String"
|
|
|
|
|
|| method.Parameters.Count != 1
|
|
|
|
|
|| method.Parameters[0].Type.FullName != "System.Int32"
|
|
|
|
|
|| method.Body == null
|
|
|
|
|
|| !method.IsStatic)
|
2024-06-22 12:39:10 -04:00
|
|
|
|
{
|
2024-06-26 14:45:54 -04:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
2024-06-26 14:45:54 -04:00
|
|
|
|
if (!method.Body.Instructions.Any(x =>
|
|
|
|
|
x.OpCode.Code == Code.Callvirt &&
|
2024-08-09 14:35:18 -04:00
|
|
|
|
((IMethodDefOrRef)x.Operand).FullName == "System.Object System.AppDomain::GetData(System.String)"))
|
2024-06-26 14:45:54 -04:00
|
|
|
|
{
|
|
|
|
|
continue;
|
2024-06-22 12:39:10 -04:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-26 14:45:54 -04:00
|
|
|
|
potentialStringDelegates.Add(method);
|
2024-06-22 12:39:10 -04:00
|
|
|
|
}
|
2024-06-26 14:45:54 -04:00
|
|
|
|
}
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
2024-06-26 14:45:54 -04:00
|
|
|
|
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))}");
|
|
|
|
|
}
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
2024-06-26 14:45:54 -04:00
|
|
|
|
var methodDef = potentialStringDelegates[0];
|
|
|
|
|
MDToken deobfRid = methodDef.MDToken;
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
2024-06-26 14:45:54 -04:00
|
|
|
|
// Construct the token string (similar to Mono.Cecil's format)
|
|
|
|
|
token = $"0x{(deobfRid.Raw | deobfRid.Rid):x4}";
|
|
|
|
|
Console.WriteLine($"Deobfuscation token: {token}");
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
2024-11-02 15:58:08 -04:00
|
|
|
|
var cmd = isLauncher
|
2024-11-02 21:30:02 -04:00
|
|
|
|
? $"--un-name \"!^<>[a-z0-9]$&!^<>[a-z0-9]__.*$&![A-Z][A-Z]\\$<>.*$&^[a-zA-Z_<{{$][a-zA-Z_0-9<>{{}}$.`-]*$\" \"{assemblyPath}\" --strtok \"{token}\""
|
2024-11-02 15:58:08 -04:00
|
|
|
|
: $"--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}\"";
|
|
|
|
|
|
|
|
|
|
var process = Process.Start(executablePath, cmd);
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
|
|
|
|
process.WaitForExit();
|
|
|
|
|
|
2024-11-02 15:58:08 -04:00
|
|
|
|
var extName = isLauncher ? "-cleaned.exe" : "-cleaned.dll";
|
|
|
|
|
|
2024-06-22 12:39:10 -04:00
|
|
|
|
// Fixes "ResolutionScope is null" by rewriting the assembly
|
2024-11-02 15:58:08 -04:00
|
|
|
|
var cleanedDllPath = Path.Combine(Path.GetDirectoryName(assemblyPath), Path.GetFileNameWithoutExtension(assemblyPath) + extName);
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
2024-06-26 14:45:54 -04:00
|
|
|
|
ModuleDefMD assemblyRewrite = null;
|
2024-06-22 12:39:10 -04:00
|
|
|
|
|
|
|
|
|
using (var memoryStream = new MemoryStream(File.ReadAllBytes(cleanedDllPath)))
|
|
|
|
|
{
|
2024-06-26 14:45:54 -04:00
|
|
|
|
assemblyRewrite = ModuleDefMD.Load(memoryStream, modCtx);
|
2024-11-02 21:30:02 -04:00
|
|
|
|
|
|
|
|
|
if (isLauncher)
|
|
|
|
|
{
|
|
|
|
|
SPTPublicizer.PublicizeClasses(assemblyRewrite);
|
|
|
|
|
}
|
2024-06-22 12:39:10 -04:00
|
|
|
|
}
|
2024-06-26 14:45:54 -04:00
|
|
|
|
|
|
|
|
|
assemblyRewrite.Write(cleanedDllPath);
|
2024-06-22 12:39:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|