Port more code

This commit is contained in:
de4dot 2012-11-01 14:39:39 +01:00
parent c5d183983b
commit 3b6ef4fa1f
13 changed files with 354 additions and 482 deletions

View File

@ -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 });
} }

View File

@ -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() {

View File

@ -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;
if (assembly != null) {
var name = assembly.Name.FullName;
cache[name] = assembly;
}
} }
void addConfigFile(string configFilename) { public void removeModule(ModuleDef module) {
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();
} }
} }
} }

View File

@ -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; }

View File

@ -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));
} }

View File

@ -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" />

View File

@ -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;

View File

@ -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() {

View File

@ -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; }

View File

@ -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;

View File

@ -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;
} }
} }
} }

View File

@ -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

@ -1 +1 @@
Subproject commit c12a2f599e25b32dfee2cc42be4f13dc2edc06d4 Subproject commit 7eb0fb7e6e47c79eebbef0ea9ea404f9b81fde51