From 0d92b37536f515bfce2dfb6c8dc177158ebb3dcb Mon Sep 17 00:00:00 2001 From: de4dot Date: Tue, 20 Dec 2011 21:47:45 +0100 Subject: [PATCH] Create DNR3 dir --- de4dot.code/de4dot.code.csproj | 41 +-- de4dot.code/deobfuscators/DeobfuscatorBase.cs | 5 + .../deobfuscators/InlinedMethodsFinder.cs | 131 ++++++++++ .../{dotNET_Reactor => }/QuickLZ.cs | 2 +- .../deobfuscators/UnusedMethodsFinder.cs | 85 ++++++ .../ApplicationModeDecrypter.cs | 2 +- .../ApplicationModeUnpacker.cs | 2 +- .../AssemblyResolver.cs | 2 +- .../v3 => dotNET_Reactor3}/DecryptMethod.cs | 2 +- .../dotNET_Reactor3/Deobfuscator.cs | 246 ++++++++++++++++++ .../v3 => dotNET_Reactor3}/MemoryPatcher.cs | 2 +- .../AntiStrongname.cs | 2 +- .../AssemblyResolver.cs | 2 +- .../BoolValueInliner.cs | 2 +- .../BooleanDecrypter.cs | 2 +- .../Deobfuscator.cs | 221 ++-------------- .../EmptyClass.cs | 2 +- .../EncryptedResource.cs | 2 +- .../MetadataTokenObfuscator.cs | 2 +- .../MethodsDecrypter.cs | 2 +- .../NativeFileDecrypter.cs | 2 +- .../NativeImageUnpacker.cs | 2 +- .../ResourceResolver.cs | 2 +- .../StringDecrypter.cs | 2 +- de4dot.cui/Program.cs | 3 +- 25 files changed, 528 insertions(+), 240 deletions(-) create mode 100644 de4dot.code/deobfuscators/InlinedMethodsFinder.cs rename de4dot.code/deobfuscators/{dotNET_Reactor => }/QuickLZ.cs (98%) create mode 100644 de4dot.code/deobfuscators/UnusedMethodsFinder.cs rename de4dot.code/deobfuscators/{dotNET_Reactor/v3 => dotNET_Reactor3}/ApplicationModeDecrypter.cs (97%) rename de4dot.code/deobfuscators/{dotNET_Reactor/v3 => dotNET_Reactor3}/ApplicationModeUnpacker.cs (99%) rename de4dot.code/deobfuscators/{dotNET_Reactor/v3 => dotNET_Reactor3}/AssemblyResolver.cs (97%) rename de4dot.code/deobfuscators/{dotNET_Reactor/v3 => dotNET_Reactor3}/DecryptMethod.cs (97%) create mode 100644 de4dot.code/deobfuscators/dotNET_Reactor3/Deobfuscator.cs rename de4dot.code/deobfuscators/{dotNET_Reactor/v3 => dotNET_Reactor3}/MemoryPatcher.cs (98%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/AntiStrongname.cs (99%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/AssemblyResolver.cs (99%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/BoolValueInliner.cs (97%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/BooleanDecrypter.cs (98%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/Deobfuscator.cs (79%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/EmptyClass.cs (98%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/EncryptedResource.cs (99%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/MetadataTokenObfuscator.cs (98%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/MethodsDecrypter.cs (99%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/NativeFileDecrypter.cs (98%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/NativeImageUnpacker.cs (98%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/ResourceResolver.cs (98%) rename de4dot.code/deobfuscators/{dotNET_Reactor => dotNET_Reactor4}/StringDecrypter.cs (99%) diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index 66a2374a..b3c2e119 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -77,30 +77,32 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + @@ -125,6 +127,7 @@ + diff --git a/de4dot.code/deobfuscators/DeobfuscatorBase.cs b/de4dot.code/deobfuscators/DeobfuscatorBase.cs index bb89c51f..d6a553e5 100644 --- a/de4dot.code/deobfuscators/DeobfuscatorBase.cs +++ b/de4dot.code/deobfuscators/DeobfuscatorBase.cs @@ -584,5 +584,10 @@ namespace de4dot.code.deobfuscators { public virtual void OnBeforeAddingResources(MetadataBuilder builder) { } + + public void findAndRemoveInlinedMethods() { + var inlinedMethods = InlinedMethodsFinder.find(module); + addMethodsToBeRemoved(new UnusedMethodsFinder(module, inlinedMethods).find(), "Inlined method"); + } } } diff --git a/de4dot.code/deobfuscators/InlinedMethodsFinder.cs b/de4dot.code/deobfuscators/InlinedMethodsFinder.cs new file mode 100644 index 00000000..9646f438 --- /dev/null +++ b/de4dot.code/deobfuscators/InlinedMethodsFinder.cs @@ -0,0 +1,131 @@ +/* + Copyright (C) 2011 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.Collections.Generic; +using Mono.Cecil; +using Mono.Cecil.Cil; +using de4dot.blocks; + +namespace de4dot.code.deobfuscators { + static class InlinedMethodsFinder { + public static List find(ModuleDefinition module) { + // Not all garbage methods are inlined, possibly because we remove some code that calls + // the garbage method before the methods inliner has a chance to inline it. Try to find + // all garbage methods and other code will figure out if there are any calls left. + + var inlinedMethods = new List(); + foreach (var type in module.GetTypes()) { + foreach (var method in type.Methods) { + if (!method.IsStatic) + continue; + if (!method.IsAssembly && !method.IsCompilerControlled) + continue; + if (method.GenericParameters.Count > 0) + continue; + if (method.Name == ".cctor") + continue; + if (method.Body == null) + continue; + var instrs = method.Body.Instructions; + if (instrs.Count < 2) + continue; + + switch (instrs[0].OpCode.Code) { + case Code.Ldc_I4: + case Code.Ldc_I4_0: + case Code.Ldc_I4_1: + case Code.Ldc_I4_2: + case Code.Ldc_I4_3: + case Code.Ldc_I4_4: + case Code.Ldc_I4_5: + case Code.Ldc_I4_6: + case Code.Ldc_I4_7: + case Code.Ldc_I4_8: + case Code.Ldc_I4_M1: + case Code.Ldc_I4_S: + case Code.Ldc_I8: + case Code.Ldc_R4: + case Code.Ldc_R8: + case Code.Ldftn: + case Code.Ldnull: + case Code.Ldstr: + case Code.Ldtoken: + case Code.Ldsfld: + case Code.Ldsflda: + if (instrs[1].OpCode.Code != Code.Ret) + continue; + break; + + case Code.Ldarg: + case Code.Ldarg_S: + case Code.Ldarg_0: + case Code.Ldarg_1: + case Code.Ldarg_2: + case Code.Ldarg_3: + case Code.Call: + if (!isCallMethod(method)) + continue; + break; + + default: + continue; + } + + inlinedMethods.Add(method); + } + } + + return inlinedMethods; + } + + static bool isCallMethod(MethodDefinition method) { + int loadIndex = 0; + int methodArgsCount = DotNetUtils.getArgsCount(method); + var instrs = method.Body.Instructions; + int i = 0; + for (; i < instrs.Count && i < methodArgsCount; i++) { + var instr = instrs[i]; + switch (instr.OpCode.Code) { + case Code.Ldarg: + case Code.Ldarg_S: + case Code.Ldarg_0: + case Code.Ldarg_1: + case Code.Ldarg_2: + case Code.Ldarg_3: + if (DotNetUtils.getArgIndex(method, instr) != loadIndex) + return false; + loadIndex++; + continue; + } + break; + } + if (loadIndex != methodArgsCount) + return false; + if (i + 1 >= instrs.Count) + return false; + + if (instrs[i].OpCode.Code != Code.Call && instrs[i].OpCode.Code != Code.Callvirt) + return false; + if (instrs[i + 1].OpCode.Code != Code.Ret) + return false; + + return true; + } + } +} diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/QuickLZ.cs b/de4dot.code/deobfuscators/QuickLZ.cs similarity index 98% rename from de4dot.code/deobfuscators/dotNET_Reactor/QuickLZ.cs rename to de4dot.code/deobfuscators/QuickLZ.cs index a54a12e3..10d65903 100644 --- a/de4dot.code/deobfuscators/dotNET_Reactor/QuickLZ.cs +++ b/de4dot.code/deobfuscators/QuickLZ.cs @@ -11,7 +11,7 @@ using System; -namespace de4dot.code.deobfuscators.dotNET_Reactor { +namespace de4dot.code.deobfuscators { static class QuickLZ { static int sig = 0x5A4C4351; // "QCLZ" diff --git a/de4dot.code/deobfuscators/UnusedMethodsFinder.cs b/de4dot.code/deobfuscators/UnusedMethodsFinder.cs new file mode 100644 index 00000000..ba4b8590 --- /dev/null +++ b/de4dot.code/deobfuscators/UnusedMethodsFinder.cs @@ -0,0 +1,85 @@ +/* + Copyright (C) 2011 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.Collections.Generic; +using Mono.Cecil; +using Mono.Cecil.Cil; +using de4dot.blocks; + +namespace de4dot.code.deobfuscators { + class UnusedMethodsFinder { + ModuleDefinition module; + Dictionary possiblyUnusedMethods = new Dictionary(); + Stack notUnusedStack = new Stack(); + + public UnusedMethodsFinder(ModuleDefinition module, IEnumerable possiblyUnusedMethods) { + this.module = module; + foreach (var method in possiblyUnusedMethods) { + if (method != module.EntryPoint) + this.possiblyUnusedMethods[method] = true; + } + } + + public IEnumerable find() { + if (possiblyUnusedMethods.Count == 0) + return possiblyUnusedMethods.Keys; + + foreach (var type in module.GetTypes()) { + foreach (var method in type.Methods) + check(method); + } + + while (notUnusedStack.Count > 0) { + var method = notUnusedStack.Pop(); + if (!possiblyUnusedMethods.Remove(method)) + continue; + check(method); + } + + return possiblyUnusedMethods.Keys; + } + + void check(MethodDefinition method) { + if (method.Body == null) + return; + if (possiblyUnusedMethods.ContainsKey(method)) + return; + + foreach (var instr in method.Body.Instructions) { + switch (instr.OpCode.Code) { + case Code.Call: + case Code.Calli: + case Code.Callvirt: + case Code.Newobj: + case Code.Ldtoken: + case Code.Ldftn: + break; + default: + continue; + } + + var calledMethod = DotNetUtils.getMethod(module, instr.Operand as MethodReference); + if (calledMethod == null) + continue; + if (possiblyUnusedMethods.ContainsKey(calledMethod)) + notUnusedStack.Push(calledMethod); + } + } + } +} diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/v3/ApplicationModeDecrypter.cs b/de4dot.code/deobfuscators/dotNET_Reactor3/ApplicationModeDecrypter.cs similarity index 97% rename from de4dot.code/deobfuscators/dotNET_Reactor/v3/ApplicationModeDecrypter.cs rename to de4dot.code/deobfuscators/dotNET_Reactor3/ApplicationModeDecrypter.cs index 3cd7a242..da2b3fdb 100644 --- a/de4dot.code/deobfuscators/dotNET_Reactor/v3/ApplicationModeDecrypter.cs +++ b/de4dot.code/deobfuscators/dotNET_Reactor3/ApplicationModeDecrypter.cs @@ -21,7 +21,7 @@ using Mono.Cecil; using de4dot.blocks; using de4dot.blocks.cflow; -namespace de4dot.code.deobfuscators.dotNET_Reactor.v3 { +namespace de4dot.code.deobfuscators.dotNET_Reactor3 { class ApplicationModeDecrypter { ModuleDefinition module; AssemblyResolver assemblyResolver; diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/v3/ApplicationModeUnpacker.cs b/de4dot.code/deobfuscators/dotNET_Reactor3/ApplicationModeUnpacker.cs similarity index 99% rename from de4dot.code/deobfuscators/dotNET_Reactor/v3/ApplicationModeUnpacker.cs rename to de4dot.code/deobfuscators/dotNET_Reactor3/ApplicationModeUnpacker.cs index 16cb7368..ae2c8d54 100644 --- a/de4dot.code/deobfuscators/dotNET_Reactor/v3/ApplicationModeUnpacker.cs +++ b/de4dot.code/deobfuscators/dotNET_Reactor3/ApplicationModeUnpacker.cs @@ -25,7 +25,7 @@ using System.Text.RegularExpressions; using Mono.Cecil; using de4dot.code.PE; -namespace de4dot.code.deobfuscators.dotNET_Reactor.v3 { +namespace de4dot.code.deobfuscators.dotNET_Reactor3 { class IniFile { Dictionary nameToValue = new Dictionary(StringComparer.OrdinalIgnoreCase); diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/v3/AssemblyResolver.cs b/de4dot.code/deobfuscators/dotNET_Reactor3/AssemblyResolver.cs similarity index 97% rename from de4dot.code/deobfuscators/dotNET_Reactor/v3/AssemblyResolver.cs rename to de4dot.code/deobfuscators/dotNET_Reactor3/AssemblyResolver.cs index 3501943c..0fb3ffc9 100644 --- a/de4dot.code/deobfuscators/dotNET_Reactor/v3/AssemblyResolver.cs +++ b/de4dot.code/deobfuscators/dotNET_Reactor3/AssemblyResolver.cs @@ -22,7 +22,7 @@ using Mono.Cecil; using de4dot.blocks; using de4dot.blocks.cflow; -namespace de4dot.code.deobfuscators.dotNET_Reactor.v3 { +namespace de4dot.code.deobfuscators.dotNET_Reactor3 { class AssemblyResolver { DecryptMethod decryptMethod = new DecryptMethod(); diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/v3/DecryptMethod.cs b/de4dot.code/deobfuscators/dotNET_Reactor3/DecryptMethod.cs similarity index 97% rename from de4dot.code/deobfuscators/dotNET_Reactor/v3/DecryptMethod.cs rename to de4dot.code/deobfuscators/dotNET_Reactor3/DecryptMethod.cs index f6c43b9b..04ff59ac 100644 --- a/de4dot.code/deobfuscators/dotNET_Reactor/v3/DecryptMethod.cs +++ b/de4dot.code/deobfuscators/dotNET_Reactor3/DecryptMethod.cs @@ -21,7 +21,7 @@ using System; using System.Collections.Generic; using Mono.Cecil; -namespace de4dot.code.deobfuscators.dotNET_Reactor.v3 { +namespace de4dot.code.deobfuscators.dotNET_Reactor3 { class DecryptMethod { MethodDefinition decryptionMethod; byte[] key; diff --git a/de4dot.code/deobfuscators/dotNET_Reactor3/Deobfuscator.cs b/de4dot.code/deobfuscators/dotNET_Reactor3/Deobfuscator.cs new file mode 100644 index 00000000..dd5d0a45 --- /dev/null +++ b/de4dot.code/deobfuscators/dotNET_Reactor3/Deobfuscator.cs @@ -0,0 +1,246 @@ +/* + Copyright (C) 2011 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 System.Text.RegularExpressions; +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.MyStuff; +using de4dot.blocks; +using de4dot.code.PE; + +namespace de4dot.code.deobfuscators.dotNET_Reactor3 { + public class DeobfuscatorInfo : DeobfuscatorInfoBase { + public const string THE_NAME = ".NET Reactor"; + public const string THE_TYPE = "dr3"; + const string DEFAULT_REGEX = DeobfuscatorBase.DEFAULT_VALID_NAME_REGEX; + BoolOption restoreTypes; + BoolOption inlineMethods; + BoolOption removeInlinedMethods; + BoolOption removeNamespaces; + BoolOption removeAntiStrongName; + + public DeobfuscatorInfo() + : base(DEFAULT_REGEX) { + restoreTypes = new BoolOption(null, makeArgName("types"), "Restore types (object -> real type)", true); + inlineMethods = new BoolOption(null, makeArgName("inline"), "Inline short methods", true); + removeInlinedMethods = new BoolOption(null, makeArgName("remove-inlined"), "Remove inlined methods", true); + removeNamespaces = new BoolOption(null, makeArgName("ns1"), "Clear namespace if there's only one class in it", true); + removeAntiStrongName = new BoolOption(null, makeArgName("sn"), "Remove anti strong name code", true); + } + + public override string Name { + get { return THE_NAME; } + } + + public override string Type { + get { return THE_TYPE; } + } + + public override IDeobfuscator createDeobfuscator() { + return new Deobfuscator(new Deobfuscator.Options { + ValidNameRegex = validNameRegex.get(), + RestoreTypes = restoreTypes.get(), + InlineMethods = inlineMethods.get(), + RemoveInlinedMethods = removeInlinedMethods.get(), + RemoveNamespaces = removeNamespaces.get(), + RemoveAntiStrongName = removeAntiStrongName.get(), + }); + } + + protected override IEnumerable