Port more code
This commit is contained in:
parent
c5d183983b
commit
3b6ef4fa1f
|
@ -228,6 +228,10 @@ namespace de4dot.blocks {
|
||||||
return method != null && method.FullName == returnType + " " + method.DeclaringType.FullName + "::" + method.Name + parameters;
|
return method != null && method.FullName == returnType + " " + method.DeclaringType.FullName + "::" + method.Name + parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool isMethod(DN.IMethod method, string returnType, string parameters) {
|
||||||
|
return method != null && method.FullName == returnType + " " + method.DeclaringType.FullName + "::" + method.Name + parameters;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool hasPinvokeMethod(TypeDefinition type, string methodName) {
|
public static bool hasPinvokeMethod(TypeDefinition type, string methodName) {
|
||||||
return getPInvokeMethod(type, methodName) != null;
|
return getPInvokeMethod(type, methodName) != null;
|
||||||
}
|
}
|
||||||
|
@ -448,6 +452,17 @@ namespace de4dot.blocks {
|
||||||
return strings;
|
return strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IList<string> getCodeStrings(DN.MethodDef method) {
|
||||||
|
var strings = new List<string>();
|
||||||
|
if (method != null && method.CilBody != null) {
|
||||||
|
foreach (var instr in method.CilBody.Instructions) {
|
||||||
|
if (instr.OpCode.Code == DNE.Code.Ldstr)
|
||||||
|
strings.Add((string)instr.Operand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
public static DN.Resource getResource(DN.ModuleDef module, string name) {
|
public static DN.Resource getResource(DN.ModuleDef module, string name) {
|
||||||
return getResource(module, new List<string> { name });
|
return getResource(module, new List<string> { name });
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,52 +20,47 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.MyStuff;
|
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code {
|
namespace de4dot.code {
|
||||||
class AssemblyModule {
|
class AssemblyModule {
|
||||||
string filename;
|
string filename;
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
|
|
||||||
public AssemblyModule(string filename) {
|
public AssemblyModule(string filename) {
|
||||||
this.filename = Utils.getFullPath(filename);
|
this.filename = Utils.getFullPath(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReaderParameters getReaderParameters() {
|
public ModuleDefMD load() {
|
||||||
return new ReaderParameters(ReadingMode.Deferred) {
|
return setModule(ModuleDefMD.Load(filename));
|
||||||
AssemblyResolver = AssemblyResolver.Instance
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModuleDefinition load() {
|
public ModuleDefMD load(byte[] fileData) {
|
||||||
return setModule(ModuleDefinition.ReadModule(filename, getReaderParameters()));
|
return setModule(ModuleDefMD.Load(fileData));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModuleDefinition load(byte[] fileData) {
|
ModuleDefMD setModule(ModuleDefMD newModule) {
|
||||||
return setModule(ModuleDefinition.ReadModule(new MemoryStream(fileData), getReaderParameters()));
|
|
||||||
}
|
|
||||||
|
|
||||||
ModuleDefinition setModule(ModuleDefinition newModule) {
|
|
||||||
module = newModule;
|
module = newModule;
|
||||||
AssemblyResolver.Instance.addModule(module);
|
AssemblyResolver.Instance.addModule(module);
|
||||||
module.FullyQualifiedName = filename;
|
module.Location = filename;
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(string newFilename, bool updateMaxStack, IWriterListener writerListener) {
|
public void save(string newFilename, bool updateMaxStack, IWriterListener writerListener) {
|
||||||
var writerParams = new WriterParameters() {
|
//TODO: var writerParams = new WriterParameters() {
|
||||||
UpdateMaxStack = updateMaxStack,
|
//TODO: UpdateMaxStack = updateMaxStack,
|
||||||
WriterListener = writerListener,
|
//TODO: WriterListener = writerListener,
|
||||||
};
|
//TODO: };
|
||||||
module.Write(newFilename, writerParams);
|
//TODO: module.Write(newFilename, writerParams);
|
||||||
|
module.Write(newFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModuleDefinition reload(byte[] newModuleData, DumpedMethods dumpedMethods) {
|
public ModuleDefMD reload(byte[] newModuleData, DumpedMethods dumpedMethods) {
|
||||||
AssemblyResolver.Instance.removeModule(module);
|
//TODO: AssemblyResolver.Instance.removeModule(module);
|
||||||
DotNetUtils.typeCaches.invalidate(module);
|
//TODO: DotNetUtils.typeCaches.invalidate(module);
|
||||||
return setModule(ModuleDefinition.ReadModule(new MemoryStream(newModuleData), getReaderParameters(), dumpedMethods));
|
//TODO: Use dumped methods
|
||||||
|
return setModule(ModuleDefMD.Load(newModuleData));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
|
|
|
@ -17,176 +17,38 @@
|
||||||
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 dot10.DotNet;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Xml;
|
|
||||||
using Mono.Cecil;
|
|
||||||
|
|
||||||
namespace de4dot.code {
|
namespace de4dot.code {
|
||||||
public class AssemblyResolver : DefaultAssemblyResolver {
|
public class AssemblyResolver : dot10.DotNet.AssemblyResolver {
|
||||||
public static readonly AssemblyResolver Instance = new AssemblyResolver();
|
public static readonly AssemblyResolver Instance = new AssemblyResolver();
|
||||||
Dictionary<string, bool> addedDirectories = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
static AssemblyResolver() {
|
|
||||||
Instance.resetSearchPaths();
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetSearchPaths() {
|
|
||||||
addedDirectories.Clear();
|
|
||||||
addOtherAssemblySearchPaths();
|
|
||||||
}
|
|
||||||
|
|
||||||
void addOtherAssemblySearchPaths() {
|
|
||||||
addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles"));
|
|
||||||
addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles(x86)"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void addOtherAssemblySearchPaths(string path) {
|
|
||||||
if (string.IsNullOrEmpty(path))
|
|
||||||
return;
|
|
||||||
addSilverlightDirs(Path.Combine(path, @"Microsoft Silverlight"));
|
|
||||||
addIfExists(path, @"Microsoft SDKs\Silverlight\v2.0\Libraries\Client");
|
|
||||||
addIfExists(path, @"Microsoft SDKs\Silverlight\v2.0\Libraries\Server");
|
|
||||||
addIfExists(path, @"Microsoft SDKs\Silverlight\v2.0\Reference Assemblies");
|
|
||||||
addIfExists(path, @"Microsoft SDKs\Silverlight\v3.0\Libraries\Client");
|
|
||||||
addIfExists(path, @"Microsoft SDKs\Silverlight\v3.0\Libraries\Server");
|
|
||||||
addIfExists(path, @"Microsoft SDKs\Silverlight\v4.0\Libraries\Client");
|
|
||||||
addIfExists(path, @"Microsoft SDKs\Silverlight\v4.0\Libraries\Server");
|
|
||||||
addIfExists(path, @"Microsoft SDKs\Silverlight\v5.0\Libraries\Client");
|
|
||||||
addIfExists(path, @"Microsoft SDKs\Silverlight\v5.0\Libraries\Server");
|
|
||||||
addIfExists(path, @"Microsoft.NET\SDK\CompactFramework\v2.0\WindowsCE");
|
|
||||||
addIfExists(path, @"Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE");
|
|
||||||
addIfExists(path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v3.0");
|
|
||||||
addIfExists(path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v4.0");
|
|
||||||
addIfExists(path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v5.0");
|
|
||||||
addIfExists(path, @"Reference Assemblies\Microsoft\FSharp\2.0\Runtime\v2.0");
|
|
||||||
addIfExists(path, @"Reference Assemblies\Microsoft\FSharp\2.0\Runtime\v4.0");
|
|
||||||
addIfExists(path, @"Reference Assemblies\Microsoft\WindowsPowerShell\v1.0");
|
|
||||||
addIfExists(path, @"Microsoft Visual Studio .NET\Common7\IDE\PublicAssemblies");
|
|
||||||
addIfExists(path, @"Microsoft Visual Studio .NET\Common7\IDE\PrivateAssemblies");
|
|
||||||
addIfExists(path, @"Microsoft Visual Studio 8.0\Common7\IDE\PublicAssemblies");
|
|
||||||
addIfExists(path, @"Microsoft Visual Studio 8.0\Common7\IDE\PrivateAssemblies");
|
|
||||||
addIfExists(path, @"Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies");
|
|
||||||
addIfExists(path, @"Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies");
|
|
||||||
addIfExists(path, @"Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies");
|
|
||||||
addIfExists(path, @"Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies");
|
|
||||||
addIfExists(path, @"Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies");
|
|
||||||
addIfExists(path, @"Microsoft Visual Studio 11.0\Common7\IDE\PrivateAssemblies");
|
|
||||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v2.0\References\Windows\x86");
|
|
||||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v2.0\References\Xbox360");
|
|
||||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Windows\x86");
|
|
||||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Xbox360");
|
|
||||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Zune");
|
|
||||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.1\References\Windows\x86");
|
|
||||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.1\References\Xbox360");
|
|
||||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.1\References\Zune");
|
|
||||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86");
|
|
||||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v4.0\References\Xbox360");
|
|
||||||
addIfExists(path, @"Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Designtimereferences");
|
|
||||||
addIfExists(path, @"Windows CE Tools\wce500\Windows Mobile 5.0 Smartphone SDK\Designtimereferences");
|
|
||||||
addIfExists(path, @"Windows Mobile 5.0 SDK R2\Managed Libraries");
|
|
||||||
addIfExists(path, @"Windows Mobile 6 SDK\Managed Libraries");
|
|
||||||
addIfExists(path, @"Windows Mobile 6.5.3 DTK\Managed Libraries");
|
|
||||||
addIfExists(path, @"Microsoft SQL Server\90\SDK\Assemblies");
|
|
||||||
addIfExists(path, @"Microsoft SQL Server\100\SDK\Assemblies");
|
|
||||||
addIfExists(path, @"Microsoft SQL Server\110\SDK\Assemblies");
|
|
||||||
addIfExists(path, @"Microsoft ASP.NET\ASP.NET MVC 2\Assemblies");
|
|
||||||
addIfExists(path, @"Microsoft ASP.NET\ASP.NET MVC 3\Assemblies");
|
|
||||||
addIfExists(path, @"Microsoft ASP.NET\ASP.NET MVC 4\Assemblies");
|
|
||||||
addIfExists(path, @"Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies");
|
|
||||||
addIfExists(path, @"Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies");
|
|
||||||
addIfExists(path, @"Microsoft SDKs\F#\3.0\Framework\v4.0");
|
|
||||||
}
|
|
||||||
|
|
||||||
// basePath is eg. "C:\Program Files (x86)\Microsoft Silverlight"
|
|
||||||
void addSilverlightDirs(string basePath) {
|
|
||||||
try {
|
|
||||||
var di = new DirectoryInfo(basePath);
|
|
||||||
foreach (var dir in di.GetDirectories()) {
|
|
||||||
if (Regex.IsMatch(dir.Name, @"^\d+(?:\.\d+){3}$"))
|
|
||||||
addIfExists(basePath, dir.Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addIfExists(string basePath, string extraPath) {
|
|
||||||
try {
|
|
||||||
var path = Path.Combine(basePath, extraPath);
|
|
||||||
if (Utils.pathExists(path))
|
|
||||||
Instance.addSearchDirectory(path);
|
|
||||||
}
|
|
||||||
catch (Exception) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addSearchDirectory(string dir) {
|
public void addSearchDirectory(string dir) {
|
||||||
if (!addedDirectories.ContainsKey(dir)) {
|
if (!PostSearchPaths.Contains(dir))
|
||||||
addedDirectories[dir] = true;
|
PostSearchPaths.Add(dir);
|
||||||
AddSearchDirectory(dir);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addModule(ModuleDefinition module) {
|
public void addModule(ModuleDef module) {
|
||||||
if (module.FullyQualifiedName != "") {
|
AddToCache(module.Assembly);
|
||||||
addSearchDirectory(Path.GetDirectoryName(module.FullyQualifiedName));
|
|
||||||
if (module.FullyQualifiedName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
|
|
||||||
addConfigFile(module.FullyQualifiedName + ".config");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var assembly = module.Assembly;
|
public void removeModule(ModuleDef module) {
|
||||||
if (assembly != null) {
|
|
||||||
var name = assembly.Name.FullName;
|
|
||||||
cache[name] = assembly;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addConfigFile(string configFilename) {
|
|
||||||
var dirName = Utils.getDirName(Utils.getFullPath(configFilename));
|
|
||||||
addSearchDirectory(dirName);
|
|
||||||
|
|
||||||
try {
|
|
||||||
using (var xmlStream = new FileStream(configFilename, FileMode.Open, FileAccess.Read, FileShare.Read)) {
|
|
||||||
var doc = new XmlDocument();
|
|
||||||
doc.Load(XmlReader.Create(xmlStream));
|
|
||||||
foreach (var tmp in doc.GetElementsByTagName("probing")) {
|
|
||||||
var probingElem = tmp as XmlElement;
|
|
||||||
if (probingElem == null)
|
|
||||||
continue;
|
|
||||||
var privatePath = probingElem.GetAttribute("privatePath");
|
|
||||||
if (string.IsNullOrEmpty(privatePath))
|
|
||||||
continue;
|
|
||||||
foreach (var path in privatePath.Split(';'))
|
|
||||||
addSearchDirectory(Path.Combine(dirName, path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException) {
|
|
||||||
}
|
|
||||||
catch (XmlException) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeModule(ModuleDefinition module) {
|
|
||||||
var assembly = module.Assembly;
|
var assembly = module.Assembly;
|
||||||
if (assembly == null)
|
if (assembly == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
removeModule(assembly.Name.FullName);
|
removeModule(assembly.FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeModule(string asmFullName) {
|
public void removeModule(string asmFullName) {
|
||||||
if (string.IsNullOrEmpty(asmFullName))
|
if (string.IsNullOrEmpty(asmFullName))
|
||||||
return;
|
return;
|
||||||
cache.Remove(asmFullName);
|
//TODO: Remove it from the cache
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearAll() {
|
public void clearAll() {
|
||||||
cache.Clear();
|
//TODO: cache.Clear();
|
||||||
resetSearchPaths();
|
//TODO: resetSearchPaths();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using de4dot.code.deobfuscators;
|
using de4dot.code.deobfuscators;
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
|
#if PORT
|
||||||
using de4dot.code.renamer;
|
using de4dot.code.renamer;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace de4dot.code {
|
namespace de4dot.code {
|
||||||
public interface IObfuscatedFile {
|
public interface IObfuscatedFile {
|
||||||
|
@ -29,7 +31,9 @@ namespace de4dot.code {
|
||||||
IDeobfuscatorContext DeobfuscatorContext { get; set; }
|
IDeobfuscatorContext DeobfuscatorContext { get; set; }
|
||||||
string Filename { get; }
|
string Filename { get; }
|
||||||
string NewFilename { get; }
|
string NewFilename { get; }
|
||||||
|
#if PORT
|
||||||
INameChecker NameChecker { get; }
|
INameChecker NameChecker { get; }
|
||||||
|
#endif
|
||||||
bool RenameResourcesInCode { get; }
|
bool RenameResourcesInCode { get; }
|
||||||
bool RemoveNamespaceWithOneType { get; }
|
bool RemoveNamespaceWithOneType { get; }
|
||||||
bool RenameResourceKeys { get; }
|
bool RenameResourceKeys { get; }
|
||||||
|
|
|
@ -22,20 +22,21 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using Mono.MyStuff;
|
|
||||||
using de4dot.code.deobfuscators;
|
using de4dot.code.deobfuscators;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.blocks.cflow;
|
using de4dot.blocks.cflow;
|
||||||
using de4dot.code.AssemblyClient;
|
using de4dot.code.AssemblyClient;
|
||||||
|
#if PORT
|
||||||
using de4dot.code.renamer;
|
using de4dot.code.renamer;
|
||||||
|
#endif
|
||||||
using de4dot.PE;
|
using de4dot.PE;
|
||||||
|
|
||||||
namespace de4dot.code {
|
namespace de4dot.code {
|
||||||
public class ObfuscatedFile : IObfuscatedFile, IDeobfuscatedFile {
|
public class ObfuscatedFile : IObfuscatedFile, IDeobfuscatedFile {
|
||||||
Options options;
|
Options options;
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
IDeobfuscator deob;
|
IDeobfuscator deob;
|
||||||
IDeobfuscatorContext deobfuscatorContext;
|
IDeobfuscatorContext deobfuscatorContext;
|
||||||
AssemblyModule assemblyModule;
|
AssemblyModule assemblyModule;
|
||||||
|
@ -46,14 +47,14 @@ namespace de4dot.code {
|
||||||
bool userStringDecrypterMethods = false;
|
bool userStringDecrypterMethods = false;
|
||||||
|
|
||||||
class SavedMethodBodies {
|
class SavedMethodBodies {
|
||||||
Dictionary<MethodDefinition, SavedMethodBody> savedMethodBodies = new Dictionary<MethodDefinition, SavedMethodBody>();
|
Dictionary<MethodDef, SavedMethodBody> savedMethodBodies = new Dictionary<MethodDef, SavedMethodBody>();
|
||||||
|
|
||||||
class SavedMethodBody {
|
class SavedMethodBody {
|
||||||
MethodDefinition method;
|
MethodDef method;
|
||||||
IList<Instruction> instructions;
|
IList<Instruction> instructions;
|
||||||
IList<ExceptionHandler> exceptionHandlers;
|
IList<ExceptionHandler> exceptionHandlers;
|
||||||
|
|
||||||
public SavedMethodBody(MethodDefinition method) {
|
public SavedMethodBody(MethodDef method) {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
DotNetUtils.copyBody(method, out instructions, out exceptionHandlers);
|
DotNetUtils.copyBody(method, out instructions, out exceptionHandlers);
|
||||||
}
|
}
|
||||||
|
@ -63,7 +64,7 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(MethodDefinition method) {
|
public void save(MethodDef method) {
|
||||||
if (isSaved(method))
|
if (isSaved(method))
|
||||||
return;
|
return;
|
||||||
savedMethodBodies[method] = new SavedMethodBody(method);
|
savedMethodBodies[method] = new SavedMethodBody(method);
|
||||||
|
@ -75,7 +76,7 @@ namespace de4dot.code {
|
||||||
savedMethodBodies.Clear();
|
savedMethodBodies.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool isSaved(MethodDefinition method) {
|
public bool isSaved(MethodDef method) {
|
||||||
return savedMethodBodies.ContainsKey(method);
|
return savedMethodBodies.ContainsKey(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,13 +104,15 @@ namespace de4dot.code {
|
||||||
get { return options.NewFilename; }
|
get { return options.NewFilename; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModuleDefinition ModuleDefinition {
|
public ModuleDefMD ModuleDefMD {
|
||||||
get { return module; }
|
get { return module; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PORT
|
||||||
public INameChecker NameChecker {
|
public INameChecker NameChecker {
|
||||||
get { return deob; }
|
get { return deob; }
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public bool RenameResourcesInCode {
|
public bool RenameResourcesInCode {
|
||||||
get { return deob.TheOptions.RenameResourcesInCode; }
|
get { return deob.TheOptions.RenameResourcesInCode; }
|
||||||
|
@ -309,8 +312,8 @@ namespace de4dot.code {
|
||||||
assemblyModule.save(options.NewFilename, options.ControlFlowDeobfuscation, deob as IWriterListener);
|
assemblyModule.save(options.NewFilename, options.ControlFlowDeobfuscation, deob as IWriterListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
IList<MethodDefinition> getAllMethods() {
|
IList<MethodDef> getAllMethods() {
|
||||||
var list = new List<MethodDefinition>();
|
var list = new List<MethodDef>();
|
||||||
|
|
||||||
foreach (var type in module.GetTypes()) {
|
foreach (var type in module.GetTypes()) {
|
||||||
foreach (var method in type.Methods)
|
foreach (var method in type.Methods)
|
||||||
|
@ -546,7 +549,7 @@ namespace de4dot.code {
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
if (!canLoadMethodBody(method)) {
|
if (!canLoadMethodBody(method)) {
|
||||||
Log.v("Invalid method body. {0:X8}", method.MetadataToken.ToInt32());
|
Log.v("Invalid method body. {0:X8}", method.MetadataToken.ToInt32());
|
||||||
method.Body = new MethodBody(method);
|
method.CilBody = new MethodBody(method);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.w("Could not deobfuscate method {0:X8}. Hello, E.T.: {1}", // E.T. = exception type
|
Log.w("Could not deobfuscate method {0:X8}. Hello, E.T.: {1}", // E.T. = exception type
|
||||||
|
@ -563,9 +566,9 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool canLoadMethodBody(MethodDefinition method) {
|
static bool canLoadMethodBody(MethodDef method) {
|
||||||
try {
|
try {
|
||||||
var body = method.Body;
|
var body = method.CilBody;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
|
@ -574,13 +577,13 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PORT
|
#if PORT
|
||||||
void deobfuscate(MethodDefinition method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter) {
|
void deobfuscate(MethodDef method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter) {
|
||||||
if (!hasNonEmptyBody(method))
|
if (!hasNonEmptyBody(method))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var blocks = new Blocks(method);
|
var blocks = new Blocks(method);
|
||||||
int numRemovedLocals = 0;
|
int numRemovedLocals = 0;
|
||||||
int oldNumInstructions = method.Body.Instructions.Count;
|
int oldNumInstructions = method.CilBody.Instructions.Count;
|
||||||
|
|
||||||
deob.deobfuscateMethodBegin(blocks);
|
deob.deobfuscateMethodBegin(blocks);
|
||||||
if (options.ControlFlowDeobfuscation) {
|
if (options.ControlFlowDeobfuscation) {
|
||||||
|
@ -606,7 +609,7 @@ namespace de4dot.code {
|
||||||
|
|
||||||
if (numRemovedLocals > 0)
|
if (numRemovedLocals > 0)
|
||||||
Log.v("Removed {0} unused local(s)", numRemovedLocals);
|
Log.v("Removed {0} unused local(s)", numRemovedLocals);
|
||||||
int numRemovedInstructions = oldNumInstructions - method.Body.Instructions.Count;
|
int numRemovedInstructions = oldNumInstructions - method.CilBody.Instructions.Count;
|
||||||
if (numRemovedInstructions > 0)
|
if (numRemovedInstructions > 0)
|
||||||
Log.v("Removed {0} dead instruction(s)", numRemovedInstructions);
|
Log.v("Removed {0} dead instruction(s)", numRemovedInstructions);
|
||||||
|
|
||||||
|
@ -620,8 +623,8 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool hasNonEmptyBody(MethodDefinition method) {
|
bool hasNonEmptyBody(MethodDef method) {
|
||||||
return method.HasBody && method.Body.Instructions.Count > 0;
|
return method.HasBody && method.CilBody.Instructions.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deobfuscateStrings(Blocks blocks) {
|
void deobfuscateStrings(Blocks blocks) {
|
||||||
|
@ -643,7 +646,7 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeNoInliningAttribute(MethodDefinition method) {
|
void removeNoInliningAttribute(MethodDef method) {
|
||||||
method.ImplAttributes = method.ImplAttributes & ~MethodImplAttributes.NoInlining;
|
method.ImplAttributes = method.ImplAttributes & ~MethodImplAttributes.NoInlining;
|
||||||
for (int i = 0; i < method.CustomAttributes.Count; i++) {
|
for (int i = 0; i < method.CustomAttributes.Count; i++) {
|
||||||
var cattr = method.CustomAttributes[i];
|
var cattr = method.CustomAttributes[i];
|
||||||
|
@ -689,15 +692,15 @@ namespace de4dot.code {
|
||||||
enum SimpleDeobFlags {
|
enum SimpleDeobFlags {
|
||||||
HasDeobfuscated = 0x1,
|
HasDeobfuscated = 0x1,
|
||||||
}
|
}
|
||||||
Dictionary<MethodDefinition, SimpleDeobFlags> simpleDeobfuscatorFlags = new Dictionary<MethodDefinition, SimpleDeobFlags>();
|
Dictionary<MethodDef, SimpleDeobFlags> simpleDeobfuscatorFlags = new Dictionary<MethodDef, SimpleDeobFlags>();
|
||||||
bool check(MethodDefinition method, SimpleDeobFlags flag) {
|
bool check(MethodDef method, SimpleDeobFlags flag) {
|
||||||
SimpleDeobFlags oldFlags;
|
SimpleDeobFlags oldFlags;
|
||||||
simpleDeobfuscatorFlags.TryGetValue(method, out oldFlags);
|
simpleDeobfuscatorFlags.TryGetValue(method, out oldFlags);
|
||||||
simpleDeobfuscatorFlags[method] = oldFlags | flag;
|
simpleDeobfuscatorFlags[method] = oldFlags | flag;
|
||||||
return (oldFlags & flag) == flag;
|
return (oldFlags & flag) == flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deobfuscate(MethodDefinition method, string msg, Action<Blocks> handler) {
|
void deobfuscate(MethodDef method, string msg, Action<Blocks> handler) {
|
||||||
if (savedMethodBodies != null)
|
if (savedMethodBodies != null)
|
||||||
savedMethodBodies.save(method);
|
savedMethodBodies.save(method);
|
||||||
|
|
||||||
|
@ -723,11 +726,11 @@ namespace de4dot.code {
|
||||||
Log.deIndent();
|
Log.deIndent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISimpleDeobfuscator.deobfuscate(MethodDefinition method) {
|
void ISimpleDeobfuscator.deobfuscate(MethodDef method) {
|
||||||
((ISimpleDeobfuscator)this).deobfuscate(method, false);
|
((ISimpleDeobfuscator)this).deobfuscate(method, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISimpleDeobfuscator.deobfuscate(MethodDefinition method, bool force) {
|
void ISimpleDeobfuscator.deobfuscate(MethodDef method, bool force) {
|
||||||
if (!force && check(method, SimpleDeobFlags.HasDeobfuscated))
|
if (!force && check(method, SimpleDeobFlags.HasDeobfuscated))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -740,7 +743,7 @@ namespace de4dot.code {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISimpleDeobfuscator.decryptStrings(MethodDefinition method, IDeobfuscator theDeob) {
|
void ISimpleDeobfuscator.decryptStrings(MethodDef method, IDeobfuscator theDeob) {
|
||||||
deobfuscate(method, "Static string decryption", (blocks) => theDeob.deobfuscateStrings(blocks));
|
deobfuscate(method, "Static string decryption", (blocks) => theDeob.deobfuscateStrings(blocks));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -274,32 +274,32 @@
|
||||||
<Compile Include="ObfuscatedFile.cs" />
|
<Compile Include="ObfuscatedFile.cs" />
|
||||||
<Compile Include="Option.cs" />
|
<Compile Include="Option.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="renamer\asmmodules\EventDef.cs" />
|
<None Include="renamer\asmmodules\EventDef.cs" />
|
||||||
<Compile Include="renamer\asmmodules\FieldDef.cs" />
|
<None Include="renamer\asmmodules\FieldDef.cs" />
|
||||||
<Compile Include="renamer\asmmodules\GenericParamDef.cs" />
|
<None Include="renamer\asmmodules\GenericParamDef.cs" />
|
||||||
<Compile Include="renamer\asmmodules\IResolver.cs" />
|
<None Include="renamer\asmmodules\IResolver.cs" />
|
||||||
<Compile Include="renamer\asmmodules\MemberRefFinder.cs" />
|
<None Include="renamer\asmmodules\MemberRefFinder.cs" />
|
||||||
<Compile Include="renamer\asmmodules\MethodDef.cs" />
|
<None Include="renamer\asmmodules\MethodDef.cs" />
|
||||||
<Compile Include="renamer\asmmodules\MethodNameGroups.cs" />
|
<None Include="renamer\asmmodules\MethodNameGroups.cs" />
|
||||||
<Compile Include="renamer\asmmodules\Module.cs" />
|
<None Include="renamer\asmmodules\Module.cs" />
|
||||||
<Compile Include="renamer\asmmodules\Modules.cs" />
|
<None Include="renamer\asmmodules\Modules.cs" />
|
||||||
<Compile Include="renamer\asmmodules\ParamDef.cs" />
|
<None Include="renamer\asmmodules\ParamDef.cs" />
|
||||||
<Compile Include="renamer\asmmodules\PropertyDef.cs" />
|
<None Include="renamer\asmmodules\PropertyDef.cs" />
|
||||||
<Compile Include="renamer\asmmodules\Ref.cs" />
|
<None Include="renamer\asmmodules\Ref.cs" />
|
||||||
<Compile Include="renamer\asmmodules\RefDict.cs" />
|
<None Include="renamer\asmmodules\RefDict.cs" />
|
||||||
<Compile Include="renamer\asmmodules\TypeDef.cs" />
|
<None Include="renamer\asmmodules\TypeDef.cs" />
|
||||||
<Compile Include="renamer\DerivedFrom.cs" />
|
<None Include="renamer\DerivedFrom.cs" />
|
||||||
<Compile Include="renamer\ExistingNames.cs" />
|
<None Include="renamer\ExistingNames.cs" />
|
||||||
<Compile Include="renamer\INameChecker.cs" />
|
<None Include="renamer\INameChecker.cs" />
|
||||||
<Compile Include="renamer\MemberInfos.cs" />
|
<None Include="renamer\MemberInfos.cs" />
|
||||||
<Compile Include="renamer\NameCreators.cs" />
|
<None Include="renamer\NameCreators.cs" />
|
||||||
<Compile Include="renamer\Renamer.cs" />
|
<None Include="renamer\Renamer.cs" />
|
||||||
<Compile Include="renamer\ResourceKeysRenamer.cs" />
|
<None Include="renamer\ResourceKeysRenamer.cs" />
|
||||||
<Compile Include="renamer\ResourceRenamer.cs" />
|
<None Include="renamer\ResourceRenamer.cs" />
|
||||||
<Compile Include="renamer\TypeInfo.cs" />
|
<None Include="renamer\TypeInfo.cs" />
|
||||||
<Compile Include="renamer\TypeNames.cs" />
|
<None Include="renamer\TypeNames.cs" />
|
||||||
<Compile Include="renamer\TypeRenamerState.cs" />
|
<None Include="renamer\TypeRenamerState.cs" />
|
||||||
<Compile Include="renamer\VariableNameState.cs" />
|
<None Include="renamer\VariableNameState.cs" />
|
||||||
<Compile Include="resources\BuiltInResourceData.cs" />
|
<Compile Include="resources\BuiltInResourceData.cs" />
|
||||||
<Compile Include="resources\IResourceData.cs" />
|
<Compile Include="resources\IResourceData.cs" />
|
||||||
<Compile Include="resources\ResourceDataCreator.cs" />
|
<Compile Include="resources\ResourceDataCreator.cs" />
|
||||||
|
|
|
@ -22,19 +22,19 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
static class DeobUtils {
|
static class DeobUtils {
|
||||||
public static void decryptAndAddResources(ModuleDefinition module, string encryptedName, Func<byte[]> decryptResource) {
|
public static void decryptAndAddResources(ModuleDef module, string encryptedName, Func<byte[]> decryptResource) {
|
||||||
Log.v("Decrypting resources, name: {0}", Utils.toCsharpString(encryptedName));
|
Log.v("Decrypting resources, name: {0}", Utils.toCsharpString(encryptedName));
|
||||||
var decryptedResourceData = decryptResource();
|
var decryptedResourceData = decryptResource();
|
||||||
if (decryptedResourceData == null)
|
if (decryptedResourceData == null)
|
||||||
throw new ApplicationException("decryptedResourceData is null");
|
throw new ApplicationException("decryptedResourceData is null");
|
||||||
var resourceModule = ModuleDefinition.ReadModule(new MemoryStream(decryptedResourceData));
|
var resourceModule = ModuleDefMD.Load(decryptedResourceData);
|
||||||
|
|
||||||
Log.indent();
|
Log.indent();
|
||||||
foreach (var rsrc in resourceModule.Resources) {
|
foreach (var rsrc in resourceModule.Resources) {
|
||||||
|
@ -44,27 +44,17 @@ namespace de4dot.code.deobfuscators {
|
||||||
Log.deIndent();
|
Log.deIndent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T lookup<T>(ModuleDefinition module, T def, string errorMessage) where T : MemberReference {
|
public static T lookup<T>(ModuleDefMD module, T def, string errorMessage) where T : class, ICodedToken {
|
||||||
if (def == null)
|
if (def == null)
|
||||||
return null;
|
return null;
|
||||||
var newDef = module.LookupToken(def.MetadataToken.ToInt32()) as T;
|
var newDef = module.ResolveToken(def.MDToken.Raw) as T;
|
||||||
if (newDef == null)
|
if (newDef == null)
|
||||||
throw new ApplicationException(errorMessage);
|
throw new ApplicationException(errorMessage);
|
||||||
return newDef;
|
return newDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ModuleReference lookup(ModuleDefinition module, ModuleReference other, string errorMessage) {
|
public static byte[] readModule(ModuleDef module) {
|
||||||
if (other == null)
|
return Utils.readFile(module.Location);
|
||||||
return null;
|
|
||||||
foreach (var modRef in module.ModuleReferences) {
|
|
||||||
if (modRef.MetadataToken.ToInt32() == other.MetadataToken.ToInt32())
|
|
||||||
return modRef;
|
|
||||||
}
|
|
||||||
throw new ApplicationException(errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] readModule(ModuleDefinition module) {
|
|
||||||
return Utils.readFile(module.FullyQualifiedName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool isCode(short[] nativeCode, byte[] code) {
|
public static bool isCode(short[] nativeCode, byte[] code) {
|
||||||
|
@ -190,7 +180,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EmbeddedResource getEmbeddedResourceFromCodeStrings(ModuleDefinition module, MethodDefinition method) {
|
public static EmbeddedResource getEmbeddedResourceFromCodeStrings(ModuleDef module, MethodDef method) {
|
||||||
foreach (var s in DotNetUtils.getCodeStrings(method)) {
|
foreach (var s in DotNetUtils.getCodeStrings(method)) {
|
||||||
var resource = DotNetUtils.getResource(module, s) as EmbeddedResource;
|
var resource = DotNetUtils.getResource(module, s) as EmbeddedResource;
|
||||||
if (resource != null)
|
if (resource != null)
|
||||||
|
@ -199,68 +189,56 @@ namespace de4dot.code.deobfuscators {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int readVariableLengthInt32(BinaryReader reader) {
|
|
||||||
byte b = reader.ReadByte();
|
|
||||||
if ((b & 0x80) == 0)
|
|
||||||
return b;
|
|
||||||
if ((b & 0x40) == 0)
|
|
||||||
return (((int)b & 0x3F) << 8) + reader.ReadByte();
|
|
||||||
return (((int)b & 0x3F) << 24) +
|
|
||||||
((int)reader.ReadByte() << 16) +
|
|
||||||
((int)reader.ReadByte() << 8) +
|
|
||||||
reader.ReadByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int readVariableLengthInt32(byte[] data, ref int index) {
|
public static int readVariableLengthInt32(byte[] data, ref int index) {
|
||||||
byte b = data[index++];
|
byte b = data[index++];
|
||||||
if ((b & 0x80) == 0)
|
if ((b & 0x80) == 0)
|
||||||
return b;
|
return b;
|
||||||
if ((b & 0x40) == 0)
|
if ((b & 0x40) == 0)
|
||||||
return (((int)b & 0x3F) << 8) + data[index++];
|
return (((int)b & 0x3F) << 8) + data[index++];
|
||||||
return (((int)b & 0x3F) << 24) +
|
return (((int)b & 0x1F) << 24) +
|
||||||
((int)data[index++] << 16) +
|
((int)data[index++] << 16) +
|
||||||
((int)data[index++] << 8) +
|
((int)data[index++] << 8) +
|
||||||
data[index++];
|
data[index++];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool hasInteger(MethodDefinition method, uint value) {
|
public static bool hasInteger(MethodDef method, uint value) {
|
||||||
return hasInteger(method, (int)value);
|
return hasInteger(method, (int)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool hasInteger(MethodDefinition method, int value) {
|
public static bool hasInteger(MethodDef method, int value) {
|
||||||
return indexOfLdci4Instruction(method, value) >= 0;
|
return indexOfLdci4Instruction(method, value) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int indexOfLdci4Instruction(MethodDefinition method, int value) {
|
public static int indexOfLdci4Instruction(MethodDef method, int value) {
|
||||||
if (method == null || method.Body == null)
|
if (method == null || method.CilBody == null)
|
||||||
return -1;
|
return -1;
|
||||||
var instrs = method.Body.Instructions;
|
var instrs = method.CilBody.Instructions;
|
||||||
for (int i = 0; i < instrs.Count; i++) {
|
for (int i = 0; i < instrs.Count; i++) {
|
||||||
var instr = instrs[i];
|
var instr = instrs[i];
|
||||||
if (!DotNetUtils.isLdcI4(instr))
|
if (!instr.IsLdcI4())
|
||||||
continue;
|
continue;
|
||||||
if (DotNetUtils.getLdcI4Value(instr) == value)
|
if (instr.GetLdcI4Value() == value)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<MethodDefinition> getInitCctors(ModuleDefinition module, int maxCctors) {
|
public static IEnumerable<MethodDef> getInitCctors(ModuleDef module, int maxCctors) {
|
||||||
var cctor = DotNetUtils.getModuleTypeCctor(module);
|
var cctor = DotNetUtils.getModuleTypeCctor(module);
|
||||||
if (cctor != null)
|
if (cctor != null)
|
||||||
yield return cctor;
|
yield return cctor;
|
||||||
|
|
||||||
var entryPoint = module.EntryPoint;
|
var entryPoint = module.EntryPoint as MethodDef;
|
||||||
if (entryPoint != null) {
|
if (entryPoint != null) {
|
||||||
cctor = DotNetUtils.getMethod(entryPoint.DeclaringType, ".cctor");
|
cctor = entryPoint.DeclaringType.FindClassConstructor();
|
||||||
if (cctor != null)
|
if (cctor != null)
|
||||||
yield return cctor;
|
yield return cctor;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var type in module.GetTypes()) {
|
foreach (var type in module.GetTypes()) {
|
||||||
if (type == DotNetUtils.getModuleType(module))
|
if (type == module.GlobalType)
|
||||||
continue;
|
continue;
|
||||||
cctor = DotNetUtils.getMethod(type, ".cctor");
|
cctor = type.FindClassConstructor();
|
||||||
if (cctor == null)
|
if (cctor == null)
|
||||||
continue;
|
continue;
|
||||||
yield return cctor;
|
yield return cctor;
|
||||||
|
@ -269,14 +247,14 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<MethodDefinition> getAllResolveHandlers(MethodDefinition method) {
|
public static List<MethodDef> getAllResolveHandlers(MethodDef method) {
|
||||||
var list = new List<MethodDefinition>();
|
var list = new List<MethodDef>();
|
||||||
if (method == null || method.Body == null)
|
if (method == null || method.CilBody == null)
|
||||||
return list;
|
return list;
|
||||||
foreach (var instr in method.Body.Instructions) {
|
foreach (var instr in method.CilBody.Instructions) {
|
||||||
if (instr.OpCode.Code != Code.Ldftn && instr.OpCode.Code != Code.Ldvirtftn)
|
if (instr.OpCode.Code != Code.Ldftn && instr.OpCode.Code != Code.Ldvirtftn)
|
||||||
continue;
|
continue;
|
||||||
var handler = instr.Operand as MethodDefinition;
|
var handler = instr.Operand as MethodDef;
|
||||||
if (handler == null)
|
if (handler == null)
|
||||||
continue;
|
continue;
|
||||||
if (!DotNetUtils.isMethod(handler, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)"))
|
if (!DotNetUtils.isMethod(handler, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)"))
|
||||||
|
@ -286,7 +264,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MethodDefinition getResolveMethod(MethodDefinition method) {
|
public static MethodDef getResolveMethod(MethodDef method) {
|
||||||
var handlers = DeobUtils.getAllResolveHandlers(method);
|
var handlers = DeobUtils.getAllResolveHandlers(method);
|
||||||
if (handlers.Count == 0)
|
if (handlers.Count == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -25,17 +25,19 @@ using dot10.PE;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.blocks.cflow;
|
using de4dot.blocks.cflow;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code {
|
||||||
//TODO: I added this iface to Cecil but now you must add something similar to dot10
|
//TODO: I added this iface to Cecil but now you must add something similar to dot10
|
||||||
interface IWriterListener {
|
interface IWriterListener {
|
||||||
internal class MetadataBuilder {
|
|
||||||
//TODO: Dummy class. Don't use
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called before adding resources, and after adding types, methods, etc.
|
// Called before adding resources, and after adding types, methods, etc.
|
||||||
void OnBeforeAddingResources(MetadataBuilder builder);
|
void OnBeforeAddingResources(MetadataBuilder builder);
|
||||||
}
|
}
|
||||||
|
//TODO: REMOVE
|
||||||
|
internal class MetadataBuilder {
|
||||||
|
//TODO: Dummy class. Don't use
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace de4dot.code.deobfuscators {
|
||||||
abstract class DeobfuscatorBase : IDeobfuscator, IWriterListener {
|
abstract class DeobfuscatorBase : IDeobfuscator, IWriterListener {
|
||||||
public const string DEFAULT_VALID_NAME_REGEX = @"^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$";
|
public const string DEFAULT_VALID_NAME_REGEX = @"^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$";
|
||||||
|
|
||||||
|
@ -497,8 +499,9 @@ namespace de4dot.code.deobfuscators {
|
||||||
if (typeDef == null)
|
if (typeDef == null)
|
||||||
continue;
|
continue;
|
||||||
for (int i = 0; i < customAttrs.Count; i++) {
|
for (int i = 0; i < customAttrs.Count; i++) {
|
||||||
if (MemberReferenceHelper.compareTypes(customAttrs[i].AttributeType, typeDef)) {
|
if (new SigComparer().Equals(typeDef, customAttrs[i].AttributeType)) {
|
||||||
customAttrs.RemoveAt(i);
|
customAttrs.RemoveAt(i);
|
||||||
|
i--;
|
||||||
Log.v("Removed custom attribute {0} ({1:X8}) (reason: {2})",
|
Log.v("Removed custom attribute {0} ({1:X8}) (reason: {2})",
|
||||||
Utils.removeNewlines(typeDef),
|
Utils.removeNewlines(typeDef),
|
||||||
typeDef.MDToken.ToUInt32(),
|
typeDef.MDToken.ToUInt32(),
|
||||||
|
@ -628,14 +631,14 @@ namespace de4dot.code.deobfuscators {
|
||||||
return DotNetUtils.getResource(module, strings);
|
return DotNetUtils.getResource(module, strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CustomAttribute getAssemblyAttribute(TypeReference attr) {
|
protected CustomAttribute getAssemblyAttribute(IType attr) {
|
||||||
var list = new List<CustomAttribute>(DotNetUtils.findAttributes(module.Assembly, attr));
|
if (module.Assembly == null)
|
||||||
return list.Count == 0 ? null : list[0];
|
return null;
|
||||||
|
return module.Assembly.CustomAttributes.Find(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CustomAttribute getModuleAttribute(TypeReference attr) {
|
protected CustomAttribute getModuleAttribute(IType attr) {
|
||||||
var list = new List<CustomAttribute>(DotNetUtils.findAttributes(module, attr));
|
return module.CustomAttributes.Find(attr);
|
||||||
return list.Count == 0 ? null : list[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool hasMetadataStream(string name) {
|
protected bool hasMetadataStream(string name) {
|
||||||
|
@ -646,7 +649,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<T> getObjectsToRemove<T>(IList<RemoveInfo<T>> removeThese) where T : MemberReference {
|
List<T> getObjectsToRemove<T>(IList<RemoveInfo<T>> removeThese) where T : class, ICodedToken {
|
||||||
var list = new List<T>(removeThese.Count);
|
var list = new List<T>(removeThese.Count);
|
||||||
foreach (var info in removeThese) {
|
foreach (var info in removeThese) {
|
||||||
if (info.obj != null)
|
if (info.obj != null)
|
||||||
|
@ -705,7 +708,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return name != null && checkValidName(name);
|
return name != null && checkValidName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnBeforeAddingResources(IWriterListener.MetadataBuilder builder) {
|
public virtual void OnBeforeAddingResources(MetadataBuilder builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void findAndRemoveInlinedMethods() {
|
protected void findAndRemoveInlinedMethods() {
|
||||||
|
|
|
@ -23,7 +23,9 @@ using Mono.Cecil;
|
||||||
using Mono.MyStuff;
|
using Mono.MyStuff;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.blocks.cflow;
|
using de4dot.blocks.cflow;
|
||||||
|
#if PORT
|
||||||
using de4dot.code.renamer;
|
using de4dot.code.renamer;
|
||||||
|
#endif
|
||||||
using de4dot.PE;
|
using de4dot.PE;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
|
@ -53,7 +55,11 @@ namespace de4dot.code.deobfuscators {
|
||||||
RenameResourceKeys = 2,
|
RenameResourceKeys = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IDeobfuscator : INameChecker {
|
public interface IDeobfuscator
|
||||||
|
#if PORT
|
||||||
|
: INameChecker
|
||||||
|
#endif
|
||||||
|
{
|
||||||
string Type { get; }
|
string Type { get; }
|
||||||
string TypeLong { get; }
|
string TypeLong { get; }
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
|
@ -19,158 +19,167 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
|
using dot10.DotNet.MD;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
class MemberReferenceBuilder {
|
class MemberReferenceBuilder : ICorLibTypes {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
Dictionary<TypeReferenceKey, TypeReference> createdTypes = new Dictionary<TypeReferenceKey, TypeReference>();
|
Dictionary<TypeSig, TypeSig> createdTypes = new Dictionary<TypeSig, TypeSig>(TypeEqualityComparer.Instance);
|
||||||
|
|
||||||
public MemberReferenceBuilder(ModuleDefinition module) {
|
public MemberReferenceBuilder(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMetadataScope CorLib {
|
public AssemblyRef CorLib {
|
||||||
get { return module.TypeSystem.Corlib; }
|
get { return module.CorLibTypes.AssemblyRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference Object {
|
public AssemblyRef AssemblyRef {
|
||||||
get { return module.TypeSystem.Object; }
|
get { return module.CorLibTypes.AssemblyRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference Void {
|
public CorLibTypeSig Object {
|
||||||
get { return module.TypeSystem.Void; }
|
get { return module.CorLibTypes.Object; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference Boolean {
|
public CorLibTypeSig Void {
|
||||||
get { return module.TypeSystem.Boolean; }
|
get { return module.CorLibTypes.Void; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference Char {
|
public CorLibTypeSig Boolean {
|
||||||
get { return module.TypeSystem.Char; }
|
get { return module.CorLibTypes.Boolean; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference SByte {
|
public CorLibTypeSig Char {
|
||||||
get { return module.TypeSystem.SByte; }
|
get { return module.CorLibTypes.Char; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference Byte {
|
public CorLibTypeSig SByte {
|
||||||
get { return module.TypeSystem.Byte; }
|
get { return module.CorLibTypes.SByte; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference Int16 {
|
public CorLibTypeSig Byte {
|
||||||
get { return module.TypeSystem.Int16; }
|
get { return module.CorLibTypes.Byte; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference UInt16 {
|
public CorLibTypeSig Int16 {
|
||||||
get { return module.TypeSystem.UInt16; }
|
get { return module.CorLibTypes.Int16; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference Int32 {
|
public CorLibTypeSig UInt16 {
|
||||||
get { return module.TypeSystem.Int32; }
|
get { return module.CorLibTypes.UInt16; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference UInt32 {
|
public CorLibTypeSig Int32 {
|
||||||
get { return module.TypeSystem.UInt32; }
|
get { return module.CorLibTypes.Int32; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference Int64 {
|
public CorLibTypeSig UInt32 {
|
||||||
get { return module.TypeSystem.Int64; }
|
get { return module.CorLibTypes.UInt32; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference UInt64 {
|
public CorLibTypeSig Int64 {
|
||||||
get { return module.TypeSystem.UInt64; }
|
get { return module.CorLibTypes.Int64; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference Single {
|
public CorLibTypeSig UInt64 {
|
||||||
get { return module.TypeSystem.Single; }
|
get { return module.CorLibTypes.UInt64; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference Double {
|
public CorLibTypeSig Single {
|
||||||
get { return module.TypeSystem.Double; }
|
get { return module.CorLibTypes.Single; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference IntPtr {
|
public CorLibTypeSig Double {
|
||||||
get { return module.TypeSystem.IntPtr; }
|
get { return module.CorLibTypes.Double; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference UIntPtr {
|
public CorLibTypeSig IntPtr {
|
||||||
get { return module.TypeSystem.UIntPtr; }
|
get { return module.CorLibTypes.IntPtr; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference String {
|
public CorLibTypeSig UIntPtr {
|
||||||
get { return module.TypeSystem.String; }
|
get { return module.CorLibTypes.UIntPtr; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference TypedReference {
|
public CorLibTypeSig String {
|
||||||
get { return module.TypeSystem.TypedReference; }
|
get { return module.CorLibTypes.String; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference type(string ns, string name, string asmSimpleName) {
|
public CorLibTypeSig TypedReference {
|
||||||
|
get { return module.CorLibTypes.TypedReference; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassSig type(string ns, string name, string asmSimpleName) {
|
||||||
return type(ns, name, findAssemblyReference(asmSimpleName));
|
return type(ns, name, findAssemblyReference(asmSimpleName));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference type(string ns, string name) {
|
public ClassSig type(string ns, string name) {
|
||||||
return type(ns, name, CorLib);
|
return type(ns, name, CorLib);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference type(string ns, string name, IMetadataScope asmRef) {
|
public ClassSig type(string ns, string name, AssemblyRef asmRef) {
|
||||||
return type(false, ns, name, asmRef);
|
return (ClassSig)type(false, ns, name, asmRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference valueType(string ns, string name, string asmSimpleName) {
|
public ValueTypeSig valueType(string ns, string name, string asmSimpleName) {
|
||||||
return valueType(ns, name, findAssemblyReference(asmSimpleName));
|
return valueType(ns, name, findAssemblyReference(asmSimpleName));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference valueType(string ns, string name) {
|
public ValueTypeSig valueType(string ns, string name) {
|
||||||
return valueType(ns, name, CorLib);
|
return valueType(ns, name, CorLib);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference valueType(string ns, string name, IMetadataScope asmRef) {
|
public ValueTypeSig valueType(string ns, string name, AssemblyRef asmRef) {
|
||||||
return type(true, ns, name, asmRef);
|
return (ValueTypeSig)type(true, ns, name, asmRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference type(bool isValueType, string ns, string name, IMetadataScope asmRef) {
|
public ClassOrValueTypeSig type(bool isValueType, string ns, string name, IResolutionScope resolutionScope) {
|
||||||
var typeRef = new TypeReference(ns, name, module, asmRef);
|
var typeRef = module.UpdateRowId(new TypeRefUser(module, ns, name, resolutionScope));
|
||||||
typeRef.IsValueType = isValueType;
|
ClassOrValueTypeSig type;
|
||||||
return add(isValueType, typeRef);
|
if (isValueType)
|
||||||
|
type = new ValueTypeSig(typeRef);
|
||||||
|
else
|
||||||
|
type = new ClassSig(typeRef);
|
||||||
|
return (ClassOrValueTypeSig)add(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeReference array(TypeReference typeRef) {
|
public ArraySig array(TypeSig typeRef) {
|
||||||
return add(false, new ArrayType(typeRef));
|
return (ArraySig)add(new ArraySig(typeRef));
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeReference add(bool isValueType, TypeReference typeRef) {
|
TypeSig add(TypeSig typeRef) {
|
||||||
var key = new TypeReferenceKey(typeRef);
|
TypeSig createdTypeRef;
|
||||||
TypeReference createdTypeRef;
|
if (createdTypes.TryGetValue(typeRef, out createdTypeRef)) {
|
||||||
if (createdTypes.TryGetValue(key, out createdTypeRef)) {
|
if (createdTypeRef.ElementType != typeRef.ElementType)
|
||||||
if (createdTypeRef.IsValueType != isValueType)
|
|
||||||
throw new ApplicationException(string.Format("Type {0}'s IsValueType is not correct", createdTypeRef));
|
throw new ApplicationException(string.Format("Type {0}'s IsValueType is not correct", createdTypeRef));
|
||||||
return createdTypeRef;
|
return createdTypeRef;
|
||||||
}
|
}
|
||||||
createdTypes[key] = typeRef;
|
createdTypes[typeRef] = typeRef;
|
||||||
return typeRef;
|
return typeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference instanceMethod(string name, TypeReference declaringType, TypeReference returnType, params TypeReference[] args) {
|
public MemberRef instanceMethod(string name, IMemberRefParent declaringType, TypeSig returnType, params TypeSig[] args) {
|
||||||
return method(true, name, declaringType, returnType, args);
|
return method(true, name, declaringType, returnType, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference staticMethod(string name, TypeReference declaringType, TypeReference returnType, params TypeReference[] args) {
|
public MemberRef staticMethod(string name, IMemberRefParent declaringType, TypeSig returnType, params TypeSig[] args) {
|
||||||
return method(false, name, declaringType, returnType, args);
|
return method(false, name, declaringType, returnType, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference method(bool isInstance, string name, TypeReference declaringType, TypeReference returnType, params TypeReference[] args) {
|
public MemberRef method(bool isInstance, string name, IMemberRefParent declaringType, TypeSig returnType, params TypeSig[] args) {
|
||||||
var method = new MethodReference(name, returnType, declaringType);
|
MethodSig sig;
|
||||||
method.HasThis = isInstance;
|
if (isInstance)
|
||||||
foreach (var arg in args)
|
sig = MethodSig.CreateInstance(returnType, args);
|
||||||
method.Parameters.Add(new ParameterDefinition(arg));
|
else
|
||||||
return method;
|
sig = MethodSig.CreateStatic(returnType, args);
|
||||||
|
return module.UpdateRowId(new MemberRefUser(module, name, sig, declaringType));
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyNameReference findAssemblyReference(string asmSimpleName) {
|
AssemblyRef findAssemblyReference(string asmSimpleName) {
|
||||||
AssemblyNameReference asmRef = null;
|
AssemblyRef asmRef = null;
|
||||||
foreach (var asmRef2 in findAssemblyReferences(asmSimpleName)) {
|
foreach (var asmRef2 in findAssemblyReferences(asmSimpleName)) {
|
||||||
if (asmRef == null || asmRef.Version == null || (asmRef2.Version != null && asmRef2.Version > asmRef.Version))
|
if (asmRef == null || asmRef.Version == null || (asmRef2.Version != null && asmRef2.Version > asmRef.Version))
|
||||||
asmRef = asmRef2;
|
asmRef = asmRef2;
|
||||||
|
@ -180,10 +189,11 @@ namespace de4dot.code.deobfuscators {
|
||||||
return asmRef;
|
return asmRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AssemblyNameReference> findAssemblyReferences(string asmSimpleName) {
|
List<AssemblyRef> findAssemblyReferences(string asmSimpleName) {
|
||||||
var asmRefs = new List<AssemblyNameReference>();
|
var asmRefs = new List<AssemblyRef>();
|
||||||
foreach (var asmRef in module.AssemblyReferences) {
|
var name = new UTF8String(asmSimpleName);
|
||||||
if (asmRef.Name == asmSimpleName)
|
foreach (var asmRef in module.GetAssemblyRefs()) {
|
||||||
|
if (UTF8String.Equals(asmRef.Name, name))
|
||||||
asmRefs.Add(asmRef);
|
asmRefs.Add(asmRef);
|
||||||
}
|
}
|
||||||
return asmRefs;
|
return asmRefs;
|
||||||
|
|
|
@ -19,15 +19,15 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
abstract class ProxyCallFixerBase {
|
abstract class ProxyCallFixerBase {
|
||||||
protected ModuleDefinition module;
|
protected ModuleDefMD module;
|
||||||
protected List<MethodDefinition> delegateCreatorMethods = new List<MethodDefinition>();
|
protected List<MethodDef> delegateCreatorMethods = new List<MethodDef>();
|
||||||
protected Dictionary<TypeDefinition, bool> delegateTypesDict = new Dictionary<TypeDefinition, bool>();
|
protected Dictionary<TypeDef, bool> delegateTypesDict = new Dictionary<TypeDef, bool>();
|
||||||
protected int errors = 0;
|
protected int errors = 0;
|
||||||
|
|
||||||
public int Errors {
|
public int Errors {
|
||||||
|
@ -35,10 +35,10 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class DelegateInfo {
|
protected class DelegateInfo {
|
||||||
public MethodReference methodRef; // Method we should call
|
public IMethod methodRef; // Method we should call
|
||||||
public FieldDefinition field; // Field holding the Delegate instance
|
public FieldDef field; // Field holding the Delegate instance
|
||||||
public OpCode callOpcode;
|
public OpCode callOpcode;
|
||||||
public DelegateInfo(FieldDefinition field, MethodReference methodRef, OpCode callOpcode) {
|
public DelegateInfo(FieldDef field, IMethod methodRef, OpCode callOpcode) {
|
||||||
this.field = field;
|
this.field = field;
|
||||||
this.methodRef = methodRef;
|
this.methodRef = methodRef;
|
||||||
this.callOpcode = callOpcode;
|
this.callOpcode = callOpcode;
|
||||||
|
@ -47,30 +47,30 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
public int RemovedDelegateCreatorCalls { get; set; }
|
public int RemovedDelegateCreatorCalls { get; set; }
|
||||||
|
|
||||||
public IEnumerable<TypeDefinition> DelegateTypes {
|
public IEnumerable<TypeDef> DelegateTypes {
|
||||||
get { return delegateTypesDict.Keys; }
|
get { return delegateTypesDict.Keys; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<TypeDefinition> DelegateCreatorTypes {
|
public IEnumerable<TypeDef> DelegateCreatorTypes {
|
||||||
get {
|
get {
|
||||||
foreach (var method in delegateCreatorMethods)
|
foreach (var method in delegateCreatorMethods)
|
||||||
yield return method.DeclaringType;
|
yield return method.DeclaringType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IEnumerable<Tuple<MethodDefinition, string>> OtherMethods {
|
public virtual IEnumerable<Tuple<MethodDef, string>> OtherMethods {
|
||||||
get { return new List<Tuple<MethodDefinition, string>>(); }
|
get { return new List<Tuple<MethodDef, string>>(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Detected {
|
public bool Detected {
|
||||||
get { return delegateCreatorMethods.Count != 0; }
|
get { return delegateCreatorMethods.Count != 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ProxyCallFixerBase(ModuleDefinition module) {
|
protected ProxyCallFixerBase(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ProxyCallFixerBase(ModuleDefinition module, ProxyCallFixerBase oldOne) {
|
protected ProxyCallFixerBase(ModuleDefMD module, ProxyCallFixerBase oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
foreach (var method in oldOne.delegateCreatorMethods)
|
foreach (var method in oldOne.delegateCreatorMethods)
|
||||||
delegateCreatorMethods.Add(lookup(method, "Could not find delegate creator method"));
|
delegateCreatorMethods.Add(lookup(method, "Could not find delegate creator method"));
|
||||||
|
@ -84,17 +84,17 @@ namespace de4dot.code.deobfuscators {
|
||||||
return new DelegateInfo(field, method, di.callOpcode);
|
return new DelegateInfo(field, method, di.callOpcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected T lookup<T>(T def, string errorMessage) where T : MemberReference {
|
protected T lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
|
||||||
return DeobUtils.lookup(module, def, errorMessage);
|
return DeobUtils.lookup(module, def, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setDelegateCreatorMethod(MethodDefinition delegateCreatorMethod) {
|
protected void setDelegateCreatorMethod(MethodDef delegateCreatorMethod) {
|
||||||
if (delegateCreatorMethod == null)
|
if (delegateCreatorMethod == null)
|
||||||
return;
|
return;
|
||||||
delegateCreatorMethods.Add(delegateCreatorMethod);
|
delegateCreatorMethods.Add(delegateCreatorMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool isDelegateCreatorMethod(MethodDefinition method) {
|
protected bool isDelegateCreatorMethod(MethodDef method) {
|
||||||
foreach (var m in delegateCreatorMethods) {
|
foreach (var m in delegateCreatorMethods) {
|
||||||
if (m == method)
|
if (m == method)
|
||||||
return true;
|
return true;
|
||||||
|
@ -102,7 +102,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual IEnumerable<TypeDefinition> getDelegateTypes() {
|
protected virtual IEnumerable<TypeDef> getDelegateTypes() {
|
||||||
foreach (var type in module.Types) {
|
foreach (var type in module.Types) {
|
||||||
if (type.BaseType == null || type.BaseType.FullName != "System.MulticastDelegate")
|
if (type.BaseType == null || type.BaseType.FullName != "System.MulticastDelegate")
|
||||||
continue;
|
continue;
|
||||||
|
@ -182,11 +182,11 @@ namespace de4dot.code.deobfuscators {
|
||||||
abstract class ProxyCallFixer1 : ProxyCallFixerBase {
|
abstract class ProxyCallFixer1 : ProxyCallFixerBase {
|
||||||
FieldDefinitionAndDeclaringTypeDict<DelegateInfo> fieldToDelegateInfo = new FieldDefinitionAndDeclaringTypeDict<DelegateInfo>();
|
FieldDefinitionAndDeclaringTypeDict<DelegateInfo> fieldToDelegateInfo = new FieldDefinitionAndDeclaringTypeDict<DelegateInfo>();
|
||||||
|
|
||||||
protected ProxyCallFixer1(ModuleDefinition module)
|
protected ProxyCallFixer1(ModuleDefMD module)
|
||||||
: base(module) {
|
: base(module) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ProxyCallFixer1(ModuleDefinition module, ProxyCallFixer1 oldOne)
|
protected ProxyCallFixer1(ModuleDefMD module, ProxyCallFixer1 oldOne)
|
||||||
: base(module, oldOne) {
|
: base(module, oldOne) {
|
||||||
foreach (var key in oldOne.fieldToDelegateInfo.getKeys())
|
foreach (var key in oldOne.fieldToDelegateInfo.getKeys())
|
||||||
fieldToDelegateInfo.add(lookup(key, "Could not find field"), copy(oldOne.fieldToDelegateInfo.find(key)));
|
fieldToDelegateInfo.add(lookup(key, "Could not find field"), copy(oldOne.fieldToDelegateInfo.find(key)));
|
||||||
|
@ -196,7 +196,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
fieldToDelegateInfo.add(di.field, di);
|
fieldToDelegateInfo.add(di.field, di);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DelegateInfo getDelegateInfo(FieldReference field) {
|
protected DelegateInfo getDelegateInfo(IField field) {
|
||||||
if (field == null)
|
if (field == null)
|
||||||
return null;
|
return null;
|
||||||
return fieldToDelegateInfo.find(field);
|
return fieldToDelegateInfo.find(field);
|
||||||
|
@ -209,8 +209,8 @@ namespace de4dot.code.deobfuscators {
|
||||||
Log.v("Finding all proxy delegates");
|
Log.v("Finding all proxy delegates");
|
||||||
foreach (var tmp in getDelegateTypes()) {
|
foreach (var tmp in getDelegateTypes()) {
|
||||||
var type = tmp;
|
var type = tmp;
|
||||||
var cctor = DotNetUtils.getMethod(type, ".cctor");
|
var cctor = type.FindClassConstructor();
|
||||||
if (cctor == null || !cctor.HasBody)
|
if (cctor == null || !cctor.HasCilBody)
|
||||||
continue;
|
continue;
|
||||||
if (!type.HasFields)
|
if (!type.HasFields)
|
||||||
continue;
|
continue;
|
||||||
|
@ -219,7 +219,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
if (context == null)
|
if (context == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Log.v("Found proxy delegate: {0} ({1:X8})", Utils.removeNewlines(type), type.MetadataToken.ToUInt32());
|
Log.v("Found proxy delegate: {0} ({1:X8})", Utils.removeNewlines(type), type.MDToken.ToUInt32());
|
||||||
RemovedDelegateCreatorCalls++;
|
RemovedDelegateCreatorCalls++;
|
||||||
|
|
||||||
Log.indent();
|
Log.indent();
|
||||||
|
@ -227,7 +227,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
if (!field.IsStatic)
|
if (!field.IsStatic)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MethodReference calledMethod;
|
IMethod calledMethod;
|
||||||
OpCode callOpcode;
|
OpCode callOpcode;
|
||||||
getCallInfo(context, field, out calledMethod, out callOpcode);
|
getCallInfo(context, field, out calledMethod, out callOpcode);
|
||||||
|
|
||||||
|
@ -238,15 +238,15 @@ namespace de4dot.code.deobfuscators {
|
||||||
Utils.removeNewlines(field.Name),
|
Utils.removeNewlines(field.Name),
|
||||||
callOpcode,
|
callOpcode,
|
||||||
Utils.removeNewlines(calledMethod),
|
Utils.removeNewlines(calledMethod),
|
||||||
calledMethod.MetadataToken.ToUInt32());
|
calledMethod.MDToken.Raw);
|
||||||
}
|
}
|
||||||
Log.deIndent();
|
Log.deIndent();
|
||||||
delegateTypesDict[type] = true;
|
delegateTypesDict[type] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract object checkCctor(ref TypeDefinition type, MethodDefinition cctor);
|
protected abstract object checkCctor(ref TypeDef type, MethodDef cctor);
|
||||||
protected abstract void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode);
|
protected abstract void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode);
|
||||||
|
|
||||||
protected override bool deobfuscate(Blocks blocks, IList<Block> allBlocks) {
|
protected override bool deobfuscate(Blocks blocks, IList<Block> allBlocks) {
|
||||||
var removeInfos = new Dictionary<Block, List<RemoveInfo>>();
|
var removeInfos = new Dictionary<Block, List<RemoveInfo>>();
|
||||||
|
@ -258,7 +258,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
if (instr.OpCode != OpCodes.Ldsfld)
|
if (instr.OpCode != OpCodes.Ldsfld)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var di = getDelegateInfo(instr.Operand as FieldReference);
|
var di = getDelegateInfo(instr.Operand as IField);
|
||||||
if (di == null)
|
if (di == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -271,9 +271,9 @@ namespace de4dot.code.deobfuscators {
|
||||||
errors++;
|
errors++;
|
||||||
Log.w("Could not fix proxy call. Method: {0} ({1:X8}), Proxy type: {2} ({3:X8})",
|
Log.w("Could not fix proxy call. Method: {0} ({1:X8}), Proxy type: {2} ({3:X8})",
|
||||||
Utils.removeNewlines(blocks.Method),
|
Utils.removeNewlines(blocks.Method),
|
||||||
blocks.Method.MetadataToken.ToInt32(),
|
blocks.Method.MDToken.ToInt32(),
|
||||||
Utils.removeNewlines(di.field.DeclaringType),
|
Utils.removeNewlines(di.field.DeclaringType),
|
||||||
di.field.DeclaringType.MetadataToken.ToInt32());
|
di.field.DeclaringType.MDToken.ToInt32());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -296,7 +296,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
if (stack <= 0)
|
if (stack <= 0)
|
||||||
return null;
|
return null;
|
||||||
var instr = instrs[i];
|
var instr = instrs[i];
|
||||||
DotNetUtils.updateStack(instr.Instruction, ref stack, false);
|
instr.Instruction.UpdateStack(ref stack, false);
|
||||||
if (stack < 0)
|
if (stack < 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
@ -305,7 +305,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return null;
|
return null;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var calledMethod = instr.Operand as MethodReference;
|
var calledMethod = instr.Operand as IMethod;
|
||||||
if (calledMethod == null)
|
if (calledMethod == null)
|
||||||
return null;
|
return null;
|
||||||
if (stack != (DotNetUtils.hasReturnValue(calledMethod) ? 1 : 0))
|
if (stack != (DotNetUtils.hasReturnValue(calledMethod) ? 1 : 0))
|
||||||
|
@ -336,28 +336,25 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
// The obfuscator could be buggy and call a proxy delegate without pushing the
|
// The obfuscator could be buggy and call a proxy delegate without pushing the
|
||||||
// instance field. SA has done it, so let's fix it.
|
// instance field. SA has done it, so let's fix it.
|
||||||
void fixBrokenCalls(MethodDefinition obfuscatedMethod, IList<Block> allBlocks) {
|
void fixBrokenCalls(MethodDef obfuscatedMethod, IList<Block> allBlocks) {
|
||||||
foreach (var block in allBlocks) {
|
foreach (var block in allBlocks) {
|
||||||
var instrs = block.Instructions;
|
var instrs = block.Instructions;
|
||||||
for (int i = 0; i < instrs.Count; i++) {
|
for (int i = 0; i < instrs.Count; i++) {
|
||||||
var call = instrs[i];
|
var call = instrs[i];
|
||||||
if (call.OpCode != OpCodes.Call && call.OpCode != OpCodes.Callvirt)
|
if (call.OpCode != OpCodes.Call && call.OpCode != OpCodes.Callvirt)
|
||||||
continue;
|
continue;
|
||||||
var methodRef = call.Operand as MethodReference;
|
var methodRef = call.Operand as IMethod;
|
||||||
if (methodRef == null || methodRef.Name != "Invoke")
|
if (methodRef == null || methodRef.Name != "Invoke")
|
||||||
continue;
|
continue;
|
||||||
var method = DotNetUtils.getMethod(module, methodRef);
|
MethodDef method = DotNetUtils.getMethod2(module, methodRef);
|
||||||
if (method == null)
|
if (method == null || method.DeclaringType == null)
|
||||||
continue;
|
continue;
|
||||||
var declaringType = DotNetUtils.getType(module, method.DeclaringType);
|
if (!delegateTypesDict.ContainsKey(method.DeclaringType))
|
||||||
if (declaringType == null)
|
|
||||||
continue;
|
|
||||||
if (!delegateTypesDict.ContainsKey(declaringType))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Oooops!!! The obfuscator is buggy. Well, let's hope it is, or it's my code. ;)
|
// Oooops!!! The obfuscator is buggy. Well, let's hope it is, or it's my code. ;)
|
||||||
|
|
||||||
Log.w("Holy obfuscator bugs, Batman! Found a proxy delegate call with no instance push in {0:X8}. Replacing it with a throw...", obfuscatedMethod.MetadataToken.ToInt32());
|
Log.w("Holy obfuscator bugs, Batman! Found a proxy delegate call with no instance push in {0:X8}. Replacing it with a throw...", obfuscatedMethod.MDToken.ToInt32());
|
||||||
block.insert(i, Instruction.Create(OpCodes.Ldnull));
|
block.insert(i, Instruction.Create(OpCodes.Ldnull));
|
||||||
block.replace(i + 1, 1, Instruction.Create(OpCodes.Throw));
|
block.replace(i + 1, 1, Instruction.Create(OpCodes.Throw));
|
||||||
i++;
|
i++;
|
||||||
|
@ -373,11 +370,11 @@ namespace de4dot.code.deobfuscators {
|
||||||
abstract class ProxyCallFixer2 : ProxyCallFixerBase {
|
abstract class ProxyCallFixer2 : ProxyCallFixerBase {
|
||||||
MethodDefinitionAndDeclaringTypeDict<DelegateInfo> proxyMethodToDelegateInfo = new MethodDefinitionAndDeclaringTypeDict<DelegateInfo>();
|
MethodDefinitionAndDeclaringTypeDict<DelegateInfo> proxyMethodToDelegateInfo = new MethodDefinitionAndDeclaringTypeDict<DelegateInfo>();
|
||||||
|
|
||||||
protected ProxyCallFixer2(ModuleDefinition module)
|
protected ProxyCallFixer2(ModuleDefMD module)
|
||||||
: base(module) {
|
: base(module) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ProxyCallFixer2(ModuleDefinition module, ProxyCallFixer2 oldOne)
|
protected ProxyCallFixer2(ModuleDefMD module, ProxyCallFixer2 oldOne)
|
||||||
: base(module, oldOne) {
|
: base(module, oldOne) {
|
||||||
foreach (var oldMethod in oldOne.proxyMethodToDelegateInfo.getKeys()) {
|
foreach (var oldMethod in oldOne.proxyMethodToDelegateInfo.getKeys()) {
|
||||||
var oldDi = oldOne.proxyMethodToDelegateInfo.find(oldMethod);
|
var oldDi = oldOne.proxyMethodToDelegateInfo.find(oldMethod);
|
||||||
|
@ -396,8 +393,8 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
protected void find2() {
|
protected void find2() {
|
||||||
foreach (var type in getDelegateTypes()) {
|
foreach (var type in getDelegateTypes()) {
|
||||||
var cctor = DotNetUtils.getMethod(type, ".cctor");
|
var cctor = type.FindClassConstructor();
|
||||||
if (cctor == null || !cctor.HasBody)
|
if (cctor == null || !cctor.HasCilBody)
|
||||||
continue;
|
continue;
|
||||||
if (!type.HasFields)
|
if (!type.HasFields)
|
||||||
continue;
|
continue;
|
||||||
|
@ -406,17 +403,17 @@ namespace de4dot.code.deobfuscators {
|
||||||
if (context == null)
|
if (context == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Log.v("Found proxy delegate: {0} ({1:X8})", Utils.removeNewlines(type), type.MetadataToken.ToUInt32());
|
Log.v("Found proxy delegate: {0} ({1:X8})", Utils.removeNewlines(type), type.MDToken.ToUInt32());
|
||||||
RemovedDelegateCreatorCalls++;
|
RemovedDelegateCreatorCalls++;
|
||||||
var fieldToMethod = getFieldToMethodDictionary(type);
|
var fieldToMethod = getFieldToMethodDictionary(type);
|
||||||
|
|
||||||
Log.indent();
|
Log.indent();
|
||||||
foreach (var field in type.Fields) {
|
foreach (var field in type.Fields) {
|
||||||
MethodDefinition proxyMethod;
|
MethodDef proxyMethod;
|
||||||
if (!fieldToMethod.TryGetValue(field, out proxyMethod))
|
if (!fieldToMethod.TryGetValue(field, out proxyMethod))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MethodReference calledMethod;
|
IMethod calledMethod;
|
||||||
OpCode callOpcode;
|
OpCode callOpcode;
|
||||||
getCallInfo(context, field, out calledMethod, out callOpcode);
|
getCallInfo(context, field, out calledMethod, out callOpcode);
|
||||||
|
|
||||||
|
@ -427,32 +424,32 @@ namespace de4dot.code.deobfuscators {
|
||||||
Utils.removeNewlines(field.Name),
|
Utils.removeNewlines(field.Name),
|
||||||
callOpcode,
|
callOpcode,
|
||||||
Utils.removeNewlines(calledMethod),
|
Utils.removeNewlines(calledMethod),
|
||||||
calledMethod.MetadataToken.ToUInt32());
|
calledMethod.MDToken.ToUInt32());
|
||||||
}
|
}
|
||||||
Log.deIndent();
|
Log.deIndent();
|
||||||
delegateTypesDict[type] = true;
|
delegateTypesDict[type] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void add(MethodDefinition method, DelegateInfo di) {
|
protected void add(MethodDef method, DelegateInfo di) {
|
||||||
proxyMethodToDelegateInfo.add(method, di);
|
proxyMethodToDelegateInfo.add(method, di);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract object checkCctor(TypeDefinition type, MethodDefinition cctor);
|
protected abstract object checkCctor(TypeDef type, MethodDef cctor);
|
||||||
protected abstract void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode);
|
protected abstract void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode);
|
||||||
|
|
||||||
Dictionary<FieldDefinition, MethodDefinition> getFieldToMethodDictionary(TypeDefinition type) {
|
Dictionary<FieldDef, MethodDef> getFieldToMethodDictionary(TypeDef type) {
|
||||||
var dict = new Dictionary<FieldDefinition, MethodDefinition>();
|
var dict = new Dictionary<FieldDef, MethodDef>();
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
if (!method.IsStatic || !method.HasBody || method.Name == ".cctor")
|
if (!method.IsStatic || !method.HasCilBody || method.Name == ".cctor")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var instructions = method.Body.Instructions;
|
var instructions = method.CilBody.Instructions;
|
||||||
for (int i = 0; i < instructions.Count; i++) {
|
for (int i = 0; i < instructions.Count; i++) {
|
||||||
var instr = instructions[i];
|
var instr = instructions[i];
|
||||||
if (instr.OpCode.Code != Code.Ldsfld)
|
if (instr.OpCode.Code != Code.Ldsfld)
|
||||||
continue;
|
continue;
|
||||||
var field = instr.Operand as FieldDefinition;
|
var field = instr.Operand as FieldDef;
|
||||||
if (field == null)
|
if (field == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -473,7 +470,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
if (instr.OpCode != OpCodes.Call)
|
if (instr.OpCode != OpCodes.Call)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var method = instr.Operand as MethodReference;
|
var method = instr.Operand as IMethod;
|
||||||
if (method == null)
|
if (method == null)
|
||||||
continue;
|
continue;
|
||||||
var di = proxyMethodToDelegateInfo.find(method);
|
var di = proxyMethodToDelegateInfo.find(method);
|
||||||
|
@ -493,11 +490,11 @@ namespace de4dot.code.deobfuscators {
|
||||||
// ldsfld delegate instance
|
// ldsfld delegate instance
|
||||||
// call static method
|
// call static method
|
||||||
abstract class ProxyCallFixer3 : ProxyCallFixer1 {
|
abstract class ProxyCallFixer3 : ProxyCallFixer1 {
|
||||||
protected ProxyCallFixer3(ModuleDefinition module)
|
protected ProxyCallFixer3(ModuleDefMD module)
|
||||||
: base(module) {
|
: base(module) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ProxyCallFixer3(ModuleDefinition module, ProxyCallFixer3 oldOne)
|
protected ProxyCallFixer3(ModuleDefMD module, ProxyCallFixer3 oldOne)
|
||||||
: base(module, oldOne) {
|
: base(module, oldOne) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,10 +511,10 @@ namespace de4dot.code.deobfuscators {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static MethodReference getCalledMethod(Instr instr) {
|
static IMethod getCalledMethod(Instr instr) {
|
||||||
if (instr.OpCode.Code != Code.Call)
|
if (instr.OpCode.Code != Code.Call)
|
||||||
return null;
|
return null;
|
||||||
return instr.Operand as MethodReference;
|
return instr.Operand as IMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using Mono.Cecil.Metadata;
|
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
|
@ -29,31 +28,31 @@ namespace de4dot.code.deobfuscators {
|
||||||
// This thing requires a lot more code than I have time to do now (similar to symbol renaming)
|
// This thing requires a lot more code than I have time to do now (similar to symbol renaming)
|
||||||
// so it will be a basic implementation only.
|
// so it will be a basic implementation only.
|
||||||
abstract class TypesRestorerBase {
|
abstract class TypesRestorerBase {
|
||||||
ModuleDefinition module;
|
ModuleDef module;
|
||||||
List<MethodDefinition> allMethods;
|
List<MethodDef> allMethods;
|
||||||
Dictionary<ParameterDefinition, TypeInfo<ParameterDefinition>> argInfos = new Dictionary<ParameterDefinition, TypeInfo<ParameterDefinition>>();
|
Dictionary<Parameter, TypeInfo<Parameter>> argInfos = new Dictionary<Parameter, TypeInfo<Parameter>>();
|
||||||
TypeInfo<ParameterDefinition> methodReturnInfo;
|
TypeInfo<Parameter> methodReturnInfo;
|
||||||
Dictionary<FieldReferenceAndDeclaringTypeKey, TypeInfo<FieldDefinition>> fieldWrites = new Dictionary<FieldReferenceAndDeclaringTypeKey, TypeInfo<FieldDefinition>>();
|
Dictionary<FieldReferenceAndDeclaringTypeKey, TypeInfo<FieldDef>> fieldWrites = new Dictionary<FieldReferenceAndDeclaringTypeKey, TypeInfo<FieldDef>>();
|
||||||
Dictionary<int, UpdatedMethod> updatedMethods = new Dictionary<int, UpdatedMethod>();
|
Dictionary<int, UpdatedMethod> updatedMethods = new Dictionary<int, UpdatedMethod>();
|
||||||
Dictionary<int, UpdatedField> updatedFields = new Dictionary<int, UpdatedField>();
|
Dictionary<int, UpdatedField> updatedFields = new Dictionary<int, UpdatedField>();
|
||||||
|
|
||||||
class UpdatedMethod {
|
class UpdatedMethod {
|
||||||
public int token;
|
public int token;
|
||||||
public TypeReference[] newArgTypes;
|
public TypeSig[] newArgTypes;
|
||||||
public TypeReference newReturnType;
|
public TypeSig newReturnType;
|
||||||
|
|
||||||
public UpdatedMethod(MethodDefinition method) {
|
public UpdatedMethod(MethodDef method) {
|
||||||
token = method.MetadataToken.ToInt32();
|
token = method.MDToken.ToInt32();
|
||||||
newArgTypes = new TypeReference[DotNetUtils.getArgsCount(method)];
|
newArgTypes = new TypeSig[DotNetUtils.getArgsCount(method)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UpdatedField {
|
class UpdatedField {
|
||||||
public int token;
|
public int token;
|
||||||
public TypeReference newFieldType;
|
public TypeSig newFieldType;
|
||||||
|
|
||||||
public UpdatedField(FieldDefinition field) {
|
public UpdatedField(FieldDef field) {
|
||||||
token = field.MetadataToken.ToInt32();
|
token = field.MDToken.ToInt32();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +89,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
types.Clear();
|
types.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool updateNewType(ModuleDefinition module) {
|
public bool updateNewType(ModuleDef module) {
|
||||||
if (types.Count == 0)
|
if (types.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -114,20 +113,20 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypesRestorerBase(ModuleDefinition module) {
|
public TypesRestorerBase(ModuleDef module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdatedMethod getUpdatedMethod(MethodDefinition method) {
|
UpdatedMethod getUpdatedMethod(MethodDef method) {
|
||||||
int token = method.MetadataToken.ToInt32();
|
int token = method.MDToken.ToInt32();
|
||||||
UpdatedMethod updatedMethod;
|
UpdatedMethod updatedMethod;
|
||||||
if (updatedMethods.TryGetValue(token, out updatedMethod))
|
if (updatedMethods.TryGetValue(token, out updatedMethod))
|
||||||
return updatedMethod;
|
return updatedMethod;
|
||||||
return updatedMethods[token] = new UpdatedMethod(method);
|
return updatedMethods[token] = new UpdatedMethod(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdatedField getUpdatedField(FieldDefinition field) {
|
UpdatedField getUpdatedField(FieldDef field) {
|
||||||
int token = field.MetadataToken.ToInt32();
|
int token = field.MDToken.ToInt32();
|
||||||
UpdatedField updatedField;
|
UpdatedField updatedField;
|
||||||
if (updatedFields.TryGetValue(token, out updatedField))
|
if (updatedFields.TryGetValue(token, out updatedField))
|
||||||
return updatedField;
|
return updatedField;
|
||||||
|
@ -135,7 +134,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deobfuscate() {
|
public void deobfuscate() {
|
||||||
allMethods = new List<MethodDefinition>();
|
allMethods = new List<MethodDef>();
|
||||||
|
|
||||||
addAllMethods();
|
addAllMethods();
|
||||||
addAllFields();
|
addAllFields();
|
||||||
|
@ -151,11 +150,11 @@ namespace de4dot.code.deobfuscators {
|
||||||
addMethods(type.Methods);
|
addMethods(type.Methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMethods(IEnumerable<MethodDefinition> methods) {
|
void addMethods(IEnumerable<MethodDef> methods) {
|
||||||
allMethods.AddRange(methods);
|
allMethods.AddRange(methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMethod(MethodDefinition method) {
|
void addMethod(MethodDef method) {
|
||||||
allMethods.Add(method);
|
allMethods.Add(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +165,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var key = new FieldReferenceAndDeclaringTypeKey(field);
|
var key = new FieldReferenceAndDeclaringTypeKey(field);
|
||||||
fieldWrites[key] = new TypeInfo<FieldDefinition>(field);
|
fieldWrites[key] = new TypeInfo<FieldDef>(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,7 +189,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
fields.Sort((a, b) => Utils.compareInt32(a.token, b.token));
|
fields.Sort((a, b) => Utils.compareInt32(a.token, b.token));
|
||||||
Log.indent();
|
Log.indent();
|
||||||
foreach (var updatedField in fields)
|
foreach (var updatedField in fields)
|
||||||
Log.v("Field {0:X8}: type {1} ({2:X8})", updatedField.token, Utils.removeNewlines(updatedField.newFieldType.FullName), updatedField.newFieldType.MetadataToken.ToInt32());
|
Log.v("Field {0:X8}: type {1} ({2:X8})", updatedField.token, Utils.removeNewlines(updatedField.newFieldType.FullName), updatedField.newFieldType.MDToken.ToInt32());
|
||||||
Log.deIndent();
|
Log.deIndent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +207,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
if (updatedMethod.newReturnType != null) {
|
if (updatedMethod.newReturnType != null) {
|
||||||
Log.v("ret: {0} ({1:X8})",
|
Log.v("ret: {0} ({1:X8})",
|
||||||
Utils.removeNewlines(updatedMethod.newReturnType.FullName),
|
Utils.removeNewlines(updatedMethod.newReturnType.FullName),
|
||||||
updatedMethod.newReturnType.MetadataToken.ToInt32());
|
updatedMethod.newReturnType.MDToken.ToInt32());
|
||||||
}
|
}
|
||||||
for (int i = 0; i < updatedMethod.newArgTypes.Length; i++) {
|
for (int i = 0; i < updatedMethod.newArgTypes.Length; i++) {
|
||||||
var updatedArg = updatedMethod.newArgTypes[i];
|
var updatedArg = updatedMethod.newArgTypes[i];
|
||||||
|
@ -217,7 +216,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
Log.v("arg {0}: {1} ({2:X8})",
|
Log.v("arg {0}: {1} ({2:X8})",
|
||||||
i,
|
i,
|
||||||
Utils.removeNewlines(updatedArg.FullName),
|
Utils.removeNewlines(updatedArg.FullName),
|
||||||
updatedArg.MetadataToken.ToInt32());
|
updatedArg.MDToken.ToInt32());
|
||||||
}
|
}
|
||||||
Log.deIndent();
|
Log.deIndent();
|
||||||
}
|
}
|
||||||
|
@ -227,7 +226,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
bool deobfuscateMethods() {
|
bool deobfuscateMethods() {
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
foreach (var method in allMethods) {
|
foreach (var method in allMethods) {
|
||||||
methodReturnInfo = new TypeInfo<ParameterDefinition>(method.MethodReturnType.Parameter2);
|
methodReturnInfo = new TypeInfo<Parameter>(method.MethodReturnType.Parameter2);
|
||||||
deobfuscateMethod(method);
|
deobfuscateMethod(method);
|
||||||
|
|
||||||
if (methodReturnInfo.updateNewType(module)) {
|
if (methodReturnInfo.updateNewType(module)) {
|
||||||
|
@ -247,14 +246,14 @@ namespace de4dot.code.deobfuscators {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sortTypeInfos(TypeInfo<ParameterDefinition> a, TypeInfo<ParameterDefinition> b) {
|
static int sortTypeInfos(TypeInfo<Parameter> a, TypeInfo<Parameter> b) {
|
||||||
if (a.arg.Method.MetadataToken.ToInt32() < b.arg.Method.MetadataToken.ToInt32()) return -1;
|
if (a.arg.Method.MDToken.ToInt32() < b.arg.Method.MDToken.ToInt32()) return -1;
|
||||||
if (a.arg.Method.MetadataToken.ToInt32() > b.arg.Method.MetadataToken.ToInt32()) return 1;
|
if (a.arg.Method.MDToken.ToInt32() > b.arg.Method.MDToken.ToInt32()) return 1;
|
||||||
|
|
||||||
return Utils.compareInt32(a.arg.Sequence, b.arg.Sequence);
|
return Utils.compareInt32(a.arg.Sequence, b.arg.Sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deobfuscateMethod(MethodDefinition method) {
|
void deobfuscateMethod(MethodDef method) {
|
||||||
if (!method.IsStatic || method.Body == null)
|
if (!method.IsStatic || method.Body == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -264,7 +263,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
foreach (var arg in method.Parameters) {
|
foreach (var arg in method.Parameters) {
|
||||||
if (!isUnknownType(arg))
|
if (!isUnknownType(arg))
|
||||||
continue;
|
continue;
|
||||||
argInfos[arg] = new TypeInfo<ParameterDefinition>(arg);
|
argInfos[arg] = new TypeInfo<Parameter>(arg);
|
||||||
}
|
}
|
||||||
if (argInfos.Count == 0 && !fixReturnType)
|
if (argInfos.Count == 0 && !fixReturnType)
|
||||||
return;
|
return;
|
||||||
|
@ -362,7 +361,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
case Code.Starg_S:
|
case Code.Starg_S:
|
||||||
|
|
||||||
case Code.Ldelema:
|
case Code.Ldelema:
|
||||||
case Code.Ldelem_Any:
|
case Code.Ldelem:
|
||||||
case Code.Ldelem_I:
|
case Code.Ldelem_I:
|
||||||
case Code.Ldelem_I1:
|
case Code.Ldelem_I1:
|
||||||
case Code.Ldelem_I2:
|
case Code.Ldelem_I2:
|
||||||
|
@ -389,7 +388,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
case Code.Ldobj:
|
case Code.Ldobj:
|
||||||
|
|
||||||
case Code.Stelem_Any:
|
case Code.Stelem:
|
||||||
case Code.Stelem_I:
|
case Code.Stelem_I:
|
||||||
case Code.Stelem_I1:
|
case Code.Stelem_I1:
|
||||||
case Code.Stelem_I2:
|
case Code.Stelem_I2:
|
||||||
|
@ -415,7 +414,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ParameterDefinition getParameter(IList<ParameterDefinition> parameters, Instruction instr) {
|
static Parameter getParameter(IList<Parameter> parameters, Instruction instr) {
|
||||||
switch (instr.OpCode.Code) {
|
switch (instr.OpCode.Code) {
|
||||||
case Code.Ldarg:
|
case Code.Ldarg:
|
||||||
case Code.Ldarg_S:
|
case Code.Ldarg_S:
|
||||||
|
@ -430,32 +429,32 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addMethodArgType(IGenericParameterProvider gpp, ParameterDefinition methodParam, FieldReference field) {
|
bool addMethodArgType(IGenericParameterProvider gpp, Parameter methodParam, FieldReference field) {
|
||||||
if (field == null)
|
if (field == null)
|
||||||
return false;
|
return false;
|
||||||
return addMethodArgType(gpp, methodParam, field.FieldType);
|
return addMethodArgType(gpp, methodParam, field.FieldType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addMethodArgType(IGenericParameterProvider gpp, ParameterDefinition methodParam, VariableDefinition otherLocal) {
|
bool addMethodArgType(IGenericParameterProvider gpp, Parameter methodParam, VariableDefinition otherLocal) {
|
||||||
if (otherLocal == null)
|
if (otherLocal == null)
|
||||||
return false;
|
return false;
|
||||||
return addMethodArgType(gpp, methodParam, otherLocal.VariableType);
|
return addMethodArgType(gpp, methodParam, otherLocal.VariableType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addMethodArgType(IGenericParameterProvider gpp, ParameterDefinition methodParam, ParameterDefinition otherParam) {
|
bool addMethodArgType(IGenericParameterProvider gpp, Parameter methodParam, Parameter otherParam) {
|
||||||
if (otherParam == null)
|
if (otherParam == null)
|
||||||
return false;
|
return false;
|
||||||
return addMethodArgType(gpp, methodParam, otherParam.ParameterType);
|
return addMethodArgType(gpp, methodParam, otherParam.ParameterType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addMethodArgType(IGenericParameterProvider gpp, ParameterDefinition methodParam, TypeReference type) {
|
bool addMethodArgType(IGenericParameterProvider gpp, Parameter methodParam, TypeReference type) {
|
||||||
if (methodParam == null || type == null)
|
if (methodParam == null || type == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!isValidType(gpp, type))
|
if (!isValidType(gpp, type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
TypeInfo<ParameterDefinition> info;
|
TypeInfo<Parameter> info;
|
||||||
if (!argInfos.TryGetValue(methodParam, out info))
|
if (!argInfos.TryGetValue(methodParam, out info))
|
||||||
return false;
|
return false;
|
||||||
if (info.Types.ContainsKey(new TypeReferenceKey(type)))
|
if (info.Types.ContainsKey(new TypeReferenceKey(type)))
|
||||||
|
@ -476,7 +475,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
for (int i = 0; i < instructions.Count; i++) {
|
for (int i = 0; i < instructions.Count; i++) {
|
||||||
var instr = instructions[i];
|
var instr = instructions[i];
|
||||||
TypeReference fieldType = null;
|
TypeReference fieldType = null;
|
||||||
TypeInfo<FieldDefinition> info = null;
|
TypeInfo<FieldDef> info = null;
|
||||||
FieldReference field;
|
FieldReference field;
|
||||||
switch (instr.OpCode.Code) {
|
switch (instr.OpCode.Code) {
|
||||||
case Code.Stfld:
|
case Code.Stfld:
|
||||||
|
@ -527,7 +526,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
var removeThese = new List<FieldDefinition>();
|
var removeThese = new List<FieldDef>();
|
||||||
foreach (var info in fieldWrites.Values) {
|
foreach (var info in fieldWrites.Values) {
|
||||||
if (info.updateNewType(module)) {
|
if (info.updateNewType(module)) {
|
||||||
removeThese.Add(info.arg);
|
removeThese.Add(info.arg);
|
||||||
|
@ -541,7 +540,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeReference getLoadedType(IGenericParameterProvider gpp, MethodDefinition method, IList<Instruction> instructions, int instrIndex, out bool wasNewobj) {
|
TypeReference getLoadedType(IGenericParameterProvider gpp, MethodDef method, IList<Instruction> instructions, int instrIndex, out bool wasNewobj) {
|
||||||
var fieldType = MethodStack.getLoadedType(method, instructions, instrIndex, out wasNewobj);
|
var fieldType = MethodStack.getLoadedType(method, instructions, instrIndex, out wasNewobj);
|
||||||
if (fieldType == null || !isValidType(gpp, fieldType))
|
if (fieldType == null || !isValidType(gpp, fieldType))
|
||||||
return null;
|
return null;
|
||||||
|
@ -605,7 +604,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
protected abstract bool isUnknownType(object o);
|
protected abstract bool isUnknownType(object o);
|
||||||
|
|
||||||
static TypeReference getCommonBaseClass(ModuleDefinition module, TypeReference a, TypeReference b) {
|
static TypeReference getCommonBaseClass(ModuleDef module, TypeReference a, TypeReference b) {
|
||||||
if (DotNetUtils.isDelegate(a) && DotNetUtils.derivesFromDelegate(DotNetUtils.getType(module, b)))
|
if (DotNetUtils.isDelegate(a) && DotNetUtils.derivesFromDelegate(DotNetUtils.getType(module, b)))
|
||||||
return b;
|
return b;
|
||||||
if (DotNetUtils.isDelegate(b) && DotNetUtils.derivesFromDelegate(DotNetUtils.getType(module, a)))
|
if (DotNetUtils.isDelegate(b) && DotNetUtils.derivesFromDelegate(DotNetUtils.getType(module, a)))
|
||||||
|
@ -615,7 +614,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TypesRestorer : TypesRestorerBase {
|
class TypesRestorer : TypesRestorerBase {
|
||||||
public TypesRestorer(ModuleDefinition module)
|
public TypesRestorer(ModuleDef module)
|
||||||
: base(module) {
|
: base(module) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,11 +629,11 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool isUnknownType(object o) {
|
protected override bool isUnknownType(object o) {
|
||||||
var arg = o as ParameterDefinition;
|
var arg = o as Parameter;
|
||||||
if (arg != null)
|
if (arg != null)
|
||||||
return MemberReferenceHelper.isSystemObject(arg.ParameterType);
|
return MemberReferenceHelper.isSystemObject(arg.ParameterType);
|
||||||
|
|
||||||
var field = o as FieldDefinition;
|
var field = o as FieldDef;
|
||||||
if (field != null)
|
if (field != null)
|
||||||
return MemberReferenceHelper.isSystemObject(field.FieldType);
|
return MemberReferenceHelper.isSystemObject(field.FieldType);
|
||||||
|
|
||||||
|
|
2
dot10
2
dot10
|
@ -1 +1 @@
|
||||||
Subproject commit c12a2f599e25b32dfee2cc42be4f13dc2edc06d4
|
Subproject commit 7eb0fb7e6e47c79eebbef0ea9ea404f9b81fde51
|
Loading…
Reference in New Issue
Block a user