From 6bfb3bc4a70fde2941581d7bc4b15a3ea5096845 Mon Sep 17 00:00:00 2001 From: xode0 Date: Sat, 6 Feb 2016 18:35:17 +0100 Subject: [PATCH] Add resource name decryption . Update Crypto StringDecrypter and move DecryptResourceName from ConstantsDecrypter to CoUtils. Follow de4dot coding style. Tabify the last commits. --- .../deobfuscators/CryptoObfuscator/CoUtils.cs | 70 +++++++++++++++++++ .../CryptoObfuscator/ConstantsDecrypter.cs | 10 ++- .../CryptoObfuscator/StringDecrypter.cs | 7 ++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/CoUtils.cs b/de4dot.code/deobfuscators/CryptoObfuscator/CoUtils.cs index 4dfa782b..3885f2d3 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/CoUtils.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/CoUtils.cs @@ -22,6 +22,7 @@ using System.Collections.Generic; using System.Text; using dnlib.DotNet; using de4dot.blocks; +using dnlib.DotNet.Emit; namespace de4dot.code.deobfuscators.CryptoObfuscator { static class CoUtils { @@ -46,5 +47,74 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { } return null; } + + public static string XorCipher(string text, int key) { + char[] array = text.ToCharArray(); + int num = array.Length; + char cKey = Convert.ToChar(key); + while (--num >= 0) { + array[num] ^= cKey; + } + return new string(array); + } + + public static string DecryptResourceName(string resourceName, int key, byte[] coddedBytes) { + int num = resourceName.Length; + char[] array = resourceName.ToCharArray(); + while (--num >= 0) { + array[num] = (char)((int)array[num] ^ ((int)coddedBytes[key & 15] | key)); + } + return new string(array); + } + + public static string DecryptResourceName(ModuleDefMD module ,MethodDef method) { + string resourceName = ""; + MethodDef cctor = method, orginalResMethod = null; + //retrive key and encrypted resource name + int key = 0; + var ils = cctor.Body.Instructions; + for (int i = 0; i < ils.Count - 2; i++) { + if (ils[i].OpCode != OpCodes.Ldstr) + continue; + if (!ils[i + 1].IsLdcI4()) + break; + key = ils[i + 1].GetLdcI4Value(); + resourceName = ils[i].Operand as String; + cctor = ils[i + 2].Operand as MethodDef; + break; + } + + //Find the method that contains resource name + while (orginalResMethod == null) { + foreach (var IL in cctor.Body.Instructions) { + if (IL.OpCode == OpCodes.Ldftn) { + MethodDef tempMethod = IL.Operand as MethodDef; + if (tempMethod.ReturnType.FullName != "System.String") + continue; + orginalResMethod = tempMethod; + break; + } else if (IL.OpCode == OpCodes.Callvirt) { + cctor = IL.Operand as MethodDef; + cctor = cctor.DeclaringType.FindStaticConstructor(); + break; + } + } + } + + //Get encrypted Resource name + string encResourcename = DotNetUtils.GetCodeStrings(orginalResMethod)[0]; + //get Decryption key + int xorKey = 0; + for (int i = 0; i < orginalResMethod.Body.Instructions.Count; i++) { + if (orginalResMethod.Body.Instructions[i].OpCode == OpCodes.Xor) { + xorKey = orginalResMethod.Body.Instructions[i - 1].GetLdcI4Value(); + } + } + + encResourcename = XorCipher(encResourcename, xorKey); + var firstResource = GetResource(module, new string[] { encResourcename }); + resourceName = DecryptResourceName(resourceName, key, firstResource.GetResourceData()); + return resourceName; + } } } diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/ConstantsDecrypter.cs b/de4dot.code/deobfuscators/CryptoObfuscator/ConstantsDecrypter.cs index 92103a07..fa8098c0 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/ConstantsDecrypter.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/ConstantsDecrypter.cs @@ -113,7 +113,15 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { if (decrypterType == null) return; - encryptedResource = CoUtils.GetResource(module, DotNetUtils.GetCodeStrings(decrypterType.FindStaticConstructor())); + MethodDef cctor = decrypterType.FindStaticConstructor(); + encryptedResource = CoUtils.GetResource(module, DotNetUtils.GetCodeStrings(cctor)); + + //if the return value is null, it is possible that resource name is encrypted + if (encryptedResource == null) { + var Resources = new string[] { CoUtils.DecryptResourceName(module,cctor) }; + encryptedResource = CoUtils.GetResource(module, Resources); + } + encryptedResource.Data.Position = 0; constantsData = resourceDecrypter.Decrypt(encryptedResource.Data.CreateStream()); } diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/StringDecrypter.cs b/de4dot.code/deobfuscators/CryptoObfuscator/StringDecrypter.cs index 691f141c..faf7d52a 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/StringDecrypter.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/StringDecrypter.cs @@ -21,6 +21,7 @@ using System; using System.Text; using dnlib.DotNet; using de4dot.blocks; +using dnlib.DotNet.Emit; namespace de4dot.code.deobfuscators.CryptoObfuscator { class StringDecrypter { @@ -87,6 +88,12 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { return Encoding.UTF8.GetString(Convert.FromBase64String(s)); } catch { + string s2 = CoUtils.DecryptResourceName(module, cctor); + try { + return Encoding.UTF8.GetString(Convert.FromBase64String(s2)); + } + catch { + } } }