From 9cfe8431f649c461694a25cf54aeb4795027bcb9 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 4 Apr 2012 21:06:10 +0200 Subject: [PATCH] Add shared deobfuscator data/methods --- blocks/DotNetUtils.cs | 10 ++ de4dot.code/AssemblyResolver.cs | 22 ++--- de4dot.code/DeobfuscatorContext.cs | 99 +++++++++++++++++++ de4dot.code/ExternalAssemblies.cs | 13 ++- de4dot.code/IDeobfuscatorContext.cs | 32 ++++++ de4dot.code/IObfuscatedFile.cs | 1 + de4dot.code/ObfuscatedFile.cs | 6 ++ de4dot.code/de4dot.code.csproj | 2 + .../deobfuscators/Babel_NET/Deobfuscator.cs | 3 +- .../deobfuscators/Babel_NET/ImageReader.cs | 13 +-- .../Babel_NET/MethodsDecrypter.cs | 16 +-- de4dot.code/deobfuscators/DeobfuscatorBase.cs | 22 +++++ .../deobfuscators/IDeobfuscatedFile.cs | 1 + de4dot.code/renamer/Renamer.cs | 5 +- de4dot.code/renamer/asmmodules/Modules.cs | 9 +- de4dot.cui/FilesDeobfuscator.cs | 11 ++- 16 files changed, 222 insertions(+), 43 deletions(-) create mode 100644 de4dot.code/DeobfuscatorContext.cs create mode 100644 de4dot.code/IDeobfuscatorContext.cs diff --git a/blocks/DotNetUtils.cs b/blocks/DotNetUtils.cs index a3c1b98e..97ea6df7 100644 --- a/blocks/DotNetUtils.cs +++ b/blocks/DotNetUtils.cs @@ -519,6 +519,16 @@ namespace de4dot.blocks { return methodCalls; } + public static bool hasString(MethodDefinition method, string s) { + if (method == null || method.Body == null) + return false; + foreach (var instr in method.Body.Instructions) { + if (instr.OpCode.Code == Code.Ldstr && (string)instr.Operand == s) + return true; + } + return false; + } + public static IList getCodeStrings(MethodDefinition method) { var strings = new List(); if (method != null && method.Body != null) { diff --git a/de4dot.code/AssemblyResolver.cs b/de4dot.code/AssemblyResolver.cs index cd16cd54..8e94a97d 100644 --- a/de4dot.code/AssemblyResolver.cs +++ b/de4dot.code/AssemblyResolver.cs @@ -27,19 +27,23 @@ using Mono.Cecil; namespace de4dot.code { public class AssemblyResolver : DefaultAssemblyResolver { public static readonly AssemblyResolver Instance = new AssemblyResolver(); - Dictionary addedAssemblies = new Dictionary(StringComparer.Ordinal); Dictionary addedDirectories = new Dictionary(StringComparer.OrdinalIgnoreCase); static AssemblyResolver() { + Instance.resetSearchPaths(); + } + + void resetSearchPaths() { + addedDirectories.Clear(); addOtherAssemblySearchPaths(); } - static void addOtherAssemblySearchPaths() { + void addOtherAssemblySearchPaths() { addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles")); addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles(x86)")); } - static void addOtherAssemblySearchPaths(string path) { + void addOtherAssemblySearchPaths(string path) { if (string.IsNullOrEmpty(path)) return; addSilverlightDirs(Path.Combine(path, @"Microsoft Silverlight")); @@ -86,7 +90,7 @@ namespace de4dot.code { } // basePath is eg. "C:\Program Files (x86)\Microsoft Silverlight" - static void addSilverlightDirs(string basePath) { + void addSilverlightDirs(string basePath) { try { var di = new DirectoryInfo(basePath); foreach (var dir in di.GetDirectories()) { @@ -98,7 +102,7 @@ namespace de4dot.code { } } - static void addIfExists(string basePath, string extraPath) { + void addIfExists(string basePath, string extraPath) { try { var path = Path.Combine(basePath, extraPath); if (Utils.pathExists(path)) @@ -125,10 +129,7 @@ namespace de4dot.code { var assembly = module.Assembly; if (assembly != null) { var name = assembly.Name.FullName; - if (!addedAssemblies.ContainsKey(name) && cache.ContainsKey(name)) - throw new ApplicationException(string.Format("Assembly {0} was loaded by other code.", name)); - addedAssemblies[name] = true; - RegisterAssembly(assembly); + cache[name] = assembly; } } @@ -169,13 +170,12 @@ namespace de4dot.code { public void removeModule(string asmFullName) { if (string.IsNullOrEmpty(asmFullName)) return; - addedAssemblies.Remove(asmFullName); cache.Remove(asmFullName); } public void clearAll() { - addedAssemblies.Clear(); cache.Clear(); + resetSearchPaths(); } } } diff --git a/de4dot.code/DeobfuscatorContext.cs b/de4dot.code/DeobfuscatorContext.cs new file mode 100644 index 00000000..2a42df6b --- /dev/null +++ b/de4dot.code/DeobfuscatorContext.cs @@ -0,0 +1,99 @@ +/* + 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 Mono.Cecil; +using de4dot.blocks; + +namespace de4dot.code { + // "global" data and methods that is shared between all deobfuscators that deobfuscate + // assemblies at the same time. + public class DeobfuscatorContext : IDeobfuscatorContext { + ExternalAssemblies externalAssemblies = new ExternalAssemblies(); + Dictionary dataDict = new Dictionary(StringComparer.Ordinal); + + public void clear() { + dataDict.Clear(); + externalAssemblies.unloadAll(); + } + + public void setData(string name, object data) { + dataDict[name] = data; + } + + public object getData(string name) { + object value; + dataDict.TryGetValue(name, out value); + return value; + } + + public void clearData(string name) { + dataDict.Remove(name); + } + + public TypeDefinition resolve(TypeReference type) { + if (type == null) + return null; + var typeDef = type as TypeDefinition; + if (typeDef != null) + return typeDef; + + return externalAssemblies.resolve(type); + } + + public MethodDefinition resolve(MethodReference method) { + if (method == null) + return null; + var methodDef = method as MethodDefinition; + if (methodDef != null) + return methodDef; + + var type = resolve(method.DeclaringType); + if (type == null) + return null; + + foreach (var m in type.Methods) { + if (MemberReferenceHelper.compareMethodReference(method, m)) + return m; + } + + return null; + } + + public FieldDefinition resolve(FieldReference field) { + if (field == null) + return null; + var fieldDef = field as FieldDefinition; + if (fieldDef != null) + return fieldDef; + + var type = resolve(field.DeclaringType); + if (type == null) + return null; + + foreach (var f in type.Fields) { + if (MemberReferenceHelper.compareFieldReference(field, f)) + return f; + } + + return null; + } + } +} diff --git a/de4dot.code/ExternalAssemblies.cs b/de4dot.code/ExternalAssemblies.cs index 54daffb1..3913f491 100644 --- a/de4dot.code/ExternalAssemblies.cs +++ b/de4dot.code/ExternalAssemblies.cs @@ -17,6 +17,7 @@ along with de4dot. If not, see . */ +using System; using System.Collections.Generic; using Mono.Cecil; using de4dot.blocks; @@ -50,7 +51,8 @@ namespace de4dot.code { // Loads assemblies that aren't renamed class ExternalAssemblies { - Dictionary assemblies = new Dictionary(); + Dictionary assemblies = new Dictionary(StringComparer.Ordinal); + Dictionary failedLoads = new Dictionary(StringComparer.Ordinal); ExternalAssembly load(TypeReference type) { var asmFullName = DotNetUtils.getFullAssemblyName(type); @@ -67,9 +69,9 @@ namespace de4dot.code { catch (AssemblyResolutionException) { } if (asmDef == null) { - // If we can't load it now, we can't load it later. Make sure above code returns null. - assemblies[asmFullName] = null; - Log.w("Could not load assembly {0}", asmFullName); + if (!failedLoads.ContainsKey(asmFullName)) + Log.w("Could not load assembly {0}", asmFullName); + failedLoads[asmFullName] = true; return null; } if (assemblies.ContainsKey(asmDef.Name.FullName)) { @@ -89,6 +91,8 @@ namespace de4dot.code { } public TypeDefinition resolve(TypeReference type) { + if (type == null) + return null; var asm = load(type); if (asm == null) return null; @@ -102,6 +106,7 @@ namespace de4dot.code { pair.Value.unload(pair.Key); } assemblies.Clear(); + failedLoads.Clear(); } } } diff --git a/de4dot.code/IDeobfuscatorContext.cs b/de4dot.code/IDeobfuscatorContext.cs new file mode 100644 index 00000000..8a666876 --- /dev/null +++ b/de4dot.code/IDeobfuscatorContext.cs @@ -0,0 +1,32 @@ +/* + 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 Mono.Cecil; + +namespace de4dot.code { + public interface IDeobfuscatorContext { + void clear(); + void setData(string name, object data); + object getData(string name); + void clearData(string name); + TypeDefinition resolve(TypeReference type); + MethodDefinition resolve(MethodReference method); + FieldDefinition resolve(FieldReference field); + } +} diff --git a/de4dot.code/IObfuscatedFile.cs b/de4dot.code/IObfuscatedFile.cs index f6ad5d1f..2923d683 100644 --- a/de4dot.code/IObfuscatedFile.cs +++ b/de4dot.code/IObfuscatedFile.cs @@ -26,6 +26,7 @@ namespace de4dot.code { public interface IObfuscatedFile { ModuleDefinition ModuleDefinition { get; } IDeobfuscator Deobfuscator { get; } + IDeobfuscatorContext DeobfuscatorContext { get; set; } string Filename { get; } string NewFilename { get; } INameChecker NameChecker { get; } diff --git a/de4dot.code/ObfuscatedFile.cs b/de4dot.code/ObfuscatedFile.cs index 3330636e..1323f9fa 100644 --- a/de4dot.code/ObfuscatedFile.cs +++ b/de4dot.code/ObfuscatedFile.cs @@ -38,6 +38,7 @@ namespace de4dot.code { ModuleDefinition module; IList allMethods; IDeobfuscator deob; + IDeobfuscatorContext deobfuscatorContext; AssemblyModule assemblyModule; IAssemblyClient assemblyClient; DynamicStringInliner dynamicStringInliner; @@ -123,6 +124,11 @@ namespace de4dot.code { get { return deob; } } + public IDeobfuscatorContext DeobfuscatorContext { + get { return deobfuscatorContext; } + set { deobfuscatorContext = value; } + } + public ObfuscatedFile(Options options, IAssemblyClientFactory assemblyClientFactory) { this.assemblyClientFactory = assemblyClientFactory; this.options = options; diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index f04a37b7..f2557242 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -58,6 +58,7 @@ + @@ -204,6 +205,7 @@ + diff --git a/de4dot.code/deobfuscators/Babel_NET/Deobfuscator.cs b/de4dot.code/deobfuscators/Babel_NET/Deobfuscator.cs index 7d7bccef..1a809fab 100644 --- a/de4dot.code/deobfuscators/Babel_NET/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/Babel_NET/Deobfuscator.cs @@ -141,7 +141,7 @@ namespace de4dot.code.deobfuscators.Babel_NET { constantsDecrypter.find(); proxyDelegateFinder = new ProxyDelegateFinder(module); proxyDelegateFinder.findDelegateCreator(); - methodsDecrypter = new MethodsDecrypter(module); + methodsDecrypter = new MethodsDecrypter(module, DeobfuscatedFile.DeobfuscatorContext); methodsDecrypter.find(); } @@ -256,7 +256,6 @@ namespace de4dot.code.deobfuscators.Babel_NET { } removeProxyDelegates(proxyDelegateFinder); - methodsDecrypter.Dispose(); base.deobfuscateEnd(); } diff --git a/de4dot.code/deobfuscators/Babel_NET/ImageReader.cs b/de4dot.code/deobfuscators/Babel_NET/ImageReader.cs index a81f2f66..31f22aac 100644 --- a/de4dot.code/deobfuscators/Babel_NET/ImageReader.cs +++ b/de4dot.code/deobfuscators/Babel_NET/ImageReader.cs @@ -27,7 +27,7 @@ using Mono.Cecil.Cil; using de4dot.blocks; namespace de4dot.code.deobfuscators.Babel_NET { - class ImageReader : IDisposable { + class ImageReader { static int METHODS_SIG = 0x0000BEBA; static int METADATA_SIG = 0x0100BEBA; static int METHOD_NAMES_SIG = 0x0200BEBA; @@ -50,9 +50,10 @@ namespace de4dot.code.deobfuscators.Babel_NET { Dictionary methodOffsets; List typeReferences; MemberReferenceConverter memberReferenceConverter; - ExternalAssemblies externalAssemblies = new ExternalAssemblies(); + IDeobfuscatorContext deobfuscatorContext; - public ImageReader(ModuleDefinition module, byte[] data) { + public ImageReader(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module, byte[] data) { + this.deobfuscatorContext = deobfuscatorContext; this.module = module; this.reader = new BinaryReader(new MemoryStream(data)); this.memberReferenceConverter = new MemberReferenceConverter(module); @@ -74,10 +75,6 @@ namespace de4dot.code.deobfuscators.Babel_NET { return true; } - public void Dispose() { - externalAssemblies.unloadAll(); - } - void initializeV10() { reader.ReadInt16(); int methodNamesOffset = (int)reader.ReadInt64(); @@ -254,7 +251,7 @@ namespace de4dot.code.deobfuscators.Babel_NET { if (type.Module == module && isModuleAssembly(type.Scope)) return DotNetUtils.getType(module, type); - return externalAssemblies.resolve(type); + return deobfuscatorContext.resolve(type); } public CallSite readCallSite() { diff --git a/de4dot.code/deobfuscators/Babel_NET/MethodsDecrypter.cs b/de4dot.code/deobfuscators/Babel_NET/MethodsDecrypter.cs index 11ed7057..643c8bce 100644 --- a/de4dot.code/deobfuscators/Babel_NET/MethodsDecrypter.cs +++ b/de4dot.code/deobfuscators/Babel_NET/MethodsDecrypter.cs @@ -25,8 +25,9 @@ using Mono.Cecil.Cil; using de4dot.blocks; namespace de4dot.code.deobfuscators.Babel_NET { - class MethodsDecrypter : IDisposable { + class MethodsDecrypter { ModuleDefinition module; + IDeobfuscatorContext deobfuscatorContext; Dictionary imageReaders = new Dictionary(StringComparer.Ordinal); TypeDefinition methodsDecrypterCreator; TypeDefinition methodsDecrypter; @@ -37,13 +38,9 @@ namespace de4dot.code.deobfuscators.Babel_NET { get { return methodsDecrypterCreator != null; } } - public MethodsDecrypter(ModuleDefinition module) { + public MethodsDecrypter(ModuleDefinition module, IDeobfuscatorContext deobfuscatorContext) { this.module = module; - } - - public void Dispose() { - foreach (var imageReader in imageReaders.Values) - imageReader.Dispose(); + this.deobfuscatorContext = deobfuscatorContext; } public void find() { @@ -104,7 +101,7 @@ namespace de4dot.code.deobfuscators.Babel_NET { } void addImageReader(string name, byte[] data) { - var imageReader = new ImageReader(module, data); + var imageReader = new ImageReader(deobfuscatorContext, module, data); if (!imageReader.initialize()) { Log.w("Could not read encrypted methods"); return; @@ -147,9 +144,6 @@ namespace de4dot.code.deobfuscators.Babel_NET { } if (numNonDecryptedMethods > 0) Log.w("{0}/{1} methods not decrypted", numNonDecryptedMethods, totalEncryptedMethods); - - foreach (var imageReader in imageReaders.Values) - imageReader.Dispose(); } List getEncryptedMethods() { diff --git a/de4dot.code/deobfuscators/DeobfuscatorBase.cs b/de4dot.code/deobfuscators/DeobfuscatorBase.cs index 6afeaf96..2ed61c96 100644 --- a/de4dot.code/deobfuscators/DeobfuscatorBase.cs +++ b/de4dot.code/deobfuscators/DeobfuscatorBase.cs @@ -48,6 +48,7 @@ namespace de4dot.code.deobfuscators { IList> attrsToRemove = new List>(); IList> resourcesToRemove = new List>(); IList> modrefsToRemove = new List>(); + IList> asmrefsToRemove = new List>(); List namesToPossiblyRemove = new List(); MethodCallRemover methodCallRemover = new MethodCallRemover(); byte[] moduleBytes; @@ -181,6 +182,7 @@ namespace de4dot.code.deobfuscators { deleteDllResources(); deleteModuleReferences(); + deleteAssemblyReferences(); } restoreBaseType(); @@ -377,6 +379,10 @@ namespace de4dot.code.deobfuscators { modrefsToRemove.Add(new RemoveInfo(modref, reason)); } + protected void addAssemblyReferenceToBeRemoved(AssemblyNameReference asmRef, string reason) { + asmrefsToRemove.Add(new RemoveInfo(asmRef, reason)); + } + void deleteEmptyCctors() { var emptyCctorsToRemove = new List(); foreach (var type in module.GetTypes()) { @@ -553,6 +559,22 @@ namespace de4dot.code.deobfuscators { Log.deIndent(); } + void deleteAssemblyReferences() { + if (!module.HasAssemblyReferences || asmrefsToRemove.Count == 0) + return; + + Log.v("Removing assembly references"); + Log.indent(); + foreach (var info in asmrefsToRemove) { + var asmRef = info.obj; + if (asmRef == null) + continue; + if (module.AssemblyReferences.Remove(asmRef)) + Log.v("Removed assembly reference {0} (reason: {1})", asmRef, info.reason); + } + Log.deIndent(); + } + public override string ToString() { return Name; } diff --git a/de4dot.code/deobfuscators/IDeobfuscatedFile.cs b/de4dot.code/deobfuscators/IDeobfuscatedFile.cs index 34fe7d22..60b34c52 100644 --- a/de4dot.code/deobfuscators/IDeobfuscatedFile.cs +++ b/de4dot.code/deobfuscators/IDeobfuscatedFile.cs @@ -19,6 +19,7 @@ namespace de4dot.code.deobfuscators { public interface IDeobfuscatedFile : ISimpleDeobfuscator { + IDeobfuscatorContext DeobfuscatorContext { get; } void createAssemblyFile(byte[] data, string assemblyName, string extension = null); void stringDecryptersAdded(); } diff --git a/de4dot.code/renamer/Renamer.cs b/de4dot.code/renamer/Renamer.cs index 7040d4ee..2b29baa8 100644 --- a/de4dot.code/renamer/Renamer.cs +++ b/de4dot.code/renamer/Renamer.cs @@ -40,7 +40,7 @@ namespace de4dot.code.renamer { public bool RestoreEvents { get; set; } public bool RestoreEventsFromNames { get; set; } - Modules modules = new Modules(); + Modules modules; MemberInfos memberInfos = new MemberInfos(); DerivedFrom isDelegateClass; MergeStateHelper mergeStateHelper; @@ -50,7 +50,7 @@ namespace de4dot.code.renamer { "System.MulticastDelegate", }; - public Renamer(IEnumerable files) { + public Renamer(IDeobfuscatorContext deobfuscatorContext, IEnumerable files) { RenameNamespaces = true; RenameTypes = true; RenameProperties = true; @@ -64,6 +64,7 @@ namespace de4dot.code.renamer { RestoreEvents = true; RestoreEventsFromNames = true; + modules = new Modules(deobfuscatorContext); isDelegateClass = new DerivedFrom(delegateClasses); mergeStateHelper = new MergeStateHelper(memberInfos); diff --git a/de4dot.code/renamer/asmmodules/Modules.cs b/de4dot.code/renamer/asmmodules/Modules.cs index 27e42bbd..8550f9e5 100644 --- a/de4dot.code/renamer/asmmodules/Modules.cs +++ b/de4dot.code/renamer/asmmodules/Modules.cs @@ -25,6 +25,7 @@ using de4dot.blocks; namespace de4dot.code.renamer.asmmodules { class Modules : IResolver { bool initializeCalled = false; + IDeobfuscatorContext deobfuscatorContext; List modules = new List(); Dictionary modulesDict = new Dictionary(); AssemblyHash assemblyHash = new AssemblyHash(); @@ -131,6 +132,10 @@ namespace de4dot.code.renamer.asmmodules { get { return modules.Count == 0; } } + public Modules(IDeobfuscatorContext deobfuscatorContext) { + this.deobfuscatorContext = deobfuscatorContext; + } + public void add(Module module) { if (initializeCalled) throw new ApplicationException("initialize() has been called"); @@ -323,7 +328,6 @@ namespace de4dot.code.renamer.asmmodules { } AssemblyKeyDictionary typeToTypeDefDict = new AssemblyKeyDictionary(); - ExternalAssemblies externalAssemblies = new ExternalAssemblies(); public TypeDef resolveOther(TypeReference type) { if (type == null) return null; @@ -333,7 +337,7 @@ namespace de4dot.code.renamer.asmmodules { if (typeToTypeDefDict.tryGetValue(type, out typeDef)) return typeDef; - var typeDefinition = externalAssemblies.resolve(type); + var typeDefinition = deobfuscatorContext.resolve(type); if (typeDefinition == null) { typeToTypeDefDict.tryGetSimilarValue(type, out typeDef); typeToTypeDefDict[type] = typeDef; @@ -379,7 +383,6 @@ namespace de4dot.code.renamer.asmmodules { } public void cleanUp() { - externalAssemblies.unloadAll(); foreach (var module in DotNetUtils.typeCaches.invalidateAll()) AssemblyResolver.Instance.removeModule(module); } diff --git a/de4dot.cui/FilesDeobfuscator.cs b/de4dot.cui/FilesDeobfuscator.cs index 15ce4718..b935b174 100644 --- a/de4dot.cui/FilesDeobfuscator.cs +++ b/de4dot.cui/FilesDeobfuscator.cs @@ -30,6 +30,7 @@ using de4dot.code.AssemblyClient; namespace de4dot.cui { class FilesDeobfuscator { Options options; + IDeobfuscatorContext deobfuscatorContext = new DeobfuscatorContext(); public class Options { public IList DeobfuscatorInfos { get; set; } @@ -81,8 +82,10 @@ namespace de4dot.cui { } void detectObfuscators() { - foreach (var file in loadAllFiles(true)) + foreach (var file in loadAllFiles(true)) { removeModule(file.ModuleDefinition); + deobfuscatorContext.clear(); + } } void deobfuscateOneAtATime() { @@ -97,6 +100,7 @@ namespace de4dot.cui { removeModule(file.ModuleDefinition); AssemblyResolver.Instance.clearAll(); + deobfuscatorContext.clear(); } catch (Exception ex) { Log.w("Could not deobfuscate {0}. Use -v to see stack trace", file.Filename); @@ -124,6 +128,7 @@ namespace de4dot.cui { DefaultStringDecrypterType = options.DefaultStringDecrypterType, DefaultStringDecrypterMethods = options.DefaultStringDecrypterMethods, AssemblyClientFactory = options.AssemblyClientFactory, + DeobfuscatorContext = deobfuscatorContext, ControlFlowDeobfuscation = options.ControlFlowDeobfuscation, KeepObfuscatorTypes = options.KeepObfuscatorTypes, CreateDestinationDir = !onlyScan, @@ -154,6 +159,7 @@ namespace de4dot.cui { public DecrypterType? DefaultStringDecrypterType { get; set; } public List DefaultStringDecrypterMethods { get; set; } public IAssemblyClientFactory AssemblyClientFactory { get; set; } + public IDeobfuscatorContext DeobfuscatorContext { get; set; } public bool ControlFlowDeobfuscation { get; set; } public bool KeepObfuscatorTypes { get; set; } public bool CreateDestinationDir { get; set; } @@ -185,6 +191,7 @@ namespace de4dot.cui { int oldIndentLevel = Log.indentLevel; try { + file.DeobfuscatorContext = options.DeobfuscatorContext; file.load(options.CreateDeobfuscators()); } catch (NotSupportedException) { @@ -351,7 +358,7 @@ namespace de4dot.cui { void rename(IEnumerable theFiles) { if (!options.RenameSymbols) return; - var renamer = new Renamer(theFiles) { + var renamer = new Renamer(deobfuscatorContext, theFiles) { RestorePropertiesFromNames = options.RestorePropsEvents, RestoreEventsFromNames = options.RestorePropsEvents, };