diff --git a/AssemblyData/Properties/AssemblyInfo.cs b/AssemblyData/Properties/AssemblyInfo.cs index 99a902f6..78293473 100644 --- a/AssemblyData/Properties/AssemblyInfo.cs +++ b/AssemblyData/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")] diff --git a/AssemblyServer-x64/Properties/AssemblyInfo.cs b/AssemblyServer-x64/Properties/AssemblyInfo.cs index 9cb5bb5b..c4330fb8 100644 --- a/AssemblyServer-x64/Properties/AssemblyInfo.cs +++ b/AssemblyServer-x64/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")] diff --git a/AssemblyServer/Properties/AssemblyInfo.cs b/AssemblyServer/Properties/AssemblyInfo.cs index 2795ab9f..815629e1 100644 --- a/AssemblyServer/Properties/AssemblyInfo.cs +++ b/AssemblyServer/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")] diff --git a/Test.Rename.Dll/Properties/AssemblyInfo.cs b/Test.Rename.Dll/Properties/AssemblyInfo.cs index 9486df2f..d3e69b3b 100644 --- a/Test.Rename.Dll/Properties/AssemblyInfo.cs +++ b/Test.Rename.Dll/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")] diff --git a/Test.Rename/Properties/AssemblyInfo.cs b/Test.Rename/Properties/AssemblyInfo.cs index 8df4d981..85be43f6 100644 --- a/Test.Rename/Properties/AssemblyInfo.cs +++ b/Test.Rename/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")] diff --git a/blocks/Properties/AssemblyInfo.cs b/blocks/Properties/AssemblyInfo.cs index d748da5e..81934537 100644 --- a/blocks/Properties/AssemblyInfo.cs +++ b/blocks/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")] diff --git a/cecil b/cecil index c8f4f6bc..86e21d47 160000 --- a/cecil +++ b/cecil @@ -1 +1 @@ -Subproject commit c8f4f6bcaaa45804631a805c3840517888dcb0bd +Subproject commit 86e21d470a0232f6b746ee2b8b7a9483c1842fea diff --git a/de4dot-x64/Properties/AssemblyInfo.cs b/de4dot-x64/Properties/AssemblyInfo.cs index f1c5a35f..5a109bcc 100644 --- a/de4dot-x64/Properties/AssemblyInfo.cs +++ b/de4dot-x64/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")] diff --git a/de4dot.code/Properties/AssemblyInfo.cs b/de4dot.code/Properties/AssemblyInfo.cs index 244d1c0e..fbdb9ad5 100644 --- a/de4dot.code/Properties/AssemblyInfo.cs +++ b/de4dot.code/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")] diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index c601dd14..d373674f 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -96,6 +96,9 @@ + + + diff --git a/de4dot.code/deobfuscators/Babel_NET/MethodReferenceReader.cs b/de4dot.code/deobfuscators/Babel_NET/MethodReferenceReader.cs index e1f1b33a..5988c41d 100644 --- a/de4dot.code/deobfuscators/Babel_NET/MethodReferenceReader.cs +++ b/de4dot.code/deobfuscators/Babel_NET/MethodReferenceReader.cs @@ -60,9 +60,9 @@ namespace de4dot.code.deobfuscators.Babel_NET { public int Flags2 { get; set; } public short MaxStack { get; set; } - public List Locals { get; set; } - public Instruction[] Instructions { get; set; } - public ExceptionHandler[] ExceptionHandlers { get; set; } + public IList Locals { get; set; } + public IList Instructions { get; set; } + public IList ExceptionHandlers { get; set; } public bool IsStatic { get { return (Flags2 & 0x10) != 0; } diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/AntiDebugger.cs b/de4dot.code/deobfuscators/CryptoObfuscator/AntiDebugger.cs index 1f9cf645..1704aa20 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/AntiDebugger.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/AntiDebugger.cs @@ -65,7 +65,9 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { if (!containsString(method, "debugger is activ") && !containsString(method, "debugger is running") && !containsString(method, "run under a debugger") && - !containsString(method, "Debugger detected")) + !containsString(method, "run under debugger") && + !containsString(method, "Debugger detected") && + !containsString(method, "Debugger was detected")) continue; antiDebuggerType = type; diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/AssemblyResolver.cs b/de4dot.code/deobfuscators/CryptoObfuscator/AssemblyResolver.cs index 1cad1e19..1dcfc324 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/AssemblyResolver.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/AssemblyResolver.cs @@ -46,6 +46,10 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { } } + public bool Detected { + get { return resolverType != null; } + } + public List AssemblyInfos { get { return assemblyInfos; } } diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/CoUtils.cs b/de4dot.code/deobfuscators/CryptoObfuscator/CoUtils.cs new file mode 100644 index 00000000..d3f37981 --- /dev/null +++ b/de4dot.code/deobfuscators/CryptoObfuscator/CoUtils.cs @@ -0,0 +1,50 @@ +/* + Copyright (C) 2011-2012 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using Mono.Cecil; +using de4dot.blocks; + +namespace de4dot.code.deobfuscators.CryptoObfuscator { + static class CoUtils { + public static EmbeddedResource getResource(ModuleDefinition module, MethodDefinition method) { + if (method == null || method.Body == null) + return null; + return getResource(module, DotNetUtils.getCodeStrings(method)); + } + + public static EmbeddedResource getResource(ModuleDefinition module, IEnumerable names) { + foreach (var name in names) { + var resource = DotNetUtils.getResource(module, name) as EmbeddedResource; + if (resource != null) + return resource; + try { + resource = DotNetUtils.getResource(module, Encoding.UTF8.GetString(Convert.FromBase64String(name))) as EmbeddedResource; + if (resource != null) + return resource; + } + catch { + } + } + return null; + } + } +} diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/ConstantsDecrypter.cs b/de4dot.code/deobfuscators/CryptoObfuscator/ConstantsDecrypter.cs index 6b3940a2..2240e431 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/ConstantsDecrypter.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/ConstantsDecrypter.cs @@ -82,7 +82,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { bool checkType(TypeDefinition type) { if (type.Methods.Count != 7) return false; - if (type.Fields.Count != 1) + if (type.Fields.Count < 1 || type.Fields.Count > 2) return false; if (!new FieldTypes(type).all(requiredTypes)) return false; @@ -106,26 +106,10 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { if (decrypterType == null) return; - encryptedResource = getResource(module, DotNetUtils.getCodeStrings(DotNetUtils.getMethod(decrypterType, ".cctor"))); + encryptedResource = CoUtils.getResource(module, DotNetUtils.getCodeStrings(DotNetUtils.getMethod(decrypterType, ".cctor"))); constantsData = resourceDecrypter.decrypt(encryptedResource.GetResourceStream()); } - static EmbeddedResource getResource(ModuleDefinition module, IEnumerable names) { - foreach (var name in names) { - var resource = DotNetUtils.getResource(module, name) as EmbeddedResource; - if (resource != null) - return resource; - try { - resource = DotNetUtils.getResource(module, Encoding.UTF8.GetString(Convert.FromBase64String(name))) as EmbeddedResource; - if (resource != null) - return resource; - } - catch { - } - } - return null; - } - public int decryptInt32(int index) { return BitConverter.ToInt32(constantsData, index); } diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs b/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs index cdceaa12..6d440bad 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs @@ -68,6 +68,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { bool foundObfuscatedSymbols = false; bool foundObfuscatorUserString = false; + MethodsDecrypter methodsDecrypter; ProxyCallFixer proxyCallFixer; ResourceDecrypter resourceDecrypter; ResourceResolver resourceResolver; @@ -111,7 +112,8 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { protected override int detectInternal() { int val = 0; - int sum = toInt32(stringDecrypter.Detected) + + int sum = toInt32(methodsDecrypter.Detected) + + toInt32(stringDecrypter.Detected) + toInt32(tamperDetection.Detected) + toInt32(proxyCallFixer.Detected) + toInt32(constantsDecrypter.Detected); @@ -134,6 +136,8 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { if (checkCryptoObfuscator()) foundObfuscatedSymbols = true; + methodsDecrypter = new MethodsDecrypter(module); + methodsDecrypter.find(); proxyCallFixer = new ProxyCallFixer(module); proxyCallFixer.findDelegateCreator(); stringDecrypter = new StringDecrypter(module); @@ -190,6 +194,14 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { DeobfuscatedFile.stringDecryptersAdded(); } + methodsDecrypter.decrypt(resourceDecrypter); + + if (methodsDecrypter.Detected) { + if (!assemblyResolver.Detected) + assemblyResolver.find(); + if (!tamperDetection.Detected) + tamperDetection.find(); + } antiDebugger = new AntiDebugger(module, DeobfuscatedFile, this); antiDebugger.find(); @@ -217,6 +229,9 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { addTypeToBeRemoved(assemblyResolver.Type, "Assembly resolver type"); addTypeToBeRemoved(tamperDetection.Type, "Tamper detection type"); addTypeToBeRemoved(antiDebugger.Type, "Anti-debugger type"); + addTypeToBeRemoved(methodsDecrypter.Type, "Methods decrypter type"); + addTypesToBeRemoved(methodsDecrypter.DelegateTypes, "Methods decrypter delegate type"); + addResourceToBeRemoved(methodsDecrypter.Resource, "Encrypted methods"); proxyCallFixer.find(); diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/MethodBodyReader.cs b/de4dot.code/deobfuscators/CryptoObfuscator/MethodBodyReader.cs new file mode 100644 index 00000000..22860f01 --- /dev/null +++ b/de4dot.code/deobfuscators/CryptoObfuscator/MethodBodyReader.cs @@ -0,0 +1,123 @@ +/* + Copyright (C) 2011-2012 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using Mono.Cecil; +using Mono.Cecil.Cil; +using de4dot.blocks; + +namespace de4dot.code.deobfuscators.CryptoObfuscator { + class MethodBodyReader : MethodBodyReaderBase { + ModuleDefinition module; + ushort maxStackSize; + + public MethodBodyReader(ModuleDefinition module, BinaryReader reader) + : base(reader) { + this.module = module; + } + + public void read(MethodDefinition method) { + this.parameters = getParameters(method); + this.Locals = getLocals(method); + + maxStackSize = (ushort)reader.ReadInt32(); + readInstructionsNumBytes(reader.ReadUInt32()); + readExceptionHandlers(); + } + + void readExceptionHandlers() { + int totalSize = reader.ReadInt32(); + if (totalSize == 0) + return; + reader.ReadInt32(); + readExceptionHandlers((totalSize - 4) / 24); + } + + static IList getParameters(MethodReference method) { + return DotNetUtils.getParameters(method); + } + + static IList getLocals(MethodDefinition method) { + if (method.Body == null) + return new List(); + return new List(method.Body.Variables); + } + + protected override FieldReference readInlineField(Instruction instr) { + return (FieldReference)module.LookupToken(reader.ReadInt32()); + } + + protected override MethodReference readInlineMethod(Instruction instr) { + return (MethodReference)module.LookupToken(reader.ReadInt32()); + } + + protected override CallSite readInlineSig(Instruction instr) { + return module.ReadCallSite(new MetadataToken(reader.ReadUInt32())); + } + + protected override string readInlineString(Instruction instr) { + return module.GetUserString(reader.ReadUInt32()); + } + + protected override MemberReference readInlineTok(Instruction instr) { + return (MemberReference)module.LookupToken(reader.ReadInt32()); + } + + protected override TypeReference readInlineType(Instruction instr) { + return (TypeReference)module.LookupToken(reader.ReadInt32()); + } + + protected override ExceptionHandler readExceptionHandler() { + var eh = new ExceptionHandler((ExceptionHandlerType)reader.ReadInt32()); + + int tryOffset = reader.ReadInt32(); + eh.TryStart = getInstruction(tryOffset); + eh.TryEnd = getInstructionOrNull(tryOffset + reader.ReadInt32()); + + int handlerOffset = reader.ReadInt32(); + eh.HandlerStart = getInstruction(handlerOffset); + eh.HandlerEnd = getInstructionOrNull(handlerOffset + reader.ReadInt32()); + + switch (eh.HandlerType) { + case ExceptionHandlerType.Catch: + eh.CatchType = (TypeReference)module.LookupToken(reader.ReadInt32()); + break; + + case ExceptionHandlerType.Filter: + eh.FilterStart = getInstruction(reader.ReadInt32()); + break; + + case ExceptionHandlerType.Finally: + case ExceptionHandlerType.Fault: + default: + reader.ReadInt32(); + break; + } + + return eh; + } + + public override void restoreMethod(MethodDefinition method) { + base.restoreMethod(method); + method.Body.MaxStackSize = maxStackSize; + } + } +} diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/MethodsDecrypter.cs b/de4dot.code/deobfuscators/CryptoObfuscator/MethodsDecrypter.cs new file mode 100644 index 00000000..d55cd744 --- /dev/null +++ b/de4dot.code/deobfuscators/CryptoObfuscator/MethodsDecrypter.cs @@ -0,0 +1,205 @@ +/* + Copyright (C) 2011-2012 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using Mono.Cecil; +using Mono.Cecil.Cil; +using de4dot.blocks; + +namespace de4dot.code.deobfuscators.CryptoObfuscator { + class MethodsDecrypter { + ModuleDefinition module; + TypeDefinition decrypterType; + MethodDefinition decryptMethod; + MethodDefinition decrypterCctor; + EmbeddedResource resource; + List delegateTypes = new List(); + + public TypeDefinition Type { + get { return decrypterType; } + } + + public IEnumerable DelegateTypes { + get { return delegateTypes; } + } + + public EmbeddedResource Resource { + get { return resource; } + } + + public bool Detected { + get { return decrypterType != null; } + } + + public MethodsDecrypter(ModuleDefinition module) { + this.module = module; + } + + public void find() { + foreach (var type in module.Types) { + if (check(type)) + break; + } + } + + static readonly string[] requiredFields = new string[] { + "System.Byte[]", + "System.Collections.Generic.Dictionary`2", + "System.ModuleHandle", + }; + bool check(TypeDefinition type) { + if (type.NestedTypes.Count != 1) + return false; + if (type.Fields.Count != 3) + return false; + if (!new FieldTypes(type).all(requiredFields)) + return false; + + var cctor = DotNetUtils.getMethod(type, ".cctor"); + if (cctor == null) + return false; + var decryptMethodTmp = findDecryptMethod(type); + if (decryptMethodTmp == null) + return false; + + decryptMethod = decryptMethodTmp; + decrypterCctor = cctor; + decrypterType = type; + return true; + } + + static readonly string[] requiredLocals = new string[] { + "System.Delegate", + "System.ModuleHandle", + "System.Reflection.Emit.DynamicILInfo", + "System.Reflection.Emit.DynamicMethod", + "System.Reflection.FieldInfo", + "System.Reflection.FieldInfo[]", + "System.Reflection.MethodBase", + "System.Reflection.MethodBody", + "System.Type", + "System.Type[]", + }; + static MethodDefinition findDecryptMethod(TypeDefinition type) { + foreach (var method in type.Methods) { + if (!method.IsStatic || method.Body == null) + continue; + if (!new LocalTypes(method).all(requiredLocals)) + continue; + if (!DotNetUtils.isMethod(method, "System.Void", "(System.Int32,System.Int32,System.Int32)")) + continue; + + return method; + } + return null; + } + + public void decrypt(ResourceDecrypter resourceDecrypter) { + if (decryptMethod == null) + return; + + resource = CoUtils.getResource(module, decrypterCctor); + if (resource == null) + return; + var decrypted = resourceDecrypter.decrypt(resource.GetResourceStream()); + var reader = new BinaryReader(new MemoryStream(decrypted)); + int numEncrypted = reader.ReadInt32(); + Log.v("Restoring {0} encrypted methods", numEncrypted); + Log.indent(); + for (int i = 0; i < numEncrypted; i++) { + int delegateTypeToken = reader.ReadInt32(); + uint codeOffset = reader.ReadUInt32(); + var origOffset = reader.BaseStream.Position; + reader.BaseStream.Position = codeOffset; + decrypt(reader, delegateTypeToken); + reader.BaseStream.Position = origOffset; + } + Log.deIndent(); + } + + void decrypt(BinaryReader reader, int delegateTypeToken) { + var delegateType = module.LookupToken(delegateTypeToken) as TypeDefinition; + if (delegateType == null) + throw new ApplicationException("Couldn't find delegate type"); + + int delToken, encMethToken, encDeclToken; + if (!getTokens(delegateType, out delToken, out encMethToken, out encDeclToken)) + throw new ApplicationException("Could not find encrypted method tokens"); + if (delToken != delegateTypeToken) + throw new ApplicationException("Invalid delegate type token"); + var encType = module.LookupToken(encDeclToken) as TypeReference; + if (encType == null) + throw new ApplicationException("Invalid declaring type token"); + var encMethod = module.LookupToken(encMethToken) as MethodDefinition; + if (encMethod == null) + throw new ApplicationException("Invalid encrypted method token"); + + var bodyReader = new MethodBodyReader(module, reader); + bodyReader.read(encMethod); + bodyReader.restoreMethod(encMethod); + Log.v("Restored method {0} ({1:X8}). Instrs:{2}, Locals:{3}, Exceptions:{4}", + Utils.removeNewlines(encMethod.FullName), + encMethod.MetadataToken.ToInt32(), + encMethod.Body.Instructions.Count, + encMethod.Body.Variables.Count, + encMethod.Body.ExceptionHandlers.Count); + delegateTypes.Add(delegateType); + } + + bool getTokens(TypeDefinition delegateType, out int delegateToken, out int encMethodToken, out int encDeclaringTypeToken) { + delegateToken = 0; + encMethodToken = 0; + encDeclaringTypeToken = 0; + + var cctor = DotNetUtils.getMethod(delegateType, ".cctor"); + if (cctor == null) + return false; + + var instrs = cctor.Body.Instructions; + for (int i = 0; i < instrs.Count - 3; i++) { + var ldci4_1 = instrs[i]; + if (!DotNetUtils.isLdcI4(ldci4_1)) + continue; + var ldci4_2 = instrs[i + 1]; + if (!DotNetUtils.isLdcI4(ldci4_2)) + continue; + var ldci4_3 = instrs[i + 2]; + if (!DotNetUtils.isLdcI4(ldci4_3)) + continue; + var call = instrs[i + 3]; + if (call.OpCode.Code != Code.Call) + continue; + var calledMethod = call.Operand as MethodDefinition; + if (calledMethod == null) + continue; + if (calledMethod != decryptMethod) + continue; + + delegateToken = DotNetUtils.getLdcI4Value(ldci4_1); + encMethodToken = DotNetUtils.getLdcI4Value(ldci4_2); + encDeclaringTypeToken = DotNetUtils.getLdcI4Value(ldci4_3); + return true; + } + + return false; + } + } +} diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/ProxyCallFixer.cs b/de4dot.code/deobfuscators/CryptoObfuscator/ProxyCallFixer.cs index 9fb4f2cb..52288048 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/ProxyCallFixer.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/ProxyCallFixer.cs @@ -110,7 +110,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { MethodDefinition getProxyCreateMethod(TypeDefinition type) { if (DotNetUtils.findFieldType(type, "System.ModuleHandle", true) == null) return null; - if (type.Fields.Count < 1 || type.Fields.Count > 8) + if (type.Fields.Count < 1 || type.Fields.Count > 10) return null; MethodDefinition createMethod = null; diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/ResourceDecrypter.cs b/de4dot.code/deobfuscators/CryptoObfuscator/ResourceDecrypter.cs index 32bada9f..0e84de0d 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/ResourceDecrypter.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/ResourceDecrypter.cs @@ -304,8 +304,12 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { return method; if (DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte,System.IO.Stream)")) return method; + if (DotNetUtils.isMethod(method, "System.Byte[]", "(System.SByte,System.IO.Stream)")) + return method; if (DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte,System.IO.Stream,System.Int32)")) return method; + if (DotNetUtils.isMethod(method, "System.Byte[]", "(System.SByte,System.IO.Stream,System.UInt32)")) + return method; } return null; } diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/TamperDetection.cs b/de4dot.code/deobfuscators/CryptoObfuscator/TamperDetection.cs index 67dde72a..e2512da4 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/TamperDetection.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/TamperDetection.cs @@ -84,7 +84,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()")) return false; - if (type.Methods.Count < 3 || type.Methods.Count > 10) + if (type.Methods.Count < 3 || type.Methods.Count > 12) return false; if (DotNetUtils.getPInvokeMethod(type, "mscoree", "StrongNameSignatureVerificationEx") != null) { } diff --git a/de4dot.code/deobfuscators/ILProtector/MethodsDecrypter.cs b/de4dot.code/deobfuscators/ILProtector/MethodsDecrypter.cs index 201c8dda..15324013 100644 --- a/de4dot.code/deobfuscators/ILProtector/MethodsDecrypter.cs +++ b/de4dot.code/deobfuscators/ILProtector/MethodsDecrypter.cs @@ -241,28 +241,9 @@ namespace de4dot.code.deobfuscators.ILProtector { } static void restoreMethod(MethodDefinition method, MethodReader methodReader) { - var body = method.Body; - // body.MaxStackSize = - body.InitLocals = methodReader.InitLocals; - - body.Variables.Clear(); - if (methodReader.Locals != null) { - foreach (var local in methodReader.Locals) - body.Variables.Add(local); - } - - body.Instructions.Clear(); - if (methodReader.Instructions != null) { - foreach (var instr in methodReader.Instructions) - body.Instructions.Add(instr); - } - - body.ExceptionHandlers.Clear(); - if (methodReader.ExceptionHandlers != null) { - foreach (var eh in methodReader.ExceptionHandlers) - body.ExceptionHandlers.Add(eh); - } + method.Body.InitLocals = methodReader.InitLocals; + methodReader.restoreMethod(method); } int getMethodId(MethodDefinition method) { diff --git a/de4dot.code/deobfuscators/MethodBodyReaderBase.cs b/de4dot.code/deobfuscators/MethodBodyReaderBase.cs index 962e4abf..7c3fe0ea 100644 --- a/de4dot.code/deobfuscators/MethodBodyReaderBase.cs +++ b/de4dot.code/deobfuscators/MethodBodyReaderBase.cs @@ -27,9 +27,9 @@ using de4dot.blocks; namespace de4dot.code.deobfuscators { abstract class MethodBodyReaderBase { protected BinaryReader reader; - public List Locals { get; set; } - public Instruction[] Instructions { get; set; } - public ExceptionHandler[] ExceptionHandlers { get; set; } + public IList Locals { get; set; } + public IList Instructions { get; set; } + public IList ExceptionHandlers { get; set; } protected IList parameters; int currentOffset; @@ -46,17 +46,34 @@ namespace de4dot.code.deobfuscators { protected void readInstructions(int numInstrs) { Instructions = new Instruction[numInstrs]; currentOffset = 0; - for (int i = 0; i < Instructions.Length; i++) { - var instr = readInstruction(); - Instructions[i] = instr; - if (instr.OpCode.Code == Code.Switch) { - int[] targets = (int[])instr.Operand; - currentOffset += instr.OpCode.Size + 4 + 4 * targets.Length; - } - else - currentOffset += Instructions[i].GetSize(); - } + for (int i = 0; i < Instructions.Count; i++) + Instructions[i] = readOneInstruction(); + fixBranches(); + } + protected void readInstructionsNumBytes(uint codeSize) { + var instrs = new List(); + long endOffs = reader.BaseStream.Position + codeSize; + while (reader.BaseStream.Position < endOffs) + instrs.Add(readOneInstruction()); + if (reader.BaseStream.Position != endOffs) + throw new ApplicationException("Could not read all instructions"); + Instructions = instrs; + fixBranches(); + } + + Instruction readOneInstruction() { + var instr = readInstruction(); + if (instr.OpCode.Code == Code.Switch) { + int[] targets = (int[])instr.Operand; + currentOffset += instr.OpCode.Size + 4 + 4 * targets.Length; + } + else + currentOffset += instr.GetSize(); + return instr; + } + + void fixBranches() { foreach (var instr in Instructions) { switch (instr.OpCode.OperandType) { case OperandType.InlineBrTarget: @@ -231,10 +248,32 @@ namespace de4dot.code.deobfuscators { protected void readExceptionHandlers(int numExceptionHandlers) { ExceptionHandlers = new ExceptionHandler[numExceptionHandlers]; - for (int i = 0; i < ExceptionHandlers.Length; i++) + for (int i = 0; i < ExceptionHandlers.Count; i++) ExceptionHandlers[i] = readExceptionHandler(); } protected abstract ExceptionHandler readExceptionHandler(); + + public virtual void restoreMethod(MethodDefinition method) { + var body = method.Body; + + body.Variables.Clear(); + if (Locals != null) { + foreach (var local in Locals) + body.Variables.Add(local); + } + + body.Instructions.Clear(); + if (Instructions != null) { + foreach (var instr in Instructions) + body.Instructions.Add(instr); + } + + body.ExceptionHandlers.Clear(); + if (ExceptionHandlers != null) { + foreach (var eh in ExceptionHandlers) + body.ExceptionHandlers.Add(eh); + } + } } } diff --git a/de4dot.cui/Properties/AssemblyInfo.cs b/de4dot.cui/Properties/AssemblyInfo.cs index f823ad03..f1fbc90a 100644 --- a/de4dot.cui/Properties/AssemblyInfo.cs +++ b/de4dot.cui/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")] [assembly: InternalsVisibleTo("de4dot, PublicKey=00240000048000009400000006020000002400005253413100040000010001007b5ffd8f48f1397cd4e21c9e30a5cb36b2c013d6f20688c90e3f0c2d24e6d67cbeea7a6ec3faf9ba081f3d6b6fbe389677adbb8337d3a16187cd13b16a34008a22b89089da41c4a08fd35615c77de0827adcca6d49b08c0ed3e0404a1c44b7d083be614acb1779e4fb275e14427f3687f375d03f3b465c8a6cdeebd1f8c7f4ea")] [assembly: InternalsVisibleTo("de4dot-x64, PublicKey=00240000048000009400000006020000002400005253413100040000010001007b5ffd8f48f1397cd4e21c9e30a5cb36b2c013d6f20688c90e3f0c2d24e6d67cbeea7a6ec3faf9ba081f3d6b6fbe389677adbb8337d3a16187cd13b16a34008a22b89089da41c4a08fd35615c77de0827adcca6d49b08c0ed3e0404a1c44b7d083be614acb1779e4fb275e14427f3687f375d03f3b465c8a6cdeebd1f8c7f4ea")] diff --git a/de4dot.mdecrypt/Properties/AssemblyInfo.cs b/de4dot.mdecrypt/Properties/AssemblyInfo.cs index 2ac21271..1b403a44 100644 --- a/de4dot.mdecrypt/Properties/AssemblyInfo.cs +++ b/de4dot.mdecrypt/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")] diff --git a/de4dot/Properties/AssemblyInfo.cs b/de4dot/Properties/AssemblyInfo.cs index 474bbe57..36dd1633 100644 --- a/de4dot/Properties/AssemblyInfo.cs +++ b/de4dot/Properties/AssemblyInfo.cs @@ -21,7 +21,7 @@ using System.Reflection; using System.Runtime.InteropServices; [assembly: AssemblyTitle("de4dot")] -[assembly: AssemblyDescription("Deobfuscates obfuscated .NET applications - AnyCpu")] +[assembly: AssemblyDescription("Deobfuscates obfuscated .NET applications - x86")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("de4dot")] @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.9.0.3405")] -[assembly: AssemblyFileVersion("1.9.0.3405")] +[assembly: AssemblyVersion("1.9.1.3405")] +[assembly: AssemblyFileVersion("1.9.1.3405")]