diff --git a/de4dot.code/deobfuscators/DeobfuscatorBase.cs b/de4dot.code/deobfuscators/DeobfuscatorBase.cs index b89cfb57..9ee289bd 100644 --- a/de4dot.code/deobfuscators/DeobfuscatorBase.cs +++ b/de4dot.code/deobfuscators/DeobfuscatorBase.cs @@ -379,7 +379,12 @@ namespace de4dot.code.deobfuscators { var typeDef = info.obj; if (typeDef == null) continue; - if (types.Remove(typeDef)) + bool removed; + if (typeDef.IsNested) + removed = typeDef.DeclaringType.NestedTypes.Remove(typeDef); + else + removed = types.Remove(typeDef); + if (removed) Log.v("Removed type {0} ({1:X8}) (reason: {2})", typeDef, typeDef.MetadataToken.ToUInt32(), info.reason); } Log.deIndent(); @@ -592,31 +597,32 @@ namespace de4dot.code.deobfuscators { public void findAndRemoveInlinedMethods() { var inlinedMethods = InlinedMethodsFinder.find(module); - addMethodsToBeRemoved(new UnusedMethodsFinder(module, inlinedMethods).find(), "Inlined method"); + addMethodsToBeRemoved(new UnusedMethodsFinder(module, inlinedMethods, getRemovedMethods()).find(), "Inlined method"); + } + + MethodCollection getRemovedMethods() { + var removedMethods = new MethodCollection(); + removedMethods.add(getMethodsToRemove()); + removedMethods.addAndNested(getTypesToRemove()); + return removedMethods; } protected bool isTypeCalled(TypeDefinition decrypterType) { if (decrypterType == null) return false; - var decrypterMethods = new Dictionary(); - foreach (var type in TypeDefinition.GetTypes(new List { decrypterType })) - addMethods(type, decrypterMethods); + var decrypterMethods = new MethodCollection(); + decrypterMethods.addAndNested(decrypterType); - var removedMethods = new Dictionary(); - foreach (var method in getMethodsToRemove()) - removedMethods[new MethodReferenceAndDeclaringTypeKey(method)] = true; - foreach (var type in TypeDefinition.GetTypes(getTypesToRemove())) - addMethods(type, removedMethods); + var removedMethods = getRemovedMethods(); foreach (var type in module.GetTypes()) { foreach (var method in type.Methods) { if (method.Body == null) continue; - var key = new MethodReferenceAndDeclaringTypeKey(method); - if (decrypterMethods.ContainsKey(key)) + if (decrypterMethods.exists(method)) break; // decrypter type / nested type method - if (removedMethods.ContainsKey(key)) + if (removedMethods.exists(method)) continue; foreach (var instr in method.Body.Instructions) { @@ -627,8 +633,7 @@ namespace de4dot.code.deobfuscators { var calledMethod = instr.Operand as MethodReference; if (calledMethod == null) break; - key = new MethodReferenceAndDeclaringTypeKey(calledMethod); - if (decrypterMethods.ContainsKey(key)) + if (decrypterMethods.exists(calledMethod)) return true; break; diff --git a/de4dot.code/deobfuscators/UnusedMethodsFinder.cs b/de4dot.code/deobfuscators/UnusedMethodsFinder.cs index ba4b8590..1d3bcc3c 100644 --- a/de4dot.code/deobfuscators/UnusedMethodsFinder.cs +++ b/de4dot.code/deobfuscators/UnusedMethodsFinder.cs @@ -25,13 +25,15 @@ using de4dot.blocks; namespace de4dot.code.deobfuscators { class UnusedMethodsFinder { ModuleDefinition module; + MethodCollection removedMethods; Dictionary possiblyUnusedMethods = new Dictionary(); Stack notUnusedStack = new Stack(); - public UnusedMethodsFinder(ModuleDefinition module, IEnumerable possiblyUnusedMethods) { + public UnusedMethodsFinder(ModuleDefinition module, IEnumerable possiblyUnusedMethods, MethodCollection removedMethods) { this.module = module; + this.removedMethods = removedMethods; foreach (var method in possiblyUnusedMethods) { - if (method != module.EntryPoint) + if (method != module.EntryPoint && !removedMethods.exists(method)) this.possiblyUnusedMethods[method] = true; } } @@ -60,6 +62,8 @@ namespace de4dot.code.deobfuscators { return; if (possiblyUnusedMethods.ContainsKey(method)) return; + if (removedMethods.exists(method)) + return; foreach (var instr in method.Body.Instructions) { switch (instr.OpCode.Code) { @@ -69,6 +73,7 @@ namespace de4dot.code.deobfuscators { case Code.Newobj: case Code.Ldtoken: case Code.Ldftn: + case Code.Ldvirtftn: break; default: continue;