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;
|
||||
}
|
||||
|
||||
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) {
|
||||
return getPInvokeMethod(type, methodName) != null;
|
||||
}
|
||||
|
@ -448,6 +452,17 @@ namespace de4dot.blocks {
|
|||
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) {
|
||||
return getResource(module, new List<string> { name });
|
||||
}
|
||||
|
|
|
@ -20,52 +20,47 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.MyStuff;
|
||||
using dot10.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code {
|
||||
class AssemblyModule {
|
||||
string filename;
|
||||
ModuleDefinition module;
|
||||
ModuleDefMD module;
|
||||
|
||||
public AssemblyModule(string filename) {
|
||||
this.filename = Utils.getFullPath(filename);
|
||||
}
|
||||
|
||||
ReaderParameters getReaderParameters() {
|
||||
return new ReaderParameters(ReadingMode.Deferred) {
|
||||
AssemblyResolver = AssemblyResolver.Instance
|
||||
};
|
||||
public ModuleDefMD load() {
|
||||
return setModule(ModuleDefMD.Load(filename));
|
||||
}
|
||||
|
||||
public ModuleDefinition load() {
|
||||
return setModule(ModuleDefinition.ReadModule(filename, getReaderParameters()));
|
||||
public ModuleDefMD load(byte[] fileData) {
|
||||
return setModule(ModuleDefMD.Load(fileData));
|
||||
}
|
||||
|
||||
public ModuleDefinition load(byte[] fileData) {
|
||||
return setModule(ModuleDefinition.ReadModule(new MemoryStream(fileData), getReaderParameters()));
|
||||
}
|
||||
|
||||
ModuleDefinition setModule(ModuleDefinition newModule) {
|
||||
ModuleDefMD setModule(ModuleDefMD newModule) {
|
||||
module = newModule;
|
||||
AssemblyResolver.Instance.addModule(module);
|
||||
module.FullyQualifiedName = filename;
|
||||
module.Location = filename;
|
||||
return module;
|
||||
}
|
||||
|
||||
public void save(string newFilename, bool updateMaxStack, IWriterListener writerListener) {
|
||||
var writerParams = new WriterParameters() {
|
||||
UpdateMaxStack = updateMaxStack,
|
||||
WriterListener = writerListener,
|
||||
};
|
||||
module.Write(newFilename, writerParams);
|
||||
//TODO: var writerParams = new WriterParameters() {
|
||||
//TODO: UpdateMaxStack = updateMaxStack,
|
||||
//TODO: WriterListener = writerListener,
|
||||
//TODO: };
|
||||
//TODO: module.Write(newFilename, writerParams);
|
||||
module.Write(newFilename);
|
||||
}
|
||||
|
||||
public ModuleDefinition reload(byte[] newModuleData, DumpedMethods dumpedMethods) {
|
||||
AssemblyResolver.Instance.removeModule(module);
|
||||
DotNetUtils.typeCaches.invalidate(module);
|
||||
return setModule(ModuleDefinition.ReadModule(new MemoryStream(newModuleData), getReaderParameters(), dumpedMethods));
|
||||
public ModuleDefMD reload(byte[] newModuleData, DumpedMethods dumpedMethods) {
|
||||
//TODO: AssemblyResolver.Instance.removeModule(module);
|
||||
//TODO: DotNetUtils.typeCaches.invalidate(module);
|
||||
//TODO: Use dumped methods
|
||||
return setModule(ModuleDefMD.Load(newModuleData));
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
|
|
|
@ -17,176 +17,38 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using Mono.Cecil;
|
||||
using dot10.DotNet;
|
||||
|
||||
namespace de4dot.code {
|
||||
public class AssemblyResolver : DefaultAssemblyResolver {
|
||||
public class AssemblyResolver : dot10.DotNet.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) {
|
||||
if (!addedDirectories.ContainsKey(dir)) {
|
||||
addedDirectories[dir] = true;
|
||||
AddSearchDirectory(dir);
|
||||
}
|
||||
if (!PostSearchPaths.Contains(dir))
|
||||
PostSearchPaths.Add(dir);
|
||||
}
|
||||
|
||||
public void addModule(ModuleDefinition module) {
|
||||
if (module.FullyQualifiedName != "") {
|
||||
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;
|
||||
}
|
||||
public void addModule(ModuleDef module) {
|
||||
AddToCache(module.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) {
|
||||
public void removeModule(ModuleDef module) {
|
||||
var assembly = module.Assembly;
|
||||
if (assembly == null)
|
||||
return;
|
||||
|
||||
removeModule(assembly.Name.FullName);
|
||||
removeModule(assembly.FullName);
|
||||
}
|
||||
|
||||
public void removeModule(string asmFullName) {
|
||||
if (string.IsNullOrEmpty(asmFullName))
|
||||
return;
|
||||
cache.Remove(asmFullName);
|
||||
//TODO: Remove it from the cache
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
cache.Clear();
|
||||
resetSearchPaths();
|
||||
//TODO: cache.Clear();
|
||||
//TODO: resetSearchPaths();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.code.deobfuscators;
|
||||
using Mono.Cecil;
|
||||
#if PORT
|
||||
using de4dot.code.renamer;
|
||||
#endif
|
||||
|
||||
namespace de4dot.code {
|
||||
public interface IObfuscatedFile {
|
||||
|
@ -29,7 +31,9 @@ namespace de4dot.code {
|
|||
IDeobfuscatorContext DeobfuscatorContext { get; set; }
|
||||
string Filename { get; }
|
||||
string NewFilename { get; }
|
||||
#if PORT
|
||||
INameChecker NameChecker { get; }
|
||||
#endif
|
||||
bool RenameResourcesInCode { get; }
|
||||
bool RemoveNamespaceWithOneType { get; }
|
||||
bool RenameResourceKeys { get; }
|
||||
|
|
|
@ -22,20 +22,21 @@ using System.Collections.Generic;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.MyStuff;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using de4dot.code.deobfuscators;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
using de4dot.code.AssemblyClient;
|
||||
#if PORT
|
||||
using de4dot.code.renamer;
|
||||
#endif
|
||||
using de4dot.PE;
|
||||
|
||||
namespace de4dot.code {
|
||||
public class ObfuscatedFile : IObfuscatedFile, IDeobfuscatedFile {
|
||||
Options options;
|
||||
ModuleDefinition module;
|
||||
ModuleDefMD module;
|
||||
IDeobfuscator deob;
|
||||
IDeobfuscatorContext deobfuscatorContext;
|
||||
AssemblyModule assemblyModule;
|
||||
|
@ -46,14 +47,14 @@ namespace de4dot.code {
|
|||
bool userStringDecrypterMethods = false;
|
||||
|
||||
class SavedMethodBodies {
|
||||
Dictionary<MethodDefinition, SavedMethodBody> savedMethodBodies = new Dictionary<MethodDefinition, SavedMethodBody>();
|
||||
Dictionary<MethodDef, SavedMethodBody> savedMethodBodies = new Dictionary<MethodDef, SavedMethodBody>();
|
||||
|
||||
class SavedMethodBody {
|
||||
MethodDefinition method;
|
||||
MethodDef method;
|
||||
IList<Instruction> instructions;
|
||||
IList<ExceptionHandler> exceptionHandlers;
|
||||
|
||||
public SavedMethodBody(MethodDefinition method) {
|
||||
public SavedMethodBody(MethodDef method) {
|
||||
this.method = method;
|
||||
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))
|
||||
return;
|
||||
savedMethodBodies[method] = new SavedMethodBody(method);
|
||||
|
@ -75,7 +76,7 @@ namespace de4dot.code {
|
|||
savedMethodBodies.Clear();
|
||||
}
|
||||
|
||||
public bool isSaved(MethodDefinition method) {
|
||||
public bool isSaved(MethodDef method) {
|
||||
return savedMethodBodies.ContainsKey(method);
|
||||
}
|
||||
}
|
||||
|
@ -103,13 +104,15 @@ namespace de4dot.code {
|
|||
get { return options.NewFilename; }
|
||||
}
|
||||
|
||||
public ModuleDefinition ModuleDefinition {
|
||||
public ModuleDefMD ModuleDefMD {
|
||||
get { return module; }
|
||||
}
|
||||
|
||||
#if PORT
|
||||
public INameChecker NameChecker {
|
||||
get { return deob; }
|
||||
}
|
||||
#endif
|
||||
|
||||
public bool RenameResourcesInCode {
|
||||
get { return deob.TheOptions.RenameResourcesInCode; }
|
||||
|
@ -309,8 +312,8 @@ namespace de4dot.code {
|
|||
assemblyModule.save(options.NewFilename, options.ControlFlowDeobfuscation, deob as IWriterListener);
|
||||
}
|
||||
|
||||
IList<MethodDefinition> getAllMethods() {
|
||||
var list = new List<MethodDefinition>();
|
||||
IList<MethodDef> getAllMethods() {
|
||||
var list = new List<MethodDef>();
|
||||
|
||||
foreach (var type in module.GetTypes()) {
|
||||
foreach (var method in type.Methods)
|
||||
|
@ -546,7 +549,7 @@ namespace de4dot.code {
|
|||
catch (Exception ex) {
|
||||
if (!canLoadMethodBody(method)) {
|
||||
Log.v("Invalid method body. {0:X8}", method.MetadataToken.ToInt32());
|
||||
method.Body = new MethodBody(method);
|
||||
method.CilBody = new MethodBody(method);
|
||||
}
|
||||
else {
|
||||
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 {
|
||||
var body = method.Body;
|
||||
var body = method.CilBody;
|
||||
return true;
|
||||
}
|
||||
catch {
|
||||
|
@ -574,13 +577,13 @@ namespace de4dot.code {
|
|||
}
|
||||
|
||||
#if PORT
|
||||
void deobfuscate(MethodDefinition method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter) {
|
||||
void deobfuscate(MethodDef method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter) {
|
||||
if (!hasNonEmptyBody(method))
|
||||
return;
|
||||
|
||||
var blocks = new Blocks(method);
|
||||
int numRemovedLocals = 0;
|
||||
int oldNumInstructions = method.Body.Instructions.Count;
|
||||
int oldNumInstructions = method.CilBody.Instructions.Count;
|
||||
|
||||
deob.deobfuscateMethodBegin(blocks);
|
||||
if (options.ControlFlowDeobfuscation) {
|
||||
|
@ -606,7 +609,7 @@ namespace de4dot.code {
|
|||
|
||||
if (numRemovedLocals > 0)
|
||||
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)
|
||||
Log.v("Removed {0} dead instruction(s)", numRemovedInstructions);
|
||||
|
||||
|
@ -620,8 +623,8 @@ namespace de4dot.code {
|
|||
}
|
||||
#endif
|
||||
|
||||
bool hasNonEmptyBody(MethodDefinition method) {
|
||||
return method.HasBody && method.Body.Instructions.Count > 0;
|
||||
bool hasNonEmptyBody(MethodDef method) {
|
||||
return method.HasBody && method.CilBody.Instructions.Count > 0;
|
||||
}
|
||||
|
||||
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;
|
||||
for (int i = 0; i < method.CustomAttributes.Count; i++) {
|
||||
var cattr = method.CustomAttributes[i];
|
||||
|
@ -689,15 +692,15 @@ namespace de4dot.code {
|
|||
enum SimpleDeobFlags {
|
||||
HasDeobfuscated = 0x1,
|
||||
}
|
||||
Dictionary<MethodDefinition, SimpleDeobFlags> simpleDeobfuscatorFlags = new Dictionary<MethodDefinition, SimpleDeobFlags>();
|
||||
bool check(MethodDefinition method, SimpleDeobFlags flag) {
|
||||
Dictionary<MethodDef, SimpleDeobFlags> simpleDeobfuscatorFlags = new Dictionary<MethodDef, SimpleDeobFlags>();
|
||||
bool check(MethodDef method, SimpleDeobFlags flag) {
|
||||
SimpleDeobFlags oldFlags;
|
||||
simpleDeobfuscatorFlags.TryGetValue(method, out oldFlags);
|
||||
simpleDeobfuscatorFlags[method] = oldFlags | 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)
|
||||
savedMethodBodies.save(method);
|
||||
|
||||
|
@ -723,11 +726,11 @@ namespace de4dot.code {
|
|||
Log.deIndent();
|
||||
}
|
||||
|
||||
void ISimpleDeobfuscator.deobfuscate(MethodDefinition method) {
|
||||
void ISimpleDeobfuscator.deobfuscate(MethodDef method) {
|
||||
((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))
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -274,32 +274,32 @@
|
|||
<Compile Include="ObfuscatedFile.cs" />
|
||||
<Compile Include="Option.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="renamer\asmmodules\EventDef.cs" />
|
||||
<Compile Include="renamer\asmmodules\FieldDef.cs" />
|
||||
<Compile Include="renamer\asmmodules\GenericParamDef.cs" />
|
||||
<Compile Include="renamer\asmmodules\IResolver.cs" />
|
||||
<Compile Include="renamer\asmmodules\MemberRefFinder.cs" />
|
||||
<Compile Include="renamer\asmmodules\MethodDef.cs" />
|
||||
<Compile Include="renamer\asmmodules\MethodNameGroups.cs" />
|
||||
<Compile Include="renamer\asmmodules\Module.cs" />
|
||||
<Compile Include="renamer\asmmodules\Modules.cs" />
|
||||
<Compile Include="renamer\asmmodules\ParamDef.cs" />
|
||||
<Compile Include="renamer\asmmodules\PropertyDef.cs" />
|
||||
<Compile Include="renamer\asmmodules\Ref.cs" />
|
||||
<Compile Include="renamer\asmmodules\RefDict.cs" />
|
||||
<Compile Include="renamer\asmmodules\TypeDef.cs" />
|
||||
<Compile Include="renamer\DerivedFrom.cs" />
|
||||
<Compile Include="renamer\ExistingNames.cs" />
|
||||
<Compile Include="renamer\INameChecker.cs" />
|
||||
<Compile Include="renamer\MemberInfos.cs" />
|
||||
<Compile Include="renamer\NameCreators.cs" />
|
||||
<Compile Include="renamer\Renamer.cs" />
|
||||
<Compile Include="renamer\ResourceKeysRenamer.cs" />
|
||||
<Compile Include="renamer\ResourceRenamer.cs" />
|
||||
<Compile Include="renamer\TypeInfo.cs" />
|
||||
<Compile Include="renamer\TypeNames.cs" />
|
||||
<Compile Include="renamer\TypeRenamerState.cs" />
|
||||
<Compile Include="renamer\VariableNameState.cs" />
|
||||
<None Include="renamer\asmmodules\EventDef.cs" />
|
||||
<None Include="renamer\asmmodules\FieldDef.cs" />
|
||||
<None Include="renamer\asmmodules\GenericParamDef.cs" />
|
||||
<None Include="renamer\asmmodules\IResolver.cs" />
|
||||
<None Include="renamer\asmmodules\MemberRefFinder.cs" />
|
||||
<None Include="renamer\asmmodules\MethodDef.cs" />
|
||||
<None Include="renamer\asmmodules\MethodNameGroups.cs" />
|
||||
<None Include="renamer\asmmodules\Module.cs" />
|
||||
<None Include="renamer\asmmodules\Modules.cs" />
|
||||
<None Include="renamer\asmmodules\ParamDef.cs" />
|
||||
<None Include="renamer\asmmodules\PropertyDef.cs" />
|
||||
<None Include="renamer\asmmodules\Ref.cs" />
|
||||
<None Include="renamer\asmmodules\RefDict.cs" />
|
||||
<None Include="renamer\asmmodules\TypeDef.cs" />
|
||||
<None Include="renamer\DerivedFrom.cs" />
|
||||
<None Include="renamer\ExistingNames.cs" />
|
||||
<None Include="renamer\INameChecker.cs" />
|
||||
<None Include="renamer\MemberInfos.cs" />
|
||||
<None Include="renamer\NameCreators.cs" />
|
||||
<None Include="renamer\Renamer.cs" />
|
||||
<None Include="renamer\ResourceKeysRenamer.cs" />
|
||||
<None Include="renamer\ResourceRenamer.cs" />
|
||||
<None Include="renamer\TypeInfo.cs" />
|
||||
<None Include="renamer\TypeNames.cs" />
|
||||
<None Include="renamer\TypeRenamerState.cs" />
|
||||
<None Include="renamer\VariableNameState.cs" />
|
||||
<Compile Include="resources\BuiltInResourceData.cs" />
|
||||
<Compile Include="resources\IResourceData.cs" />
|
||||
<Compile Include="resources\ResourceDataCreator.cs" />
|
||||
|
|
|
@ -22,19 +22,19 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators {
|
||||
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));
|
||||
var decryptedResourceData = decryptResource();
|
||||
if (decryptedResourceData == null)
|
||||
throw new ApplicationException("decryptedResourceData is null");
|
||||
var resourceModule = ModuleDefinition.ReadModule(new MemoryStream(decryptedResourceData));
|
||||
var resourceModule = ModuleDefMD.Load(decryptedResourceData);
|
||||
|
||||
Log.indent();
|
||||
foreach (var rsrc in resourceModule.Resources) {
|
||||
|
@ -44,27 +44,17 @@ namespace de4dot.code.deobfuscators {
|
|||
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)
|
||||
return null;
|
||||
var newDef = module.LookupToken(def.MetadataToken.ToInt32()) as T;
|
||||
var newDef = module.ResolveToken(def.MDToken.Raw) as T;
|
||||
if (newDef == null)
|
||||
throw new ApplicationException(errorMessage);
|
||||
return newDef;
|
||||
}
|
||||
|
||||
public static ModuleReference lookup(ModuleDefinition module, ModuleReference other, string errorMessage) {
|
||||
if (other == null)
|
||||
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 byte[] readModule(ModuleDef module) {
|
||||
return Utils.readFile(module.Location);
|
||||
}
|
||||
|
||||
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)) {
|
||||
var resource = DotNetUtils.getResource(module, s) as EmbeddedResource;
|
||||
if (resource != null)
|
||||
|
@ -199,68 +189,56 @@ namespace de4dot.code.deobfuscators {
|
|||
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) {
|
||||
byte b = data[index++];
|
||||
if ((b & 0x80) == 0)
|
||||
return b;
|
||||
if ((b & 0x40) == 0)
|
||||
return (((int)b & 0x3F) << 8) + data[index++];
|
||||
return (((int)b & 0x3F) << 24) +
|
||||
return (((int)b & 0x1F) << 24) +
|
||||
((int)data[index++] << 16) +
|
||||
((int)data[index++] << 8) +
|
||||
data[index++];
|
||||
}
|
||||
|
||||
public static bool hasInteger(MethodDefinition method, uint value) {
|
||||
public static bool hasInteger(MethodDef method, uint 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;
|
||||
}
|
||||
|
||||
public static int indexOfLdci4Instruction(MethodDefinition method, int value) {
|
||||
if (method == null || method.Body == null)
|
||||
public static int indexOfLdci4Instruction(MethodDef method, int value) {
|
||||
if (method == null || method.CilBody == null)
|
||||
return -1;
|
||||
var instrs = method.Body.Instructions;
|
||||
var instrs = method.CilBody.Instructions;
|
||||
for (int i = 0; i < instrs.Count; i++) {
|
||||
var instr = instrs[i];
|
||||
if (!DotNetUtils.isLdcI4(instr))
|
||||
if (!instr.IsLdcI4())
|
||||
continue;
|
||||
if (DotNetUtils.getLdcI4Value(instr) == value)
|
||||
if (instr.GetLdcI4Value() == value)
|
||||
return i;
|
||||
}
|
||||
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);
|
||||
if (cctor != null)
|
||||
yield return cctor;
|
||||
|
||||
var entryPoint = module.EntryPoint;
|
||||
var entryPoint = module.EntryPoint as MethodDef;
|
||||
if (entryPoint != null) {
|
||||
cctor = DotNetUtils.getMethod(entryPoint.DeclaringType, ".cctor");
|
||||
cctor = entryPoint.DeclaringType.FindClassConstructor();
|
||||
if (cctor != null)
|
||||
yield return cctor;
|
||||
}
|
||||
|
||||
foreach (var type in module.GetTypes()) {
|
||||
if (type == DotNetUtils.getModuleType(module))
|
||||
if (type == module.GlobalType)
|
||||
continue;
|
||||
cctor = DotNetUtils.getMethod(type, ".cctor");
|
||||
cctor = type.FindClassConstructor();
|
||||
if (cctor == null)
|
||||
continue;
|
||||
yield return cctor;
|
||||
|
@ -269,14 +247,14 @@ namespace de4dot.code.deobfuscators {
|
|||
}
|
||||
}
|
||||
|
||||
public static List<MethodDefinition> getAllResolveHandlers(MethodDefinition method) {
|
||||
var list = new List<MethodDefinition>();
|
||||
if (method == null || method.Body == null)
|
||||
public static List<MethodDef> getAllResolveHandlers(MethodDef method) {
|
||||
var list = new List<MethodDef>();
|
||||
if (method == null || method.CilBody == null)
|
||||
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)
|
||||
continue;
|
||||
var handler = instr.Operand as MethodDefinition;
|
||||
var handler = instr.Operand as MethodDef;
|
||||
if (handler == null)
|
||||
continue;
|
||||
if (!DotNetUtils.isMethod(handler, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)"))
|
||||
|
@ -286,7 +264,7 @@ namespace de4dot.code.deobfuscators {
|
|||
return list;
|
||||
}
|
||||
|
||||
public static MethodDefinition getResolveMethod(MethodDefinition method) {
|
||||
public static MethodDef getResolveMethod(MethodDef method) {
|
||||
var handlers = DeobUtils.getAllResolveHandlers(method);
|
||||
if (handlers.Count == 0)
|
||||
return null;
|
||||
|
|
|
@ -25,17 +25,19 @@ using dot10.PE;
|
|||
using de4dot.blocks;
|
||||
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
|
||||
interface IWriterListener {
|
||||
internal class MetadataBuilder {
|
||||
//TODO: Dummy class. Don't use
|
||||
}
|
||||
|
||||
// Called before adding resources, and after adding types, methods, etc.
|
||||
void OnBeforeAddingResources(MetadataBuilder builder);
|
||||
}
|
||||
//TODO: REMOVE
|
||||
internal class MetadataBuilder {
|
||||
//TODO: Dummy class. Don't use
|
||||
}
|
||||
}
|
||||
|
||||
namespace de4dot.code.deobfuscators {
|
||||
abstract class DeobfuscatorBase : IDeobfuscator, IWriterListener {
|
||||
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)
|
||||
continue;
|
||||
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);
|
||||
i--;
|
||||
Log.v("Removed custom attribute {0} ({1:X8}) (reason: {2})",
|
||||
Utils.removeNewlines(typeDef),
|
||||
typeDef.MDToken.ToUInt32(),
|
||||
|
@ -628,14 +631,14 @@ namespace de4dot.code.deobfuscators {
|
|||
return DotNetUtils.getResource(module, strings);
|
||||
}
|
||||
|
||||
protected CustomAttribute getAssemblyAttribute(TypeReference attr) {
|
||||
var list = new List<CustomAttribute>(DotNetUtils.findAttributes(module.Assembly, attr));
|
||||
return list.Count == 0 ? null : list[0];
|
||||
protected CustomAttribute getAssemblyAttribute(IType attr) {
|
||||
if (module.Assembly == null)
|
||||
return null;
|
||||
return module.Assembly.CustomAttributes.Find(attr);
|
||||
}
|
||||
|
||||
protected CustomAttribute getModuleAttribute(TypeReference attr) {
|
||||
var list = new List<CustomAttribute>(DotNetUtils.findAttributes(module, attr));
|
||||
return list.Count == 0 ? null : list[0];
|
||||
protected CustomAttribute getModuleAttribute(IType attr) {
|
||||
return module.CustomAttributes.Find(attr);
|
||||
}
|
||||
|
||||
protected bool hasMetadataStream(string name) {
|
||||
|
@ -646,7 +649,7 @@ namespace de4dot.code.deobfuscators {
|
|||
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);
|
||||
foreach (var info in removeThese) {
|
||||
if (info.obj != null)
|
||||
|
@ -705,7 +708,7 @@ namespace de4dot.code.deobfuscators {
|
|||
return name != null && checkValidName(name);
|
||||
}
|
||||
|
||||
public virtual void OnBeforeAddingResources(IWriterListener.MetadataBuilder builder) {
|
||||
public virtual void OnBeforeAddingResources(MetadataBuilder builder) {
|
||||
}
|
||||
|
||||
protected void findAndRemoveInlinedMethods() {
|
||||
|
|
|
@ -23,7 +23,9 @@ using Mono.Cecil;
|
|||
using Mono.MyStuff;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
#if PORT
|
||||
using de4dot.code.renamer;
|
||||
#endif
|
||||
using de4dot.PE;
|
||||
|
||||
namespace de4dot.code.deobfuscators {
|
||||
|
@ -53,7 +55,11 @@ namespace de4dot.code.deobfuscators {
|
|||
RenameResourceKeys = 2,
|
||||
}
|
||||
|
||||
public interface IDeobfuscator : INameChecker {
|
||||
public interface IDeobfuscator
|
||||
#if PORT
|
||||
: INameChecker
|
||||
#endif
|
||||
{
|
||||
string Type { get; }
|
||||
string TypeLong { get; }
|
||||
string Name { get; }
|
||||
|
|
|
@ -19,158 +19,167 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.MD;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators {
|
||||
class MemberReferenceBuilder {
|
||||
ModuleDefinition module;
|
||||
Dictionary<TypeReferenceKey, TypeReference> createdTypes = new Dictionary<TypeReferenceKey, TypeReference>();
|
||||
class MemberReferenceBuilder : ICorLibTypes {
|
||||
ModuleDefMD module;
|
||||
Dictionary<TypeSig, TypeSig> createdTypes = new Dictionary<TypeSig, TypeSig>(TypeEqualityComparer.Instance);
|
||||
|
||||
public MemberReferenceBuilder(ModuleDefinition module) {
|
||||
public MemberReferenceBuilder(ModuleDefMD module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public IMetadataScope CorLib {
|
||||
get { return module.TypeSystem.Corlib; }
|
||||
public AssemblyRef CorLib {
|
||||
get { return module.CorLibTypes.AssemblyRef; }
|
||||
}
|
||||
|
||||
public TypeReference Object {
|
||||
get { return module.TypeSystem.Object; }
|
||||
public AssemblyRef AssemblyRef {
|
||||
get { return module.CorLibTypes.AssemblyRef; }
|
||||
}
|
||||
|
||||
public TypeReference Void {
|
||||
get { return module.TypeSystem.Void; }
|
||||
public CorLibTypeSig Object {
|
||||
get { return module.CorLibTypes.Object; }
|
||||
}
|
||||
|
||||
public TypeReference Boolean {
|
||||
get { return module.TypeSystem.Boolean; }
|
||||
public CorLibTypeSig Void {
|
||||
get { return module.CorLibTypes.Void; }
|
||||
}
|
||||
|
||||
public TypeReference Char {
|
||||
get { return module.TypeSystem.Char; }
|
||||
public CorLibTypeSig Boolean {
|
||||
get { return module.CorLibTypes.Boolean; }
|
||||
}
|
||||
|
||||
public TypeReference SByte {
|
||||
get { return module.TypeSystem.SByte; }
|
||||
public CorLibTypeSig Char {
|
||||
get { return module.CorLibTypes.Char; }
|
||||
}
|
||||
|
||||
public TypeReference Byte {
|
||||
get { return module.TypeSystem.Byte; }
|
||||
public CorLibTypeSig SByte {
|
||||
get { return module.CorLibTypes.SByte; }
|
||||
}
|
||||
|
||||
public TypeReference Int16 {
|
||||
get { return module.TypeSystem.Int16; }
|
||||
public CorLibTypeSig Byte {
|
||||
get { return module.CorLibTypes.Byte; }
|
||||
}
|
||||
|
||||
public TypeReference UInt16 {
|
||||
get { return module.TypeSystem.UInt16; }
|
||||
public CorLibTypeSig Int16 {
|
||||
get { return module.CorLibTypes.Int16; }
|
||||
}
|
||||
|
||||
public TypeReference Int32 {
|
||||
get { return module.TypeSystem.Int32; }
|
||||
public CorLibTypeSig UInt16 {
|
||||
get { return module.CorLibTypes.UInt16; }
|
||||
}
|
||||
|
||||
public TypeReference UInt32 {
|
||||
get { return module.TypeSystem.UInt32; }
|
||||
public CorLibTypeSig Int32 {
|
||||
get { return module.CorLibTypes.Int32; }
|
||||
}
|
||||
|
||||
public TypeReference Int64 {
|
||||
get { return module.TypeSystem.Int64; }
|
||||
public CorLibTypeSig UInt32 {
|
||||
get { return module.CorLibTypes.UInt32; }
|
||||
}
|
||||
|
||||
public TypeReference UInt64 {
|
||||
get { return module.TypeSystem.UInt64; }
|
||||
public CorLibTypeSig Int64 {
|
||||
get { return module.CorLibTypes.Int64; }
|
||||
}
|
||||
|
||||
public TypeReference Single {
|
||||
get { return module.TypeSystem.Single; }
|
||||
public CorLibTypeSig UInt64 {
|
||||
get { return module.CorLibTypes.UInt64; }
|
||||
}
|
||||
|
||||
public TypeReference Double {
|
||||
get { return module.TypeSystem.Double; }
|
||||
public CorLibTypeSig Single {
|
||||
get { return module.CorLibTypes.Single; }
|
||||
}
|
||||
|
||||
public TypeReference IntPtr {
|
||||
get { return module.TypeSystem.IntPtr; }
|
||||
public CorLibTypeSig Double {
|
||||
get { return module.CorLibTypes.Double; }
|
||||
}
|
||||
|
||||
public TypeReference UIntPtr {
|
||||
get { return module.TypeSystem.UIntPtr; }
|
||||
public CorLibTypeSig IntPtr {
|
||||
get { return module.CorLibTypes.IntPtr; }
|
||||
}
|
||||
|
||||
public TypeReference String {
|
||||
get { return module.TypeSystem.String; }
|
||||
public CorLibTypeSig UIntPtr {
|
||||
get { return module.CorLibTypes.UIntPtr; }
|
||||
}
|
||||
|
||||
public TypeReference TypedReference {
|
||||
get { return module.TypeSystem.TypedReference; }
|
||||
public CorLibTypeSig String {
|
||||
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));
|
||||
}
|
||||
|
||||
public TypeReference type(string ns, string name) {
|
||||
public ClassSig type(string ns, string name) {
|
||||
return type(ns, name, CorLib);
|
||||
}
|
||||
|
||||
public TypeReference type(string ns, string name, IMetadataScope asmRef) {
|
||||
return type(false, ns, name, asmRef);
|
||||
public ClassSig type(string ns, string name, AssemblyRef 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));
|
||||
}
|
||||
|
||||
public TypeReference valueType(string ns, string name) {
|
||||
public ValueTypeSig valueType(string ns, string name) {
|
||||
return valueType(ns, name, CorLib);
|
||||
}
|
||||
|
||||
public TypeReference valueType(string ns, string name, IMetadataScope asmRef) {
|
||||
return type(true, ns, name, asmRef);
|
||||
public ValueTypeSig valueType(string ns, string name, AssemblyRef asmRef) {
|
||||
return (ValueTypeSig)type(true, ns, name, asmRef);
|
||||
}
|
||||
|
||||
public TypeReference type(bool isValueType, string ns, string name, IMetadataScope asmRef) {
|
||||
var typeRef = new TypeReference(ns, name, module, asmRef);
|
||||
typeRef.IsValueType = isValueType;
|
||||
return add(isValueType, typeRef);
|
||||
public ClassOrValueTypeSig type(bool isValueType, string ns, string name, IResolutionScope resolutionScope) {
|
||||
var typeRef = module.UpdateRowId(new TypeRefUser(module, ns, name, resolutionScope));
|
||||
ClassOrValueTypeSig type;
|
||||
if (isValueType)
|
||||
type = new ValueTypeSig(typeRef);
|
||||
else
|
||||
type = new ClassSig(typeRef);
|
||||
return (ClassOrValueTypeSig)add(type);
|
||||
}
|
||||
|
||||
public TypeReference array(TypeReference typeRef) {
|
||||
return add(false, new ArrayType(typeRef));
|
||||
public ArraySig array(TypeSig typeRef) {
|
||||
return (ArraySig)add(new ArraySig(typeRef));
|
||||
}
|
||||
|
||||
TypeReference add(bool isValueType, TypeReference typeRef) {
|
||||
var key = new TypeReferenceKey(typeRef);
|
||||
TypeReference createdTypeRef;
|
||||
if (createdTypes.TryGetValue(key, out createdTypeRef)) {
|
||||
if (createdTypeRef.IsValueType != isValueType)
|
||||
TypeSig add(TypeSig typeRef) {
|
||||
TypeSig createdTypeRef;
|
||||
if (createdTypes.TryGetValue(typeRef, out createdTypeRef)) {
|
||||
if (createdTypeRef.ElementType != typeRef.ElementType)
|
||||
throw new ApplicationException(string.Format("Type {0}'s IsValueType is not correct", createdTypeRef));
|
||||
return createdTypeRef;
|
||||
}
|
||||
createdTypes[key] = typeRef;
|
||||
createdTypes[typeRef] = 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public MethodReference method(bool isInstance, string name, TypeReference declaringType, TypeReference returnType, params TypeReference[] args) {
|
||||
var method = new MethodReference(name, returnType, declaringType);
|
||||
method.HasThis = isInstance;
|
||||
foreach (var arg in args)
|
||||
method.Parameters.Add(new ParameterDefinition(arg));
|
||||
return method;
|
||||
public MemberRef method(bool isInstance, string name, IMemberRefParent declaringType, TypeSig returnType, params TypeSig[] args) {
|
||||
MethodSig sig;
|
||||
if (isInstance)
|
||||
sig = MethodSig.CreateInstance(returnType, args);
|
||||
else
|
||||
sig = MethodSig.CreateStatic(returnType, args);
|
||||
return module.UpdateRowId(new MemberRefUser(module, name, sig, declaringType));
|
||||
}
|
||||
|
||||
AssemblyNameReference findAssemblyReference(string asmSimpleName) {
|
||||
AssemblyNameReference asmRef = null;
|
||||
AssemblyRef findAssemblyReference(string asmSimpleName) {
|
||||
AssemblyRef asmRef = null;
|
||||
foreach (var asmRef2 in findAssemblyReferences(asmSimpleName)) {
|
||||
if (asmRef == null || asmRef.Version == null || (asmRef2.Version != null && asmRef2.Version > asmRef.Version))
|
||||
asmRef = asmRef2;
|
||||
|
@ -180,10 +189,11 @@ namespace de4dot.code.deobfuscators {
|
|||
return asmRef;
|
||||
}
|
||||
|
||||
List<AssemblyNameReference> findAssemblyReferences(string asmSimpleName) {
|
||||
var asmRefs = new List<AssemblyNameReference>();
|
||||
foreach (var asmRef in module.AssemblyReferences) {
|
||||
if (asmRef.Name == asmSimpleName)
|
||||
List<AssemblyRef> findAssemblyReferences(string asmSimpleName) {
|
||||
var asmRefs = new List<AssemblyRef>();
|
||||
var name = new UTF8String(asmSimpleName);
|
||||
foreach (var asmRef in module.GetAssemblyRefs()) {
|
||||
if (UTF8String.Equals(asmRef.Name, name))
|
||||
asmRefs.Add(asmRef);
|
||||
}
|
||||
return asmRefs;
|
||||
|
|
|
@ -19,15 +19,15 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators {
|
||||
abstract class ProxyCallFixerBase {
|
||||
protected ModuleDefinition module;
|
||||
protected List<MethodDefinition> delegateCreatorMethods = new List<MethodDefinition>();
|
||||
protected Dictionary<TypeDefinition, bool> delegateTypesDict = new Dictionary<TypeDefinition, bool>();
|
||||
protected ModuleDefMD module;
|
||||
protected List<MethodDef> delegateCreatorMethods = new List<MethodDef>();
|
||||
protected Dictionary<TypeDef, bool> delegateTypesDict = new Dictionary<TypeDef, bool>();
|
||||
protected int errors = 0;
|
||||
|
||||
public int Errors {
|
||||
|
@ -35,10 +35,10 @@ namespace de4dot.code.deobfuscators {
|
|||
}
|
||||
|
||||
protected class DelegateInfo {
|
||||
public MethodReference methodRef; // Method we should call
|
||||
public FieldDefinition field; // Field holding the Delegate instance
|
||||
public IMethod methodRef; // Method we should call
|
||||
public FieldDef field; // Field holding the Delegate instance
|
||||
public OpCode callOpcode;
|
||||
public DelegateInfo(FieldDefinition field, MethodReference methodRef, OpCode callOpcode) {
|
||||
public DelegateInfo(FieldDef field, IMethod methodRef, OpCode callOpcode) {
|
||||
this.field = field;
|
||||
this.methodRef = methodRef;
|
||||
this.callOpcode = callOpcode;
|
||||
|
@ -47,30 +47,30 @@ namespace de4dot.code.deobfuscators {
|
|||
|
||||
public int RemovedDelegateCreatorCalls { get; set; }
|
||||
|
||||
public IEnumerable<TypeDefinition> DelegateTypes {
|
||||
public IEnumerable<TypeDef> DelegateTypes {
|
||||
get { return delegateTypesDict.Keys; }
|
||||
}
|
||||
|
||||
public IEnumerable<TypeDefinition> DelegateCreatorTypes {
|
||||
public IEnumerable<TypeDef> DelegateCreatorTypes {
|
||||
get {
|
||||
foreach (var method in delegateCreatorMethods)
|
||||
yield return method.DeclaringType;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IEnumerable<Tuple<MethodDefinition, string>> OtherMethods {
|
||||
get { return new List<Tuple<MethodDefinition, string>>(); }
|
||||
public virtual IEnumerable<Tuple<MethodDef, string>> OtherMethods {
|
||||
get { return new List<Tuple<MethodDef, string>>(); }
|
||||
}
|
||||
|
||||
public bool Detected {
|
||||
get { return delegateCreatorMethods.Count != 0; }
|
||||
}
|
||||
|
||||
protected ProxyCallFixerBase(ModuleDefinition module) {
|
||||
protected ProxyCallFixerBase(ModuleDefMD module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
protected ProxyCallFixerBase(ModuleDefinition module, ProxyCallFixerBase oldOne) {
|
||||
protected ProxyCallFixerBase(ModuleDefMD module, ProxyCallFixerBase oldOne) {
|
||||
this.module = module;
|
||||
foreach (var method in oldOne.delegateCreatorMethods)
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
protected void setDelegateCreatorMethod(MethodDefinition delegateCreatorMethod) {
|
||||
protected void setDelegateCreatorMethod(MethodDef delegateCreatorMethod) {
|
||||
if (delegateCreatorMethod == null)
|
||||
return;
|
||||
delegateCreatorMethods.Add(delegateCreatorMethod);
|
||||
}
|
||||
|
||||
protected bool isDelegateCreatorMethod(MethodDefinition method) {
|
||||
protected bool isDelegateCreatorMethod(MethodDef method) {
|
||||
foreach (var m in delegateCreatorMethods) {
|
||||
if (m == method)
|
||||
return true;
|
||||
|
@ -102,7 +102,7 @@ namespace de4dot.code.deobfuscators {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<TypeDefinition> getDelegateTypes() {
|
||||
protected virtual IEnumerable<TypeDef> getDelegateTypes() {
|
||||
foreach (var type in module.Types) {
|
||||
if (type.BaseType == null || type.BaseType.FullName != "System.MulticastDelegate")
|
||||
continue;
|
||||
|
@ -182,11 +182,11 @@ namespace de4dot.code.deobfuscators {
|
|||
abstract class ProxyCallFixer1 : ProxyCallFixerBase {
|
||||
FieldDefinitionAndDeclaringTypeDict<DelegateInfo> fieldToDelegateInfo = new FieldDefinitionAndDeclaringTypeDict<DelegateInfo>();
|
||||
|
||||
protected ProxyCallFixer1(ModuleDefinition module)
|
||||
protected ProxyCallFixer1(ModuleDefMD module)
|
||||
: base(module) {
|
||||
}
|
||||
|
||||
protected ProxyCallFixer1(ModuleDefinition module, ProxyCallFixer1 oldOne)
|
||||
protected ProxyCallFixer1(ModuleDefMD module, ProxyCallFixer1 oldOne)
|
||||
: base(module, oldOne) {
|
||||
foreach (var key in oldOne.fieldToDelegateInfo.getKeys())
|
||||
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);
|
||||
}
|
||||
|
||||
protected DelegateInfo getDelegateInfo(FieldReference field) {
|
||||
protected DelegateInfo getDelegateInfo(IField field) {
|
||||
if (field == null)
|
||||
return null;
|
||||
return fieldToDelegateInfo.find(field);
|
||||
|
@ -209,8 +209,8 @@ namespace de4dot.code.deobfuscators {
|
|||
Log.v("Finding all proxy delegates");
|
||||
foreach (var tmp in getDelegateTypes()) {
|
||||
var type = tmp;
|
||||
var cctor = DotNetUtils.getMethod(type, ".cctor");
|
||||
if (cctor == null || !cctor.HasBody)
|
||||
var cctor = type.FindClassConstructor();
|
||||
if (cctor == null || !cctor.HasCilBody)
|
||||
continue;
|
||||
if (!type.HasFields)
|
||||
continue;
|
||||
|
@ -219,7 +219,7 @@ namespace de4dot.code.deobfuscators {
|
|||
if (context == null)
|
||||
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++;
|
||||
|
||||
Log.indent();
|
||||
|
@ -227,7 +227,7 @@ namespace de4dot.code.deobfuscators {
|
|||
if (!field.IsStatic)
|
||||
continue;
|
||||
|
||||
MethodReference calledMethod;
|
||||
IMethod calledMethod;
|
||||
OpCode callOpcode;
|
||||
getCallInfo(context, field, out calledMethod, out callOpcode);
|
||||
|
||||
|
@ -238,15 +238,15 @@ namespace de4dot.code.deobfuscators {
|
|||
Utils.removeNewlines(field.Name),
|
||||
callOpcode,
|
||||
Utils.removeNewlines(calledMethod),
|
||||
calledMethod.MetadataToken.ToUInt32());
|
||||
calledMethod.MDToken.Raw);
|
||||
}
|
||||
Log.deIndent();
|
||||
delegateTypesDict[type] = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract object checkCctor(ref TypeDefinition type, MethodDefinition cctor);
|
||||
protected abstract void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode);
|
||||
protected abstract object checkCctor(ref TypeDef type, MethodDef cctor);
|
||||
protected abstract void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode);
|
||||
|
||||
protected override bool deobfuscate(Blocks blocks, IList<Block> allBlocks) {
|
||||
var removeInfos = new Dictionary<Block, List<RemoveInfo>>();
|
||||
|
@ -258,7 +258,7 @@ namespace de4dot.code.deobfuscators {
|
|||
if (instr.OpCode != OpCodes.Ldsfld)
|
||||
continue;
|
||||
|
||||
var di = getDelegateInfo(instr.Operand as FieldReference);
|
||||
var di = getDelegateInfo(instr.Operand as IField);
|
||||
if (di == null)
|
||||
continue;
|
||||
|
||||
|
@ -271,9 +271,9 @@ namespace de4dot.code.deobfuscators {
|
|||
errors++;
|
||||
Log.w("Could not fix proxy call. Method: {0} ({1:X8}), Proxy type: {2} ({3:X8})",
|
||||
Utils.removeNewlines(blocks.Method),
|
||||
blocks.Method.MetadataToken.ToInt32(),
|
||||
blocks.Method.MDToken.ToInt32(),
|
||||
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)
|
||||
return null;
|
||||
var instr = instrs[i];
|
||||
DotNetUtils.updateStack(instr.Instruction, ref stack, false);
|
||||
instr.Instruction.UpdateStack(ref stack, false);
|
||||
if (stack < 0)
|
||||
return null;
|
||||
|
||||
|
@ -305,7 +305,7 @@ namespace de4dot.code.deobfuscators {
|
|||
return null;
|
||||
continue;
|
||||
}
|
||||
var calledMethod = instr.Operand as MethodReference;
|
||||
var calledMethod = instr.Operand as IMethod;
|
||||
if (calledMethod == null)
|
||||
return null;
|
||||
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
|
||||
// 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) {
|
||||
var instrs = block.Instructions;
|
||||
for (int i = 0; i < instrs.Count; i++) {
|
||||
var call = instrs[i];
|
||||
if (call.OpCode != OpCodes.Call && call.OpCode != OpCodes.Callvirt)
|
||||
continue;
|
||||
var methodRef = call.Operand as MethodReference;
|
||||
var methodRef = call.Operand as IMethod;
|
||||
if (methodRef == null || methodRef.Name != "Invoke")
|
||||
continue;
|
||||
var method = DotNetUtils.getMethod(module, methodRef);
|
||||
if (method == null)
|
||||
MethodDef method = DotNetUtils.getMethod2(module, methodRef);
|
||||
if (method == null || method.DeclaringType == null)
|
||||
continue;
|
||||
var declaringType = DotNetUtils.getType(module, method.DeclaringType);
|
||||
if (declaringType == null)
|
||||
continue;
|
||||
if (!delegateTypesDict.ContainsKey(declaringType))
|
||||
if (!delegateTypesDict.ContainsKey(method.DeclaringType))
|
||||
continue;
|
||||
|
||||
// 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.replace(i + 1, 1, Instruction.Create(OpCodes.Throw));
|
||||
i++;
|
||||
|
@ -373,11 +370,11 @@ namespace de4dot.code.deobfuscators {
|
|||
abstract class ProxyCallFixer2 : ProxyCallFixerBase {
|
||||
MethodDefinitionAndDeclaringTypeDict<DelegateInfo> proxyMethodToDelegateInfo = new MethodDefinitionAndDeclaringTypeDict<DelegateInfo>();
|
||||
|
||||
protected ProxyCallFixer2(ModuleDefinition module)
|
||||
protected ProxyCallFixer2(ModuleDefMD module)
|
||||
: base(module) {
|
||||
}
|
||||
|
||||
protected ProxyCallFixer2(ModuleDefinition module, ProxyCallFixer2 oldOne)
|
||||
protected ProxyCallFixer2(ModuleDefMD module, ProxyCallFixer2 oldOne)
|
||||
: base(module, oldOne) {
|
||||
foreach (var oldMethod in oldOne.proxyMethodToDelegateInfo.getKeys()) {
|
||||
var oldDi = oldOne.proxyMethodToDelegateInfo.find(oldMethod);
|
||||
|
@ -396,8 +393,8 @@ namespace de4dot.code.deobfuscators {
|
|||
|
||||
protected void find2() {
|
||||
foreach (var type in getDelegateTypes()) {
|
||||
var cctor = DotNetUtils.getMethod(type, ".cctor");
|
||||
if (cctor == null || !cctor.HasBody)
|
||||
var cctor = type.FindClassConstructor();
|
||||
if (cctor == null || !cctor.HasCilBody)
|
||||
continue;
|
||||
if (!type.HasFields)
|
||||
continue;
|
||||
|
@ -406,17 +403,17 @@ namespace de4dot.code.deobfuscators {
|
|||
if (context == null)
|
||||
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++;
|
||||
var fieldToMethod = getFieldToMethodDictionary(type);
|
||||
|
||||
Log.indent();
|
||||
foreach (var field in type.Fields) {
|
||||
MethodDefinition proxyMethod;
|
||||
MethodDef proxyMethod;
|
||||
if (!fieldToMethod.TryGetValue(field, out proxyMethod))
|
||||
continue;
|
||||
|
||||
MethodReference calledMethod;
|
||||
IMethod calledMethod;
|
||||
OpCode callOpcode;
|
||||
getCallInfo(context, field, out calledMethod, out callOpcode);
|
||||
|
||||
|
@ -427,32 +424,32 @@ namespace de4dot.code.deobfuscators {
|
|||
Utils.removeNewlines(field.Name),
|
||||
callOpcode,
|
||||
Utils.removeNewlines(calledMethod),
|
||||
calledMethod.MetadataToken.ToUInt32());
|
||||
calledMethod.MDToken.ToUInt32());
|
||||
}
|
||||
Log.deIndent();
|
||||
delegateTypesDict[type] = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void add(MethodDefinition method, DelegateInfo di) {
|
||||
protected void add(MethodDef method, DelegateInfo di) {
|
||||
proxyMethodToDelegateInfo.add(method, di);
|
||||
}
|
||||
|
||||
protected abstract object checkCctor(TypeDefinition type, MethodDefinition cctor);
|
||||
protected abstract void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode);
|
||||
protected abstract object checkCctor(TypeDef type, MethodDef cctor);
|
||||
protected abstract void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode);
|
||||
|
||||
Dictionary<FieldDefinition, MethodDefinition> getFieldToMethodDictionary(TypeDefinition type) {
|
||||
var dict = new Dictionary<FieldDefinition, MethodDefinition>();
|
||||
Dictionary<FieldDef, MethodDef> getFieldToMethodDictionary(TypeDef type) {
|
||||
var dict = new Dictionary<FieldDef, MethodDef>();
|
||||
foreach (var method in type.Methods) {
|
||||
if (!method.IsStatic || !method.HasBody || method.Name == ".cctor")
|
||||
if (!method.IsStatic || !method.HasCilBody || method.Name == ".cctor")
|
||||
continue;
|
||||
|
||||
var instructions = method.Body.Instructions;
|
||||
var instructions = method.CilBody.Instructions;
|
||||
for (int i = 0; i < instructions.Count; i++) {
|
||||
var instr = instructions[i];
|
||||
if (instr.OpCode.Code != Code.Ldsfld)
|
||||
continue;
|
||||
var field = instr.Operand as FieldDefinition;
|
||||
var field = instr.Operand as FieldDef;
|
||||
if (field == null)
|
||||
continue;
|
||||
|
||||
|
@ -473,7 +470,7 @@ namespace de4dot.code.deobfuscators {
|
|||
if (instr.OpCode != OpCodes.Call)
|
||||
continue;
|
||||
|
||||
var method = instr.Operand as MethodReference;
|
||||
var method = instr.Operand as IMethod;
|
||||
if (method == null)
|
||||
continue;
|
||||
var di = proxyMethodToDelegateInfo.find(method);
|
||||
|
@ -493,11 +490,11 @@ namespace de4dot.code.deobfuscators {
|
|||
// ldsfld delegate instance
|
||||
// call static method
|
||||
abstract class ProxyCallFixer3 : ProxyCallFixer1 {
|
||||
protected ProxyCallFixer3(ModuleDefinition module)
|
||||
protected ProxyCallFixer3(ModuleDefMD module)
|
||||
: base(module) {
|
||||
}
|
||||
|
||||
protected ProxyCallFixer3(ModuleDefinition module, ProxyCallFixer3 oldOne)
|
||||
protected ProxyCallFixer3(ModuleDefMD module, ProxyCallFixer3 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)
|
||||
return null;
|
||||
return instr.Operand as MethodReference;
|
||||
return instr.Operand as IMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.Cecil.Metadata;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
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)
|
||||
// so it will be a basic implementation only.
|
||||
abstract class TypesRestorerBase {
|
||||
ModuleDefinition module;
|
||||
List<MethodDefinition> allMethods;
|
||||
Dictionary<ParameterDefinition, TypeInfo<ParameterDefinition>> argInfos = new Dictionary<ParameterDefinition, TypeInfo<ParameterDefinition>>();
|
||||
TypeInfo<ParameterDefinition> methodReturnInfo;
|
||||
Dictionary<FieldReferenceAndDeclaringTypeKey, TypeInfo<FieldDefinition>> fieldWrites = new Dictionary<FieldReferenceAndDeclaringTypeKey, TypeInfo<FieldDefinition>>();
|
||||
ModuleDef module;
|
||||
List<MethodDef> allMethods;
|
||||
Dictionary<Parameter, TypeInfo<Parameter>> argInfos = new Dictionary<Parameter, TypeInfo<Parameter>>();
|
||||
TypeInfo<Parameter> methodReturnInfo;
|
||||
Dictionary<FieldReferenceAndDeclaringTypeKey, TypeInfo<FieldDef>> fieldWrites = new Dictionary<FieldReferenceAndDeclaringTypeKey, TypeInfo<FieldDef>>();
|
||||
Dictionary<int, UpdatedMethod> updatedMethods = new Dictionary<int, UpdatedMethod>();
|
||||
Dictionary<int, UpdatedField> updatedFields = new Dictionary<int, UpdatedField>();
|
||||
|
||||
class UpdatedMethod {
|
||||
public int token;
|
||||
public TypeReference[] newArgTypes;
|
||||
public TypeReference newReturnType;
|
||||
public TypeSig[] newArgTypes;
|
||||
public TypeSig newReturnType;
|
||||
|
||||
public UpdatedMethod(MethodDefinition method) {
|
||||
token = method.MetadataToken.ToInt32();
|
||||
newArgTypes = new TypeReference[DotNetUtils.getArgsCount(method)];
|
||||
public UpdatedMethod(MethodDef method) {
|
||||
token = method.MDToken.ToInt32();
|
||||
newArgTypes = new TypeSig[DotNetUtils.getArgsCount(method)];
|
||||
}
|
||||
}
|
||||
|
||||
class UpdatedField {
|
||||
public int token;
|
||||
public TypeReference newFieldType;
|
||||
public TypeSig newFieldType;
|
||||
|
||||
public UpdatedField(FieldDefinition field) {
|
||||
token = field.MetadataToken.ToInt32();
|
||||
public UpdatedField(FieldDef field) {
|
||||
token = field.MDToken.ToInt32();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +89,7 @@ namespace de4dot.code.deobfuscators {
|
|||
types.Clear();
|
||||
}
|
||||
|
||||
public bool updateNewType(ModuleDefinition module) {
|
||||
public bool updateNewType(ModuleDef module) {
|
||||
if (types.Count == 0)
|
||||
return false;
|
||||
|
||||
|
@ -114,20 +113,20 @@ namespace de4dot.code.deobfuscators {
|
|||
}
|
||||
}
|
||||
|
||||
public TypesRestorerBase(ModuleDefinition module) {
|
||||
public TypesRestorerBase(ModuleDef module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
UpdatedMethod getUpdatedMethod(MethodDefinition method) {
|
||||
int token = method.MetadataToken.ToInt32();
|
||||
UpdatedMethod getUpdatedMethod(MethodDef method) {
|
||||
int token = method.MDToken.ToInt32();
|
||||
UpdatedMethod updatedMethod;
|
||||
if (updatedMethods.TryGetValue(token, out updatedMethod))
|
||||
return updatedMethod;
|
||||
return updatedMethods[token] = new UpdatedMethod(method);
|
||||
}
|
||||
|
||||
UpdatedField getUpdatedField(FieldDefinition field) {
|
||||
int token = field.MetadataToken.ToInt32();
|
||||
UpdatedField getUpdatedField(FieldDef field) {
|
||||
int token = field.MDToken.ToInt32();
|
||||
UpdatedField updatedField;
|
||||
if (updatedFields.TryGetValue(token, out updatedField))
|
||||
return updatedField;
|
||||
|
@ -135,7 +134,7 @@ namespace de4dot.code.deobfuscators {
|
|||
}
|
||||
|
||||
public void deobfuscate() {
|
||||
allMethods = new List<MethodDefinition>();
|
||||
allMethods = new List<MethodDef>();
|
||||
|
||||
addAllMethods();
|
||||
addAllFields();
|
||||
|
@ -151,11 +150,11 @@ namespace de4dot.code.deobfuscators {
|
|||
addMethods(type.Methods);
|
||||
}
|
||||
|
||||
void addMethods(IEnumerable<MethodDefinition> methods) {
|
||||
void addMethods(IEnumerable<MethodDef> methods) {
|
||||
allMethods.AddRange(methods);
|
||||
}
|
||||
|
||||
void addMethod(MethodDefinition method) {
|
||||
void addMethod(MethodDef method) {
|
||||
allMethods.Add(method);
|
||||
}
|
||||
|
||||
|
@ -166,7 +165,7 @@ namespace de4dot.code.deobfuscators {
|
|||
continue;
|
||||
|
||||
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));
|
||||
Log.indent();
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -208,7 +207,7 @@ namespace de4dot.code.deobfuscators {
|
|||
if (updatedMethod.newReturnType != null) {
|
||||
Log.v("ret: {0} ({1:X8})",
|
||||
Utils.removeNewlines(updatedMethod.newReturnType.FullName),
|
||||
updatedMethod.newReturnType.MetadataToken.ToInt32());
|
||||
updatedMethod.newReturnType.MDToken.ToInt32());
|
||||
}
|
||||
for (int i = 0; i < updatedMethod.newArgTypes.Length; i++) {
|
||||
var updatedArg = updatedMethod.newArgTypes[i];
|
||||
|
@ -217,7 +216,7 @@ namespace de4dot.code.deobfuscators {
|
|||
Log.v("arg {0}: {1} ({2:X8})",
|
||||
i,
|
||||
Utils.removeNewlines(updatedArg.FullName),
|
||||
updatedArg.MetadataToken.ToInt32());
|
||||
updatedArg.MDToken.ToInt32());
|
||||
}
|
||||
Log.deIndent();
|
||||
}
|
||||
|
@ -227,7 +226,7 @@ namespace de4dot.code.deobfuscators {
|
|||
bool deobfuscateMethods() {
|
||||
bool changed = false;
|
||||
foreach (var method in allMethods) {
|
||||
methodReturnInfo = new TypeInfo<ParameterDefinition>(method.MethodReturnType.Parameter2);
|
||||
methodReturnInfo = new TypeInfo<Parameter>(method.MethodReturnType.Parameter2);
|
||||
deobfuscateMethod(method);
|
||||
|
||||
if (methodReturnInfo.updateNewType(module)) {
|
||||
|
@ -247,14 +246,14 @@ namespace de4dot.code.deobfuscators {
|
|||
return changed;
|
||||
}
|
||||
|
||||
static int sortTypeInfos(TypeInfo<ParameterDefinition> a, TypeInfo<ParameterDefinition> b) {
|
||||
if (a.arg.Method.MetadataToken.ToInt32() < b.arg.Method.MetadataToken.ToInt32()) return -1;
|
||||
if (a.arg.Method.MetadataToken.ToInt32() > b.arg.Method.MetadataToken.ToInt32()) return 1;
|
||||
static int sortTypeInfos(TypeInfo<Parameter> a, TypeInfo<Parameter> b) {
|
||||
if (a.arg.Method.MDToken.ToInt32() < b.arg.Method.MDToken.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);
|
||||
}
|
||||
|
||||
void deobfuscateMethod(MethodDefinition method) {
|
||||
void deobfuscateMethod(MethodDef method) {
|
||||
if (!method.IsStatic || method.Body == null)
|
||||
return;
|
||||
|
||||
|
@ -264,7 +263,7 @@ namespace de4dot.code.deobfuscators {
|
|||
foreach (var arg in method.Parameters) {
|
||||
if (!isUnknownType(arg))
|
||||
continue;
|
||||
argInfos[arg] = new TypeInfo<ParameterDefinition>(arg);
|
||||
argInfos[arg] = new TypeInfo<Parameter>(arg);
|
||||
}
|
||||
if (argInfos.Count == 0 && !fixReturnType)
|
||||
return;
|
||||
|
@ -362,7 +361,7 @@ namespace de4dot.code.deobfuscators {
|
|||
case Code.Starg_S:
|
||||
|
||||
case Code.Ldelema:
|
||||
case Code.Ldelem_Any:
|
||||
case Code.Ldelem:
|
||||
case Code.Ldelem_I:
|
||||
case Code.Ldelem_I1:
|
||||
case Code.Ldelem_I2:
|
||||
|
@ -389,7 +388,7 @@ namespace de4dot.code.deobfuscators {
|
|||
|
||||
case Code.Ldobj:
|
||||
|
||||
case Code.Stelem_Any:
|
||||
case Code.Stelem:
|
||||
case Code.Stelem_I:
|
||||
case Code.Stelem_I1:
|
||||
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) {
|
||||
case Code.Ldarg:
|
||||
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)
|
||||
return false;
|
||||
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)
|
||||
return false;
|
||||
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)
|
||||
return false;
|
||||
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)
|
||||
return false;
|
||||
|
||||
if (!isValidType(gpp, type))
|
||||
return false;
|
||||
|
||||
TypeInfo<ParameterDefinition> info;
|
||||
TypeInfo<Parameter> info;
|
||||
if (!argInfos.TryGetValue(methodParam, out info))
|
||||
return false;
|
||||
if (info.Types.ContainsKey(new TypeReferenceKey(type)))
|
||||
|
@ -476,7 +475,7 @@ namespace de4dot.code.deobfuscators {
|
|||
for (int i = 0; i < instructions.Count; i++) {
|
||||
var instr = instructions[i];
|
||||
TypeReference fieldType = null;
|
||||
TypeInfo<FieldDefinition> info = null;
|
||||
TypeInfo<FieldDef> info = null;
|
||||
FieldReference field;
|
||||
switch (instr.OpCode.Code) {
|
||||
case Code.Stfld:
|
||||
|
@ -527,7 +526,7 @@ namespace de4dot.code.deobfuscators {
|
|||
}
|
||||
|
||||
bool changed = false;
|
||||
var removeThese = new List<FieldDefinition>();
|
||||
var removeThese = new List<FieldDef>();
|
||||
foreach (var info in fieldWrites.Values) {
|
||||
if (info.updateNewType(module)) {
|
||||
removeThese.Add(info.arg);
|
||||
|
@ -541,7 +540,7 @@ namespace de4dot.code.deobfuscators {
|
|||
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);
|
||||
if (fieldType == null || !isValidType(gpp, fieldType))
|
||||
return null;
|
||||
|
@ -605,7 +604,7 @@ namespace de4dot.code.deobfuscators {
|
|||
|
||||
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)))
|
||||
return b;
|
||||
if (DotNetUtils.isDelegate(b) && DotNetUtils.derivesFromDelegate(DotNetUtils.getType(module, a)))
|
||||
|
@ -615,7 +614,7 @@ namespace de4dot.code.deobfuscators {
|
|||
}
|
||||
|
||||
class TypesRestorer : TypesRestorerBase {
|
||||
public TypesRestorer(ModuleDefinition module)
|
||||
public TypesRestorer(ModuleDef module)
|
||||
: base(module) {
|
||||
}
|
||||
|
||||
|
@ -630,11 +629,11 @@ namespace de4dot.code.deobfuscators {
|
|||
}
|
||||
|
||||
protected override bool isUnknownType(object o) {
|
||||
var arg = o as ParameterDefinition;
|
||||
var arg = o as Parameter;
|
||||
if (arg != null)
|
||||
return MemberReferenceHelper.isSystemObject(arg.ParameterType);
|
||||
|
||||
var field = o as FieldDefinition;
|
||||
var field = o as FieldDef;
|
||||
if (field != null)
|
||||
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