Port more code
This commit is contained in:
parent
3b6ef4fa1f
commit
1341cc7199
|
@ -933,11 +933,11 @@ namespace de4dot.blocks {
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<DN.IType> getArgs(DN.IMethod method) {
|
public static List<DN.TypeSig> getArgs(DN.IMethod method) {
|
||||||
var sig = method.MethodSig;
|
var sig = method.MethodSig;
|
||||||
var args = new List<DN.IType>(sig.Params.Count + 1);
|
var args = new List<DN.TypeSig>(sig.Params.Count + 1);
|
||||||
if (sig.HasThis && !sig.ExplicitThis)
|
if (sig.ImplicitThis)
|
||||||
args.Add(method.DeclaringType);
|
args.Add(DN.Extensions.ToTypeSig(method.DeclaringType));
|
||||||
foreach (var arg in sig.Params)
|
foreach (var arg in sig.Params)
|
||||||
args.Add(arg);
|
args.Add(arg);
|
||||||
return args;
|
return args;
|
||||||
|
@ -969,7 +969,7 @@ namespace de4dot.blocks {
|
||||||
if (sig == null)
|
if (sig == null)
|
||||||
return 0;
|
return 0;
|
||||||
int count = sig.Params.Count;
|
int count = sig.Params.Count;
|
||||||
if (sig.HasThis && !sig.ExplicitThis)
|
if (sig.ImplicitThis)
|
||||||
count++;
|
count++;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@ namespace de4dot.blocks.cflow {
|
||||||
protected bool checkSameMethods(IMethod method, MethodDef methodToInline, int ignoreLastMethodToInlineArgs) {
|
protected bool checkSameMethods(IMethod method, MethodDef methodToInline, int ignoreLastMethodToInlineArgs) {
|
||||||
var methodToInlineArgs = methodToInline.Parameters;
|
var methodToInlineArgs = methodToInline.Parameters;
|
||||||
var methodArgs = DotNetUtils.getArgs(method);
|
var methodArgs = DotNetUtils.getArgs(method);
|
||||||
bool hasImplicitThis = method.MethodSig.HasThis && !method.MethodSig.ExplicitThis;
|
bool hasImplicitThis = method.MethodSig.ImplicitThis;
|
||||||
if (methodToInlineArgs.Length - ignoreLastMethodToInlineArgs != methodArgs.Count)
|
if (methodToInlineArgs.Length - ignoreLastMethodToInlineArgs != methodArgs.Count)
|
||||||
return false;
|
return false;
|
||||||
for (int i = 0; i < methodArgs.Count; i++) {
|
for (int i = 0; i < methodArgs.Count; i++) {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code {
|
namespace de4dot.code {
|
||||||
|
@ -48,6 +48,7 @@ namespace de4dot.code {
|
||||||
dataDict.Remove(name);
|
dataDict.Remove(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PORT
|
||||||
static TypeReference getNonGenericTypeReference(TypeReference typeReference) {
|
static TypeReference getNonGenericTypeReference(TypeReference typeReference) {
|
||||||
if (typeReference == null)
|
if (typeReference == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -104,5 +105,6 @@ namespace de4dot.code {
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,20 +19,20 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code {
|
namespace de4dot.code {
|
||||||
class ExternalAssembly {
|
class ExternalAssembly {
|
||||||
AssemblyDefinition asmDef;
|
AssemblyDef asmDef;
|
||||||
|
|
||||||
public ExternalAssembly(AssemblyDefinition asmDef) {
|
public ExternalAssembly(AssemblyDef asmDef) {
|
||||||
this.asmDef = asmDef;
|
this.asmDef = asmDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeDefinition resolve(TypeReference type) {
|
public TypeDef resolve(ITypeDefOrRef type) {
|
||||||
foreach (var module in asmDef.Modules) {
|
foreach (var module in asmDef.Modules) {
|
||||||
var typeDef = DotNetUtils.getType(module, type);
|
var typeDef = module.Find(type);
|
||||||
if (typeDef != null)
|
if (typeDef != null)
|
||||||
return typeDef;
|
return typeDef;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ namespace de4dot.code {
|
||||||
|
|
||||||
public void unload(string asmFullName) {
|
public void unload(string asmFullName) {
|
||||||
foreach (var module in asmDef.Modules) {
|
foreach (var module in asmDef.Modules) {
|
||||||
DotNetUtils.typeCaches.invalidate(module);
|
//TODO: DotNetUtils.typeCaches.invalidate(module);
|
||||||
AssemblyResolver.Instance.removeModule(module);
|
AssemblyResolver.Instance.removeModule(module);
|
||||||
}
|
}
|
||||||
AssemblyResolver.Instance.removeModule(asmFullName);
|
AssemblyResolver.Instance.removeModule(asmFullName);
|
||||||
|
@ -54,45 +54,38 @@ namespace de4dot.code {
|
||||||
Dictionary<string, ExternalAssembly> assemblies = new Dictionary<string, ExternalAssembly>(StringComparer.Ordinal);
|
Dictionary<string, ExternalAssembly> assemblies = new Dictionary<string, ExternalAssembly>(StringComparer.Ordinal);
|
||||||
Dictionary<string, bool> failedLoads = new Dictionary<string, bool>(StringComparer.Ordinal);
|
Dictionary<string, bool> failedLoads = new Dictionary<string, bool>(StringComparer.Ordinal);
|
||||||
|
|
||||||
ExternalAssembly load(TypeReference type) {
|
ExternalAssembly load(TypeRef type) {
|
||||||
var asmFullName = DotNetUtils.getFullAssemblyName(type);
|
if (type == null || type.DefinitionAssembly == null)
|
||||||
if (asmFullName == null)
|
|
||||||
return null;
|
return null;
|
||||||
|
var asmFullName = type.DefinitionAssembly.FullName;
|
||||||
ExternalAssembly asm;
|
ExternalAssembly asm;
|
||||||
if (assemblies.TryGetValue(asmFullName, out asm))
|
if (assemblies.TryGetValue(asmFullName, out asm))
|
||||||
return asm;
|
return asm;
|
||||||
|
|
||||||
AssemblyDefinition asmDef = null;
|
var asmDef = AssemblyResolver.Instance.Resolve(type.DefinitionAssembly, type.OwnerModule);
|
||||||
try {
|
|
||||||
asmDef = AssemblyResolver.Instance.Resolve(asmFullName);
|
|
||||||
}
|
|
||||||
catch (ResolutionException) {
|
|
||||||
}
|
|
||||||
catch (AssemblyResolutionException) {
|
|
||||||
}
|
|
||||||
if (asmDef == null) {
|
if (asmDef == null) {
|
||||||
if (!failedLoads.ContainsKey(asmFullName))
|
if (!failedLoads.ContainsKey(asmFullName))
|
||||||
Log.w("Could not load assembly {0}", asmFullName);
|
Log.w("Could not load assembly {0}", asmFullName);
|
||||||
failedLoads[asmFullName] = true;
|
failedLoads[asmFullName] = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (assemblies.ContainsKey(asmDef.Name.FullName)) {
|
if (assemblies.ContainsKey(asmDef.FullName)) {
|
||||||
assemblies[asmFullName] = assemblies[asmDef.Name.FullName];
|
assemblies[asmFullName] = assemblies[asmDef.FullName];
|
||||||
return assemblies[asmDef.Name.FullName];
|
return assemblies[asmDef.FullName];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asmFullName == asmDef.Name.FullName)
|
if (asmFullName == asmDef.FullName)
|
||||||
Log.v("Loaded assembly {0}", asmFullName);
|
Log.v("Loaded assembly {0}", asmFullName);
|
||||||
else
|
else
|
||||||
Log.v("Loaded assembly {0} (but wanted {1})", asmDef.Name.FullName, asmFullName);
|
Log.v("Loaded assembly {0} (but wanted {1})", asmDef.FullName, asmFullName);
|
||||||
|
|
||||||
asm = new ExternalAssembly(asmDef);
|
asm = new ExternalAssembly(asmDef);
|
||||||
assemblies[asmFullName] = asm;
|
assemblies[asmFullName] = asm;
|
||||||
assemblies[asmDef.Name.FullName] = asm;
|
assemblies[asmDef.FullName] = asm;
|
||||||
return asm;
|
return asm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeDefinition resolve(TypeReference type) {
|
public TypeDef resolve(TypeRef type) {
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return null;
|
return null;
|
||||||
var asm = load(type);
|
var asm = load(type);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
|
|
||||||
namespace de4dot.code {
|
namespace de4dot.code {
|
||||||
public interface IDeobfuscatorContext {
|
public interface IDeobfuscatorContext {
|
||||||
|
@ -25,8 +25,10 @@ namespace de4dot.code {
|
||||||
void setData(string name, object data);
|
void setData(string name, object data);
|
||||||
object getData(string name);
|
object getData(string name);
|
||||||
void clearData(string name);
|
void clearData(string name);
|
||||||
TypeDefinition resolve(TypeReference type);
|
#if PORT
|
||||||
MethodDefinition resolve(MethodReference method);
|
TypeDef resolve(TypeRef type);
|
||||||
FieldDefinition resolve(FieldReference field);
|
MethodDef resolve(IMethod method);
|
||||||
|
FieldDef resolve(IField field);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code {
|
namespace de4dot.code {
|
||||||
|
@ -83,7 +83,7 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
|
|
||||||
var sortedTargets = new List<Instruction>(targets.Keys);
|
var sortedTargets = new List<Instruction>(targets.Keys);
|
||||||
sortedTargets.Sort((a, b) => Utils.compareInt32(a.Offset, b.Offset));
|
sortedTargets.Sort((a, b) => a.Offset.CompareTo(b.Offset));
|
||||||
for (int i = 0; i < sortedTargets.Count; i++)
|
for (int i = 0; i < sortedTargets.Count; i++)
|
||||||
labels[sortedTargets[i]] = string.Format("label_{0}", i);
|
labels[sortedTargets[i]] = string.Format("label_{0}", i);
|
||||||
}
|
}
|
||||||
|
@ -131,13 +131,13 @@ namespace de4dot.code {
|
||||||
ExInfo exInfo;
|
ExInfo exInfo;
|
||||||
if (exInfos.TryGetValue(instr, out exInfo))
|
if (exInfos.TryGetValue(instr, out exInfo))
|
||||||
printExInfo(exInfo);
|
printExInfo(exInfo);
|
||||||
var instrString = instr.GetOpCodeString();
|
var instrString = instr.OpCode.Name;
|
||||||
var operandString = getOperandString(instr);
|
var operandString = getOperandString(instr);
|
||||||
var memberReference = instr.Operand as MemberReference;
|
var memberReference = instr.Operand as ITokenOperand;
|
||||||
if (operandString == "")
|
if (operandString == "")
|
||||||
Log.log(logLevel, "{0}", instrString);
|
Log.log(logLevel, "{0}", instrString);
|
||||||
else if (memberReference != null)
|
else if (memberReference != null)
|
||||||
Log.log(logLevel, "{0,-9} {1} // {2:X8}", instrString, Utils.removeNewlines(operandString), memberReference.MetadataToken.ToUInt32());
|
Log.log(logLevel, "{0,-9} {1} // {2:X8}", instrString, Utils.removeNewlines(operandString), memberReference.MDToken.ToUInt32());
|
||||||
else
|
else
|
||||||
Log.log(logLevel, "{0,-9} {1}", instrString, Utils.removeNewlines(operandString));
|
Log.log(logLevel, "{0,-9} {1}", instrString, Utils.removeNewlines(operandString));
|
||||||
}
|
}
|
||||||
|
@ -160,12 +160,12 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
else if (instr.Operand is string)
|
else if (instr.Operand is string)
|
||||||
return Utils.toCsharpString((string)instr.Operand);
|
return Utils.toCsharpString((string)instr.Operand);
|
||||||
else if (instr.Operand is ParameterDefinition) {
|
else if (instr.Operand is Parameter) {
|
||||||
var arg = (ParameterDefinition)instr.Operand;
|
var arg = (Parameter)instr.Operand;
|
||||||
var s = instr.GetOperandString();
|
var s = instr.GetOperandString();
|
||||||
if (s != "")
|
if (s != "")
|
||||||
return s;
|
return s;
|
||||||
return string.Format("<arg_{0}>", DotNetUtils.getArgIndex(arg));
|
return string.Format("<arg_{0}>", arg.Index);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return instr.GetOperandString();
|
return instr.GetOperandString();
|
||||||
|
|
|
@ -19,17 +19,16 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using Mono.Cecil.Metadata;
|
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code {
|
namespace de4dot.code {
|
||||||
// A simple class that statically detects the values of some local variables
|
// A simple class that statically detects the values of some local variables
|
||||||
class VariableValues {
|
class VariableValues {
|
||||||
IList<Block> allBlocks;
|
IList<Block> allBlocks;
|
||||||
IList<VariableDefinition> locals;
|
IList<Local> locals;
|
||||||
Dictionary<VariableDefinition, Variable> variableToValue = new Dictionary<VariableDefinition, Variable>();
|
Dictionary<Local, Variable> variableToValue = new Dictionary<Local, Variable>();
|
||||||
|
|
||||||
public class Variable {
|
public class Variable {
|
||||||
int writes = 0;
|
int writes = 0;
|
||||||
|
@ -58,7 +57,7 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public VariableValues(IList<VariableDefinition> locals, IList<Block> allBlocks) {
|
public VariableValues(IList<Local> locals, IList<Block> allBlocks) {
|
||||||
this.locals = locals;
|
this.locals = locals;
|
||||||
this.allBlocks = allBlocks;
|
this.allBlocks = allBlocks;
|
||||||
init();
|
init();
|
||||||
|
@ -136,7 +135,7 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Variable getValue(VariableDefinition variable) {
|
public Variable getValue(Local variable) {
|
||||||
return variableToValue[variable];
|
return variableToValue[variable];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +143,7 @@ namespace de4dot.code {
|
||||||
abstract class MethodReturnValueInliner {
|
abstract class MethodReturnValueInliner {
|
||||||
protected List<CallResult> callResults;
|
protected List<CallResult> callResults;
|
||||||
List<Block> allBlocks;
|
List<Block> allBlocks;
|
||||||
MethodDefinition theMethod;
|
MethodDef theMethod;
|
||||||
VariableValues variableValues;
|
VariableValues variableValues;
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
bool useUnknownArgs = false;
|
bool useUnknownArgs = false;
|
||||||
|
@ -166,8 +165,8 @@ namespace de4dot.code {
|
||||||
this.callEndIndex = callEndIndex;
|
this.callEndIndex = callEndIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference getMethodReference() {
|
public IMethod getMethodReference() {
|
||||||
return (MethodReference)block.Instructions[callEndIndex].Operand;
|
return (IMethod)block.Instructions[callEndIndex].Operand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,14 +176,14 @@ namespace de4dot.code {
|
||||||
|
|
||||||
public abstract bool HasHandlers { get; }
|
public abstract bool HasHandlers { get; }
|
||||||
|
|
||||||
public MethodDefinition Method {
|
public MethodDef Method {
|
||||||
get { return theMethod; }
|
get { return theMethod; }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void inlineAllCalls();
|
protected abstract void inlineAllCalls();
|
||||||
|
|
||||||
// Returns null if method is not a method we should inline
|
// Returns null if method is not a method we should inline
|
||||||
protected abstract CallResult createCallResult(MethodReference method, GenericInstanceMethod gim, Block block, int callInstrIndex);
|
protected abstract CallResult createCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex);
|
||||||
|
|
||||||
public int decrypt(Blocks blocks) {
|
public int decrypt(Blocks blocks) {
|
||||||
if (!HasHandlers)
|
if (!HasHandlers)
|
||||||
|
@ -192,7 +191,7 @@ namespace de4dot.code {
|
||||||
return decrypt(blocks.Method, blocks.MethodBlocks.getAllBlocks());
|
return decrypt(blocks.Method, blocks.MethodBlocks.getAllBlocks());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int decrypt(MethodDefinition method, List<Block> allBlocks) {
|
public int decrypt(MethodDef method, List<Block> allBlocks) {
|
||||||
if (!HasHandlers)
|
if (!HasHandlers)
|
||||||
return 0;
|
return 0;
|
||||||
try {
|
try {
|
||||||
|
@ -217,9 +216,9 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getLocalVariableValue(VariableDefinition variable, out object value) {
|
bool getLocalVariableValue(Local variable, out object value) {
|
||||||
if (variableValues == null)
|
if (variableValues == null)
|
||||||
variableValues = new VariableValues(theMethod.Body.Variables, allBlocks);
|
variableValues = new VariableValues(theMethod.CilBody.LocalList, allBlocks);
|
||||||
var val = variableValues.getValue(variable);
|
var val = variableValues.getValue(variable);
|
||||||
if (!val.isValid()) {
|
if (!val.isValid()) {
|
||||||
value = null;
|
value = null;
|
||||||
|
@ -239,14 +238,14 @@ namespace de4dot.code {
|
||||||
var instr = block.Instructions[i];
|
var instr = block.Instructions[i];
|
||||||
if (instr.OpCode != OpCodes.Call)
|
if (instr.OpCode != OpCodes.Call)
|
||||||
continue;
|
continue;
|
||||||
var method = instr.Operand as MethodReference;
|
var method = instr.Operand as IMethod;
|
||||||
if (method == null)
|
if (method == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MethodReference elementMethod = method;
|
IMethod elementMethod = method;
|
||||||
var gim = method as GenericInstanceMethod;
|
var gim = method as MethodSpec;
|
||||||
if (gim != null)
|
if (gim != null)
|
||||||
elementMethod = gim.ElementMethod;
|
elementMethod = gim.Method;
|
||||||
var callResult = createCallResult(elementMethod, gim, block, i);
|
var callResult = createCallResult(elementMethod, gim, block, i);
|
||||||
if (callResult == null)
|
if (callResult == null)
|
||||||
continue;
|
continue;
|
||||||
|
@ -259,7 +258,7 @@ namespace de4dot.code {
|
||||||
bool findArgs(CallResult callResult) {
|
bool findArgs(CallResult callResult) {
|
||||||
var block = callResult.block;
|
var block = callResult.block;
|
||||||
var method = callResult.getMethodReference();
|
var method = callResult.getMethodReference();
|
||||||
var methodArgs = DotNetUtils.getParameters(method);
|
var methodArgs = DotNetUtils.getArgs(method);
|
||||||
int numArgs = methodArgs.Count;
|
int numArgs = methodArgs.Count;
|
||||||
var args = new object[numArgs];
|
var args = new object[numArgs];
|
||||||
|
|
||||||
|
@ -269,9 +268,9 @@ namespace de4dot.code {
|
||||||
if (!getArg(method, block, ref arg, ref instrIndex))
|
if (!getArg(method, block, ref arg, ref instrIndex))
|
||||||
return false;
|
return false;
|
||||||
if (arg is int)
|
if (arg is int)
|
||||||
arg = fixIntArg(methodArgs[i].ParameterType, (int)arg);
|
arg = fixIntArg(methodArgs[i], (int)arg);
|
||||||
else if (arg is long)
|
else if (arg is long)
|
||||||
arg = fixIntArg(methodArgs[i].ParameterType, (long)arg);
|
arg = fixIntArg(methodArgs[i], (long)arg);
|
||||||
args[i] = arg;
|
args[i] = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,8 +279,8 @@ namespace de4dot.code {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
object fixIntArg(TypeReference type, long value) {
|
object fixIntArg(TypeSig type, long value) {
|
||||||
switch (type.EType) {
|
switch (type.ElementType) {
|
||||||
case ElementType.Boolean: return value != 0;
|
case ElementType.Boolean: return value != 0;
|
||||||
case ElementType.Char: return (char)value;
|
case ElementType.Char: return (char)value;
|
||||||
case ElementType.I1: return (sbyte)value;
|
case ElementType.I1: return (sbyte)value;
|
||||||
|
@ -296,7 +295,7 @@ namespace de4dot.code {
|
||||||
throw new ApplicationException(string.Format("Wrong type {0}", type));
|
throw new ApplicationException(string.Format("Wrong type {0}", type));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getArg(MethodReference method, Block block, ref object arg, ref int instrIndex) {
|
bool getArg(IMethod method, Block block, ref object arg, ref int instrIndex) {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (instrIndex < 0) {
|
if (instrIndex < 0) {
|
||||||
// We're here if there were no cflow deobfuscation, or if there are two or
|
// We're here if there were no cflow deobfuscation, or if there are two or
|
||||||
|
@ -304,7 +303,7 @@ namespace de4dot.code {
|
||||||
// merged because one is outside the exception handler (eg. buggy obfuscator).
|
// merged because one is outside the exception handler (eg. buggy obfuscator).
|
||||||
Log.w("Could not find all arguments to method {0} ({1:X8})",
|
Log.w("Could not find all arguments to method {0} ({1:X8})",
|
||||||
Utils.removeNewlines(method),
|
Utils.removeNewlines(method),
|
||||||
method.MetadataToken.ToInt32());
|
method.MDToken.ToInt32());
|
||||||
errors++;
|
errors++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -343,7 +342,7 @@ namespace de4dot.code {
|
||||||
case Code.Ldloc_1:
|
case Code.Ldloc_1:
|
||||||
case Code.Ldloc_2:
|
case Code.Ldloc_2:
|
||||||
case Code.Ldloc_3:
|
case Code.Ldloc_3:
|
||||||
getLocalVariableValue(Instr.getLocalVar(theMethod.Body.Variables, instr), out arg);
|
getLocalVariableValue(instr.Instruction.GetLocal(theMethod.CilBody.LocalList), out arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldfld:
|
case Code.Ldfld:
|
||||||
|
@ -353,11 +352,11 @@ namespace de4dot.code {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
int pushes, pops;
|
int pushes, pops;
|
||||||
DotNetUtils.calculateStackUsage(instr.Instruction, false, out pushes, out pops);
|
instr.Instruction.CalculateStackUsage(false, out pushes, out pops);
|
||||||
if (!useUnknownArgs || pushes != 1) {
|
if (!useUnknownArgs || pushes != 1) {
|
||||||
Log.w("Could not find all arguments to method {0} ({1:X8}), instr: {2}",
|
Log.w("Could not find all arguments to method {0} ({1:X8}), instr: {2}",
|
||||||
Utils.removeNewlines(method),
|
Utils.removeNewlines(method),
|
||||||
method.MetadataToken.ToInt32(),
|
method.MDToken.ToInt32(),
|
||||||
instr);
|
instr);
|
||||||
errors++;
|
errors++;
|
||||||
return false;
|
return false;
|
||||||
|
@ -381,10 +380,10 @@ namespace de4dot.code {
|
||||||
callResults.Sort((a, b) => {
|
callResults.Sort((a, b) => {
|
||||||
int i1 = allBlocks.FindIndex((x) => a.block == x);
|
int i1 = allBlocks.FindIndex((x) => a.block == x);
|
||||||
int i2 = allBlocks.FindIndex((x) => b.block == x);
|
int i2 = allBlocks.FindIndex((x) => b.block == x);
|
||||||
if (i1 < i2) return -1;
|
if (i1 != i2)
|
||||||
if (i1 > i2) return 1;
|
return i1.CompareTo(i2);
|
||||||
|
|
||||||
return Utils.compareInt32(a.callStartIndex, b.callStartIndex);
|
return a.callStartIndex.CompareTo(b.callStartIndex);
|
||||||
});
|
});
|
||||||
callResults.Reverse();
|
callResults.Reverse();
|
||||||
inlineReturnValues(callResults);
|
inlineReturnValues(callResults);
|
||||||
|
|
|
@ -432,26 +432,28 @@ namespace de4dot.code {
|
||||||
if (typeString != null && typeString != type.FullName)
|
if (typeString != null && typeString != type.FullName)
|
||||||
continue;
|
continue;
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
if (!method.IsStatic || method.MethodReturnType.ReturnType.FullName != "System.String")
|
if (!method.IsStatic)
|
||||||
|
continue;
|
||||||
|
if (method.MethodSig.RetType.ElementType != ElementType.String && method.MethodSig.RetType.ElementType != ElementType.Object)
|
||||||
continue;
|
continue;
|
||||||
if (methodName != null && methodName != method.Name)
|
if (methodName != null && methodName != method.Name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (argsStrings == null) {
|
if (argsStrings == null) {
|
||||||
if (method.Parameters.Count == 0)
|
if (method.Parameters.Length == 0)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (argsStrings.Length != method.Parameters.Count)
|
if (argsStrings.Length != method.Parameters.Length)
|
||||||
continue;
|
continue;
|
||||||
for (int i = 0; i < argsStrings.Length; i++) {
|
for (int i = 0; i < argsStrings.Length; i++) {
|
||||||
if (argsStrings[i] != method.Parameters[i].ParameterType.FullName)
|
if (argsStrings[i] != method.Parameters[i].Type.FullName)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.v("Adding string decrypter; token: {0:X8}, method: {1}", method.MetadataToken.ToInt32(), Utils.removeNewlines(method.FullName));
|
Log.v("Adding string decrypter; token: {0:X8}, method: {1}", method.MDToken.ToInt32(), Utils.removeNewlines(method.FullName));
|
||||||
tokens.Add(method.MetadataToken.ToInt32());
|
tokens.Add(method.MDToken.ToInt32());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,30 +532,26 @@ namespace de4dot.code {
|
||||||
|
|
||||||
Log.v("Deobfuscating methods");
|
Log.v("Deobfuscating methods");
|
||||||
var methodPrinter = new MethodPrinter();
|
var methodPrinter = new MethodPrinter();
|
||||||
#if PORT
|
|
||||||
var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators);
|
var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators);
|
||||||
#endif
|
|
||||||
foreach (var method in getAllMethods()) {
|
foreach (var method in getAllMethods()) {
|
||||||
Log.v("Deobfuscating {0} ({1:X8})", Utils.removeNewlines(method), method.MetadataToken.ToUInt32());
|
Log.v("Deobfuscating {0} ({1:X8})", Utils.removeNewlines(method), method.MDToken.ToUInt32());
|
||||||
Log.indent();
|
Log.indent();
|
||||||
|
|
||||||
int oldIndentLevel = Log.indentLevel;
|
int oldIndentLevel = Log.indentLevel;
|
||||||
try {
|
try {
|
||||||
#if PORT
|
|
||||||
deobfuscate(method, cflowDeobfuscator, methodPrinter);
|
deobfuscate(method, cflowDeobfuscator, methodPrinter);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
catch (ApplicationException) {
|
catch (ApplicationException) {
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
if (!canLoadMethodBody(method)) {
|
if (!canLoadMethodBody(method)) {
|
||||||
Log.v("Invalid method body. {0:X8}", method.MetadataToken.ToInt32());
|
Log.v("Invalid method body. {0:X8}", method.MDToken.ToInt32());
|
||||||
method.CilBody = new MethodBody(method);
|
method.CilBody = new CilBody();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.w("Could not deobfuscate method {0:X8}. Hello, E.T.: {1}", // E.T. = exception type
|
Log.w("Could not deobfuscate method {0:X8}. Hello, E.T.: {1}", // E.T. = exception type
|
||||||
method.MetadataToken.ToInt32(),
|
method.MDToken.ToInt32(),
|
||||||
ex.GetType());
|
ex.GetType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -576,7 +574,6 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PORT
|
|
||||||
void deobfuscate(MethodDef method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter) {
|
void deobfuscate(MethodDef method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter) {
|
||||||
if (!hasNonEmptyBody(method))
|
if (!hasNonEmptyBody(method))
|
||||||
return;
|
return;
|
||||||
|
@ -621,10 +618,9 @@ namespace de4dot.code {
|
||||||
Log.deIndent();
|
Log.deIndent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool hasNonEmptyBody(MethodDef method) {
|
bool hasNonEmptyBody(MethodDef method) {
|
||||||
return method.HasBody && method.CilBody.Instructions.Count > 0;
|
return method.HasCilBody && method.CilBody.Instructions.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deobfuscateStrings(Blocks blocks) {
|
void deobfuscateStrings(Blocks blocks) {
|
||||||
|
@ -647,10 +643,10 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeNoInliningAttribute(MethodDef method) {
|
void removeNoInliningAttribute(MethodDef method) {
|
||||||
method.ImplAttributes = method.ImplAttributes & ~MethodImplAttributes.NoInlining;
|
method.IsNoInlining = false;
|
||||||
for (int i = 0; i < method.CustomAttributes.Count; i++) {
|
for (int i = 0; i < method.CustomAttributes.Count; i++) {
|
||||||
var cattr = method.CustomAttributes[i];
|
var cattr = method.CustomAttributes[i];
|
||||||
if (cattr.AttributeType.FullName != "System.Runtime.CompilerServices.MethodImplAttribute")
|
if (cattr.TypeFullName != "System.Runtime.CompilerServices.MethodImplAttribute")
|
||||||
continue;
|
continue;
|
||||||
int options = 0;
|
int options = 0;
|
||||||
if (!getMethodImplOptions(cattr, ref options))
|
if (!getMethodImplOptions(cattr, ref options))
|
||||||
|
@ -663,13 +659,13 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool getMethodImplOptions(CustomAttribute cattr, ref int value) {
|
static bool getMethodImplOptions(CustomAttribute cattr, ref int value) {
|
||||||
if (cattr.ConstructorArguments.Count != 1)
|
if (cattr.Arguments.Count != 1)
|
||||||
return false;
|
return false;
|
||||||
if (cattr.ConstructorArguments[0].Type.FullName != "System.Int16" &&
|
if (cattr.Arguments[0].Type.ElementType != ElementType.I2 &&
|
||||||
cattr.ConstructorArguments[0].Type.FullName != "System.Runtime.CompilerServices.MethodImplOptions")
|
cattr.Arguments[0].Type.FullName != "System.Runtime.CompilerServices.MethodImplOptions")
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var arg = cattr.ConstructorArguments[0].Value;
|
var arg = cattr.Arguments[0].Value;
|
||||||
if (arg is short) {
|
if (arg is short) {
|
||||||
value = (short)arg;
|
value = (short)arg;
|
||||||
return true;
|
return true;
|
||||||
|
@ -704,7 +700,7 @@ namespace de4dot.code {
|
||||||
if (savedMethodBodies != null)
|
if (savedMethodBodies != null)
|
||||||
savedMethodBodies.save(method);
|
savedMethodBodies.save(method);
|
||||||
|
|
||||||
Log.v("{0}: {1} ({2:X8})", msg, Utils.removeNewlines(method), method.MetadataToken.ToUInt32());
|
Log.v("{0}: {1} ({2:X8})", msg, Utils.removeNewlines(method), method.MDToken.ToUInt32());
|
||||||
Log.indent();
|
Log.indent();
|
||||||
|
|
||||||
if (hasNonEmptyBody(method)) {
|
if (hasNonEmptyBody(method)) {
|
||||||
|
@ -719,7 +715,7 @@ namespace de4dot.code {
|
||||||
DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers);
|
DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers);
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Log.v("Could not deobfuscate {0:X8}", method.MetadataToken.ToInt32());
|
Log.v("Could not deobfuscate {0:X8}", method.MDToken.ToInt32());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using de4dot.code.AssemblyClient;
|
using de4dot.code.AssemblyClient;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ namespace de4dot.code {
|
||||||
if (ldstrIndex + 1 < block.Instructions.Count) {
|
if (ldstrIndex + 1 < block.Instructions.Count) {
|
||||||
var instr = block.Instructions[ldstrIndex + 1];
|
var instr = block.Instructions[ldstrIndex + 1];
|
||||||
if (instr.OpCode.Code == Code.Call) {
|
if (instr.OpCode.Code == Code.Call) {
|
||||||
var calledMethod = instr.Operand as MethodReference;
|
var calledMethod = instr.Operand as IMethod;
|
||||||
if (calledMethod != null &&
|
if (calledMethod != null &&
|
||||||
calledMethod.FullName == "System.String System.String::Intern(System.String)") {
|
calledMethod.FullName == "System.String System.String::Intern(System.String)") {
|
||||||
block.remove(ldstrIndex + 1, 1);
|
block.remove(ldstrIndex + 1, 1);
|
||||||
|
@ -68,8 +68,8 @@ namespace de4dot.code {
|
||||||
|
|
||||||
class MyCallResult : CallResult {
|
class MyCallResult : CallResult {
|
||||||
public int methodId;
|
public int methodId;
|
||||||
public GenericInstanceMethod gim;
|
public MethodSpec gim;
|
||||||
public MyCallResult(Block block, int callEndIndex, int methodId, GenericInstanceMethod gim)
|
public MyCallResult(Block block, int callEndIndex, int methodId, MethodSpec gim)
|
||||||
: base(block, callEndIndex) {
|
: base(block, callEndIndex) {
|
||||||
this.methodId = methodId;
|
this.methodId = methodId;
|
||||||
this.gim = gim;
|
this.gim = gim;
|
||||||
|
@ -93,9 +93,9 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override CallResult createCallResult(MethodReference method, GenericInstanceMethod gim, Block block, int callInstrIndex) {
|
protected override CallResult createCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex) {
|
||||||
int methodId;
|
int methodId;
|
||||||
if (!methodTokenToId.TryGetValue(method.MetadataToken.ToInt32(), out methodId))
|
if (!methodTokenToId.TryGetValue(method.MDToken.ToInt32(), out methodId))
|
||||||
return null;
|
return null;
|
||||||
return new MyCallResult(block, callInstrIndex, methodId, gim);
|
return new MyCallResult(block, callInstrIndex, methodId, gim);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ namespace de4dot.code {
|
||||||
AssemblyData.SimpleData.pack(list[i].args);
|
AssemblyData.SimpleData.pack(list[i].args);
|
||||||
args[i] = list[i].args;
|
args[i] = list[i].args;
|
||||||
}
|
}
|
||||||
var decryptedStrings = assemblyClient.Service.decryptStrings(methodId, args, Method.MetadataToken.ToInt32());
|
var decryptedStrings = assemblyClient.Service.decryptStrings(methodId, args, Method.MDToken.ToInt32());
|
||||||
if (decryptedStrings.Length != args.Length)
|
if (decryptedStrings.Length != args.Length)
|
||||||
throw new ApplicationException("Invalid decrypted strings array length");
|
throw new ApplicationException("Invalid decrypted strings array length");
|
||||||
AssemblyData.SimpleData.unpack(decryptedStrings);
|
AssemblyData.SimpleData.unpack(decryptedStrings);
|
||||||
|
@ -128,27 +128,27 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
|
|
||||||
class StaticStringInliner : StringInlinerBase {
|
class StaticStringInliner : StringInlinerBase {
|
||||||
MethodDefinitionAndDeclaringTypeDict<Func<MethodDefinition, GenericInstanceMethod, object[], string>> stringDecrypters = new MethodDefinitionAndDeclaringTypeDict<Func<MethodDefinition, GenericInstanceMethod, object[], string>>();
|
MethodDefinitionAndDeclaringTypeDict<Func<MethodDef, MethodSpec, object[], string>> stringDecrypters = new MethodDefinitionAndDeclaringTypeDict<Func<MethodDef, MethodSpec, object[], string>>();
|
||||||
|
|
||||||
public override bool HasHandlers {
|
public override bool HasHandlers {
|
||||||
get { return stringDecrypters.Count != 0; }
|
get { return stringDecrypters.Count != 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<MethodDefinition> Methods {
|
public IEnumerable<MethodDef> Methods {
|
||||||
get { return stringDecrypters.getKeys(); }
|
get { return stringDecrypters.getKeys(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyCallResult : CallResult {
|
class MyCallResult : CallResult {
|
||||||
public MethodReference methodReference;
|
public IMethod IMethod;
|
||||||
public GenericInstanceMethod gim;
|
public MethodSpec gim;
|
||||||
public MyCallResult(Block block, int callEndIndex, MethodReference method, GenericInstanceMethod gim)
|
public MyCallResult(Block block, int callEndIndex, IMethod method, MethodSpec gim)
|
||||||
: base(block, callEndIndex) {
|
: base(block, callEndIndex) {
|
||||||
this.methodReference = method;
|
this.IMethod = method;
|
||||||
this.gim = gim;
|
this.gim = gim;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(MethodDefinition method, Func<MethodDefinition, GenericInstanceMethod, object[], string> handler) {
|
public void add(MethodDef method, Func<MethodDef, MethodSpec, object[], string> handler) {
|
||||||
if (method != null)
|
if (method != null)
|
||||||
stringDecrypters.add(method, handler);
|
stringDecrypters.add(method, handler);
|
||||||
}
|
}
|
||||||
|
@ -156,12 +156,12 @@ namespace de4dot.code {
|
||||||
protected override void inlineAllCalls() {
|
protected override void inlineAllCalls() {
|
||||||
foreach (var tmp in callResults) {
|
foreach (var tmp in callResults) {
|
||||||
var callResult = (MyCallResult)tmp;
|
var callResult = (MyCallResult)tmp;
|
||||||
var handler = stringDecrypters.find(callResult.methodReference);
|
var handler = stringDecrypters.find(callResult.IMethod);
|
||||||
callResult.returnValue = handler((MethodDefinition)callResult.methodReference, callResult.gim, callResult.args);
|
callResult.returnValue = handler((MethodDef)callResult.IMethod, callResult.gim, callResult.args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override CallResult createCallResult(MethodReference method, GenericInstanceMethod gim, Block block, int callInstrIndex) {
|
protected override CallResult createCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex) {
|
||||||
if (stringDecrypters.find(method) == null)
|
if (stringDecrypters.find(method) == null)
|
||||||
return null;
|
return null;
|
||||||
return new MyCallResult(block, callInstrIndex, method, gim);
|
return new MyCallResult(block, callInstrIndex, method, gim);
|
||||||
|
|
|
@ -214,12 +214,6 @@ namespace de4dot.code {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int compareInt32(int a, int b) {
|
|
||||||
if (a < b) return -1;
|
|
||||||
if (a > b) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] readFile(string filename) {
|
public static byte[] readFile(string filename) {
|
||||||
// If the file is on the network, and we read more than 2MB, we'll read from the wrong
|
// If the file is on the network, and we read more than 2MB, we'll read from the wrong
|
||||||
// offset in the file! Tested: VMware 8, Win7 x64.
|
// offset in the file! Tested: VMware 8, Win7 x64.
|
||||||
|
|
|
@ -219,7 +219,6 @@
|
||||||
<None Include="deobfuscators\MaxtoCode\StringDecrypter.cs" />
|
<None Include="deobfuscators\MaxtoCode\StringDecrypter.cs" />
|
||||||
<Compile Include="deobfuscators\MemberReferenceBuilder.cs" />
|
<Compile Include="deobfuscators\MemberReferenceBuilder.cs" />
|
||||||
<Compile Include="deobfuscators\MethodBodyParser.cs" />
|
<Compile Include="deobfuscators\MethodBodyParser.cs" />
|
||||||
<Compile Include="deobfuscators\MethodBodyReaderBase.cs" />
|
|
||||||
<Compile Include="deobfuscators\MethodCallRestorerBase.cs" />
|
<Compile Include="deobfuscators\MethodCallRestorerBase.cs" />
|
||||||
<Compile Include="deobfuscators\MethodCollection.cs" />
|
<Compile Include="deobfuscators\MethodCollection.cs" />
|
||||||
<Compile Include="deobfuscators\MethodsDecrypter.cs" />
|
<Compile Include="deobfuscators\MethodsDecrypter.cs" />
|
||||||
|
|
|
@ -120,7 +120,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
block.Instructions[instrIndex - 1] = new Instr(Instruction.Create(OpCodes.Nop));
|
block.Instructions[instrIndex - 1] = new Instr(Instruction.Create(OpCodes.Nop));
|
||||||
block.Instructions[instrIndex] = new Instr(DotNetUtils.createLdci4(newValue));
|
block.Instructions[instrIndex] = new Instr(Instruction.CreateLdcI4(newValue));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -392,7 +392,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
|
||||||
|
|
||||||
static Instruction ldc_read(BinaryReader reader) {
|
static Instruction ldc_read(BinaryReader reader) {
|
||||||
switch ((ElementType)reader.ReadByte()) {
|
switch ((ElementType)reader.ReadByte()) {
|
||||||
case ElementType.I4: return DotNetUtils.createLdci4(reader.ReadInt32());
|
case ElementType.I4: return Instruction.CreateLdcI4(reader.ReadInt32());
|
||||||
case ElementType.I8: return Instruction.Create(OpCodes.Ldc_I8, reader.ReadInt64());
|
case ElementType.I8: return Instruction.Create(OpCodes.Ldc_I8, reader.ReadInt64());
|
||||||
case ElementType.R4: return Instruction.Create(OpCodes.Ldc_R4, reader.ReadSingle());
|
case ElementType.R4: return Instruction.Create(OpCodes.Ldc_R4, reader.ReadSingle());
|
||||||
case ElementType.R8: return Instruction.Create(OpCodes.Ldc_R8, reader.ReadDouble());
|
case ElementType.R8: return Instruction.Create(OpCodes.Ldc_R8, reader.ReadDouble());
|
||||||
|
|
|
@ -115,7 +115,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
block.remove(i, 3 - 1);
|
block.remove(i, 3 - 1);
|
||||||
instrs[i] = new Instr(DotNetUtils.createLdci4(info.array[ldci4.getLdcI4Value()]));
|
instrs[i] = new Instr(Instruction.CreateLdcI4(info.array[ldci4.getLdcI4Value()]));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
block.remove(i, 3 - 1);
|
block.remove(i, 3 - 1);
|
||||||
instrs[i] = new Instr(DotNetUtils.createLdci4(info.array[ldci4.getLdcI4Value()]));
|
instrs[i] = new Instr(Instruction.CreateLdcI4(info.array[ldci4.getLdcI4Value()]));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
|
@ -28,7 +28,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
public int NumRemovedExceptionLoggers { get; set; }
|
public int NumRemovedExceptionLoggers { get; set; }
|
||||||
|
|
||||||
public void add(MethodDefinition exceptionLogger) {
|
public void add(MethodDef exceptionLogger) {
|
||||||
exceptionLoggerMethods.add(exceptionLogger, true);
|
exceptionLoggerMethods.add(exceptionLogger, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
if (tryBlock.TryHandlerBlocks.Count != 1)
|
if (tryBlock.TryHandlerBlocks.Count != 1)
|
||||||
continue;
|
continue;
|
||||||
var catchBlock = tryBlock.TryHandlerBlocks[0];
|
var catchBlock = tryBlock.TryHandlerBlocks[0];
|
||||||
if (catchBlock.HandlerType != ExceptionHandlerType.Catch ||
|
if (catchBlock.HandlerType != ExceptionClause.Catch ||
|
||||||
catchBlock.CatchType.FullName != "System.Exception") {
|
catchBlock.CatchType.FullName != "System.Exception") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
if (failed || calls != 1 || callInstr.OpCode.Code != Code.Call)
|
if (failed || calls != 1 || callInstr.OpCode.Code != Code.Call)
|
||||||
continue;
|
continue;
|
||||||
var calledMethod = callInstr.Operand as MethodReference;
|
var calledMethod = callInstr.Operand as IMethod;
|
||||||
if (calledMethod == null)
|
if (calledMethod == null)
|
||||||
continue;
|
continue;
|
||||||
if (!isExceptionLogger(calledMethod))
|
if (!isExceptionLogger(calledMethod))
|
||||||
|
@ -86,7 +86,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool isExceptionLogger(MethodReference method) {
|
protected virtual bool isExceptionLogger(IMethod method) {
|
||||||
return exceptionLoggerMethods.find(method);
|
return exceptionLoggerMethods.find(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.MyStuff;
|
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.blocks.cflow;
|
using de4dot.blocks.cflow;
|
||||||
#if PORT
|
#if PORT
|
||||||
|
@ -78,7 +77,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
// Returns null or the unpacked .NET PE file
|
// Returns null or the unpacked .NET PE file
|
||||||
byte[] unpackNativeFile(PeImage peImage);
|
byte[] unpackNativeFile(PeImage peImage);
|
||||||
|
|
||||||
void init(ModuleDefinition module);
|
void init(ModuleDefMD module);
|
||||||
|
|
||||||
// Returns 0 if it's not detected, or > 0 if detected (higher value => more likely true).
|
// Returns 0 if it's not detected, or > 0 if detected (higher value => more likely true).
|
||||||
// This method is always called.
|
// This method is always called.
|
||||||
|
@ -90,7 +89,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
// This is only called if getDecryptedModule() != null, and after the module has been
|
// This is only called if getDecryptedModule() != null, and after the module has been
|
||||||
// reloaded. Should return a new IDeobfuscator with the same options and the new module.
|
// reloaded. Should return a new IDeobfuscator with the same options and the new module.
|
||||||
IDeobfuscator moduleReloaded(ModuleDefinition module);
|
IDeobfuscator moduleReloaded(ModuleDefMD module);
|
||||||
|
|
||||||
// Called before all other deobfuscation methods
|
// Called before all other deobfuscation methods
|
||||||
void deobfuscateBegin();
|
void deobfuscateBegin();
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
public interface ISimpleDeobfuscator {
|
public interface ISimpleDeobfuscator {
|
||||||
void deobfuscate(MethodDefinition method);
|
void deobfuscate(MethodDef method);
|
||||||
void deobfuscate(MethodDefinition method, bool force);
|
void deobfuscate(MethodDef method, bool force);
|
||||||
void decryptStrings(MethodDefinition method, IDeobfuscator deob);
|
void decryptStrings(MethodDef method, IDeobfuscator deob);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,279 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2011-2012 de4dot@gmail.com
|
|
||||||
|
|
||||||
This file is part of de4dot.
|
|
||||||
|
|
||||||
de4dot is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
de4dot is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using Mono.Cecil;
|
|
||||||
using Mono.Cecil.Cil;
|
|
||||||
using de4dot.blocks;
|
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
|
||||||
abstract class MethodBodyReaderBase {
|
|
||||||
protected BinaryReader reader;
|
|
||||||
public IList<VariableDefinition> Locals { get; set; }
|
|
||||||
public IList<Instruction> Instructions { get; set; }
|
|
||||||
public IList<ExceptionHandler> ExceptionHandlers { get; set; }
|
|
||||||
protected IList<ParameterDefinition> parameters;
|
|
||||||
int currentOffset;
|
|
||||||
|
|
||||||
public MethodBodyReaderBase(BinaryReader reader) {
|
|
||||||
this.reader = reader;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setLocals(IList<TypeReference> types) {
|
|
||||||
Locals = new List<VariableDefinition>(types.Count);
|
|
||||||
foreach (var type in types)
|
|
||||||
Locals.Add(new VariableDefinition(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void readInstructions(int numInstrs) {
|
|
||||||
Instructions = new Instruction[numInstrs];
|
|
||||||
currentOffset = 0;
|
|
||||||
for (int i = 0; i < Instructions.Count; i++)
|
|
||||||
Instructions[i] = readOneInstruction();
|
|
||||||
fixBranches();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void readInstructionsNumBytes(uint codeSize) {
|
|
||||||
var instrs = new List<Instruction>();
|
|
||||||
long endOffs = reader.BaseStream.Position + codeSize;
|
|
||||||
while (reader.BaseStream.Position < endOffs)
|
|
||||||
instrs.Add(readOneInstruction());
|
|
||||||
if (reader.BaseStream.Position != endOffs)
|
|
||||||
throw new ApplicationException("Could not read all instructions");
|
|
||||||
Instructions = instrs;
|
|
||||||
fixBranches();
|
|
||||||
}
|
|
||||||
|
|
||||||
Instruction readOneInstruction() {
|
|
||||||
var instr = readInstruction();
|
|
||||||
if (instr.OpCode.Code == Code.Switch) {
|
|
||||||
int[] targets = (int[])instr.Operand;
|
|
||||||
currentOffset += instr.OpCode.Size + 4 + 4 * targets.Length;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
currentOffset += instr.GetSize();
|
|
||||||
return instr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fixBranches() {
|
|
||||||
foreach (var instr in Instructions) {
|
|
||||||
switch (instr.OpCode.OperandType) {
|
|
||||||
case OperandType.InlineBrTarget:
|
|
||||||
case OperandType.ShortInlineBrTarget:
|
|
||||||
instr.Operand = getInstruction((int)instr.Operand);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OperandType.InlineSwitch:
|
|
||||||
var intTargets = (int[])instr.Operand;
|
|
||||||
var targets = new Instruction[intTargets.Length];
|
|
||||||
for (int i = 0; i < intTargets.Length; i++)
|
|
||||||
targets[i] = getInstruction(intTargets[i]);
|
|
||||||
instr.Operand = targets;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Instruction getInstructionOrNull(int offset) {
|
|
||||||
foreach (var instr in Instructions) {
|
|
||||||
if (instr.Offset == offset)
|
|
||||||
return instr;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Instruction getInstruction(int offset) {
|
|
||||||
var instr = getInstructionOrNull(offset);
|
|
||||||
if (instr != null)
|
|
||||||
return instr;
|
|
||||||
throw new ApplicationException(string.Format("No instruction found at offset {0:X4}", offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
Instruction readInstruction() {
|
|
||||||
int offset = currentOffset;
|
|
||||||
var opcode = readOpCode();
|
|
||||||
var instr = new Instruction {
|
|
||||||
OpCode = opcode,
|
|
||||||
Offset = offset,
|
|
||||||
};
|
|
||||||
instr.Operand = readOperand(instr);
|
|
||||||
return instr;
|
|
||||||
}
|
|
||||||
|
|
||||||
object readOperand(Instruction instr) {
|
|
||||||
switch (instr.OpCode.OperandType) {
|
|
||||||
case OperandType.InlineBrTarget:
|
|
||||||
return readInlineBrTarget(instr);
|
|
||||||
case OperandType.InlineField:
|
|
||||||
return readInlineField(instr);
|
|
||||||
case OperandType.InlineI:
|
|
||||||
return readInlineI(instr);
|
|
||||||
case OperandType.InlineI8:
|
|
||||||
return readInlineI8(instr);
|
|
||||||
case OperandType.InlineMethod:
|
|
||||||
return readInlineMethod(instr);
|
|
||||||
case OperandType.InlineNone:
|
|
||||||
return readInlineNone(instr);
|
|
||||||
case OperandType.InlinePhi:
|
|
||||||
return readInlinePhi(instr);
|
|
||||||
case OperandType.InlineR:
|
|
||||||
return readInlineR(instr);
|
|
||||||
case OperandType.InlineSig:
|
|
||||||
return readInlineSig(instr);
|
|
||||||
case OperandType.InlineString:
|
|
||||||
return readInlineString(instr);
|
|
||||||
case OperandType.InlineSwitch:
|
|
||||||
return readInlineSwitch(instr);
|
|
||||||
case OperandType.InlineTok:
|
|
||||||
return readInlineTok(instr);
|
|
||||||
case OperandType.InlineType:
|
|
||||||
return readInlineType(instr);
|
|
||||||
case OperandType.InlineVar:
|
|
||||||
return readInlineVar(instr);
|
|
||||||
case OperandType.InlineArg:
|
|
||||||
return readInlineArg(instr);
|
|
||||||
case OperandType.ShortInlineBrTarget:
|
|
||||||
return readShortInlineBrTarget(instr);
|
|
||||||
case OperandType.ShortInlineI:
|
|
||||||
return readShortInlineI(instr);
|
|
||||||
case OperandType.ShortInlineR:
|
|
||||||
return readShortInlineR(instr);
|
|
||||||
case OperandType.ShortInlineVar:
|
|
||||||
return readShortInlineVar(instr);
|
|
||||||
case OperandType.ShortInlineArg:
|
|
||||||
return readShortInlineArg(instr);
|
|
||||||
default:
|
|
||||||
throw new ApplicationException(string.Format("Unknown operand type {0}", instr.OpCode.OperandType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual int readInlineBrTarget(Instruction instr) {
|
|
||||||
return currentOffset + instr.GetSize() + reader.ReadInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract FieldReference readInlineField(Instruction instr);
|
|
||||||
|
|
||||||
protected virtual int readInlineI(Instruction instr) {
|
|
||||||
return reader.ReadInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual long readInlineI8(Instruction instr) {
|
|
||||||
return reader.ReadInt64();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract MethodReference readInlineMethod(Instruction instr);
|
|
||||||
|
|
||||||
protected virtual object readInlineNone(Instruction instr) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual object readInlinePhi(Instruction instr) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual double readInlineR(Instruction instr) {
|
|
||||||
return reader.ReadDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract CallSite readInlineSig(Instruction instr);
|
|
||||||
|
|
||||||
protected abstract string readInlineString(Instruction instr);
|
|
||||||
|
|
||||||
protected virtual int[] readInlineSwitch(Instruction instr) {
|
|
||||||
var targets = new int[reader.ReadInt32()];
|
|
||||||
int offset = currentOffset + instr.OpCode.Size + 4 + 4 * targets.Length;
|
|
||||||
for (int i = 0; i < targets.Length; i++)
|
|
||||||
targets[i] = offset + reader.ReadInt32();
|
|
||||||
return targets;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract MemberReference readInlineTok(Instruction instr);
|
|
||||||
|
|
||||||
protected abstract TypeReference readInlineType(Instruction instr);
|
|
||||||
|
|
||||||
protected virtual VariableDefinition readInlineVar(Instruction instr) {
|
|
||||||
return Locals[reader.ReadUInt16()];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual ParameterDefinition readInlineArg(Instruction instr) {
|
|
||||||
return parameters[reader.ReadUInt16()];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual int readShortInlineBrTarget(Instruction instr) {
|
|
||||||
return currentOffset + instr.GetSize() + reader.ReadSByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual object readShortInlineI(Instruction instr) {
|
|
||||||
if (instr.OpCode.Code == Code.Ldc_I4_S)
|
|
||||||
return reader.ReadSByte();
|
|
||||||
return reader.ReadByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual float readShortInlineR(Instruction instr) {
|
|
||||||
return reader.ReadSingle();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual VariableDefinition readShortInlineVar(Instruction instr) {
|
|
||||||
return Locals[reader.ReadByte()];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual ParameterDefinition readShortInlineArg(Instruction instr) {
|
|
||||||
return parameters[reader.ReadByte()];
|
|
||||||
}
|
|
||||||
|
|
||||||
OpCode readOpCode() {
|
|
||||||
var op = reader.ReadByte();
|
|
||||||
if (op != 0xFE)
|
|
||||||
return OpCodes.OneByteOpCode[op];
|
|
||||||
return OpCodes.TwoBytesOpCode[reader.ReadByte()];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void readExceptionHandlers(int numExceptionHandlers) {
|
|
||||||
ExceptionHandlers = new ExceptionHandler[numExceptionHandlers];
|
|
||||||
for (int i = 0; i < ExceptionHandlers.Count; i++)
|
|
||||||
ExceptionHandlers[i] = readExceptionHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract ExceptionHandler readExceptionHandler();
|
|
||||||
|
|
||||||
public virtual void restoreMethod(MethodDefinition method) {
|
|
||||||
var body = method.Body;
|
|
||||||
|
|
||||||
body.Variables.Clear();
|
|
||||||
if (Locals != null) {
|
|
||||||
foreach (var local in Locals)
|
|
||||||
body.Variables.Add(local);
|
|
||||||
}
|
|
||||||
|
|
||||||
body.Instructions.Clear();
|
|
||||||
if (Instructions != null) {
|
|
||||||
foreach (var instr in Instructions)
|
|
||||||
body.Instructions.Add(instr);
|
|
||||||
}
|
|
||||||
|
|
||||||
body.ExceptionHandlers.Clear();
|
|
||||||
if (ExceptionHandlers != null) {
|
|
||||||
foreach (var eh in ExceptionHandlers)
|
|
||||||
body.ExceptionHandlers.Add(eh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,32 +18,32 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
class MethodCallRestorerBase {
|
class MethodCallRestorerBase {
|
||||||
protected MemberReferenceBuilder builder;
|
protected MemberReferenceBuilder builder;
|
||||||
protected ModuleDefinition module;
|
protected ModuleDefMD module;
|
||||||
MethodDefinitionAndDeclaringTypeDict<NewMethodInfo> oldToNewMethod = new MethodDefinitionAndDeclaringTypeDict<NewMethodInfo>();
|
MethodDefinitionAndDeclaringTypeDict<NewMethodInfo> oldToNewMethod = new MethodDefinitionAndDeclaringTypeDict<NewMethodInfo>();
|
||||||
|
|
||||||
class NewMethodInfo {
|
class NewMethodInfo {
|
||||||
public OpCode opCode;
|
public OpCode opCode;
|
||||||
public MethodReference method;
|
public IMethod method;
|
||||||
|
|
||||||
public NewMethodInfo(OpCode opCode, MethodReference method) {
|
public NewMethodInfo(OpCode opCode, IMethod method) {
|
||||||
this.opCode = opCode;
|
this.opCode = opCode;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodCallRestorerBase(ModuleDefinition module) {
|
public MethodCallRestorerBase(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.builder = new MemberReferenceBuilder(module);
|
this.builder = new MemberReferenceBuilder(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createGetManifestResourceStream1(MethodDefinition oldMethod) {
|
public void createGetManifestResourceStream1(MethodDef oldMethod) {
|
||||||
if (oldMethod == null)
|
if (oldMethod == null)
|
||||||
return;
|
return;
|
||||||
var assemblyType = builder.type("System.Reflection", "Assembly", builder.CorLib);
|
var assemblyType = builder.type("System.Reflection", "Assembly", builder.CorLib);
|
||||||
|
@ -52,7 +52,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
add(oldMethod, newMethod, OpCodes.Callvirt);
|
add(oldMethod, newMethod, OpCodes.Callvirt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createGetManifestResourceStream2(MethodDefinition oldMethod) {
|
public void createGetManifestResourceStream2(MethodDef oldMethod) {
|
||||||
if (oldMethod == null)
|
if (oldMethod == null)
|
||||||
return;
|
return;
|
||||||
var assemblyType = builder.type("System.Reflection", "Assembly", builder.CorLib);
|
var assemblyType = builder.type("System.Reflection", "Assembly", builder.CorLib);
|
||||||
|
@ -62,7 +62,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
add(oldMethod, newMethod, OpCodes.Callvirt);
|
add(oldMethod, newMethod, OpCodes.Callvirt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createGetManifestResourceNames(MethodDefinition oldMethod) {
|
public void createGetManifestResourceNames(MethodDef oldMethod) {
|
||||||
if (oldMethod == null)
|
if (oldMethod == null)
|
||||||
return;
|
return;
|
||||||
var assemblyType = builder.type("System.Reflection", "Assembly", builder.CorLib);
|
var assemblyType = builder.type("System.Reflection", "Assembly", builder.CorLib);
|
||||||
|
@ -71,7 +71,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
add(oldMethod, newMethod, OpCodes.Callvirt);
|
add(oldMethod, newMethod, OpCodes.Callvirt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createBitmapCtor(MethodDefinition oldMethod) {
|
public void createBitmapCtor(MethodDef oldMethod) {
|
||||||
if (oldMethod == null)
|
if (oldMethod == null)
|
||||||
return;
|
return;
|
||||||
var bitmapType = builder.type("System.Drawing", "Bitmap", "System.Drawing");
|
var bitmapType = builder.type("System.Drawing", "Bitmap", "System.Drawing");
|
||||||
|
@ -80,7 +80,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
add(oldMethod, newMethod, OpCodes.Newobj);
|
add(oldMethod, newMethod, OpCodes.Newobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createIconCtor(MethodDefinition oldMethod) {
|
public void createIconCtor(MethodDef oldMethod) {
|
||||||
if (oldMethod == null)
|
if (oldMethod == null)
|
||||||
return;
|
return;
|
||||||
var iconType = builder.type("System.Drawing", "Icon", "System.Drawing");
|
var iconType = builder.type("System.Drawing", "Icon", "System.Drawing");
|
||||||
|
@ -89,11 +89,11 @@ namespace de4dot.code.deobfuscators {
|
||||||
add(oldMethod, newMethod, OpCodes.Newobj);
|
add(oldMethod, newMethod, OpCodes.Newobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void add(MethodDefinition oldMethod, MethodReference newMethod) {
|
protected void add(MethodDef oldMethod, IMethod newMethod) {
|
||||||
add(oldMethod, newMethod, OpCodes.Callvirt);
|
add(oldMethod, newMethod, OpCodes.Callvirt);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void add(MethodDefinition oldMethod, MethodReference newMethod, OpCode opCode) {
|
protected void add(MethodDef oldMethod, IMethod newMethod, OpCode opCode) {
|
||||||
if (oldMethod == null)
|
if (oldMethod == null)
|
||||||
return;
|
return;
|
||||||
oldToNewMethod.add(oldMethod, new NewMethodInfo(opCode, newMethod));
|
oldToNewMethod.add(oldMethod, new NewMethodInfo(opCode, newMethod));
|
||||||
|
@ -106,7 +106,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
var call = instrs[i];
|
var call = instrs[i];
|
||||||
if (call.OpCode.Code != Code.Call)
|
if (call.OpCode.Code != Code.Call)
|
||||||
continue;
|
continue;
|
||||||
var calledMethod = call.Operand as MethodDefinition;
|
var calledMethod = call.Operand as MethodDef;
|
||||||
if (calledMethod == null)
|
if (calledMethod == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
|
@ -79,7 +79,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
public static PushedArgs getPushedArgInstructions(IList<Instruction> instructions, int index) {
|
public static PushedArgs getPushedArgInstructions(IList<Instruction> instructions, int index) {
|
||||||
try {
|
try {
|
||||||
int pushes, pops;
|
int pushes, pops;
|
||||||
DotNetUtils.calculateStackUsage(instructions[index], false, out pushes, out pops);
|
instructions[index].CalculateStackUsage(false, out pushes, out pops);
|
||||||
if (pops != -1)
|
if (pops != -1)
|
||||||
return getPushedArgInstructions(instructions, index, pops);
|
return getPushedArgInstructions(instructions, index, pops);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
int pushes, pops;
|
int pushes, pops;
|
||||||
DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops);
|
instr.CalculateStackUsage(false, out pushes, out pops);
|
||||||
if (pops == -1)
|
if (pops == -1)
|
||||||
break;
|
break;
|
||||||
if (instr.OpCode.Code == Code.Dup) {
|
if (instr.OpCode.Code == Code.Dup) {
|
||||||
|
@ -128,7 +128,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
instr = getPreviousInstruction(instructions, ref index);
|
instr = getPreviousInstruction(instructions, ref index);
|
||||||
if (instr != null) {
|
if (instr != null) {
|
||||||
int pushes, pops;
|
int pushes, pops;
|
||||||
DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops);
|
instr.CalculateStackUsage(false, out pushes, out pops);
|
||||||
if (pushes == 1 && pops == 0)
|
if (pushes == 1 && pops == 0)
|
||||||
pushedArgs.set(0, instr);
|
pushedArgs.set(0, instr);
|
||||||
}
|
}
|
||||||
|
@ -138,96 +138,97 @@ namespace de4dot.code.deobfuscators {
|
||||||
return pushedArgs;
|
return pushedArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeReference getLoadedType(MethodDefinition method, IList<Instruction> instructions, int instrIndex) {
|
public static TypeSig getLoadedType(MethodDef method, IList<Instruction> instructions, int instrIndex) {
|
||||||
bool wasNewobj;
|
bool wasNewobj;
|
||||||
return getLoadedType(method, instructions, instrIndex, 0, out wasNewobj);
|
return getLoadedType(method, instructions, instrIndex, 0, out wasNewobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeReference getLoadedType(MethodDefinition method, IList<Instruction> instructions, int instrIndex, int argIndexFromEnd) {
|
public static TypeSig getLoadedType(MethodDef method, IList<Instruction> instructions, int instrIndex, int argIndexFromEnd) {
|
||||||
bool wasNewobj;
|
bool wasNewobj;
|
||||||
return getLoadedType(method, instructions, instrIndex, argIndexFromEnd, out wasNewobj);
|
return getLoadedType(method, instructions, instrIndex, argIndexFromEnd, out wasNewobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeReference getLoadedType(MethodDefinition method, IList<Instruction> instructions, int instrIndex, out bool wasNewobj) {
|
public static TypeSig getLoadedType(MethodDef method, IList<Instruction> instructions, int instrIndex, out bool wasNewobj) {
|
||||||
return getLoadedType(method, instructions, instrIndex, 0, out wasNewobj);
|
return getLoadedType(method, instructions, instrIndex, 0, out wasNewobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeReference getLoadedType(MethodDefinition method, IList<Instruction> instructions, int instrIndex, int argIndexFromEnd, out bool wasNewobj) {
|
public static TypeSig getLoadedType(MethodDef method, IList<Instruction> instructions, int instrIndex, int argIndexFromEnd, out bool wasNewobj) {
|
||||||
wasNewobj = false;
|
wasNewobj = false;
|
||||||
var pushedArgs = MethodStack.getPushedArgInstructions(instructions, instrIndex);
|
var pushedArgs = MethodStack.getPushedArgInstructions(instructions, instrIndex);
|
||||||
var pushInstr = pushedArgs.getEnd(argIndexFromEnd);
|
var pushInstr = pushedArgs.getEnd(argIndexFromEnd);
|
||||||
if (pushInstr == null)
|
if (pushInstr == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
TypeReference type;
|
TypeSig type;
|
||||||
VariableDefinition local;
|
Local local;
|
||||||
|
var corLibTypes = method.DeclaringType.OwnerModule.CorLibTypes;
|
||||||
switch (pushInstr.OpCode.Code) {
|
switch (pushInstr.OpCode.Code) {
|
||||||
case Code.Ldstr:
|
case Code.Ldstr:
|
||||||
type = method.Module.TypeSystem.String;
|
type = corLibTypes.String;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Conv_I:
|
case Code.Conv_I:
|
||||||
case Code.Conv_Ovf_I:
|
case Code.Conv_Ovf_I:
|
||||||
case Code.Conv_Ovf_I_Un:
|
case Code.Conv_Ovf_I_Un:
|
||||||
type = method.Module.TypeSystem.IntPtr;
|
type = corLibTypes.IntPtr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Conv_U:
|
case Code.Conv_U:
|
||||||
case Code.Conv_Ovf_U:
|
case Code.Conv_Ovf_U:
|
||||||
case Code.Conv_Ovf_U_Un:
|
case Code.Conv_Ovf_U_Un:
|
||||||
type = method.Module.TypeSystem.UIntPtr;
|
type = corLibTypes.UIntPtr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Conv_I8:
|
case Code.Conv_I8:
|
||||||
case Code.Conv_Ovf_I8:
|
case Code.Conv_Ovf_I8:
|
||||||
case Code.Conv_Ovf_I8_Un:
|
case Code.Conv_Ovf_I8_Un:
|
||||||
type = method.Module.TypeSystem.Int64;
|
type = corLibTypes.Int64;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Conv_U8:
|
case Code.Conv_U8:
|
||||||
case Code.Conv_Ovf_U8:
|
case Code.Conv_Ovf_U8:
|
||||||
case Code.Conv_Ovf_U8_Un:
|
case Code.Conv_Ovf_U8_Un:
|
||||||
type = method.Module.TypeSystem.UInt64;
|
type = corLibTypes.UInt64;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Conv_R8:
|
case Code.Conv_R8:
|
||||||
case Code.Ldc_R8:
|
case Code.Ldc_R8:
|
||||||
case Code.Ldelem_R8:
|
case Code.Ldelem_R8:
|
||||||
case Code.Ldind_R8:
|
case Code.Ldind_R8:
|
||||||
type = method.Module.TypeSystem.Double;
|
type = corLibTypes.Double;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Call:
|
case Code.Call:
|
||||||
case Code.Calli:
|
case Code.Calli:
|
||||||
case Code.Callvirt:
|
case Code.Callvirt:
|
||||||
var calledMethod = pushInstr.Operand as MethodReference;
|
var calledMethod = pushInstr.Operand as IMethod;
|
||||||
if (calledMethod == null)
|
if (calledMethod == null)
|
||||||
return null;
|
return null;
|
||||||
type = calledMethod.MethodReturnType.ReturnType;
|
type = calledMethod.MethodSig.RetType;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Newarr:
|
case Code.Newarr:
|
||||||
type = pushInstr.Operand as TypeReference;
|
var type2 = pushInstr.Operand as ITypeDefOrRef;
|
||||||
if (type == null)
|
if (type2 == null)
|
||||||
return null;
|
return null;
|
||||||
type = new ArrayType(type);
|
type = new SZArraySig(type2.ToTypeSig());
|
||||||
wasNewobj = true;
|
wasNewobj = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Newobj:
|
case Code.Newobj:
|
||||||
var ctor = pushInstr.Operand as MethodReference;
|
var ctor = pushInstr.Operand as IMethod;
|
||||||
if (ctor == null)
|
if (ctor == null)
|
||||||
return null;
|
return null;
|
||||||
type = ctor.DeclaringType;
|
type = ctor.DeclaringType.ToTypeSig();
|
||||||
wasNewobj = true;
|
wasNewobj = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Castclass:
|
case Code.Castclass:
|
||||||
case Code.Isinst:
|
case Code.Isinst:
|
||||||
case Code.Unbox_Any:
|
case Code.Unbox_Any:
|
||||||
case Code.Ldelem_Any:
|
case Code.Ldelem:
|
||||||
case Code.Ldobj:
|
case Code.Ldobj:
|
||||||
type = pushInstr.Operand as TypeReference;
|
type = (pushInstr.Operand as ITypeDefOrRef).ToTypeSig();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldarg:
|
case Code.Ldarg:
|
||||||
|
@ -236,7 +237,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
case Code.Ldarg_1:
|
case Code.Ldarg_1:
|
||||||
case Code.Ldarg_2:
|
case Code.Ldarg_2:
|
||||||
case Code.Ldarg_3:
|
case Code.Ldarg_3:
|
||||||
type = DotNetUtils.getArgType(method, pushInstr);
|
type = pushInstr.GetArgumentType(method.MethodSig, method.DeclaringType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldloc:
|
case Code.Ldloc:
|
||||||
|
@ -245,44 +246,44 @@ namespace de4dot.code.deobfuscators {
|
||||||
case Code.Ldloc_1:
|
case Code.Ldloc_1:
|
||||||
case Code.Ldloc_2:
|
case Code.Ldloc_2:
|
||||||
case Code.Ldloc_3:
|
case Code.Ldloc_3:
|
||||||
local = DotNetUtils.getLocalVar(method.Body.Variables, pushInstr);
|
local = pushInstr.GetLocal(method.CilBody.LocalList);
|
||||||
if (local == null)
|
if (local == null)
|
||||||
return null;
|
return null;
|
||||||
type = local.VariableType;
|
type = local.Type.RemovePinned();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldloca:
|
case Code.Ldloca:
|
||||||
case Code.Ldloca_S:
|
case Code.Ldloca_S:
|
||||||
local = pushInstr.Operand as VariableDefinition;
|
local = pushInstr.Operand as Local;
|
||||||
if (local == null)
|
if (local == null)
|
||||||
return null;
|
return null;
|
||||||
type = createByReferenceType(local.VariableType);
|
type = createByReferenceType(local.Type.RemovePinned());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldarga:
|
case Code.Ldarga:
|
||||||
case Code.Ldarga_S:
|
case Code.Ldarga_S:
|
||||||
type = createByReferenceType(DotNetUtils.getArgType(method, pushInstr));
|
type = createByReferenceType(pushInstr.GetArgumentType(method.MethodSig, method.DeclaringType));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldfld:
|
case Code.Ldfld:
|
||||||
case Code.Ldsfld:
|
case Code.Ldsfld:
|
||||||
var field = pushInstr.Operand as FieldReference;
|
var field = pushInstr.Operand as IField;
|
||||||
if (field == null)
|
if (field == null || field.FieldSig == null)
|
||||||
return null;
|
return null;
|
||||||
type = field.FieldType;
|
type = field.FieldSig.Type;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldflda:
|
case Code.Ldflda:
|
||||||
case Code.Ldsflda:
|
case Code.Ldsflda:
|
||||||
var field2 = pushInstr.Operand as FieldReference;
|
var field2 = pushInstr.Operand as IField;
|
||||||
if (field2 == null)
|
if (field2 == null || field2.FieldSig == null)
|
||||||
return null;
|
return null;
|
||||||
type = createByReferenceType(field2.FieldType);
|
type = createByReferenceType(field2.FieldSig.Type);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldelema:
|
case Code.Ldelema:
|
||||||
case Code.Unbox:
|
case Code.Unbox:
|
||||||
type = createByReferenceType(pushInstr.Operand as TypeReference);
|
type = createByReferenceType(pushInstr.Operand as ITypeDefOrRef);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -292,10 +293,16 @@ namespace de4dot.code.deobfuscators {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ByReferenceType createByReferenceType(TypeReference elementType) {
|
static ByRefSig createByReferenceType(ITypeDefOrRef elementType) {
|
||||||
if (elementType == null)
|
if (elementType == null)
|
||||||
return null;
|
return null;
|
||||||
return new ByReferenceType(elementType);
|
return new ByRefSig(elementType.ToTypeSig());
|
||||||
|
}
|
||||||
|
|
||||||
|
static ByRefSig createByReferenceType(TypeSig elementType) {
|
||||||
|
if (elementType == null)
|
||||||
|
return null;
|
||||||
|
return new ByRefSig(elementType);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction getPreviousInstruction(IList<Instruction> instructions, ref int instrIndex) {
|
static Instruction getPreviousInstruction(IList<Instruction> instructions, ref int instrIndex) {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Mono.MyStuff;
|
using dot10.DotNet;
|
||||||
using de4dot.code.AssemblyClient;
|
using de4dot.code.AssemblyClient;
|
||||||
using de4dot.mdecrypt;
|
using de4dot.mdecrypt;
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
class StringCounts {
|
class StringCounts {
|
||||||
|
@ -66,37 +66,37 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
class FieldTypes : StringCounts {
|
class FieldTypes : StringCounts {
|
||||||
public FieldTypes(TypeDefinition type) {
|
public FieldTypes(TypeDef type) {
|
||||||
init(type.Fields);
|
init(type.Fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldTypes(IEnumerable<FieldDefinition> fields) {
|
public FieldTypes(IEnumerable<FieldDef> fields) {
|
||||||
init(fields);
|
init(fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(IEnumerable<FieldDefinition> fields) {
|
void init(IEnumerable<FieldDef> fields) {
|
||||||
if (fields == null)
|
if (fields == null)
|
||||||
return;
|
return;
|
||||||
foreach (var field in fields)
|
foreach (var field in fields)
|
||||||
add(field.FieldType.FullName);
|
add(field.FieldSig.Type.FullName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalTypes : StringCounts {
|
class LocalTypes : StringCounts {
|
||||||
public LocalTypes(MethodDefinition method) {
|
public LocalTypes(MethodDef method) {
|
||||||
if (method != null && method.Body != null)
|
if (method != null && method.CilBody != null)
|
||||||
init(method.Body.Variables);
|
init(method.CilBody.LocalList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalTypes(IEnumerable<VariableDefinition> locals) {
|
public LocalTypes(IEnumerable<Local> locals) {
|
||||||
init(locals);
|
init(locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(IEnumerable<VariableDefinition> locals) {
|
void init(IEnumerable<Local> locals) {
|
||||||
if (locals == null)
|
if (locals == null)
|
||||||
return;
|
return;
|
||||||
foreach (var local in locals)
|
foreach (var local in locals)
|
||||||
add(local.VariableType.FullName);
|
add(local.Type.FullName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,7 +186,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Log.v("Changing field types to real type");
|
Log.v("Changing field types to real type");
|
||||||
fields.Sort((a, b) => Utils.compareInt32(a.token, b.token));
|
fields.Sort((a, b) => a.token.CompareTo(b.token));
|
||||||
Log.indent();
|
Log.indent();
|
||||||
foreach (var updatedField in fields)
|
foreach (var updatedField in fields)
|
||||||
Log.v("Field {0:X8}: type {1} ({2:X8})", updatedField.token, Utils.removeNewlines(updatedField.newFieldType.FullName), updatedField.newFieldType.MDToken.ToInt32());
|
Log.v("Field {0:X8}: type {1} ({2:X8})", updatedField.token, Utils.removeNewlines(updatedField.newFieldType.FullName), updatedField.newFieldType.MDToken.ToInt32());
|
||||||
|
@ -199,7 +199,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Log.v("Changing method args and return types to real type");
|
Log.v("Changing method args and return types to real type");
|
||||||
methods.Sort((a, b) => Utils.compareInt32(a.token, b.token));
|
methods.Sort((a, b) => a.token.CompareTo(b.token));
|
||||||
Log.indent();
|
Log.indent();
|
||||||
foreach (var updatedMethod in methods) {
|
foreach (var updatedMethod in methods) {
|
||||||
Log.v("Method {0:X8}", updatedMethod.token);
|
Log.v("Method {0:X8}", updatedMethod.token);
|
||||||
|
@ -250,7 +250,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
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;
|
||||||
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);
|
return a.arg.Sequence.CompareTo(b.arg.Sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deobfuscateMethod(MethodDef method) {
|
void deobfuscateMethod(MethodDef method) {
|
||||||
|
|
|
@ -19,19 +19,19 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using dot10.DotNet;
|
||||||
using Mono.Cecil.Cil;
|
using dot10.DotNet.Emit;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
abstract class ValueInlinerBase<TValue> : MethodReturnValueInliner {
|
abstract class ValueInlinerBase<TValue> : MethodReturnValueInliner {
|
||||||
MethodDefinitionAndDeclaringTypeDict<Func<MethodDefinition, GenericInstanceMethod, object[], object>> decrypterMethods = new MethodDefinitionAndDeclaringTypeDict<Func<MethodDefinition, GenericInstanceMethod, object[], object>>();
|
MethodDefinitionAndDeclaringTypeDict<Func<MethodDef, MethodSpec, object[], object>> decrypterMethods = new MethodDefinitionAndDeclaringTypeDict<Func<MethodDef, MethodSpec, object[], object>>();
|
||||||
bool removeUnbox = false;
|
bool removeUnbox = false;
|
||||||
|
|
||||||
class MyCallResult : CallResult {
|
class MyCallResult : CallResult {
|
||||||
public MethodReference methodReference;
|
public IMethod methodReference;
|
||||||
public GenericInstanceMethod gim;
|
public MethodSpec gim;
|
||||||
public MyCallResult(Block block, int callEndIndex, MethodReference method, GenericInstanceMethod gim)
|
public MyCallResult(Block block, int callEndIndex, IMethod method, MethodSpec gim)
|
||||||
: base(block, callEndIndex) {
|
: base(block, callEndIndex) {
|
||||||
this.methodReference = method;
|
this.methodReference = method;
|
||||||
this.gim = gim;
|
this.gim = gim;
|
||||||
|
@ -47,15 +47,15 @@ namespace de4dot.code.deobfuscators {
|
||||||
get { return decrypterMethods.Count != 0; }
|
get { return decrypterMethods.Count != 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<MethodDefinition> Methods {
|
public IEnumerable<MethodDef> Methods {
|
||||||
get { return decrypterMethods.getKeys(); }
|
get { return decrypterMethods.getKeys(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(MethodDefinition method, Func<MethodDefinition, GenericInstanceMethod, object[], object> handler) {
|
public void add(MethodDef method, Func<MethodDef, MethodSpec, object[], object> handler) {
|
||||||
if (method == null)
|
if (method == null)
|
||||||
return;
|
return;
|
||||||
if (decrypterMethods.find(method) != null)
|
if (decrypterMethods.find(method) != null)
|
||||||
throw new ApplicationException(string.Format("Handler for method {0:X8} has already been added", method.MetadataToken.ToInt32()));
|
throw new ApplicationException(string.Format("Handler for method {0:X8} has already been added", method.MDToken.ToInt32()));
|
||||||
if (method != null)
|
if (method != null)
|
||||||
decrypterMethods.add(method, handler);
|
decrypterMethods.add(method, handler);
|
||||||
}
|
}
|
||||||
|
@ -64,11 +64,11 @@ namespace de4dot.code.deobfuscators {
|
||||||
foreach (var tmp in callResults) {
|
foreach (var tmp in callResults) {
|
||||||
var callResult = (MyCallResult)tmp;
|
var callResult = (MyCallResult)tmp;
|
||||||
var handler = decrypterMethods.find(callResult.methodReference);
|
var handler = decrypterMethods.find(callResult.methodReference);
|
||||||
callResult.returnValue = handler((MethodDefinition)callResult.methodReference, callResult.gim, callResult.args);
|
callResult.returnValue = handler((MethodDef)callResult.methodReference, callResult.gim, callResult.args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override CallResult createCallResult(MethodReference method, GenericInstanceMethod gim, Block block, int callInstrIndex) {
|
protected override CallResult createCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex) {
|
||||||
if (decrypterMethods.find(method) == null)
|
if (decrypterMethods.find(method) == null)
|
||||||
return null;
|
return null;
|
||||||
return new MyCallResult(block, callInstrIndex, method, gim);
|
return new MyCallResult(block, callInstrIndex, method, gim);
|
||||||
|
@ -83,7 +83,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
var unbox = instrs[index];
|
var unbox = instrs[index];
|
||||||
if (unbox.OpCode.Code != Code.Unbox_Any)
|
if (unbox.OpCode.Code != Code.Unbox_Any)
|
||||||
return false;
|
return false;
|
||||||
var type = unbox.Operand as TypeReference;
|
var type = unbox.Operand as ITypeDefOrRef;
|
||||||
if (type == null || type.FullName != unboxType)
|
if (type == null || type.FullName != unboxType)
|
||||||
return false;
|
return false;
|
||||||
block.remove(index, 1);
|
block.remove(index, 1);
|
||||||
|
@ -97,7 +97,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
var block = callResult.block;
|
var block = callResult.block;
|
||||||
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||||
|
|
||||||
block.replace(callResult.callStartIndex, num, DotNetUtils.createLdci4((bool)callResult.returnValue ? 1 : 0));
|
block.replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((bool)callResult.returnValue ? 1 : 0));
|
||||||
removeUnboxInstruction(block, callResult.callStartIndex + 1, "System.Boolean");
|
removeUnboxInstruction(block, callResult.callStartIndex + 1, "System.Boolean");
|
||||||
Log.v("Decrypted boolean: {0}", callResult.returnValue);
|
Log.v("Decrypted boolean: {0}", callResult.returnValue);
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
var block = callResult.block;
|
var block = callResult.block;
|
||||||
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||||
|
|
||||||
block.replace(callResult.callStartIndex, num, DotNetUtils.createLdci4((int)callResult.returnValue));
|
block.replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
|
||||||
removeUnboxInstruction(block, callResult.callStartIndex + 1, "System.Int32");
|
removeUnboxInstruction(block, callResult.callStartIndex + 1, "System.Int32");
|
||||||
Log.v("Decrypted int32: {0}", callResult.returnValue);
|
Log.v("Decrypted int32: {0}", callResult.returnValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ namespace de4dot.code.resources {
|
||||||
|
|
||||||
public List<UserResourceType> getSortedTypes() {
|
public List<UserResourceType> getSortedTypes() {
|
||||||
var list = new List<UserResourceType>(dict.Values);
|
var list = new List<UserResourceType>(dict.Values);
|
||||||
list.Sort((a, b) => Utils.compareInt32((int)a.Code, (int)b.Code));
|
list.Sort((a, b) => ((int)a.Code).CompareTo((int)b.Code));
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ namespace de4dot.code.resources {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sortResourceInfo(ResourceInfo a, ResourceInfo b) {
|
static int sortResourceInfo(ResourceInfo a, ResourceInfo b) {
|
||||||
return Utils.compareInt32((int)a.offset, (int)b.offset);
|
return ((int)a.offset).CompareTo((int)b.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResourceInfo {
|
class ResourceInfo {
|
||||||
|
|
2
dot10
2
dot10
|
@ -1 +1 @@
|
||||||
Subproject commit 7eb0fb7e6e47c79eebbef0ea9ea404f9b81fde51
|
Subproject commit 3b128874ff6bd531f588c487e9aeb76fb62acfec
|
Loading…
Reference in New Issue
Block a user