Add code to dump DNR native methods to a file
This commit is contained in:
parent
b259991415
commit
900ec1bf07
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user