Add shared deobfuscator data/methods
This commit is contained in:
parent
7c8259905b
commit
9cfe8431f6
|
@ -519,6 +519,16 @@ namespace de4dot.blocks {
|
||||||
return methodCalls;
|
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<string> getCodeStrings(MethodDefinition method) {
|
public static IList<string> getCodeStrings(MethodDefinition method) {
|
||||||
var strings = new List<string>();
|
var strings = new List<string>();
|
||||||
if (method != null && method.Body != null) {
|
if (method != null && method.Body != null) {
|
||||||
|
|
|
@ -27,19 +27,23 @@ using Mono.Cecil;
|
||||||
namespace de4dot.code {
|
namespace de4dot.code {
|
||||||
public class AssemblyResolver : DefaultAssemblyResolver {
|
public class AssemblyResolver : DefaultAssemblyResolver {
|
||||||
public static readonly AssemblyResolver Instance = new AssemblyResolver();
|
public static readonly AssemblyResolver Instance = new AssemblyResolver();
|
||||||
Dictionary<string, bool> addedAssemblies = new Dictionary<string, bool>(StringComparer.Ordinal);
|
|
||||||
Dictionary<string, bool> addedDirectories = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
Dictionary<string, bool> addedDirectories = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
static AssemblyResolver() {
|
static AssemblyResolver() {
|
||||||
|
Instance.resetSearchPaths();
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetSearchPaths() {
|
||||||
|
addedDirectories.Clear();
|
||||||
addOtherAssemblySearchPaths();
|
addOtherAssemblySearchPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addOtherAssemblySearchPaths() {
|
void addOtherAssemblySearchPaths() {
|
||||||
addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles"));
|
addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles"));
|
||||||
addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles(x86)"));
|
addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles(x86)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addOtherAssemblySearchPaths(string path) {
|
void addOtherAssemblySearchPaths(string path) {
|
||||||
if (string.IsNullOrEmpty(path))
|
if (string.IsNullOrEmpty(path))
|
||||||
return;
|
return;
|
||||||
addSilverlightDirs(Path.Combine(path, @"Microsoft Silverlight"));
|
addSilverlightDirs(Path.Combine(path, @"Microsoft Silverlight"));
|
||||||
|
@ -86,7 +90,7 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
|
|
||||||
// basePath is eg. "C:\Program Files (x86)\Microsoft Silverlight"
|
// basePath is eg. "C:\Program Files (x86)\Microsoft Silverlight"
|
||||||
static void addSilverlightDirs(string basePath) {
|
void addSilverlightDirs(string basePath) {
|
||||||
try {
|
try {
|
||||||
var di = new DirectoryInfo(basePath);
|
var di = new DirectoryInfo(basePath);
|
||||||
foreach (var dir in di.GetDirectories()) {
|
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 {
|
try {
|
||||||
var path = Path.Combine(basePath, extraPath);
|
var path = Path.Combine(basePath, extraPath);
|
||||||
if (Utils.pathExists(path))
|
if (Utils.pathExists(path))
|
||||||
|
@ -125,10 +129,7 @@ namespace de4dot.code {
|
||||||
var assembly = module.Assembly;
|
var assembly = module.Assembly;
|
||||||
if (assembly != null) {
|
if (assembly != null) {
|
||||||
var name = assembly.Name.FullName;
|
var name = assembly.Name.FullName;
|
||||||
if (!addedAssemblies.ContainsKey(name) && cache.ContainsKey(name))
|
cache[name] = assembly;
|
||||||
throw new ApplicationException(string.Format("Assembly {0} was loaded by other code.", name));
|
|
||||||
addedAssemblies[name] = true;
|
|
||||||
RegisterAssembly(assembly);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,13 +170,12 @@ namespace de4dot.code {
|
||||||
public void removeModule(string asmFullName) {
|
public void removeModule(string asmFullName) {
|
||||||
if (string.IsNullOrEmpty(asmFullName))
|
if (string.IsNullOrEmpty(asmFullName))
|
||||||
return;
|
return;
|
||||||
addedAssemblies.Remove(asmFullName);
|
|
||||||
cache.Remove(asmFullName);
|
cache.Remove(asmFullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearAll() {
|
public void clearAll() {
|
||||||
addedAssemblies.Clear();
|
|
||||||
cache.Clear();
|
cache.Clear();
|
||||||
|
resetSearchPaths();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
99
de4dot.code/DeobfuscatorContext.cs
Normal file
99
de4dot.code/DeobfuscatorContext.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<string, object> dataDict = new Dictionary<string, object>(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
@ -50,7 +51,8 @@ namespace de4dot.code {
|
||||||
|
|
||||||
// Loads assemblies that aren't renamed
|
// Loads assemblies that aren't renamed
|
||||||
class ExternalAssemblies {
|
class ExternalAssemblies {
|
||||||
Dictionary<string, ExternalAssembly> assemblies = new Dictionary<string, ExternalAssembly>();
|
Dictionary<string, ExternalAssembly> assemblies = new Dictionary<string, ExternalAssembly>(StringComparer.Ordinal);
|
||||||
|
Dictionary<string, bool> failedLoads = new Dictionary<string, bool>(StringComparer.Ordinal);
|
||||||
|
|
||||||
ExternalAssembly load(TypeReference type) {
|
ExternalAssembly load(TypeReference type) {
|
||||||
var asmFullName = DotNetUtils.getFullAssemblyName(type);
|
var asmFullName = DotNetUtils.getFullAssemblyName(type);
|
||||||
|
@ -67,9 +69,9 @@ namespace de4dot.code {
|
||||||
catch (AssemblyResolutionException) {
|
catch (AssemblyResolutionException) {
|
||||||
}
|
}
|
||||||
if (asmDef == null) {
|
if (asmDef == null) {
|
||||||
// If we can't load it now, we can't load it later. Make sure above code returns null.
|
if (!failedLoads.ContainsKey(asmFullName))
|
||||||
assemblies[asmFullName] = null;
|
Log.w("Could not load assembly {0}", asmFullName);
|
||||||
Log.w("Could not load assembly {0}", asmFullName);
|
failedLoads[asmFullName] = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (assemblies.ContainsKey(asmDef.Name.FullName)) {
|
if (assemblies.ContainsKey(asmDef.Name.FullName)) {
|
||||||
|
@ -89,6 +91,8 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeDefinition resolve(TypeReference type) {
|
public TypeDefinition resolve(TypeReference type) {
|
||||||
|
if (type == null)
|
||||||
|
return null;
|
||||||
var asm = load(type);
|
var asm = load(type);
|
||||||
if (asm == null)
|
if (asm == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -102,6 +106,7 @@ namespace de4dot.code {
|
||||||
pair.Value.unload(pair.Key);
|
pair.Value.unload(pair.Key);
|
||||||
}
|
}
|
||||||
assemblies.Clear();
|
assemblies.Clear();
|
||||||
|
failedLoads.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
32
de4dot.code/IDeobfuscatorContext.cs
Normal file
32
de4dot.code/IDeobfuscatorContext.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ namespace de4dot.code {
|
||||||
public interface IObfuscatedFile {
|
public interface IObfuscatedFile {
|
||||||
ModuleDefinition ModuleDefinition { get; }
|
ModuleDefinition ModuleDefinition { get; }
|
||||||
IDeobfuscator Deobfuscator { get; }
|
IDeobfuscator Deobfuscator { get; }
|
||||||
|
IDeobfuscatorContext DeobfuscatorContext { get; set; }
|
||||||
string Filename { get; }
|
string Filename { get; }
|
||||||
string NewFilename { get; }
|
string NewFilename { get; }
|
||||||
INameChecker NameChecker { get; }
|
INameChecker NameChecker { get; }
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace de4dot.code {
|
||||||
ModuleDefinition module;
|
ModuleDefinition module;
|
||||||
IList<MethodDefinition> allMethods;
|
IList<MethodDefinition> allMethods;
|
||||||
IDeobfuscator deob;
|
IDeobfuscator deob;
|
||||||
|
IDeobfuscatorContext deobfuscatorContext;
|
||||||
AssemblyModule assemblyModule;
|
AssemblyModule assemblyModule;
|
||||||
IAssemblyClient assemblyClient;
|
IAssemblyClient assemblyClient;
|
||||||
DynamicStringInliner dynamicStringInliner;
|
DynamicStringInliner dynamicStringInliner;
|
||||||
|
@ -123,6 +124,11 @@ namespace de4dot.code {
|
||||||
get { return deob; }
|
get { return deob; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IDeobfuscatorContext DeobfuscatorContext {
|
||||||
|
get { return deobfuscatorContext; }
|
||||||
|
set { deobfuscatorContext = value; }
|
||||||
|
}
|
||||||
|
|
||||||
public ObfuscatedFile(Options options, IAssemblyClientFactory assemblyClientFactory) {
|
public ObfuscatedFile(Options options, IAssemblyClientFactory assemblyClientFactory) {
|
||||||
this.assemblyClientFactory = assemblyClientFactory;
|
this.assemblyClientFactory = assemblyClientFactory;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
<Compile Include="AssemblyClient\NewProcessAssemblyServerLoader.cs" />
|
<Compile Include="AssemblyClient\NewProcessAssemblyServerLoader.cs" />
|
||||||
<Compile Include="AssemblyClient\SameAppDomainAssemblyServerLoader.cs" />
|
<Compile Include="AssemblyClient\SameAppDomainAssemblyServerLoader.cs" />
|
||||||
<Compile Include="AssemblyResolver.cs" />
|
<Compile Include="AssemblyResolver.cs" />
|
||||||
|
<Compile Include="DeobfuscatorContext.cs" />
|
||||||
<Compile Include="deobfuscators\ArrayFinder.cs" />
|
<Compile Include="deobfuscators\ArrayFinder.cs" />
|
||||||
<Compile Include="deobfuscators\Babel_NET\AssemblyResolver.cs" />
|
<Compile Include="deobfuscators\Babel_NET\AssemblyResolver.cs" />
|
||||||
<Compile Include="deobfuscators\Babel_NET\BabelUtils.cs" />
|
<Compile Include="deobfuscators\Babel_NET\BabelUtils.cs" />
|
||||||
|
@ -204,6 +205,7 @@
|
||||||
<Compile Include="deobfuscators\ValueInlinerBase.cs" />
|
<Compile Include="deobfuscators\ValueInlinerBase.cs" />
|
||||||
<Compile Include="deobfuscators\Xenocode\Deobfuscator.cs" />
|
<Compile Include="deobfuscators\Xenocode\Deobfuscator.cs" />
|
||||||
<Compile Include="deobfuscators\Xenocode\StringDecrypter.cs" />
|
<Compile Include="deobfuscators\Xenocode\StringDecrypter.cs" />
|
||||||
|
<Compile Include="IDeobfuscatorContext.cs" />
|
||||||
<Compile Include="IObfuscatedFile.cs" />
|
<Compile Include="IObfuscatedFile.cs" />
|
||||||
<Compile Include="Log.cs" />
|
<Compile Include="Log.cs" />
|
||||||
<Compile Include="AssemblyModule.cs" />
|
<Compile Include="AssemblyModule.cs" />
|
||||||
|
|
|
@ -141,7 +141,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
constantsDecrypter.find();
|
constantsDecrypter.find();
|
||||||
proxyDelegateFinder = new ProxyDelegateFinder(module);
|
proxyDelegateFinder = new ProxyDelegateFinder(module);
|
||||||
proxyDelegateFinder.findDelegateCreator();
|
proxyDelegateFinder.findDelegateCreator();
|
||||||
methodsDecrypter = new MethodsDecrypter(module);
|
methodsDecrypter = new MethodsDecrypter(module, DeobfuscatedFile.DeobfuscatorContext);
|
||||||
methodsDecrypter.find();
|
methodsDecrypter.find();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +256,6 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
removeProxyDelegates(proxyDelegateFinder);
|
removeProxyDelegates(proxyDelegateFinder);
|
||||||
methodsDecrypter.Dispose();
|
|
||||||
base.deobfuscateEnd();
|
base.deobfuscateEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ using Mono.Cecil.Cil;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
class ImageReader : IDisposable {
|
class ImageReader {
|
||||||
static int METHODS_SIG = 0x0000BEBA;
|
static int METHODS_SIG = 0x0000BEBA;
|
||||||
static int METADATA_SIG = 0x0100BEBA;
|
static int METADATA_SIG = 0x0100BEBA;
|
||||||
static int METHOD_NAMES_SIG = 0x0200BEBA;
|
static int METHOD_NAMES_SIG = 0x0200BEBA;
|
||||||
|
@ -50,9 +50,10 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
Dictionary<string, int> methodOffsets;
|
Dictionary<string, int> methodOffsets;
|
||||||
List<TypeReference> typeReferences;
|
List<TypeReference> typeReferences;
|
||||||
MemberReferenceConverter memberReferenceConverter;
|
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.module = module;
|
||||||
this.reader = new BinaryReader(new MemoryStream(data));
|
this.reader = new BinaryReader(new MemoryStream(data));
|
||||||
this.memberReferenceConverter = new MemberReferenceConverter(module);
|
this.memberReferenceConverter = new MemberReferenceConverter(module);
|
||||||
|
@ -74,10 +75,6 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
externalAssemblies.unloadAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void initializeV10() {
|
void initializeV10() {
|
||||||
reader.ReadInt16();
|
reader.ReadInt16();
|
||||||
int methodNamesOffset = (int)reader.ReadInt64();
|
int methodNamesOffset = (int)reader.ReadInt64();
|
||||||
|
@ -254,7 +251,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
if (type.Module == module && isModuleAssembly(type.Scope))
|
if (type.Module == module && isModuleAssembly(type.Scope))
|
||||||
return DotNetUtils.getType(module, type);
|
return DotNetUtils.getType(module, type);
|
||||||
|
|
||||||
return externalAssemblies.resolve(type);
|
return deobfuscatorContext.resolve(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CallSite readCallSite() {
|
public CallSite readCallSite() {
|
||||||
|
|
|
@ -25,8 +25,9 @@ using Mono.Cecil.Cil;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
class MethodsDecrypter : IDisposable {
|
class MethodsDecrypter {
|
||||||
ModuleDefinition module;
|
ModuleDefinition module;
|
||||||
|
IDeobfuscatorContext deobfuscatorContext;
|
||||||
Dictionary<string, ImageReader> imageReaders = new Dictionary<string, ImageReader>(StringComparer.Ordinal);
|
Dictionary<string, ImageReader> imageReaders = new Dictionary<string, ImageReader>(StringComparer.Ordinal);
|
||||||
TypeDefinition methodsDecrypterCreator;
|
TypeDefinition methodsDecrypterCreator;
|
||||||
TypeDefinition methodsDecrypter;
|
TypeDefinition methodsDecrypter;
|
||||||
|
@ -37,13 +38,9 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
get { return methodsDecrypterCreator != null; }
|
get { return methodsDecrypterCreator != null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodsDecrypter(ModuleDefinition module) {
|
public MethodsDecrypter(ModuleDefinition module, IDeobfuscatorContext deobfuscatorContext) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
this.deobfuscatorContext = deobfuscatorContext;
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
foreach (var imageReader in imageReaders.Values)
|
|
||||||
imageReader.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void find() {
|
public void find() {
|
||||||
|
@ -104,7 +101,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
void addImageReader(string name, byte[] data) {
|
void addImageReader(string name, byte[] data) {
|
||||||
var imageReader = new ImageReader(module, data);
|
var imageReader = new ImageReader(deobfuscatorContext, module, data);
|
||||||
if (!imageReader.initialize()) {
|
if (!imageReader.initialize()) {
|
||||||
Log.w("Could not read encrypted methods");
|
Log.w("Could not read encrypted methods");
|
||||||
return;
|
return;
|
||||||
|
@ -147,9 +144,6 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
if (numNonDecryptedMethods > 0)
|
if (numNonDecryptedMethods > 0)
|
||||||
Log.w("{0}/{1} methods not decrypted", numNonDecryptedMethods, totalEncryptedMethods);
|
Log.w("{0}/{1} methods not decrypted", numNonDecryptedMethods, totalEncryptedMethods);
|
||||||
|
|
||||||
foreach (var imageReader in imageReaders.Values)
|
|
||||||
imageReader.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<EncryptInfo> getEncryptedMethods() {
|
List<EncryptInfo> getEncryptedMethods() {
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
IList<RemoveInfo<TypeDefinition>> attrsToRemove = new List<RemoveInfo<TypeDefinition>>();
|
IList<RemoveInfo<TypeDefinition>> attrsToRemove = new List<RemoveInfo<TypeDefinition>>();
|
||||||
IList<RemoveInfo<Resource>> resourcesToRemove = new List<RemoveInfo<Resource>>();
|
IList<RemoveInfo<Resource>> resourcesToRemove = new List<RemoveInfo<Resource>>();
|
||||||
IList<RemoveInfo<ModuleReference>> modrefsToRemove = new List<RemoveInfo<ModuleReference>>();
|
IList<RemoveInfo<ModuleReference>> modrefsToRemove = new List<RemoveInfo<ModuleReference>>();
|
||||||
|
IList<RemoveInfo<AssemblyNameReference>> asmrefsToRemove = new List<RemoveInfo<AssemblyNameReference>>();
|
||||||
List<string> namesToPossiblyRemove = new List<string>();
|
List<string> namesToPossiblyRemove = new List<string>();
|
||||||
MethodCallRemover methodCallRemover = new MethodCallRemover();
|
MethodCallRemover methodCallRemover = new MethodCallRemover();
|
||||||
byte[] moduleBytes;
|
byte[] moduleBytes;
|
||||||
|
@ -181,6 +182,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
deleteDllResources();
|
deleteDllResources();
|
||||||
deleteModuleReferences();
|
deleteModuleReferences();
|
||||||
|
deleteAssemblyReferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreBaseType();
|
restoreBaseType();
|
||||||
|
@ -377,6 +379,10 @@ namespace de4dot.code.deobfuscators {
|
||||||
modrefsToRemove.Add(new RemoveInfo<ModuleReference>(modref, reason));
|
modrefsToRemove.Add(new RemoveInfo<ModuleReference>(modref, reason));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void addAssemblyReferenceToBeRemoved(AssemblyNameReference asmRef, string reason) {
|
||||||
|
asmrefsToRemove.Add(new RemoveInfo<AssemblyNameReference>(asmRef, reason));
|
||||||
|
}
|
||||||
|
|
||||||
void deleteEmptyCctors() {
|
void deleteEmptyCctors() {
|
||||||
var emptyCctorsToRemove = new List<MethodDefinition>();
|
var emptyCctorsToRemove = new List<MethodDefinition>();
|
||||||
foreach (var type in module.GetTypes()) {
|
foreach (var type in module.GetTypes()) {
|
||||||
|
@ -553,6 +559,22 @@ namespace de4dot.code.deobfuscators {
|
||||||
Log.deIndent();
|
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() {
|
public override string ToString() {
|
||||||
return Name;
|
return Name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
public interface IDeobfuscatedFile : ISimpleDeobfuscator {
|
public interface IDeobfuscatedFile : ISimpleDeobfuscator {
|
||||||
|
IDeobfuscatorContext DeobfuscatorContext { get; }
|
||||||
void createAssemblyFile(byte[] data, string assemblyName, string extension = null);
|
void createAssemblyFile(byte[] data, string assemblyName, string extension = null);
|
||||||
void stringDecryptersAdded();
|
void stringDecryptersAdded();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace de4dot.code.renamer {
|
||||||
public bool RestoreEvents { get; set; }
|
public bool RestoreEvents { get; set; }
|
||||||
public bool RestoreEventsFromNames { get; set; }
|
public bool RestoreEventsFromNames { get; set; }
|
||||||
|
|
||||||
Modules modules = new Modules();
|
Modules modules;
|
||||||
MemberInfos memberInfos = new MemberInfos();
|
MemberInfos memberInfos = new MemberInfos();
|
||||||
DerivedFrom isDelegateClass;
|
DerivedFrom isDelegateClass;
|
||||||
MergeStateHelper mergeStateHelper;
|
MergeStateHelper mergeStateHelper;
|
||||||
|
@ -50,7 +50,7 @@ namespace de4dot.code.renamer {
|
||||||
"System.MulticastDelegate",
|
"System.MulticastDelegate",
|
||||||
};
|
};
|
||||||
|
|
||||||
public Renamer(IEnumerable<IObfuscatedFile> files) {
|
public Renamer(IDeobfuscatorContext deobfuscatorContext, IEnumerable<IObfuscatedFile> files) {
|
||||||
RenameNamespaces = true;
|
RenameNamespaces = true;
|
||||||
RenameTypes = true;
|
RenameTypes = true;
|
||||||
RenameProperties = true;
|
RenameProperties = true;
|
||||||
|
@ -64,6 +64,7 @@ namespace de4dot.code.renamer {
|
||||||
RestoreEvents = true;
|
RestoreEvents = true;
|
||||||
RestoreEventsFromNames = true;
|
RestoreEventsFromNames = true;
|
||||||
|
|
||||||
|
modules = new Modules(deobfuscatorContext);
|
||||||
isDelegateClass = new DerivedFrom(delegateClasses);
|
isDelegateClass = new DerivedFrom(delegateClasses);
|
||||||
mergeStateHelper = new MergeStateHelper(memberInfos);
|
mergeStateHelper = new MergeStateHelper(memberInfos);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ using de4dot.blocks;
|
||||||
namespace de4dot.code.renamer.asmmodules {
|
namespace de4dot.code.renamer.asmmodules {
|
||||||
class Modules : IResolver {
|
class Modules : IResolver {
|
||||||
bool initializeCalled = false;
|
bool initializeCalled = false;
|
||||||
|
IDeobfuscatorContext deobfuscatorContext;
|
||||||
List<Module> modules = new List<Module>();
|
List<Module> modules = new List<Module>();
|
||||||
Dictionary<ModuleDefinition, Module> modulesDict = new Dictionary<ModuleDefinition, Module>();
|
Dictionary<ModuleDefinition, Module> modulesDict = new Dictionary<ModuleDefinition, Module>();
|
||||||
AssemblyHash assemblyHash = new AssemblyHash();
|
AssemblyHash assemblyHash = new AssemblyHash();
|
||||||
|
@ -131,6 +132,10 @@ namespace de4dot.code.renamer.asmmodules {
|
||||||
get { return modules.Count == 0; }
|
get { return modules.Count == 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Modules(IDeobfuscatorContext deobfuscatorContext) {
|
||||||
|
this.deobfuscatorContext = deobfuscatorContext;
|
||||||
|
}
|
||||||
|
|
||||||
public void add(Module module) {
|
public void add(Module module) {
|
||||||
if (initializeCalled)
|
if (initializeCalled)
|
||||||
throw new ApplicationException("initialize() has been called");
|
throw new ApplicationException("initialize() has been called");
|
||||||
|
@ -323,7 +328,6 @@ namespace de4dot.code.renamer.asmmodules {
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyKeyDictionary<TypeDef> typeToTypeDefDict = new AssemblyKeyDictionary<TypeDef>();
|
AssemblyKeyDictionary<TypeDef> typeToTypeDefDict = new AssemblyKeyDictionary<TypeDef>();
|
||||||
ExternalAssemblies externalAssemblies = new ExternalAssemblies();
|
|
||||||
public TypeDef resolveOther(TypeReference type) {
|
public TypeDef resolveOther(TypeReference type) {
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -333,7 +337,7 @@ namespace de4dot.code.renamer.asmmodules {
|
||||||
if (typeToTypeDefDict.tryGetValue(type, out typeDef))
|
if (typeToTypeDefDict.tryGetValue(type, out typeDef))
|
||||||
return typeDef;
|
return typeDef;
|
||||||
|
|
||||||
var typeDefinition = externalAssemblies.resolve(type);
|
var typeDefinition = deobfuscatorContext.resolve(type);
|
||||||
if (typeDefinition == null) {
|
if (typeDefinition == null) {
|
||||||
typeToTypeDefDict.tryGetSimilarValue(type, out typeDef);
|
typeToTypeDefDict.tryGetSimilarValue(type, out typeDef);
|
||||||
typeToTypeDefDict[type] = typeDef;
|
typeToTypeDefDict[type] = typeDef;
|
||||||
|
@ -379,7 +383,6 @@ namespace de4dot.code.renamer.asmmodules {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanUp() {
|
public void cleanUp() {
|
||||||
externalAssemblies.unloadAll();
|
|
||||||
foreach (var module in DotNetUtils.typeCaches.invalidateAll())
|
foreach (var module in DotNetUtils.typeCaches.invalidateAll())
|
||||||
AssemblyResolver.Instance.removeModule(module);
|
AssemblyResolver.Instance.removeModule(module);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ using de4dot.code.AssemblyClient;
|
||||||
namespace de4dot.cui {
|
namespace de4dot.cui {
|
||||||
class FilesDeobfuscator {
|
class FilesDeobfuscator {
|
||||||
Options options;
|
Options options;
|
||||||
|
IDeobfuscatorContext deobfuscatorContext = new DeobfuscatorContext();
|
||||||
|
|
||||||
public class Options {
|
public class Options {
|
||||||
public IList<IDeobfuscatorInfo> DeobfuscatorInfos { get; set; }
|
public IList<IDeobfuscatorInfo> DeobfuscatorInfos { get; set; }
|
||||||
|
@ -81,8 +82,10 @@ namespace de4dot.cui {
|
||||||
}
|
}
|
||||||
|
|
||||||
void detectObfuscators() {
|
void detectObfuscators() {
|
||||||
foreach (var file in loadAllFiles(true))
|
foreach (var file in loadAllFiles(true)) {
|
||||||
removeModule(file.ModuleDefinition);
|
removeModule(file.ModuleDefinition);
|
||||||
|
deobfuscatorContext.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void deobfuscateOneAtATime() {
|
void deobfuscateOneAtATime() {
|
||||||
|
@ -97,6 +100,7 @@ namespace de4dot.cui {
|
||||||
|
|
||||||
removeModule(file.ModuleDefinition);
|
removeModule(file.ModuleDefinition);
|
||||||
AssemblyResolver.Instance.clearAll();
|
AssemblyResolver.Instance.clearAll();
|
||||||
|
deobfuscatorContext.clear();
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
Log.w("Could not deobfuscate {0}. Use -v to see stack trace", file.Filename);
|
Log.w("Could not deobfuscate {0}. Use -v to see stack trace", file.Filename);
|
||||||
|
@ -124,6 +128,7 @@ namespace de4dot.cui {
|
||||||
DefaultStringDecrypterType = options.DefaultStringDecrypterType,
|
DefaultStringDecrypterType = options.DefaultStringDecrypterType,
|
||||||
DefaultStringDecrypterMethods = options.DefaultStringDecrypterMethods,
|
DefaultStringDecrypterMethods = options.DefaultStringDecrypterMethods,
|
||||||
AssemblyClientFactory = options.AssemblyClientFactory,
|
AssemblyClientFactory = options.AssemblyClientFactory,
|
||||||
|
DeobfuscatorContext = deobfuscatorContext,
|
||||||
ControlFlowDeobfuscation = options.ControlFlowDeobfuscation,
|
ControlFlowDeobfuscation = options.ControlFlowDeobfuscation,
|
||||||
KeepObfuscatorTypes = options.KeepObfuscatorTypes,
|
KeepObfuscatorTypes = options.KeepObfuscatorTypes,
|
||||||
CreateDestinationDir = !onlyScan,
|
CreateDestinationDir = !onlyScan,
|
||||||
|
@ -154,6 +159,7 @@ namespace de4dot.cui {
|
||||||
public DecrypterType? DefaultStringDecrypterType { get; set; }
|
public DecrypterType? DefaultStringDecrypterType { get; set; }
|
||||||
public List<string> DefaultStringDecrypterMethods { get; set; }
|
public List<string> DefaultStringDecrypterMethods { get; set; }
|
||||||
public IAssemblyClientFactory AssemblyClientFactory { get; set; }
|
public IAssemblyClientFactory AssemblyClientFactory { get; set; }
|
||||||
|
public IDeobfuscatorContext DeobfuscatorContext { get; set; }
|
||||||
public bool ControlFlowDeobfuscation { get; set; }
|
public bool ControlFlowDeobfuscation { get; set; }
|
||||||
public bool KeepObfuscatorTypes { get; set; }
|
public bool KeepObfuscatorTypes { get; set; }
|
||||||
public bool CreateDestinationDir { get; set; }
|
public bool CreateDestinationDir { get; set; }
|
||||||
|
@ -185,6 +191,7 @@ namespace de4dot.cui {
|
||||||
|
|
||||||
int oldIndentLevel = Log.indentLevel;
|
int oldIndentLevel = Log.indentLevel;
|
||||||
try {
|
try {
|
||||||
|
file.DeobfuscatorContext = options.DeobfuscatorContext;
|
||||||
file.load(options.CreateDeobfuscators());
|
file.load(options.CreateDeobfuscators());
|
||||||
}
|
}
|
||||||
catch (NotSupportedException) {
|
catch (NotSupportedException) {
|
||||||
|
@ -351,7 +358,7 @@ namespace de4dot.cui {
|
||||||
void rename(IEnumerable<IObfuscatedFile> theFiles) {
|
void rename(IEnumerable<IObfuscatedFile> theFiles) {
|
||||||
if (!options.RenameSymbols)
|
if (!options.RenameSymbols)
|
||||||
return;
|
return;
|
||||||
var renamer = new Renamer(theFiles) {
|
var renamer = new Renamer(deobfuscatorContext, theFiles) {
|
||||||
RestorePropertiesFromNames = options.RestorePropsEvents,
|
RestorePropertiesFromNames = options.RestorePropsEvents,
|
||||||
RestoreEventsFromNames = options.RestorePropsEvents,
|
RestoreEventsFromNames = options.RestorePropsEvents,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user