diff --git a/de4dot.code/deobfuscators/Confuser/AntiDumping.cs b/de4dot.code/deobfuscators/Confuser/AntiDumping.cs index c8958ec1..81e9f43d 100644 --- a/de4dot.code/deobfuscators/Confuser/AntiDumping.cs +++ b/de4dot.code/deobfuscators/Confuser/AntiDumping.cs @@ -17,6 +17,7 @@ along with de4dot. If not, see . */ +using System; using Mono.Cecil; using Mono.Cecil.Cil; using de4dot.blocks; @@ -25,6 +26,18 @@ namespace de4dot.code.deobfuscators.Confuser { class AntiDumping : IVersionProvider { ModuleDefinition module; MethodDefinition initMethod; + ConfuserVersion version = ConfuserVersion.Unknown; + + enum ConfuserVersion { + Unknown, + v14_r58564, + v14_r58852, + v16_r69339, + v17_r74708, + v18_r75257, + v19_r75725, + v19_r76186, + } public MethodDefinition InitMethod { get { return initMethod; } @@ -57,11 +70,16 @@ namespace de4dot.code.deobfuscators.Confuser { var calledMethod = instr.Operand as MethodDefinition; if (calledMethod == null) continue; + if (calledMethod == null || !calledMethod.IsStatic) + continue; if (!DotNetUtils.isMethod(calledMethod, "System.Void", "()")) continue; + var type = calledMethod.DeclaringType; + if (type.NestedTypes.Count > 0) + continue; simpleDeobfuscator.deobfuscate(calledMethod, true); - if (checkInitMethod_v14_r58852(calledMethod) || checkInitMethod_v14_r58564(calledMethod)) { + if (checkType(type, calledMethod)) { initMethod = calledMethod; return true; } @@ -69,54 +87,159 @@ namespace de4dot.code.deobfuscators.Confuser { return false; } - static bool checkInitMethod_v14_r58564(MethodDefinition method) { - if (method == null || method.Body == null || !method.IsStatic) + bool checkType(TypeDefinition type, MethodDefinition initMethod) { + return checkType_v14_r58564(type, initMethod) || + checkType_v14_r58852(type, initMethod); + } + + bool checkType_v14_r58564(TypeDefinition type, MethodDefinition initMethod) { + var virtualProtect = DotNetUtils.getPInvokeMethod(type, "VirtualProtect"); + if (virtualProtect == null) return false; - if (!DotNetUtils.isMethod(method, "System.Void", "()")) + if (!DotNetUtils.callsMethod(initMethod, "System.IntPtr System.Runtime.InteropServices.Marshal::GetHINSTANCE(System.Reflection.Module)")) return false; - if (DotNetUtils.getPInvokeMethod(method.DeclaringType, "kernel32", "VirtualProtect") == null) + if (ConfuserUtils.countCalls(initMethod, virtualProtect) != 3) return false; - if (!DeobUtils.hasInteger(method, 224)) + if (!DeobUtils.hasInteger(initMethod, 224)) return false; - if (!DeobUtils.hasInteger(method, 240)) + if (!DeobUtils.hasInteger(initMethod, 240)) return false; - if (!DeobUtils.hasInteger(method, 267)) + if (!DeobUtils.hasInteger(initMethod, 267)) return false; - var type = method.DeclaringType; - if (type.Methods.Count != 2) + + version = ConfuserVersion.v14_r58564; + return true; + } + + bool checkType_v14_r58852(TypeDefinition type, MethodDefinition initMethod) { + var virtualProtect = DotNetUtils.getPInvokeMethod(type, "VirtualProtect"); + if (virtualProtect == null) return false; - if (type.Fields.Count != 0) + if (!DotNetUtils.callsMethod(initMethod, "System.IntPtr System.Runtime.InteropServices.Marshal::GetHINSTANCE(System.Reflection.Module)")) return false; - if (type.Properties.Count != 0) + int virtualProtectCalls = ConfuserUtils.countCalls(initMethod, virtualProtect); + if (virtualProtectCalls != 14 && virtualProtectCalls != 16) + return false; + if (!DeobUtils.hasInteger(initMethod, 0x3C)) + return false; + if (!DeobUtils.hasInteger(initMethod, 0x6c64746e)) + return false; + if (!DeobUtils.hasInteger(initMethod, 0x6c642e6c)) + return false; + if (!DeobUtils.hasInteger(initMethod, 0x6f43744e)) + return false; + if (!DeobUtils.hasInteger(initMethod, 0x6e69746e)) + return false; + int locallocs = ConfuserUtils.countOpCode(initMethod, Code.Localloc); + + if (DeobUtils.hasInteger(initMethod, 0x18)) + version = ConfuserVersion.v14_r58852; + else if (virtualProtectCalls == 16) + version = ConfuserVersion.v16_r69339; + else if (virtualProtectCalls == 14) { + if (locallocs == 2) + version = ConfuserVersion.v17_r74708; + else if (locallocs == 1) { + if (DotNetUtils.hasString(initMethod, "")) + version = ConfuserVersion.v18_r75257; + else if (isRev75725(initMethod)) + version = ConfuserVersion.v19_r75725; + else + version = ConfuserVersion.v19_r76186; + } + else + return false; + } + else return false; return true; } - static bool checkInitMethod_v14_r58852(MethodDefinition method) { - if (method == null || method.Body == null || !method.IsStatic) - return false; - if (!DotNetUtils.isMethod(method, "System.Void", "()")) - return false; - if (!DeobUtils.hasInteger(method, 0x3C)) - return false; - if (!DeobUtils.hasInteger(method, 0x6c64746e)) - return false; - if (!DeobUtils.hasInteger(method, 0x6c642e6c)) - return false; - if (!DeobUtils.hasInteger(method, 0x6f43744e)) - return false; - if (!DeobUtils.hasInteger(method, 0x6e69746e)) - return false; - if (DotNetUtils.getPInvokeMethod(method.DeclaringType, "kernel32", "VirtualProtect") == null) - return false; + static bool isRev75725(MethodDefinition method) { + var instrs = method.Body.Instructions; + for (int i = 0; i < instrs.Count - 9; i++) { + if (!DotNetUtils.isLdcI4(instrs[i]) || DotNetUtils.getLdcI4Value(instrs[i]) != 8) + continue; + if (!DotNetUtils.isLdcI4(instrs[i + 1]) || DotNetUtils.getLdcI4Value(instrs[i + 1]) != 64) + continue; + if (instrs[i + 2].OpCode.Code != Code.Ldloca && instrs[i + 2].OpCode.Code != Code.Ldloca_S) + continue; + var call = instrs[i + 3]; + if (call.OpCode.Code != Code.Call) + continue; + var calledMethod = call.Operand as MethodDefinition; + if (calledMethod == null || calledMethod.PInvokeInfo == null || calledMethod.PInvokeInfo.EntryPoint != "VirtualProtect") + continue; + if (instrs[i + 4].OpCode.Code != Code.Pop) + continue; - return true; + var ldloc = instrs[i + 5]; + if (!DotNetUtils.isLdloc(ldloc)) + continue; + var local = DotNetUtils.getLocalVar(method.Body.Variables, ldloc); + if (local == null) + continue; + + if (!DotNetUtils.isLdcI4(instrs[i + 6]) || DotNetUtils.getLdcI4Value(instrs[i + 6]) != 0) + continue; + if (instrs[i + 7].OpCode.Code != Code.Stind_I4) + continue; + + ldloc = instrs[i + 8]; + if (!DotNetUtils.isLdloc(ldloc) || local != DotNetUtils.getLocalVar(method.Body.Variables, ldloc)) + continue; + if (!DotNetUtils.isLdcI4(instrs[i + 9]) || DotNetUtils.getLdcI4Value(instrs[i + 9]) != 4) + continue; + + return true; + } + return false; } public bool getRevisionRange(out int minRev, out int maxRev) { - minRev = maxRev = 0; - return false; + switch (version) { + case ConfuserVersion.Unknown: + minRev = maxRev = 0; + return false; + + case ConfuserVersion.v14_r58564: + minRev = 58564; + maxRev = 58817; + return true; + + case ConfuserVersion.v14_r58852: + minRev = 58852; + maxRev = 67058; + return true; + + case ConfuserVersion.v16_r69339: + minRev = 69339; + maxRev = 74637; + return true; + + case ConfuserVersion.v17_r74708: + minRev = 74708; + maxRev = 75184; + return true; + + case ConfuserVersion.v18_r75257: + minRev = 75257; + maxRev = 75720; + return true; + + case ConfuserVersion.v19_r75725: + minRev = 75725; + maxRev = 76163; + return true; + + case ConfuserVersion.v19_r76186: + minRev = 76186; + maxRev = int.MaxValue; + return true; + + default: throw new ApplicationException("Invalid version"); + } } } }