From 3e49c0bfa5b17c5c88c7650d33cfe5e206e60a91 Mon Sep 17 00:00:00 2001 From: de4dot Date: Tue, 31 Jul 2012 19:56:10 +0200 Subject: [PATCH] Support Confuser 1.4 r58564 compressor --- .../deobfuscators/Confuser/Deobfuscator.cs | 25 +++++----- .../Confuser/JitMethodsDecrypter.cs | 4 +- .../Confuser/MemoryMethodsDecrypter.cs | 4 +- .../Confuser/MethodsDecrypterBase.cs | 3 +- .../deobfuscators/Confuser/Unpacker.cs | 50 +++++++++++++++++-- 5 files changed, 65 insertions(+), 21 deletions(-) diff --git a/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs b/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs index fd6d44de..7df0810d 100644 --- a/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs @@ -195,23 +195,23 @@ namespace de4dot.code.deobfuscators.Confuser { var peImage = new PeImage(fileData); if ((decryptState & DecryptState.CanDecryptMethods) != 0) { + bool decrypted = false; if (jitMethodsDecrypter != null && jitMethodsDecrypter.Detected) { jitMethodsDecrypter.initialize(); if (!jitMethodsDecrypter.decrypt(peImage, fileData, ref dumpedMethods)) return false; - - decryptState &= ~DecryptState.CanDecryptMethods; - newFileData = fileData; - ModuleBytes = newFileData; - return true; + decrypted = true; } - - if (memoryMethodsDecrypter != null && memoryMethodsDecrypter.Detected) { + else if (memoryMethodsDecrypter != null && memoryMethodsDecrypter.Detected) { memoryMethodsDecrypter.initialize(); if (!memoryMethodsDecrypter.decrypt(peImage, fileData, ref dumpedMethods)) return false; + decrypted = true; + } + if (decrypted) { decryptState &= ~DecryptState.CanDecryptMethods; + decryptState |= DecryptState.CanUnpack; newFileData = fileData; ModuleBytes = newFileData; return true; @@ -220,8 +220,7 @@ namespace de4dot.code.deobfuscators.Confuser { if ((decryptState & DecryptState.CanUnpack) != 0) { if (unpacker != null && unpacker.Detected) { - decryptState &= ~DecryptState.CanUnpack; - decryptState |= DecryptState.CanDecryptMethods; + decryptState |= DecryptState.CanDecryptMethods | DecryptState.CanUnpack; newFileData = unpacker.unpack(); ModuleBytes = newFileData; return true; @@ -238,8 +237,8 @@ namespace de4dot.code.deobfuscators.Confuser { newOne.DeobfuscatedFile = DeobfuscatedFile; newOne.ModuleBytes = ModuleBytes; newOne.setModule(module); - newOne.jitMethodsDecrypter = new JitMethodsDecrypter(module, jitMethodsDecrypter); - if ((decryptState & DecryptState.CanDecryptMethods) != 0) { + newOne.jitMethodsDecrypter = new JitMethodsDecrypter(module, DeobfuscatedFile, jitMethodsDecrypter); + if ((newOne.decryptState & DecryptState.CanDecryptMethods) != 0) { try { newOne.jitMethodsDecrypter.find(); } @@ -248,8 +247,8 @@ namespace de4dot.code.deobfuscators.Confuser { if (newOne.jitMethodsDecrypter.Detected) return newOne; } - newOne.memoryMethodsDecrypter = new MemoryMethodsDecrypter(module, memoryMethodsDecrypter); - if ((decryptState & DecryptState.CanDecryptMethods) != 0) { + newOne.memoryMethodsDecrypter = new MemoryMethodsDecrypter(module, DeobfuscatedFile, memoryMethodsDecrypter); + if ((newOne.decryptState & DecryptState.CanDecryptMethods) != 0) { newOne.memoryMethodsDecrypter.find(); if (newOne.memoryMethodsDecrypter.Detected) return newOne; diff --git a/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs b/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs index e6b01620..0164f914 100644 --- a/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs +++ b/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs @@ -46,8 +46,8 @@ namespace de4dot.code.deobfuscators.Confuser { : base(module, simpleDeobfuscator) { } - public JitMethodsDecrypter(ModuleDefinition module, JitMethodsDecrypter other) - : base(module, other) { + public JitMethodsDecrypter(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator, JitMethodsDecrypter other) + : base(module, simpleDeobfuscator, other) { } protected override bool checkType(TypeDefinition type, MethodDefinition initMethod) { diff --git a/de4dot.code/deobfuscators/Confuser/MemoryMethodsDecrypter.cs b/de4dot.code/deobfuscators/Confuser/MemoryMethodsDecrypter.cs index 60f01ec8..1e94c0da 100644 --- a/de4dot.code/deobfuscators/Confuser/MemoryMethodsDecrypter.cs +++ b/de4dot.code/deobfuscators/Confuser/MemoryMethodsDecrypter.cs @@ -41,8 +41,8 @@ namespace de4dot.code.deobfuscators.Confuser { : base(module, simpleDeobfuscator) { } - public MemoryMethodsDecrypter(ModuleDefinition module, MemoryMethodsDecrypter other) - : base(module, other) { + public MemoryMethodsDecrypter(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator, MemoryMethodsDecrypter other) + : base(module, simpleDeobfuscator, other) { } protected override bool checkType(TypeDefinition type, MethodDefinition initMethod) { diff --git a/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs b/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs index 957d91fa..ef5b7939 100644 --- a/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs +++ b/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs @@ -53,8 +53,9 @@ namespace de4dot.code.deobfuscators.Confuser { this.simpleDeobfuscator = simpleDeobfuscator; } - protected MethodsDecrypterBase(ModuleDefinition module, MethodsDecrypterBase other) { + protected MethodsDecrypterBase(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator, MethodsDecrypterBase other) { this.module = module; + this.simpleDeobfuscator = simpleDeobfuscator; if (other != null) this.initMethod = lookup(other.initMethod, "Could not find initMethod"); } diff --git a/de4dot.code/deobfuscators/Confuser/Unpacker.cs b/de4dot.code/deobfuscators/Confuser/Unpacker.cs index 66d1b265..9569e390 100644 --- a/de4dot.code/deobfuscators/Confuser/Unpacker.cs +++ b/de4dot.code/deobfuscators/Confuser/Unpacker.cs @@ -17,6 +17,8 @@ along with de4dot. If not, see . */ +using System; +using System.IO; using Mono.Cecil; using Mono.Cecil.Cil; using de4dot.blocks; @@ -25,6 +27,14 @@ namespace de4dot.code.deobfuscators.Confuser { class Unpacker { ModuleDefinition module; EmbeddedResource resource; + uint key; + ConfuserVersion version = ConfuserVersion.Unknown; + + enum ConfuserVersion { + Unknown, + v10_r42915, + v14_r58564, + } public bool Detected { get { return resource != null; } @@ -52,19 +62,48 @@ namespace de4dot.code.deobfuscators.Confuser { var type = entryPoint.DeclaringType; if (!new FieldTypes(type).all(requiredFields)) return; - if (findDecryptMethod(type) == null) + var decyptMethod = findDecryptMethod(type); + if (decyptMethod == null) return; + if (new LocalTypes(decyptMethod).exists("System.IO.MemoryStream")) + version = ConfuserVersion.v10_r42915; + else + version = ConfuserVersion.v14_r58564; var cctor = DotNetUtils.getMethod(type, ".cctor"); if (cctor == null) return; + if (version == ConfuserVersion.v14_r58564) { + simpleDeobfuscator.deobfuscate(decyptMethod); + if (!findKey(decyptMethod, out key)) + throw new ApplicationException("Could not find magic"); + } + simpleDeobfuscator.deobfuscate(cctor); simpleDeobfuscator.decryptStrings(cctor, deob); resource = findResource(cctor); } + static bool findKey(MethodDefinition method, out uint key) { + var instrs = method.Body.Instructions; + for (int i = 0; i < instrs.Count - 2; i++) { + if (instrs[i].OpCode.Code != Code.Xor) + continue; + var ldci4 = instrs[i + 1]; + if (!DotNetUtils.isLdcI4(ldci4)) + continue; + if (instrs[i + 2].OpCode.Code != Code.Xor) + continue; + + key = (uint)DotNetUtils.getLdcI4Value(ldci4); + return true; + } + key = 0; + return false; + } + EmbeddedResource findResource(MethodDefinition method) { return DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(method)) as EmbeddedResource; } @@ -72,7 +111,6 @@ namespace de4dot.code.deobfuscators.Confuser { static string[] requiredDecryptLocals = new string[] { "System.Byte[]", "System.IO.Compression.DeflateStream", - "System.IO.MemoryStream", }; static MethodDefinition findDecryptMethod(TypeDefinition type) { foreach (var method in type.Methods) { @@ -93,8 +131,14 @@ namespace de4dot.code.deobfuscators.Confuser { return null; var data = resource.GetResourceData(); for (int i = 0; i < data.Length; i++) - data[i] ^= (byte)i; + data[i] ^= (byte)(i ^ key); data = DeobUtils.inflate(data, true); + + if (version == ConfuserVersion.v14_r58564) { + var reader = new BinaryReader(new MemoryStream(data)); + data = reader.ReadBytes(reader.ReadInt32()); + } + return data; } }