From a3dbf5273d0798b786db88b3052dab6f0e107013 Mon Sep 17 00:00:00 2001 From: de4dot Date: Sun, 5 Aug 2012 02:07:43 +0200 Subject: [PATCH] Support Confuser 1.7 r73822 constants encrypter --- .../Confuser/ConstantsDecrypterV15.cs | 137 +++++++++++++++--- .../deobfuscators/Confuser/Deobfuscator.cs | 1 + 2 files changed, 121 insertions(+), 17 deletions(-) diff --git a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV15.cs b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV15.cs index f4e99818..69324ece 100644 --- a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV15.cs +++ b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV15.cs @@ -31,6 +31,7 @@ namespace de4dot.code.deobfuscators.Confuser { ModuleDefinition module; byte[] fileData; ISimpleDeobfuscator simpleDeobfuscator; + FieldDefinition dictField, streamField; MethodDefinition decryptMethod; MethodDefinition nativeMethod; EmbeddedResource resource; @@ -47,6 +48,9 @@ namespace de4dot.code.deobfuscators.Confuser { v17_r73740_dynamic, v17_r73764_dynamic, v17_r73764_native, + v17_r73822_normal, + v17_r73822_dynamic, + v17_r73822_native, } public MethodDefinition Method { @@ -57,6 +61,15 @@ namespace de4dot.code.deobfuscators.Confuser { get { return nativeMethod; } } + public IEnumerable Fields { + get { + return new List { + streamField, + dictField, + }; + } + } + public EmbeddedResource Resource { get { return resource; } } @@ -71,7 +84,7 @@ namespace de4dot.code.deobfuscators.Confuser { this.simpleDeobfuscator = simpleDeobfuscator; } - static readonly string[] requiredLocals = new string[] { + static readonly string[] requiredLocals1 = new string[] { "System.Byte[]", "System.Collections.Generic.Dictionary`2", "System.IO.BinaryReader", @@ -79,6 +92,12 @@ namespace de4dot.code.deobfuscators.Confuser { "System.IO.MemoryStream", "System.Reflection.Assembly", }; + static readonly string[] requiredLocals2 = new string[] { + "System.Byte[]", + "System.IO.BinaryReader", + "System.IO.Compression.DeflateStream", + "System.Reflection.Assembly", + }; public void find() { var type = DotNetUtils.getModuleType(module); if (type == null) @@ -88,26 +107,39 @@ namespace de4dot.code.deobfuscators.Confuser { continue; if (!DotNetUtils.isMethod(method, "System.Object", "(System.UInt32)")) continue; + var localTypes = new LocalTypes(method); - if (!localTypes.all(requiredLocals)) - continue; - if (localTypes.exists("System.Collections.BitArray")) // or System.Random - version = ConfuserVersion.v15_r60785_normal; - else if (DeobUtils.hasInteger(method, 0x100) && + if (localTypes.all(requiredLocals1)) { + if (localTypes.exists("System.Collections.BitArray")) // or System.Random + version = ConfuserVersion.v15_r60785_normal; + else if (DeobUtils.hasInteger(method, 0x100) && + DeobUtils.hasInteger(method, 0x10000) && + DeobUtils.hasInteger(method, 0xFFFF)) + version = ConfuserVersion.v17_r73404_normal; + else if (DotNetUtils.callsMethod(method, "System.String System.Text.Encoding::GetString(System.Byte[])")) { + if (findInstruction(method.Body.Instructions, 0, Code.Conv_I8) >= 0) + version = ConfuserVersion.v15_r60785_dynamic; + else + version = ConfuserVersion.v17_r73740_dynamic; + } + else if (DotNetUtils.callsMethod(method, "System.String System.Text.Encoding::GetString(System.Byte[],System.Int32,System.Int32)")) { + if ((nativeMethod = findNativeMethod(method)) == null) + version = ConfuserVersion.v17_r73764_dynamic; + else + version = ConfuserVersion.v17_r73764_native; + } + else + continue; + } + else if (localTypes.all(requiredLocals2)) { + if (DeobUtils.hasInteger(method, 0x100) && DeobUtils.hasInteger(method, 0x10000) && DeobUtils.hasInteger(method, 0xFFFF)) - version = ConfuserVersion.v17_r73404_normal; - else if (DotNetUtils.callsMethod(method, "System.String System.Text.Encoding::GetString(System.Byte[])")) { - if (findInstruction(method.Body.Instructions, 0, Code.Conv_I8) >= 0) - version = ConfuserVersion.v15_r60785_dynamic; + version = ConfuserVersion.v17_r73822_normal; + else if ((nativeMethod = findNativeMethod(method)) == null) + version = ConfuserVersion.v17_r73822_dynamic; else - version = ConfuserVersion.v17_r73740_dynamic; - } - else if (DotNetUtils.callsMethod(method, "System.String System.Text.Encoding::GetString(System.Byte[],System.Int32,System.Int32)")) { - if ((nativeMethod = findNativeMethod(method)) == null) - version = ConfuserVersion.v17_r73764_dynamic; - else - version = ConfuserVersion.v17_r73764_native; + version = ConfuserVersion.v17_r73822_native; } else continue; @@ -143,11 +175,79 @@ namespace de4dot.code.deobfuscators.Confuser { throw new ApplicationException("Could not find all keys"); if (!initializeTypeCodes()) throw new ApplicationException("Could not find all type codes"); + if (!initializeFields()) + throw new ApplicationException("Could not find all fields"); var constants = DeobUtils.inflate(resource.GetResourceData(), true); reader = new BinaryReader(new MemoryStream(constants)); } + bool initializeFields() { + switch (version) { + case ConfuserVersion.v17_r73822_normal: + case ConfuserVersion.v17_r73822_dynamic: + case ConfuserVersion.v17_r73822_native: + if ((dictField = findDictField(decryptMethod, decryptMethod.DeclaringType)) == null) + return false; + if ((streamField = findStreamField(decryptMethod, decryptMethod.DeclaringType)) == null) + return false; + break; + + default: + break; + } + + return true; + } + + static FieldDefinition findDictField(MethodDefinition method, TypeDefinition declaringType) { + var instrs = method.Body.Instructions; + for (int i = 0; i < instrs.Count - 1; i++) { + var newobj = instrs[i]; + if (newobj.OpCode.Code != Code.Newobj) + continue; + var ctor = newobj.Operand as MethodReference; + if (ctor == null || ctor.FullName != "System.Void System.Collections.Generic.Dictionary`2::.ctor()") + continue; + + var stsfld = instrs[i + 1]; + if (stsfld.OpCode.Code != Code.Stsfld) + continue; + var field = stsfld.Operand as FieldDefinition; + if (field == null || field.DeclaringType != declaringType) + continue; + if (field.FieldType.FullName != "System.Collections.Generic.Dictionary`2") + continue; + + return field; + } + return null; + } + + static FieldDefinition findStreamField(MethodDefinition method, TypeDefinition declaringType) { + var instrs = method.Body.Instructions; + for (int i = 0; i < instrs.Count - 1; i++) { + var newobj = instrs[i]; + if (newobj.OpCode.Code != Code.Newobj) + continue; + var ctor = newobj.Operand as MethodReference; + if (ctor == null || ctor.FullName != "System.Void System.IO.MemoryStream::.ctor()") + continue; + + var stsfld = instrs[i + 1]; + if (stsfld.OpCode.Code != Code.Stsfld) + continue; + var field = stsfld.Operand as FieldDefinition; + if (field == null || field.DeclaringType != declaringType) + continue; + if (field.FieldType.FullName != "System.IO.MemoryStream") + continue; + + return field; + } + return null; + } + bool initializeKeys() { if (!findKey0(decryptMethod, out key0)) return false; @@ -370,6 +470,9 @@ namespace de4dot.code.deobfuscators.Confuser { case ConfuserVersion.v17_r73740_dynamic: return decryptConstant_v17_r73740_dynamic(encrypted, offs); case ConfuserVersion.v17_r73764_dynamic: return decryptConstant_v17_r73740_dynamic(encrypted, offs); case ConfuserVersion.v17_r73764_native: return decryptConstant_v17_r73764_native(encrypted, offs); + case ConfuserVersion.v17_r73822_normal: return decryptConstant_v17_r73404_normal(encrypted, offs); + case ConfuserVersion.v17_r73822_dynamic: return decryptConstant_v17_r73740_dynamic(encrypted, offs); + case ConfuserVersion.v17_r73822_native: return decryptConstant_v17_r73764_native(encrypted, offs); default: throw new ApplicationException("Invalid version"); } } diff --git a/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs b/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs index 07af376b..6a628543 100644 --- a/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs @@ -443,6 +443,7 @@ namespace de4dot.code.deobfuscators.Confuser { singleValueInliner.RemoveUnbox = true; doubleValueInliner.RemoveUnbox = true; DeobfuscatedFile.stringDecryptersAdded(); + addFieldsToBeRemoved(constantsDecrypterV15.Fields, "Constants decrypter field"); addMethodToBeRemoved(constantsDecrypterV15.Method, "Constants decrypter method"); addMethodToBeRemoved(constantsDecrypterV15.NativeMethod, "Constants decrypter native method"); addResourceToBeRemoved(constantsDecrypterV15.Resource, "Encrypted constants");