diff --git a/de4dot.code/deobfuscators/DeobfuscatorBase.cs b/de4dot.code/deobfuscators/DeobfuscatorBase.cs index 87959fee..daf5f0c8 100644 --- a/de4dot.code/deobfuscators/DeobfuscatorBase.cs +++ b/de4dot.code/deobfuscators/DeobfuscatorBase.cs @@ -47,7 +47,7 @@ namespace de4dot.deobfuscators { IList> modrefsToRemove = new List>(); List namesToPossiblyRemove = new List(); bool scanForObfuscatorCalled = false; - Dictionary cctorInitCallsToRemove = new Dictionary(); + MethodCallRemover methodCallRemover = new MethodCallRemover(); internal class OptionsBase : IDeobfuscatorOptions { public bool RenameResourcesInCode { get; set; } @@ -109,7 +109,7 @@ namespace de4dot.deobfuscators { } public virtual void deobfuscateMethodEnd(Blocks blocks) { - removeInitializeMethodCalls(blocks); + removeMethodCalls(blocks); } public virtual void deobfuscateStrings(Blocks blocks) { @@ -139,39 +139,105 @@ namespace de4dot.deobfuscators { return new List(); } - public void addCctorInitCallToBeRemoved(MethodDefinition method) { - if (method == null) - return; - if (method.Parameters.Count != 0) - throw new ApplicationException(string.Format("Method takes params: {0}", method)); - if (DotNetUtils.hasReturnValue(method)) - throw new ApplicationException(string.Format("Method has a return value: {0}", method)); - cctorInitCallsToRemove[new MethodReferenceAndDeclaringTypeKey(method)] = method; - } + class MethodCallRemover { + Dictionary> methodNameInfos = new Dictionary>(StringComparer.Ordinal); + Dictionary> methodRefInfos = new Dictionary>(); - void removeInitializeMethodCalls(Blocks blocks) { - if (blocks.Method.Name != ".cctor") - return; + void checkMethod(MethodReference methodToBeRemoved) { + if (methodToBeRemoved.Parameters.Count != 0) + throw new ApplicationException(string.Format("Method takes params: {0}", methodToBeRemoved)); + if (DotNetUtils.hasReturnValue(methodToBeRemoved)) + throw new ApplicationException(string.Format("Method has a return value: {0}", methodToBeRemoved)); + } - foreach (var block in blocks.MethodBlocks.getAllBlocks()) { + public void add(string method, MethodReference methodToBeRemoved) { + if (methodToBeRemoved == null) + return; + checkMethod(methodToBeRemoved); + + Dictionary dict; + if (!methodNameInfos.TryGetValue(method, out dict)) + methodNameInfos[method] = dict = new Dictionary(); + dict[new MethodReferenceAndDeclaringTypeKey(methodToBeRemoved)] = true; + } + + public void add(MethodDefinition method, MethodReference methodToBeRemoved) { + if (method == null || methodToBeRemoved == null) + return; + checkMethod(methodToBeRemoved); + + Dictionary dict; + var methodKey = new MethodReferenceAndDeclaringTypeKey(method); + if (!methodRefInfos.TryGetValue(methodKey, out dict)) + methodRefInfos[methodKey] = dict = new Dictionary(); + dict[new MethodReferenceAndDeclaringTypeKey(methodToBeRemoved)] = true; + } + + public void removeAll(Blocks blocks) { + if (blocks.Method.Name != ".cctor") + return; + + var allBlocks = blocks.MethodBlocks.getAllBlocks(); + + removeAll(allBlocks, blocks, blocks.Method.Name); + removeAll(allBlocks, blocks, blocks.Method); + } + + void removeAll(IList allBlocks, Blocks blocks, string method) { + Dictionary info; + if (!methodNameInfos.TryGetValue(method, out info)) + return; + + removeCalls(allBlocks, blocks, info); + } + + void removeAll(IList allBlocks, Blocks blocks, MethodDefinition method) { + Dictionary info; + if (!methodRefInfos.TryGetValue(new MethodReferenceAndDeclaringTypeKey(method), out info)) + return; + + removeCalls(allBlocks, blocks, info); + } + + void removeCalls(IList allBlocks, Blocks blocks, Dictionary info) { var instrsToDelete = new List(); - for (int i = 0; i < block.Instructions.Count; i++) { - var instr = block.Instructions[i]; - if (instr.OpCode == OpCodes.Call) { + foreach (var block in allBlocks) { + instrsToDelete.Clear(); + for (int i = 0; i < block.Instructions.Count; i++) { + var instr = block.Instructions[i]; + if (instr.OpCode != OpCodes.Call) + continue; var destMethod = instr.Operand as MethodReference; if (destMethod == null) continue; + var key = new MethodReferenceAndDeclaringTypeKey(destMethod); - if (cctorInitCallsToRemove.ContainsKey(key)) { + if (info.ContainsKey(key)) { Log.v("Removed call to {0}", destMethod); instrsToDelete.Add(i); } } + block.remove(instrsToDelete); } - block.remove(instrsToDelete); } } + public void addCctorInitCallToBeRemoved(MethodReference methodToBeRemoved) { + methodCallRemover.add(".cctor", methodToBeRemoved); + } + + public void addModuleCctorInitCallToBeRemoved(MethodReference methodToBeRemoved) { + methodCallRemover.add(DotNetUtils.getMethod(DotNetUtils.getModuleType(module), ".cctor"), methodToBeRemoved); + } + + public void addCallToBeRemoved(MethodDefinition method, MethodReference methodToBeRemoved) { + methodCallRemover.add(method, methodToBeRemoved); + } + + void removeMethodCalls(Blocks blocks) { + methodCallRemover.removeAll(blocks); + } + protected void addMethodsToBeRemoved(IEnumerable methods, string reason) { foreach (var method in methods) addMethodToBeRemoved(method, reason); diff --git a/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs b/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs index ab718d6c..cbeb1b98 100644 --- a/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs @@ -292,7 +292,7 @@ namespace de4dot.deobfuscators.SmartAssembly { public override void deobfuscateBegin() { base.deobfuscateBegin(); if (options.RemoveMemoryManager) - addCctorInitCallToBeRemoved(memoryManagerInfo.CctorInitMethod); + addModuleCctorInitCallToBeRemoved(memoryManagerInfo.CctorInitMethod); initDecrypters(); proxyDelegateFinder.find(); } @@ -309,8 +309,8 @@ namespace de4dot.deobfuscators.SmartAssembly { assemblyResolverInfo.findTypes(); resourceResolverInfo.findTypes(); - addCctorInitCallToBeRemoved(assemblyResolverInfo.CallResolverMethod); - addCctorInitCallToBeRemoved(resourceResolverInfo.CallResolverMethod); + addModuleCctorInitCallToBeRemoved(assemblyResolverInfo.CallResolverMethod); + addModuleCctorInitCallToBeRemoved(resourceResolverInfo.CallResolverMethod); resourceDecrypterInfo.setSimpleZipType(getGlobalSimpleZipType(), DeobfuscatedFile);