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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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