Add code to dump DNR native methods to a file

This commit is contained in:
de4dot 2011-11-25 15:16:50 +01:00
parent b259991415
commit 900ec1bf07
3 changed files with 39 additions and 6 deletions

View File

@ -208,21 +208,28 @@ namespace de4dot {
class NoArgOption : Option { class NoArgOption : Option {
Action action; Action action;
bool triggered;
public override bool NeedArgument { public override bool NeedArgument {
get { return false; } get { return false; }
} }
public NoArgOption(string shortName, string longName, string description, Action action) public NoArgOption(string shortName, string longName, string description, Action action = null)
: base(shortName, longName, description) { : base(shortName, longName, description) {
this.action = action; this.action = action;
} }
public override bool set(string val, out string error) { public override bool set(string val, out string error) {
action(); triggered = true;
if (action != null)
action();
error = ""; error = "";
return true; return true;
} }
public bool get() {
return triggered;
}
} }
class OneArgOption : Option { class OneArgOption : Option {

View File

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
@ -39,6 +40,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
BoolOption decryptResources; BoolOption decryptResources;
BoolOption removeNamespaces; BoolOption removeNamespaces;
BoolOption removeAntiStrongName; BoolOption removeAntiStrongName;
NoArgOption dumpNativeMethods;
public DeobfuscatorInfo() public DeobfuscatorInfo()
: base(DEFAULT_REGEX) { : base(DEFAULT_REGEX) {
@ -51,6 +53,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
decryptResources = new BoolOption(null, makeArgName("rsrc"), "Decrypt resources", true); decryptResources = new BoolOption(null, makeArgName("rsrc"), "Decrypt resources", true);
removeNamespaces = new BoolOption(null, makeArgName("ns1"), "Clear namespace if there's only one class in it", true); removeNamespaces = new BoolOption(null, makeArgName("ns1"), "Clear namespace if there's only one class in it", true);
removeAntiStrongName = new BoolOption(null, makeArgName("sn"), "Remove anti strong name code", true); removeAntiStrongName = new BoolOption(null, makeArgName("sn"), "Remove anti strong name code", true);
dumpNativeMethods = new NoArgOption(null, makeArgName("dump-native"), "Dump native methods to filename.dll.native");
} }
public override string Name { public override string Name {
@ -73,6 +76,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
DecryptResources = decryptResources.get(), DecryptResources = decryptResources.get(),
RemoveNamespaces = removeNamespaces.get(), RemoveNamespaces = removeNamespaces.get(),
RemoveAntiStrongName = removeAntiStrongName.get(), RemoveAntiStrongName = removeAntiStrongName.get(),
DumpNativeMethods = dumpNativeMethods.get(),
}); });
} }
@ -87,6 +91,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
decryptResources, decryptResources,
removeNamespaces, removeNamespaces,
removeAntiStrongName, removeAntiStrongName,
dumpNativeMethods,
}; };
} }
} }
@ -120,6 +125,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
public bool DecryptResources { get; set; } public bool DecryptResources { get; set; }
public bool RemoveNamespaces { get; set; } public bool RemoveNamespaces { get; set; }
public bool RemoveAntiStrongName { get; set; } public bool RemoveAntiStrongName { get; set; }
public bool DumpNativeMethods { get; set; }
} }
public override string Type { public override string Type {
@ -365,9 +371,25 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
if (!options.DecryptMethods) if (!options.DecryptMethods)
return false; return false;
if (!methodsDecrypter.decrypt(peImage, DeobfuscatedFile, ref dumpedMethods)) var tokenToNativeCode = new Dictionary<uint,byte[]>();
if (!methodsDecrypter.decrypt(peImage, DeobfuscatedFile, ref dumpedMethods, tokenToNativeCode))
return false; return false;
if (options.DumpNativeMethods) {
using (var fileStream = new FileStream(module.FullyQualifiedName + ".native", FileMode.Create, FileAccess.Write, FileShare.Read)) {
var sortedTokens = new List<uint>(tokenToNativeCode.Keys);
sortedTokens.Sort();
var writer = new BinaryWriter(fileStream);
var nops = new byte[] { 0x90, 0x90, 0x90, 0x90 };
foreach (var token in sortedTokens) {
writer.Write((byte)0xB8);
writer.Write(token);
writer.Write(tokenToNativeCode[token]);
writer.Write(nops);
}
}
}
newFileData = fileData; newFileData = fileData;
return true; return true;
} }

View File

@ -96,7 +96,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
static short[] nativeLdci4 = new short[] { 0x55, 0x8B, 0xEC, 0xB8, -1, -1, -1, -1, 0x5D, 0xC3 }; static short[] nativeLdci4 = new short[] { 0x55, 0x8B, 0xEC, 0xB8, -1, -1, -1, -1, 0x5D, 0xC3 };
static short[] nativeLdci4_0 = new short[] { 0x55, 0x8B, 0xEC, 0x33, 0xC0, 0x5D, 0xC3 }; static short[] nativeLdci4_0 = new short[] { 0x55, 0x8B, 0xEC, 0x33, 0xC0, 0x5D, 0xC3 };
public bool decrypt(PE.PeImage peImage, ISimpleDeobfuscator simpleDeobfuscator, ref Dictionary<uint, DumpedMethod> dumpedMethods) { public bool decrypt(PE.PeImage peImage, ISimpleDeobfuscator simpleDeobfuscator, ref Dictionary<uint, DumpedMethod> dumpedMethods, Dictionary<uint,byte[]> tokenToNativeCode) {
if (encryptedResource.Method == null) if (encryptedResource.Method == null)
return false; return false;
@ -188,6 +188,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
Log.w("Could not find method having code RVA {0:X8}", rva); Log.w("Could not find method having code RVA {0:X8}", rva);
continue; continue;
} }
uint methodToken = 0x06000001 + (uint)methodIndex;
if (isNativeCode) { if (isNativeCode) {
if (!foundNativeCode) { if (!foundNativeCode) {
@ -195,7 +196,10 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
Log.w("Found native code. Assembly won't run."); Log.w("Found native code. Assembly won't run.");
} }
//TODO: Convert to CIL code //TODO: Convert to CIL code
Log.v("Found native code. Ignoring it for now... Assembly won't run. token: {0:X8}", 0x06000001 + methodIndex); Log.v("Found native code. Ignoring it for now... Assembly won't run. token: {0:X8}", methodToken);
if (tokenToNativeCode != null)
tokenToNativeCode[methodToken] = methodData;
// Convert return true / false methods. The others are converted to // Convert return true / false methods. The others are converted to
// throw 0xDEADCODE. // throw 0xDEADCODE.
@ -215,7 +219,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
} }
var dm = new DumpedMethod(); var dm = new DumpedMethod();
dm.token = (uint)(0x06000001 + methodIndex); dm.token = methodToken;
dm.code = methodData; dm.code = methodData;
offset = methodDef.fileOffset + (uint)(methodIndex * methodDef.totalSize); offset = methodDef.fileOffset + (uint)(methodIndex * methodDef.totalSize);