From 2cef02aefba531b7ba08f662e418996104344fe9 Mon Sep 17 00:00:00 2001 From: de4dot Date: Sat, 2 Feb 2013 17:03:56 +0100 Subject: [PATCH] Support Confuser 1.9 r78363 --- .../deobfuscators/Confuser/AntiDebugger.cs | 54 +++++++++--- .../Confuser/ConstantsDecrypterV18.cs | 23 ++++- .../deobfuscators/Confuser/ProxyCallFixer.cs | 86 +++++++++++++++++-- .../deobfuscators/Confuser/VersionDetector.cs | 2 +- 4 files changed, 143 insertions(+), 22 deletions(-) diff --git a/de4dot.code/deobfuscators/Confuser/AntiDebugger.cs b/de4dot.code/deobfuscators/Confuser/AntiDebugger.cs index 68200b40..f30a523a 100644 --- a/de4dot.code/deobfuscators/Confuser/AntiDebugger.cs +++ b/de4dot.code/deobfuscators/Confuser/AntiDebugger.cs @@ -40,6 +40,8 @@ namespace de4dot.code.deobfuscators.Confuser { v17_r74021_normal, v17_r74021_safe, v19_r76119_safe, + v19_r78363_normal, + v19_r78363_safe, } public MethodDef InitMethod { @@ -135,8 +137,7 @@ namespace de4dot.code.deobfuscators.Confuser { var antiDebugMethod = GetAntiDebugMethod(type, initMethod); if (antiDebugMethod == null) return false; - if (!DotNetUtils.HasString(antiDebugMethod, "Debugger detected (Managed)")) - return false; + bool hasDebuggerStrings = DotNetUtils.HasString(antiDebugMethod, "Debugger detected (Managed)"); if (DotNetUtils.CallsMethod(initMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) { int failFastCalls = ConfuserUtils.CountCalls(antiDebugMethod, "System.Void System.Environment::FailFast(System.String)"); @@ -147,11 +148,15 @@ namespace de4dot.code.deobfuscators.Confuser { return false; if (!DotNetUtils.CallsMethod(antiDebugMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) { + if (!hasDebuggerStrings) + return false; if (ConfuserUtils.CountCalls(antiDebugMethod, ntQueryInformationProcess) != 2) return false; version = ConfuserVersion.v16_r61954_normal; } else if (failFastCalls == 8) { + if (!hasDebuggerStrings) + return false; if (ConfuserUtils.CountCalls(antiDebugMethod, ntQueryInformationProcess) != 2) return false; version = ConfuserVersion.v17_r73822_normal; @@ -161,12 +166,17 @@ namespace de4dot.code.deobfuscators.Confuser { return false; if (ConfuserUtils.CountCalls(antiDebugMethod, ntQueryInformationProcess) != 0) return false; - version = ConfuserVersion.v17_r74021_normal; + if (hasDebuggerStrings) + version = ConfuserVersion.v17_r74021_normal; + else + version = ConfuserVersion.v19_r78363_normal; } else return false; } else if (!DotNetUtils.CallsMethod(initMethod, "System.Void System.Threading.ThreadStart::.ctor(System.Object,System.IntPtr)")) { + if (!hasDebuggerStrings) + return false; if (!DotNetUtils.CallsMethod(initMethod, "System.Void System.Diagnostics.Process::EnterDebugMode()")) return false; if (!CheckProfilerStrings1(antiDebugMethod)) @@ -174,6 +184,8 @@ namespace de4dot.code.deobfuscators.Confuser { version = ConfuserVersion.v14_r57588_normal; } else { + if (!hasDebuggerStrings) + return false; if (!DotNetUtils.CallsMethod(initMethod, "System.Void System.Diagnostics.Process::EnterDebugMode()")) return false; if (!CheckProfilerStrings1(antiDebugMethod)) @@ -204,9 +216,8 @@ namespace de4dot.code.deobfuscators.Confuser { var antiDebugMethod = GetAntiDebugMethod(type, initMethod); if (antiDebugMethod == null) return false; - if (!DotNetUtils.HasString(antiDebugMethod, "Debugger detected (Managed)") && - !DotNetUtils.HasString(antiDebugMethod, "Debugger is detected (Managed)")) - return false; + bool hasDebuggerStrings = DotNetUtils.HasString(antiDebugMethod, "Debugger detected (Managed)") || + DotNetUtils.HasString(antiDebugMethod, "Debugger is detected (Managed)"); if (!DotNetUtils.CallsMethod(initMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) return false; if (ConfuserUtils.CountCalls(antiDebugMethod, ntQueryInformationProcess) != 0) @@ -218,14 +229,19 @@ namespace de4dot.code.deobfuscators.Confuser { if (failFastCalls != 2) return false; - if (!DotNetUtils.CallsMethod(antiDebugMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) - version = ConfuserVersion.v16_r61954_safe; - else if (DotNetUtils.GetPInvokeMethod(type, "IsDebuggerPresent") == null) - version = ConfuserVersion.v17_r73822_safe; - else if (CheckProfilerStrings1(initMethod)) - version = ConfuserVersion.v17_r74021_safe; - else - version = ConfuserVersion.v19_r76119_safe; + if (hasDebuggerStrings) { + if (!DotNetUtils.CallsMethod(antiDebugMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) + version = ConfuserVersion.v16_r61954_safe; + else if (DotNetUtils.GetPInvokeMethod(type, "IsDebuggerPresent") == null) + version = ConfuserVersion.v17_r73822_safe; + else if (CheckProfilerStrings1(initMethod)) + version = ConfuserVersion.v17_r74021_safe; + else + version = ConfuserVersion.v19_r76119_safe; + } + else { + version = ConfuserVersion.v19_r78363_safe; + } } return true; @@ -259,6 +275,11 @@ namespace de4dot.code.deobfuscators.Confuser { case ConfuserVersion.v19_r76119_safe: minRev = 76119; + maxRev = 78342; + return true; + + case ConfuserVersion.v19_r78363_safe: + minRev = 78363; maxRev = int.MaxValue; return true; @@ -284,6 +305,11 @@ namespace de4dot.code.deobfuscators.Confuser { case ConfuserVersion.v17_r74021_normal: minRev = 74021; + maxRev = 78342; + return true; + + case ConfuserVersion.v19_r78363_normal: + minRev = 78363; maxRev = int.MaxValue; return true; diff --git a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV18.cs b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV18.cs index c233fe20..e908d364 100644 --- a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV18.cs +++ b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV18.cs @@ -57,6 +57,9 @@ namespace de4dot.code.deobfuscators.Confuser { v19_r78056_normal, v19_r78056_dynamic, v19_r78056_native, + v19_r78363_normal, + v19_r78363_dynamic, + v19_r78363_native, } public class DecrypterInfo { @@ -118,6 +121,9 @@ namespace de4dot.code.deobfuscators.Confuser { case ConfuserVersion.v19_r78056_normal: case ConfuserVersion.v19_r78056_dynamic: case ConfuserVersion.v19_r78056_native: + case ConfuserVersion.v19_r78363_normal: + case ConfuserVersion.v19_r78363_dynamic: + case ConfuserVersion.v19_r78363_native: return Hash1(key0l * magic); default: throw new ApplicationException("Invalid version"); @@ -214,8 +220,10 @@ namespace de4dot.code.deobfuscators.Confuser { InitVersion(cctor, ConfuserVersion.v18_r75369_normal, ConfuserVersion.v18_r75369_dynamic, ConfuserVersion.v18_r75369_native); else if (!DotNetUtils.CallsMethod(method, "System.Void System.Threading.Monitor::Exit(System.Object)")) InitVersion(cctor, ConfuserVersion.v19_r77172_normal, ConfuserVersion.v19_r77172_dynamic, ConfuserVersion.v19_r77172_native); - else + else if (!DotNetUtils.CallsMethod(method, "System.Void System.Diagnostics.StackFrame::.ctor(System.Int32)")) InitVersion(cctor, ConfuserVersion.v19_r78056_normal, ConfuserVersion.v19_r78056_dynamic, ConfuserVersion.v19_r78056_native); + else + InitVersion(cctor, ConfuserVersion.v19_r78363_normal, ConfuserVersion.v19_r78363_dynamic, ConfuserVersion.v19_r78363_native); } else return; @@ -412,6 +420,9 @@ namespace de4dot.code.deobfuscators.Confuser { case ConfuserVersion.v19_r78056_normal: case ConfuserVersion.v19_r78056_dynamic: case ConfuserVersion.v19_r78056_native: + case ConfuserVersion.v19_r78363_normal: + case ConfuserVersion.v19_r78363_dynamic: + case ConfuserVersion.v19_r78363_native: return FindKeys_v18_r75369(info); default: throw new ApplicationException("Invalid version"); @@ -585,18 +596,21 @@ namespace de4dot.code.deobfuscators.Confuser { case ConfuserVersion.v18_r75369_normal: case ConfuserVersion.v19_r77172_normal: case ConfuserVersion.v19_r78056_normal: + case ConfuserVersion.v19_r78363_normal: return DecryptResource_v18_r75367_normal(encrypted); case ConfuserVersion.v18_r75367_dynamic: case ConfuserVersion.v18_r75369_dynamic: case ConfuserVersion.v19_r77172_dynamic: case ConfuserVersion.v19_r78056_dynamic: + case ConfuserVersion.v19_r78363_dynamic: return DecryptResource_v18_r75367_dynamic(encrypted); case ConfuserVersion.v18_r75367_native: case ConfuserVersion.v18_r75369_native: case ConfuserVersion.v19_r77172_native: case ConfuserVersion.v19_r78056_native: + case ConfuserVersion.v19_r78363_native: return DecryptResource_v18_r75367_native(encrypted); default: @@ -795,6 +809,13 @@ namespace de4dot.code.deobfuscators.Confuser { case ConfuserVersion.v19_r78056_dynamic: case ConfuserVersion.v19_r78056_native: minRev = 78056; + maxRev = 78342; + return true; + + case ConfuserVersion.v19_r78363_normal: + case ConfuserVersion.v19_r78363_dynamic: + case ConfuserVersion.v19_r78363_native: + minRev = 78363; maxRev = int.MaxValue; return true; diff --git a/de4dot.code/deobfuscators/Confuser/ProxyCallFixer.cs b/de4dot.code/deobfuscators/Confuser/ProxyCallFixer.cs index b82cf135..b22346b4 100644 --- a/de4dot.code/deobfuscators/Confuser/ProxyCallFixer.cs +++ b/de4dot.code/deobfuscators/Confuser/ProxyCallFixer.cs @@ -60,6 +60,8 @@ namespace de4dot.code.deobfuscators.Confuser { v18_r75369_native, v19_r76101_normal, v19_r76101_native, + v19_r78363_normal, + v19_r78363_native, } enum ProxyCreatorType { @@ -235,12 +237,14 @@ namespace de4dot.code.deobfuscators.Confuser { case ConfuserVersion.v18_r75367_normal: case ConfuserVersion.v18_r75369_normal: case ConfuserVersion.v19_r76101_normal: + case ConfuserVersion.v19_r78363_normal: GetCallInfo_v18_r75367_normal(info, creatorInfo, out calledMethod, out callOpcode); break; case ConfuserVersion.v18_r75367_native: case ConfuserVersion.v18_r75369_native: case ConfuserVersion.v19_r76101_native: + case ConfuserVersion.v19_r78363_native: GetCallInfo_v18_r75367_native(info, creatorInfo, out calledMethod, out callOpcode); break; @@ -476,7 +480,8 @@ namespace de4dot.code.deobfuscators.Confuser { else continue; - var proxyType = GetProxyCreatorType(method); + int tmpVer; + var proxyType = GetProxyCreatorType(method, simpleDeobfuscator, out tmpVer); if (proxyType == ProxyCreatorType.None) continue; @@ -507,10 +512,18 @@ namespace de4dot.code.deobfuscators.Confuser { theVersion = proxyType != ProxyCreatorType.CallOrCallvirt || callvirtChar == 9 ? ConfuserVersion.v18_r75367_native : ConfuserVersion.v18_r75369_native; else if (FindMagic_v18_r75367(method, out magic)) theVersion = proxyType != ProxyCreatorType.CallOrCallvirt || callvirtChar == 9 ? ConfuserVersion.v18_r75367_normal : ConfuserVersion.v18_r75369_normal; - else if (FindMagic_v19_r76101(method, out magic)) - theVersion = ConfuserVersion.v19_r76101_normal; - else if ((nativeMethod = FindNativeMethod_v19_r76101(method)) != null) - theVersion = ConfuserVersion.v19_r76101_native; + else if (FindMagic_v19_r76101(method, out magic)) { + if (tmpVer == 1) + theVersion = ConfuserVersion.v19_r76101_normal; + else if (tmpVer == 2) + theVersion = ConfuserVersion.v19_r78363_normal; + } + else if ((nativeMethod = FindNativeMethod_v19_r76101(method)) != null) { + if (tmpVer == 1) + theVersion = ConfuserVersion.v19_r76101_native; + else if (tmpVer == 2) + theVersion = ConfuserVersion.v19_r78363_native; + } else { if (proxyType == ProxyCreatorType.CallOrCallvirt && !DotNetUtils.CallsMethod(method, "System.Int32 System.String::get_Length()")) theVersion = ConfuserVersion.v11_r50378; @@ -798,7 +811,27 @@ namespace de4dot.code.deobfuscators.Confuser { return false; } - static ProxyCreatorType GetProxyCreatorType(MethodDef method) { + static ProxyCreatorType GetProxyCreatorType(MethodDef method, ISimpleDeobfuscator simpleDeobfuscator, out int version) { + var type = GetProxyCreatorTypeV1(method); + if (type != ProxyCreatorType.None) { + version = 1; + return type; + } + + simpleDeobfuscator.Deobfuscate(method); + + type = GetProxyCreatorTypeV2(method); + if (type != ProxyCreatorType.None) { + version = 2; + return type; + } + + version = 0; + return ProxyCreatorType.None; + } + + // <= 1.9 r78342 (refs to System.Reflection.Emit.OpCodes) + static ProxyCreatorType GetProxyCreatorTypeV1(MethodDef method) { foreach (var instr in method.Body.Instructions) { var field = instr.Operand as IField; if (field == null) @@ -815,6 +848,41 @@ namespace de4dot.code.deobfuscators.Confuser { return ProxyCreatorType.None; } + // >= 1.9 r78363 (no refs to System.Reflection.Emit.OpCodes) + static ProxyCreatorType GetProxyCreatorTypeV2(MethodDef method) { + if (!DeobUtils.HasInteger(method, 0x2A)) + return ProxyCreatorType.None; + if (CheckCtorProxyTypeV2(method)) + return ProxyCreatorType.Newobj; + if (CheckCallProxyTypeV2(method)) + return ProxyCreatorType.CallOrCallvirt; + return ProxyCreatorType.None; + } + + static bool CheckCtorProxyTypeV2(MethodDef method) { + var instrs = method.Body.Instructions; + for (int i = 0; i < instrs.Count; i++) { + var ldci4 = instrs[i]; + if (!ldci4.IsLdcI4() || ldci4.GetLdcI4Value() != 2) + continue; + if (instrs[i + 1].OpCode.Code != Code.Mul) + continue; + ldci4 = instrs[i + 2]; + if (!ldci4.IsLdcI4() || ldci4.GetLdcI4Value() != 0x73) + continue; + if (instrs[i + 3].OpCode.Code != Code.Stelem_I1) + continue; + + return true; + } + return false; + } + + static bool CheckCallProxyTypeV2(MethodDef method) { + return DeobUtils.HasInteger(method, 0x28) && + DeobUtils.HasInteger(method, 0x6F); + } + public new void Find() { if (delegateCreatorMethods.Count == 0) return; @@ -1116,6 +1184,12 @@ namespace de4dot.code.deobfuscators.Confuser { case ConfuserVersion.v19_r76101_normal: case ConfuserVersion.v19_r76101_native: minRev = 76101; + maxRev = 78342; + return true; + + case ConfuserVersion.v19_r78363_normal: + case ConfuserVersion.v19_r78363_native: + minRev = 78363; maxRev = int.MaxValue; return true; diff --git a/de4dot.code/deobfuscators/Confuser/VersionDetector.cs b/de4dot.code/deobfuscators/Confuser/VersionDetector.cs index 0802855f..9389bc4b 100644 --- a/de4dot.code/deobfuscators/Confuser/VersionDetector.cs +++ b/de4dot.code/deobfuscators/Confuser/VersionDetector.cs @@ -45,7 +45,7 @@ namespace de4dot.code.deobfuscators.Confuser { 76119, 76163, 76186, 76271, 76360, 76509, 76542, 76548, 76558, 76580, 76656, 76871, 76923, 76924, 76933, 76934, 76972, 76974, 77124, 77172, 77447, 77501, 78056, 78072, - 78086, 78196, 78197, + 78086, 78196, 78197, 78342, 78363, 78377, }; static Dictionary revToVersion = new Dictionary {