Use standard .NET naming convention

This commit is contained in:
de4dot 2013-01-19 13:03:57 +01:00
parent fa6c10b8c0
commit 211d1b67f6
319 changed files with 10050 additions and 10050 deletions

View File

@ -30,17 +30,17 @@ namespace AssemblyData {
List<string> assemblySearchPaths = new List<string>(); List<string> assemblySearchPaths = new List<string>();
public AssemblyResolver() { public AssemblyResolver() {
AppDomain.CurrentDomain.AssemblyResolve += assemblyResolve; AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;
} }
void addAssemblySearchPath(string path) { void AddAssemblySearchPath(string path) {
if (assemblySearchPathsDict.ContainsKey(path)) if (assemblySearchPathsDict.ContainsKey(path))
return; return;
assemblySearchPathsDict[path] = true; assemblySearchPathsDict[path] = true;
assemblySearchPaths.Add(path); assemblySearchPaths.Add(path);
} }
Assembly get(string assemblyFullName) { Assembly Get(string assemblyFullName) {
var asmName = new AssemblyName(assemblyFullName); var asmName = new AssemblyName(assemblyFullName);
Assembly assembly; Assembly assembly;
@ -53,8 +53,8 @@ namespace AssemblyData {
} }
static string[] assemblyExtensions = new string[] { ".dll", ".exe" }; static string[] assemblyExtensions = new string[] { ".dll", ".exe" };
Assembly assemblyResolve(object sender, ResolveEventArgs args) { Assembly AssemblyResolve(object sender, ResolveEventArgs args) {
var assembly = get(args.Name); var assembly = Get(args.Name);
if (assembly != null) if (assembly != null)
return assembly; return assembly;
@ -65,8 +65,8 @@ namespace AssemblyData {
var filename = Path.Combine(path, asmName.Name + ext); var filename = Path.Combine(path, asmName.Name + ext);
if (!new FileInfo(filename).Exists) if (!new FileInfo(filename).Exists)
continue; continue;
addConfigFile(filename + ".config"); AddConfigFile(filename + ".config");
return addAssembly(Assembly.LoadFile(filename)); return AddAssembly(Assembly.LoadFile(filename));
} }
catch (IOException) { catch (IOException) {
} }
@ -86,12 +86,12 @@ namespace AssemblyData {
return null; return null;
} }
public Assembly load(string filename) { public Assembly Load(string filename) {
addConfigFile(filename + ".config"); AddConfigFile(filename + ".config");
return addAssembly(loadFile(filename)); return AddAssembly(LoadFile(filename));
} }
Assembly loadFile(string filename) { Assembly LoadFile(string filename) {
try { try {
return Assembly.LoadFrom(filename); return Assembly.LoadFrom(filename);
} }
@ -101,16 +101,16 @@ namespace AssemblyData {
} }
} }
Assembly addAssembly(Assembly assembly) { Assembly AddAssembly(Assembly assembly) {
var asmName = assembly.GetName(); var asmName = assembly.GetName();
assemblies[asmName.FullName] = assembly; assemblies[asmName.FullName] = assembly;
assemblies[asmName.Name] = assembly; assemblies[asmName.Name] = assembly;
return assembly; return assembly;
} }
void addConfigFile(string configFilename) { void AddConfigFile(string configFilename) {
var dirName = Utils.getDirName(Utils.getFullPath(configFilename)); var dirName = Utils.GetDirName(Utils.GetFullPath(configFilename));
addAssemblySearchPath(dirName); AddAssemblySearchPath(dirName);
try { try {
using (var xmlStream = new FileStream(configFilename, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var xmlStream = new FileStream(configFilename, FileMode.Open, FileAccess.Read, FileShare.Read)) {
@ -124,7 +124,7 @@ namespace AssemblyData {
if (string.IsNullOrEmpty(privatePath)) if (string.IsNullOrEmpty(privatePath))
continue; continue;
foreach (var path in privatePath.Split(';')) foreach (var path in privatePath.Split(';'))
addAssemblySearchPath(Path.Combine(dirName, path)); AddAssemblySearchPath(Path.Combine(dirName, path));
} }
} }
} }

View File

@ -26,19 +26,19 @@ using AssemblyData;
namespace AssemblyServer { namespace AssemblyServer {
public static class Start { public static class Start {
public static int main(string[] args) { public static int Main2(string[] args) {
if (args.Length != 2) if (args.Length != 2)
Environment.Exit(1); Environment.Exit(1);
var channelName = args[0]; var channelName = args[0];
var uri = args[1]; var uri = args[1];
var service = new AssemblyService(); var service = new AssemblyService();
startServer(service, channelName, uri); StartServer(service, channelName, uri);
service.waitExit(); service.WaitExit();
return 0; return 0;
} }
static void startServer(AssemblyService service, string name, string uri) { static void StartServer(AssemblyService service, string name, string uri) {
var props = new Hashtable(); var props = new Hashtable();
props["portName"] = name; props["portName"] = name;
var provider = new BinaryServerFormatterSinkProvider(); var provider = new BinaryServerFormatterSinkProvider();

View File

@ -33,14 +33,14 @@ namespace AssemblyData {
AssemblyResolver assemblyResolver = new AssemblyResolver(); AssemblyResolver assemblyResolver = new AssemblyResolver();
bool installCompileMethodCalled = false; bool installCompileMethodCalled = false;
public void doNothing() { public void DoNothing() {
} }
public void exit() { public void Exit() {
exitEvent.Set(); exitEvent.Set();
} }
public void waitExit() { public void WaitExit() {
exitEvent.WaitOne(); exitEvent.WaitOne();
} }
@ -48,28 +48,28 @@ namespace AssemblyData {
return null; return null;
} }
void checkStringDecrypter() { void CheckStringDecrypter() {
if (stringDecrypter == null) if (stringDecrypter == null)
throw new ApplicationException("setStringDecrypterType() hasn't been called yet."); throw new ApplicationException("setStringDecrypterType() hasn't been called yet.");
} }
void checkAssembly() { void CheckAssembly() {
if (assembly == null) if (assembly == null)
throw new ApplicationException("loadAssembly() hasn't been called yet."); throw new ApplicationException("loadAssembly() hasn't been called yet.");
} }
public void loadAssembly(string filename) { public void LoadAssembly(string filename) {
if (assembly != null) if (assembly != null)
throw new ApplicationException("Only one assembly can be explicitly loaded"); throw new ApplicationException("Only one assembly can be explicitly loaded");
try { try {
assembly = assemblyResolver.load(filename); assembly = assemblyResolver.Load(filename);
} }
catch (BadImageFormatException) { catch (BadImageFormatException) {
throw new ApplicationException(string.Format("Could not load assembly {0}. Maybe it's 32-bit or 64-bit only?", filename)); throw new ApplicationException(string.Format("Could not load assembly {0}. Maybe it's 32-bit or 64-bit only?", filename));
} }
} }
public void setStringDecrypterType(StringDecrypterType type) { public void SetStringDecrypterType(StringDecrypterType type) {
if (stringDecrypter != null) if (stringDecrypter != null)
throw new ApplicationException("StringDecrypterType already set"); throw new ApplicationException("StringDecrypterType already set");
@ -87,25 +87,25 @@ namespace AssemblyData {
} }
} }
public int defineStringDecrypter(int methodToken) { public int DefineStringDecrypter(int methodToken) {
checkStringDecrypter(); CheckStringDecrypter();
var methodInfo = findMethod(methodToken); var methodInfo = FindMethod(methodToken);
if (methodInfo == null) if (methodInfo == null)
throw new ApplicationException(string.Format("Could not find method {0:X8}", methodToken)); throw new ApplicationException(string.Format("Could not find method {0:X8}", methodToken));
if (methodInfo.ReturnType != typeof(string) && methodInfo.ReturnType != typeof(object)) if (methodInfo.ReturnType != typeof(string) && methodInfo.ReturnType != typeof(object))
throw new ApplicationException(string.Format("Method return type must be string or object: {0}", methodInfo)); throw new ApplicationException(string.Format("Method return type must be string or object: {0}", methodInfo));
return stringDecrypter.defineStringDecrypter(methodInfo); return stringDecrypter.DefineStringDecrypter(methodInfo);
} }
public object[] decryptStrings(int stringDecrypterMethod, object[] args, int callerToken) { public object[] DecryptStrings(int stringDecrypterMethod, object[] args, int callerToken) {
checkStringDecrypter(); CheckStringDecrypter();
var caller = getCaller(callerToken); var caller = GetCaller(callerToken);
foreach (var arg in args) foreach (var arg in args)
SimpleData.unpack((object[])arg); SimpleData.Unpack((object[])arg);
return SimpleData.pack(stringDecrypter.decryptStrings(stringDecrypterMethod, args, caller)); return SimpleData.Pack(stringDecrypter.DecryptStrings(stringDecrypterMethod, args, caller));
} }
MethodBase getCaller(int callerToken) { MethodBase GetCaller(int callerToken) {
try { try {
return assembly.GetModules()[0].ResolveMethod(callerToken); return assembly.GetModules()[0].ResolveMethod(callerToken);
} }
@ -114,8 +114,8 @@ namespace AssemblyData {
} }
} }
MethodInfo findMethod(int methodToken) { MethodInfo FindMethod(int methodToken) {
checkAssembly(); CheckAssembly();
foreach (var module in assembly.GetModules()) { foreach (var module in assembly.GetModules()) {
var method = module.ResolveMethod(methodToken) as MethodInfo; var method = module.ResolveMethod(methodToken) as MethodInfo;
@ -126,28 +126,28 @@ namespace AssemblyData {
return null; return null;
} }
public void installCompileMethod(DecryptMethodsInfo decryptMethodsInfo) { public void InstallCompileMethod(DecryptMethodsInfo decryptMethodsInfo) {
if (installCompileMethodCalled) if (installCompileMethodCalled)
throw new ApplicationException("installCompileMethod() has already been called"); throw new ApplicationException("installCompileMethod() has already been called");
installCompileMethodCalled = true; installCompileMethodCalled = true;
DynamicMethodsDecrypter.Instance.DecryptMethodsInfo = decryptMethodsInfo; DynamicMethodsDecrypter.Instance.DecryptMethodsInfo = decryptMethodsInfo;
DynamicMethodsDecrypter.Instance.installCompileMethod(); DynamicMethodsDecrypter.Instance.InstallCompileMethod();
} }
public void loadObfuscator(string filename) { public void LoadObfuscator(string filename) {
loadAssembly(filename); LoadAssembly(filename);
DynamicMethodsDecrypter.Instance.Module = assembly.ManifestModule; DynamicMethodsDecrypter.Instance.Module = assembly.ManifestModule;
DynamicMethodsDecrypter.Instance.loadObfuscator(); DynamicMethodsDecrypter.Instance.LoadObfuscator();
} }
public bool canDecryptMethods() { public bool CanDecryptMethods() {
checkAssembly(); CheckAssembly();
return DynamicMethodsDecrypter.Instance.canDecryptMethods(); return DynamicMethodsDecrypter.Instance.CanDecryptMethods();
} }
public DumpedMethods decryptMethods() { public DumpedMethods DecryptMethods() {
checkAssembly(); CheckAssembly();
return DynamicMethodsDecrypter.Instance.decryptMethods(); return DynamicMethodsDecrypter.Instance.DecryptMethods();
} }
} }
} }

View File

@ -27,12 +27,12 @@ namespace AssemblyData {
delegate string DecryptString(object[] args); delegate string DecryptString(object[] args);
List<DecryptString> stringDecryptMethods = new List<DecryptString>(); List<DecryptString> stringDecryptMethods = new List<DecryptString>();
public int defineStringDecrypter(MethodInfo method) { public int DefineStringDecrypter(MethodInfo method) {
stringDecryptMethods.Add(buildDynamicMethod(method)); stringDecryptMethods.Add(BuildDynamicMethod(method));
return stringDecryptMethods.Count - 1; return stringDecryptMethods.Count - 1;
} }
public object[] decryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller) { public object[] DecryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller) {
if (stringDecrypterMethod > stringDecryptMethods.Count) if (stringDecrypterMethod > stringDecryptMethods.Count)
throw new ApplicationException("Invalid string decrypter method"); throw new ApplicationException("Invalid string decrypter method");
@ -43,9 +43,9 @@ namespace AssemblyData {
return rv; return rv;
} }
DecryptString buildDynamicMethod(MethodInfo method) { DecryptString BuildDynamicMethod(MethodInfo method) {
var dm = new DynamicMethod("", typeof(string), new Type[] { typeof(object[]) }, typeof(DelegateStringDecrypter), true); var dm = new DynamicMethod("", typeof(string), new Type[] { typeof(object[]) }, typeof(DelegateStringDecrypter), true);
Utils.addCallStringDecrypterMethodInstructions(method, dm.GetILGenerator()); Utils.AddCallStringDecrypterMethodInstructions(method, dm.GetILGenerator());
return (DecryptString)dm.CreateDelegate(typeof(DecryptString)); return (DecryptString)dm.CreateDelegate(typeof(DecryptString));
} }
} }

View File

@ -36,26 +36,26 @@ namespace AssemblyData {
} }
} }
public int defineStringDecrypter(MethodInfo method) { public int DefineStringDecrypter(MethodInfo method) {
decryptInfos.Add(new DecryptInfo(method)); decryptInfos.Add(new DecryptInfo(method));
return decryptInfos.Count - 1; return decryptInfos.Count - 1;
} }
public object[] decryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller) { public object[] DecryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller) {
var decryptInfo = decryptInfos[stringDecrypterMethod]; var decryptInfo = decryptInfos[stringDecrypterMethod];
if (decryptInfo.decryptString == null) if (decryptInfo.decryptString == null)
decryptInfo.decryptString = createDecryptString(decryptInfo.method); decryptInfo.decryptString = CreateDecryptString(decryptInfo.method);
methodsRewriter.setCaller(decryptInfo.decryptString, caller); methodsRewriter.SetCaller(decryptInfo.decryptString, caller);
var result = new object[args.Length]; var result = new object[args.Length];
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
result[i] = decryptInfo.decryptString((object[])args[i]); result[i] = decryptInfo.decryptString((object[])args[i]);
return result; return result;
} }
RewrittenMethod createDecryptString(MethodInfo method) { RewrittenMethod CreateDecryptString(MethodInfo method) {
methodsRewriter.createMethod(method); methodsRewriter.CreateMethod(method);
return methodsRewriter.createDelegate(method); return methodsRewriter.CreateDelegate(method);
} }
} }
} }

View File

@ -28,18 +28,18 @@ namespace AssemblyData {
} }
public interface IAssemblyService { public interface IAssemblyService {
void doNothing(); void DoNothing();
void exit(); void Exit();
void loadAssembly(string filename); void LoadAssembly(string filename);
void setStringDecrypterType(StringDecrypterType type); void SetStringDecrypterType(StringDecrypterType type);
int defineStringDecrypter(int methodToken); int DefineStringDecrypter(int methodToken);
object[] decryptStrings(int stringDecrypterMethod, object[] args, int callerToken); object[] DecryptStrings(int stringDecrypterMethod, object[] args, int callerToken);
void installCompileMethod(DecryptMethodsInfo decryptMethodsInfo); void InstallCompileMethod(DecryptMethodsInfo decryptMethodsInfo);
void loadObfuscator(string filename); void LoadObfuscator(string filename);
bool canDecryptMethods(); bool CanDecryptMethods();
DumpedMethods decryptMethods(); DumpedMethods DecryptMethods();
} }
} }

View File

@ -21,7 +21,7 @@ using System.Reflection;
namespace AssemblyData { namespace AssemblyData {
interface IStringDecrypter { interface IStringDecrypter {
int defineStringDecrypter(MethodInfo method); int DefineStringDecrypter(MethodInfo method);
object[] decryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller); object[] DecryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller);
} }
} }

View File

@ -51,7 +51,7 @@ namespace AssemblyData {
} }
public static class SimpleData { public static class SimpleData {
public static object[] pack(object[] args) { public static object[] Pack(object[] args) {
for (int i = 0; i < args.Length; i++) { for (int i = 0; i < args.Length; i++) {
var s = args[i] as string; var s = args[i] as string;
if (s != null) if (s != null)
@ -60,7 +60,7 @@ namespace AssemblyData {
return args; return args;
} }
public static object[] unpack(object[] args) { public static object[] Unpack(object[] args) {
for (int i = 0; i < args.Length; i++) { for (int i = 0; i < args.Length; i++) {
var s = args[i] as MyString; var s = args[i] as MyString;
if (s != null) if (s != null)

View File

@ -68,11 +68,11 @@ namespace AssemblyData {
static class Utils { static class Utils {
static Random random = new Random(); static Random random = new Random();
public static uint getRandomUint() { public static uint GetRandomUint() {
return (uint)(random.NextDouble() * uint.MaxValue); return (uint)(random.NextDouble() * uint.MaxValue);
} }
public static Type getDelegateType(Type returnType, Type[] args) { public static Type GetDelegateType(Type returnType, Type[] args) {
Type[] types; Type[] types;
if (returnType == typeof(void)) { if (returnType == typeof(void)) {
types = args; types = args;
@ -133,7 +133,7 @@ namespace AssemblyData {
} }
} }
public static string randomName(int min, int max) { public static string RandomName(int min, int max) {
int numChars = random.Next(min, max + 1); int numChars = random.Next(min, max + 1);
var sb = new StringBuilder(numChars); var sb = new StringBuilder(numChars);
int numLower = 0; int numLower = 0;
@ -153,7 +153,7 @@ namespace AssemblyData {
return sb.ToString(); return sb.ToString();
} }
public static void addCallStringDecrypterMethodInstructions(MethodInfo method, ILGenerator ilg) { public static void AddCallStringDecrypterMethodInstructions(MethodInfo method, ILGenerator ilg) {
var args = method.GetParameters(); var args = method.GetParameters();
for (int i = 0; i < args.Length; i++) { for (int i = 0; i < args.Length; i++) {
var arg = args[i].ParameterType; var arg = args[i].ParameterType;
@ -171,7 +171,7 @@ namespace AssemblyData {
ilg.Emit(OpCodes.Ret); ilg.Emit(OpCodes.Ret);
} }
public static string getFullPath(string path) { public static string GetFullPath(string path) {
try { try {
return Path.GetFullPath(path); return Path.GetFullPath(path);
} }
@ -180,7 +180,7 @@ namespace AssemblyData {
} }
} }
public static string getDirName(string name) { public static string GetDirName(string name) {
return Path.GetDirectoryName(name); return Path.GetDirectoryName(name);
} }
} }

View File

@ -35,10 +35,10 @@ namespace AssemblyData.methodsrewriter {
public AssemblyResolver(string asmName) { public AssemblyResolver(string asmName) {
assembly = Assembly.Load(new AssemblyName(asmName)); assembly = Assembly.Load(new AssemblyName(asmName));
initTypes(); InitTypes();
} }
void initTypes() { void InitTypes() {
foreach (var type in assembly.GetTypes()) { foreach (var type in assembly.GetTypes()) {
string key = (type.Namespace ?? "") + "." + type.Name; string key = (type.Namespace ?? "") + "." + type.Name;
List<TypeResolver> list; List<TypeResolver> list;
@ -48,7 +48,7 @@ namespace AssemblyData.methodsrewriter {
} }
} }
TypeResolver getTypeResolver(ITypeDefOrRef typeRef) { TypeResolver GetTypeResolver(ITypeDefOrRef typeRef) {
if (typeRef == null) if (typeRef == null)
return null; return null;
var scopeType = typeRef.ScopeType; var scopeType = typeRef.ScopeType;
@ -65,30 +65,30 @@ namespace AssemblyData.methodsrewriter {
} }
foreach (var resolver in list) { foreach (var resolver in list) {
if (ResolverUtils.compareTypes(resolver.type, scopeType)) if (ResolverUtils.CompareTypes(resolver.type, scopeType))
return resolver; return resolver;
} }
return null; return null;
} }
public FieldInfo resolve(IField fieldRef) { public FieldInfo Resolve(IField fieldRef) {
var resolver = getTypeResolver(fieldRef.DeclaringType); var resolver = GetTypeResolver(fieldRef.DeclaringType);
if (resolver != null) if (resolver != null)
return resolver.resolve(fieldRef); return resolver.Resolve(fieldRef);
return resolveGlobalField(fieldRef); return ResolveGlobalField(fieldRef);
} }
FieldInfo resolveGlobalField(IField fieldRef) { FieldInfo ResolveGlobalField(IField fieldRef) {
initGlobalFields(); InitGlobalFields();
foreach (var globalField in globalFields) { foreach (var globalField in globalFields) {
if (ResolverUtils.compareFields(globalField, fieldRef)) if (ResolverUtils.CompareFields(globalField, fieldRef))
return globalField; return globalField;
} }
return null; return null;
} }
void initGlobalFields() { void InitGlobalFields() {
if (globalFields != null) if (globalFields != null)
return; return;
globalFields = new List<FieldInfo>(); globalFields = new List<FieldInfo>();
@ -100,23 +100,23 @@ namespace AssemblyData.methodsrewriter {
} }
} }
public MethodBase resolve(IMethod methodRef) { public MethodBase Resolve(IMethod methodRef) {
var resolver = getTypeResolver(methodRef.DeclaringType); var resolver = GetTypeResolver(methodRef.DeclaringType);
if (resolver != null) if (resolver != null)
return resolver.resolve(methodRef); return resolver.Resolve(methodRef);
return resolveGlobalMethod(methodRef); return ResolveGlobalMethod(methodRef);
} }
MethodBase resolveGlobalMethod(IMethod methodRef) { MethodBase ResolveGlobalMethod(IMethod methodRef) {
initGlobalMethods(); InitGlobalMethods();
foreach (var globalMethod in globalMethods) { foreach (var globalMethod in globalMethods) {
if (ResolverUtils.compareMethods(globalMethod, methodRef)) if (ResolverUtils.CompareMethods(globalMethod, methodRef))
return globalMethod; return globalMethod;
} }
return null; return null;
} }
void initGlobalMethods() { void InitGlobalMethods() {
if (globalMethods != null) if (globalMethods != null)
return; return;
globalMethods = new List<MethodBase>(); globalMethods = new List<MethodBase>();
@ -128,8 +128,8 @@ namespace AssemblyData.methodsrewriter {
} }
} }
public Type resolve(ITypeDefOrRef typeRef) { public Type Resolve(ITypeDefOrRef typeRef) {
var resolver = getTypeResolver(typeRef); var resolver = GetTypeResolver(typeRef);
if (resolver != null) if (resolver != null)
return resolver.type; return resolver.type;

View File

@ -81,14 +81,14 @@ namespace AssemblyData.methodsrewriter {
this.methodName = methodName; this.methodName = methodName;
} }
public void setMethodInfo(MMethod methodInfo) { public void SetMethodInfo(MMethod methodInfo) {
this.methodInfo = methodInfo; this.methodInfo = methodInfo;
methodReturnType = ResolverUtils.getReturnType(methodInfo.methodBase); methodReturnType = ResolverUtils.GetReturnType(methodInfo.methodBase);
methodParameters = getMethodParameterTypes(methodInfo.methodBase); methodParameters = GetMethodParameterTypes(methodInfo.methodBase);
delegateType = Utils.getDelegateType(methodReturnType, methodParameters); delegateType = Utils.GetDelegateType(methodReturnType, methodParameters);
} }
public Delegate generate(IList<Instruction> allInstructions, IList<ExceptionHandler> allExceptionHandlers) { public Delegate Generate(IList<Instruction> allInstructions, IList<ExceptionHandler> allExceptionHandlers) {
this.allInstructions = allInstructions; this.allInstructions = allInstructions;
this.allExceptionHandlers = allExceptionHandlers; this.allExceptionHandlers = allExceptionHandlers;
@ -96,37 +96,37 @@ namespace AssemblyData.methodsrewriter {
var lastInstr = allInstructions[allInstructions.Count - 1]; var lastInstr = allInstructions[allInstructions.Count - 1];
ilg = dm.GetILGenerator((int)lastInstr.Offset + lastInstr.GetSize()); ilg = dm.GetILGenerator((int)lastInstr.Offset + lastInstr.GetSize());
initInstrToIndex(); InitInstrToIndex();
initLocals(); InitLocals();
initLabels(); InitLabels();
exceptionHandlersStack = new Stack<ExceptionHandler>(); exceptionHandlersStack = new Stack<ExceptionHandler>();
for (int i = 0; i < allInstructions.Count; i++) { for (int i = 0; i < allInstructions.Count; i++) {
updateExceptionHandlers(i); UpdateExceptionHandlers(i);
var instr = allInstructions[i]; var instr = allInstructions[i];
ilg.MarkLabel(labels[i]); ilg.MarkLabel(labels[i]);
if (instr.Operand is Operand) if (instr.Operand is Operand)
writeSpecialInstr(instr, (Operand)instr.Operand); WriteSpecialInstr(instr, (Operand)instr.Operand);
else else
writeInstr(instr); WriteInstr(instr);
} }
updateExceptionHandlers(-1); UpdateExceptionHandlers(-1);
return dm.CreateDelegate(delegateType); return dm.CreateDelegate(delegateType);
} }
Instruction getExceptionInstruction(int instructionIndex) { Instruction GetExceptionInstruction(int instructionIndex) {
return instructionIndex < 0 ? null : allInstructions[instructionIndex]; return instructionIndex < 0 ? null : allInstructions[instructionIndex];
} }
void updateExceptionHandlers(int instructionIndex) { void UpdateExceptionHandlers(int instructionIndex) {
var instr = getExceptionInstruction(instructionIndex); var instr = GetExceptionInstruction(instructionIndex);
updateExceptionHandlers(instr); UpdateExceptionHandlers(instr);
if (addTryStart(instr)) if (AddTryStart(instr))
updateExceptionHandlers(instr); UpdateExceptionHandlers(instr);
} }
void updateExceptionHandlers(Instruction instr) { void UpdateExceptionHandlers(Instruction instr) {
while (exceptionHandlersStack.Count > 0) { while (exceptionHandlersStack.Count > 0) {
var ex = exceptionHandlersStack.Peek(); var ex = exceptionHandlersStack.Peek();
if (ex.TryEnd == instr) { if (ex.TryEnd == instr) {
@ -137,11 +137,11 @@ namespace AssemblyData.methodsrewriter {
if (ex.HandlerType == ExceptionHandlerType.Finally) if (ex.HandlerType == ExceptionHandlerType.Finally)
ilg.BeginFinallyBlock(); ilg.BeginFinallyBlock();
else else
ilg.BeginCatchBlock(Resolver.getRtType(ex.CatchType)); ilg.BeginCatchBlock(Resolver.GetRtType(ex.CatchType));
} }
if (ex.HandlerEnd == instr) { if (ex.HandlerEnd == instr) {
exceptionHandlersStack.Pop(); exceptionHandlersStack.Pop();
if (exceptionHandlersStack.Count == 0 || !isSameTryBlock(ex, exceptionHandlersStack.Peek())) if (exceptionHandlersStack.Count == 0 || !IsSameTryBlock(ex, exceptionHandlersStack.Peek()))
ilg.EndExceptionBlock(); ilg.EndExceptionBlock();
} }
else else
@ -149,7 +149,7 @@ namespace AssemblyData.methodsrewriter {
} }
} }
bool addTryStart(Instruction instr) { bool AddTryStart(Instruction instr) {
var list = new List<ExceptionHandler>(); var list = new List<ExceptionHandler>();
foreach (var ex in allExceptionHandlers) { foreach (var ex in allExceptionHandlers) {
if (ex.TryStart == instr) if (ex.TryStart == instr)
@ -158,7 +158,7 @@ namespace AssemblyData.methodsrewriter {
list.Reverse(); list.Reverse();
foreach (var ex in list) { foreach (var ex in list) {
if (exceptionHandlersStack.Count == 0 || !isSameTryBlock(ex, exceptionHandlersStack.Peek())) if (exceptionHandlersStack.Count == 0 || !IsSameTryBlock(ex, exceptionHandlersStack.Peek()))
ilg.BeginExceptionBlock(); ilg.BeginExceptionBlock();
exceptionHandlersStack.Push(ex); exceptionHandlersStack.Push(ex);
} }
@ -166,33 +166,33 @@ namespace AssemblyData.methodsrewriter {
return list.Count > 0; return list.Count > 0;
} }
static bool isSameTryBlock(ExceptionHandler ex1, ExceptionHandler ex2) { static bool IsSameTryBlock(ExceptionHandler ex1, ExceptionHandler ex2) {
return ex1.TryStart == ex2.TryStart && ex1.TryEnd == ex2.TryEnd; return ex1.TryStart == ex2.TryStart && ex1.TryEnd == ex2.TryEnd;
} }
void initInstrToIndex() { void InitInstrToIndex() {
instrToIndex = new Dictionary<Instruction, int>(allInstructions.Count); instrToIndex = new Dictionary<Instruction, int>(allInstructions.Count);
for (int i = 0; i < allInstructions.Count; i++) for (int i = 0; i < allInstructions.Count; i++)
instrToIndex[allInstructions[i]] = i; instrToIndex[allInstructions[i]] = i;
} }
void initLocals() { void InitLocals() {
locals = new List<LocalBuilder>(); locals = new List<LocalBuilder>();
foreach (var local in methodInfo.methodDef.Body.Variables) foreach (var local in methodInfo.methodDef.Body.Variables)
locals.Add(ilg.DeclareLocal(Resolver.getRtType(local.Type), local.Type.RemoveModifiers().IsPinned)); locals.Add(ilg.DeclareLocal(Resolver.GetRtType(local.Type), local.Type.RemoveModifiers().IsPinned));
tempObjLocal = ilg.DeclareLocal(typeof(object)); tempObjLocal = ilg.DeclareLocal(typeof(object));
tempObjArrayLocal = ilg.DeclareLocal(typeof(object[])); tempObjArrayLocal = ilg.DeclareLocal(typeof(object[]));
} }
void initLabels() { void InitLabels() {
labels = new List<Label>(allInstructions.Count); labels = new List<Label>(allInstructions.Count);
for (int i = 0; i < allInstructions.Count; i++) for (int i = 0; i < allInstructions.Count; i++)
labels.Add(ilg.DefineLabel()); labels.Add(ilg.DefineLabel());
} }
Type[] getMethodParameterTypes(MethodBase method) { Type[] GetMethodParameterTypes(MethodBase method) {
var list = new List<Type>(); var list = new List<Type>();
if (ResolverUtils.hasThis(method)) if (ResolverUtils.HasThis(method))
list.Add(method.DeclaringType); list.Add(method.DeclaringType);
foreach (var param in method.GetParameters()) foreach (var param in method.GetParameters())
@ -204,19 +204,19 @@ namespace AssemblyData.methodsrewriter {
return list.ToArray(); return list.ToArray();
} }
void writeSpecialInstr(Instruction instr, Operand operand) { void WriteSpecialInstr(Instruction instr, Operand operand) {
BindingFlags flags; BindingFlags flags;
switch (operand.type) { switch (operand.type) {
case Operand.Type.ThisArg: case Operand.Type.ThisArg:
ilg.Emit(convertOpCode(instr.OpCode), (short)thisArgIndex); ilg.Emit(ConvertOpCode(instr.OpCode), (short)thisArgIndex);
break; break;
case Operand.Type.TempObj: case Operand.Type.TempObj:
ilg.Emit(convertOpCode(instr.OpCode), tempObjLocal); ilg.Emit(ConvertOpCode(instr.OpCode), tempObjLocal);
break; break;
case Operand.Type.TempObjArray: case Operand.Type.TempObjArray:
ilg.Emit(convertOpCode(instr.OpCode), tempObjArrayLocal); ilg.Emit(ConvertOpCode(instr.OpCode), tempObjArrayLocal);
break; break;
case Operand.Type.OurMethod: case Operand.Type.OurMethod:
@ -225,19 +225,19 @@ namespace AssemblyData.methodsrewriter {
var ourMethod = methodsRewriter.GetType().GetMethod(methodName, flags); var ourMethod = methodsRewriter.GetType().GetMethod(methodName, flags);
if (ourMethod == null) if (ourMethod == null)
throw new ApplicationException(string.Format("Could not find method {0}", methodName)); throw new ApplicationException(string.Format("Could not find method {0}", methodName));
ilg.Emit(convertOpCode(instr.OpCode), ourMethod); ilg.Emit(ConvertOpCode(instr.OpCode), ourMethod);
break; break;
case Operand.Type.NewMethod: case Operand.Type.NewMethod:
var methodBase = (MethodBase)operand.data; var methodBase = (MethodBase)operand.data;
var delegateType = methodsRewriter.getDelegateType(methodBase); var delegateType = methodsRewriter.GetDelegateType(methodBase);
flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance; flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance;
var invokeMethod = delegateType.GetMethod("Invoke", flags); var invokeMethod = delegateType.GetMethod("Invoke", flags);
ilg.Emit(convertOpCode(instr.OpCode), invokeMethod); ilg.Emit(ConvertOpCode(instr.OpCode), invokeMethod);
break; break;
case Operand.Type.ReflectionType: case Operand.Type.ReflectionType:
ilg.Emit(convertOpCode(instr.OpCode), (Type)operand.data); ilg.Emit(ConvertOpCode(instr.OpCode), (Type)operand.data);
break; break;
default: default:
@ -245,19 +245,19 @@ namespace AssemblyData.methodsrewriter {
} }
} }
Label getLabel(Instruction target) { Label GetLabel(Instruction target) {
return labels[instrToIndex[target]]; return labels[instrToIndex[target]];
} }
Label[] getLabels(Instruction[] targets) { Label[] GetLabels(Instruction[] targets) {
var labels = new Label[targets.Length]; var labels = new Label[targets.Length];
for (int i = 0; i < labels.Length; i++) for (int i = 0; i < labels.Length; i++)
labels[i] = getLabel(targets[i]); labels[i] = GetLabel(targets[i]);
return labels; return labels;
} }
void writeInstr(Instruction instr) { void WriteInstr(Instruction instr) {
var opcode = convertOpCode(instr.OpCode); var opcode = ConvertOpCode(instr.OpCode);
switch (instr.OpCode.OperandType) { switch (instr.OpCode.OperandType) {
case OperandType.InlineNone: case OperandType.InlineNone:
ilg.Emit(opcode); ilg.Emit(opcode);
@ -265,11 +265,11 @@ namespace AssemblyData.methodsrewriter {
case OperandType.InlineBrTarget: case OperandType.InlineBrTarget:
case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineBrTarget:
ilg.Emit(opcode, getLabel((Instruction)instr.Operand)); ilg.Emit(opcode, GetLabel((Instruction)instr.Operand));
break; break;
case OperandType.InlineSwitch: case OperandType.InlineSwitch:
ilg.Emit(opcode, getLabels((Instruction[])instr.Operand)); ilg.Emit(opcode, GetLabels((Instruction[])instr.Operand));
break; break;
case OperandType.ShortInlineI: case OperandType.ShortInlineI:
@ -303,7 +303,7 @@ namespace AssemblyData.methodsrewriter {
case OperandType.InlineType: case OperandType.InlineType:
case OperandType.InlineMethod: case OperandType.InlineMethod:
case OperandType.InlineField: case OperandType.InlineField:
var obj = Resolver.getRtObject((ITokenOperand)instr.Operand); var obj = Resolver.GetRtObject((ITokenOperand)instr.Operand);
if (obj is ConstructorInfo) if (obj is ConstructorInfo)
ilg.Emit(opcode, (ConstructorInfo)obj); ilg.Emit(opcode, (ConstructorInfo)obj);
else if (obj is MethodInfo) else if (obj is MethodInfo)
@ -330,7 +330,7 @@ namespace AssemblyData.methodsrewriter {
} }
} }
ROpCode convertOpCode(OpCode opcode) { ROpCode ConvertOpCode(OpCode opcode) {
ROpCode ropcode; ROpCode ropcode;
if (dnlibToReflection.TryGetValue(opcode, out ropcode)) if (dnlibToReflection.TryGetValue(opcode, out ropcode))
return ropcode; return ropcode;

View File

@ -22,6 +22,6 @@ using System.Reflection;
namespace AssemblyData.methodsrewriter { namespace AssemblyData.methodsrewriter {
interface IMethodsRewriter { interface IMethodsRewriter {
Type getDelegateType(MethodBase methodBase); Type GetDelegateType(MethodBase methodBase);
} }
} }

View File

@ -29,7 +29,7 @@ namespace AssemblyData.methodsrewriter {
this.methodDef = methodDef; this.methodDef = methodDef;
} }
public bool hasInstructions() { public bool HasInstructions() {
return methodDef.Body != null && methodDef.Body.Instructions.Count != 0; return methodDef.Body != null && methodDef.Body.Instructions.Count != 0;
} }

View File

@ -36,10 +36,10 @@ namespace AssemblyData.methodsrewriter {
public MModule(Module module, ModuleDefMD moduleDef) { public MModule(Module module, ModuleDefMD moduleDef) {
this.module = module; this.module = module;
this.moduleDef = moduleDef; this.moduleDef = moduleDef;
initTokenToType(); InitTokenToType();
} }
void initTokenToType() { void InitTokenToType() {
moduleType = moduleDef.Types[0]; moduleType = moduleDef.Types[0];
foreach (var typeDef in moduleDef.GetTypes()) { foreach (var typeDef in moduleDef.GetTypes()) {
int token = (int)typeDef.MDToken.Raw; int token = (int)typeDef.MDToken.Raw;
@ -49,27 +49,27 @@ namespace AssemblyData.methodsrewriter {
} }
catch { catch {
tokenToType[token] = null; tokenToType[token] = null;
typeRefToType.add(typeDef, null); typeRefToType.Add(typeDef, null);
continue; continue;
} }
var mtype = new MType(type, typeDef); var mtype = new MType(type, typeDef);
tokenToType[token] = mtype; tokenToType[token] = mtype;
typeRefToType.add(typeDef, mtype); typeRefToType.Add(typeDef, mtype);
} }
} }
public MType getType(IType typeRef) { public MType GetType(IType typeRef) {
return typeRefToType.find(typeRef); return typeRefToType.Find(typeRef);
} }
public MMethod getMethod(IMethod methodRef) { public MMethod GetMethod(IMethod methodRef) {
var type = getType(methodRef.DeclaringType); var type = GetType(methodRef.DeclaringType);
if (type != null) if (type != null)
return type.getMethod(methodRef); return type.GetMethod(methodRef);
if (!new SigComparer().Equals(moduleType, methodRef.DeclaringType)) if (!new SigComparer().Equals(moduleType, methodRef.DeclaringType))
return null; return null;
initGlobalMethods(); InitGlobalMethods();
foreach (var method in tokenToGlobalMethod.Values) { foreach (var method in tokenToGlobalMethod.Values) {
if (new SigComparer().Equals(methodRef, method.methodDef)) if (new SigComparer().Equals(methodRef, method.methodDef))
return method; return method;
@ -78,14 +78,14 @@ namespace AssemblyData.methodsrewriter {
return null; return null;
} }
public MField getField(IField fieldRef) { public MField GetField(IField fieldRef) {
var type = getType(fieldRef.DeclaringType); var type = GetType(fieldRef.DeclaringType);
if (type != null) if (type != null)
return type.getField(fieldRef); return type.GetField(fieldRef);
if (!new SigComparer().Equals(moduleType, fieldRef.DeclaringType)) if (!new SigComparer().Equals(moduleType, fieldRef.DeclaringType))
return null; return null;
initGlobalFields(); InitGlobalFields();
foreach (var field in tokenToGlobalField.Values) { foreach (var field in tokenToGlobalField.Values) {
if (new SigComparer().Equals(fieldRef, field.fieldDef)) if (new SigComparer().Equals(fieldRef, field.fieldDef))
return field; return field;
@ -94,21 +94,21 @@ namespace AssemblyData.methodsrewriter {
return null; return null;
} }
public MMethod getMethod(MethodBase method) { public MMethod GetMethod(MethodBase method) {
if (method.Module != module) if (method.Module != module)
throw new ApplicationException("Not our module"); throw new ApplicationException("Not our module");
if (method.DeclaringType == null) if (method.DeclaringType == null)
return getGlobalMethod(method); return GetGlobalMethod(method);
var type = tokenToType[method.DeclaringType.MetadataToken]; var type = tokenToType[method.DeclaringType.MetadataToken];
return type.getMethod(method.MetadataToken); return type.GetMethod(method.MetadataToken);
} }
public MMethod getGlobalMethod(MethodBase method) { public MMethod GetGlobalMethod(MethodBase method) {
initGlobalMethods(); InitGlobalMethods();
return tokenToGlobalMethod[method.MetadataToken]; return tokenToGlobalMethod[method.MetadataToken];
} }
void initGlobalMethods() { void InitGlobalMethods() {
if (tokenToGlobalMethod != null) if (tokenToGlobalMethod != null)
return; return;
tokenToGlobalMethod = new Dictionary<int, MMethod>(); tokenToGlobalMethod = new Dictionary<int, MMethod>();
@ -125,7 +125,7 @@ namespace AssemblyData.methodsrewriter {
} }
} }
void initGlobalFields() { void InitGlobalFields() {
if (tokenToGlobalField != null) if (tokenToGlobalField != null)
return; return;
tokenToGlobalField = new Dictionary<int, MField>(); tokenToGlobalField = new Dictionary<int, MField>();

View File

@ -37,27 +37,27 @@ namespace AssemblyData.methodsrewriter {
this.typeDef = typeDef; this.typeDef = typeDef;
} }
public MMethod getMethod(IMethod methodRef) { public MMethod GetMethod(IMethod methodRef) {
initMethods(); InitMethods();
return methodRefToMethod.find(methodRef); return methodRefToMethod.Find(methodRef);
} }
public MField getField(IField fieldRef) { public MField GetField(IField fieldRef) {
initFields(); InitFields();
return fieldRefToField.find(fieldRef); return fieldRefToField.Find(fieldRef);
} }
public MMethod getMethod(int token) { public MMethod GetMethod(int token) {
initMethods(); InitMethods();
return tokenToMethod[token]; return tokenToMethod[token];
} }
public MField getField(int token) { public MField GetField(int token) {
initFields(); InitFields();
return tokenToField[token]; return tokenToField[token];
} }
void initMethods() { void InitMethods() {
if (tokenToMethod != null) if (tokenToMethod != null)
return; return;
tokenToMethod = new Dictionary<int, MMethod>(typeDef.Methods.Count); tokenToMethod = new Dictionary<int, MMethod>(typeDef.Methods.Count);
@ -65,17 +65,17 @@ namespace AssemblyData.methodsrewriter {
var tmpTokenToMethod = new Dictionary<int, MethodBase>(); var tmpTokenToMethod = new Dictionary<int, MethodBase>();
var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
foreach (var m in ResolverUtils.getMethodBases(type, flags)) foreach (var m in ResolverUtils.GetMethodBases(type, flags))
tmpTokenToMethod[m.MetadataToken] = m; tmpTokenToMethod[m.MetadataToken] = m;
foreach (var m in typeDef.Methods) { foreach (var m in typeDef.Methods) {
var token = (int)m.MDToken.Raw; var token = (int)m.MDToken.Raw;
var method = new MMethod(tmpTokenToMethod[token], m); var method = new MMethod(tmpTokenToMethod[token], m);
tokenToMethod[token] = method; tokenToMethod[token] = method;
methodRefToMethod.add(method.methodDef, method); methodRefToMethod.Add(method.methodDef, method);
} }
} }
void initFields() { void InitFields() {
if (tokenToField != null) if (tokenToField != null)
return; return;
tokenToField = new Dictionary<int, MField>(typeDef.Fields.Count); tokenToField = new Dictionary<int, MField>(typeDef.Fields.Count);
@ -89,7 +89,7 @@ namespace AssemblyData.methodsrewriter {
var token = (int)f.MDToken.Raw; var token = (int)f.MDToken.Raw;
var field = new MField(tmpTokenToField[token], f); var field = new MField(tmpTokenToField[token], f);
tokenToField[token] = field; tokenToField[token] = field;
fieldRefToField.add(field.fieldDef, field); fieldRefToField.Add(field.fieldDef, field);
} }
} }

View File

@ -62,16 +62,16 @@ namespace AssemblyData.methodsrewriter {
} }
} }
public MethodBase getNext() { public MethodBase GetNext() {
return methods[next++ % methods.Count]; return methods[next++ % methods.Count];
} }
} }
public MethodBase getMethod(Module module) { public MethodBase GetMethod(Module module) {
MethodsModule methodsModule; MethodsModule methodsModule;
if (!moduleToMethods.TryGetValue(module, out methodsModule)) if (!moduleToMethods.TryGetValue(module, out methodsModule))
moduleToMethods[module] = methodsModule = new MethodsModule(module); moduleToMethods[module] = methodsModule = new MethodsModule(module);
return methodsModule.getNext(); return methodsModule.GetNext();
} }
} }
@ -112,20 +112,20 @@ namespace AssemblyData.methodsrewriter {
this.rewrittenMethodName = rewrittenMethodName; this.rewrittenMethodName = rewrittenMethodName;
} }
public bool isRewrittenMethod(string name) { public bool IsRewrittenMethod(string name) {
return name == rewrittenMethodName; return name == rewrittenMethodName;
} }
public bool isDelegateMethod(string name) { public bool IsDelegateMethod(string name) {
return name == delegateMethodName; return name == delegateMethodName;
} }
} }
public Type getDelegateType(MethodBase methodBase) { public Type GetDelegateType(MethodBase methodBase) {
return realMethodToNewMethod[methodBase].delegateType; return realMethodToNewMethod[methodBase].delegateType;
} }
public RewrittenMethod createDelegate(MethodBase realMethod) { public RewrittenMethod CreateDelegate(MethodBase realMethod) {
var newMethodInfo = realMethodToNewMethod[realMethod]; var newMethodInfo = realMethodToNewMethod[realMethod];
if (newMethodInfo.rewrittenMethod != null) if (newMethodInfo.rewrittenMethod != null)
return newMethodInfo.rewrittenMethod; return newMethodInfo.rewrittenMethod;
@ -135,7 +135,7 @@ namespace AssemblyData.methodsrewriter {
ilg.Emit(ROpCodes.Ldarg_0); ilg.Emit(ROpCodes.Ldarg_0);
ilg.Emit(ROpCodes.Ldc_I4, newMethodInfo.delegateIndex); ilg.Emit(ROpCodes.Ldc_I4, newMethodInfo.delegateIndex);
ilg.Emit(ROpCodes.Call, GetType().GetMethod("rtGetDelegateInstance", BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance)); ilg.Emit(ROpCodes.Call, GetType().GetMethod("RtGetDelegateInstance", BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance));
ilg.Emit(ROpCodes.Castclass, newMethodInfo.delegateType); ilg.Emit(ROpCodes.Castclass, newMethodInfo.delegateType);
var args = newMethodInfo.oldMethod.GetParameters(); var args = newMethodInfo.oldMethod.GetParameters();
@ -156,7 +156,7 @@ namespace AssemblyData.methodsrewriter {
var flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance; var flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance;
var invokeMethod = newMethodInfo.delegateType.GetMethod("Invoke", flags); var invokeMethod = newMethodInfo.delegateType.GetMethod("Invoke", flags);
ilg.Emit(ROpCodes.Call, invokeMethod); ilg.Emit(ROpCodes.Call, invokeMethod);
if (ResolverUtils.getReturnType(newMethodInfo.oldMethod) == typeof(void)) if (ResolverUtils.GetReturnType(newMethodInfo.oldMethod) == typeof(void))
ilg.Emit(ROpCodes.Ldnull); ilg.Emit(ROpCodes.Ldnull);
ilg.Emit(ROpCodes.Ret); ilg.Emit(ROpCodes.Ret);
@ -164,50 +164,50 @@ namespace AssemblyData.methodsrewriter {
return newMethodInfo.rewrittenMethod; return newMethodInfo.rewrittenMethod;
} }
public void setCaller(RewrittenMethod rewrittenMethod, MethodBase caller) { public void SetCaller(RewrittenMethod rewrittenMethod, MethodBase caller) {
if (caller == null) if (caller == null)
return; return;
var newMethodInfo = getNewMethodInfo(rewrittenMethod.Method.Name); var newMethodInfo = GetNewMethodInfo(rewrittenMethod.Method.Name);
newStackMethodDict[newMethodInfo] = caller; newStackMethodDict[newMethodInfo] = caller;
} }
string getDelegateMethodName(MethodBase method) { string GetDelegateMethodName(MethodBase method) {
string name = null; string name = null;
do { do {
name = string.Format(" {0} {1:X8} DMN {2:X8} ", method.Name, method.MetadataToken, Utils.getRandomUint()); name = string.Format(" {0} {1:X8} DMN {2:X8} ", method.Name, method.MetadataToken, Utils.GetRandomUint());
} while (delegateNameToNewMethodInfo.ContainsKey(name)); } while (delegateNameToNewMethodInfo.ContainsKey(name));
return name; return name;
} }
public void createMethod(MethodBase realMethod) { public void CreateMethod(MethodBase realMethod) {
if (realMethodToNewMethod.ContainsKey(realMethod)) if (realMethodToNewMethod.ContainsKey(realMethod))
return; return;
var newMethodInfo = new NewMethodInfo(realMethod, newMethodInfos.Count, getDelegateMethodName(realMethod), getDelegateMethodName(realMethod)); var newMethodInfo = new NewMethodInfo(realMethod, newMethodInfos.Count, GetDelegateMethodName(realMethod), GetDelegateMethodName(realMethod));
newMethodInfos.Add(newMethodInfo); newMethodInfos.Add(newMethodInfo);
delegateNameToNewMethodInfo[newMethodInfo.delegateMethodName] = newMethodInfo; delegateNameToNewMethodInfo[newMethodInfo.delegateMethodName] = newMethodInfo;
delegateNameToNewMethodInfo[newMethodInfo.rewrittenMethodName] = newMethodInfo; delegateNameToNewMethodInfo[newMethodInfo.rewrittenMethodName] = newMethodInfo;
realMethodToNewMethod[realMethod] = newMethodInfo; realMethodToNewMethod[realMethod] = newMethodInfo;
var moduleInfo = Resolver.loadAssembly(realMethod.Module); var moduleInfo = Resolver.LoadAssembly(realMethod.Module);
var methodInfo = moduleInfo.getMethod(realMethod); var methodInfo = moduleInfo.GetMethod(realMethod);
if (!methodInfo.hasInstructions()) if (!methodInfo.HasInstructions())
throw new ApplicationException(string.Format("Method {0} ({1:X8}) has no body", methodInfo.methodDef, methodInfo.methodDef.MDToken.Raw)); throw new ApplicationException(string.Format("Method {0} ({1:X8}) has no body", methodInfo.methodDef, methodInfo.methodDef.MDToken.Raw));
var codeGenerator = new CodeGenerator(this, newMethodInfo.delegateMethodName); var codeGenerator = new CodeGenerator(this, newMethodInfo.delegateMethodName);
codeGenerator.setMethodInfo(methodInfo); codeGenerator.SetMethodInfo(methodInfo);
newMethodInfo.delegateType = codeGenerator.DelegateType; newMethodInfo.delegateType = codeGenerator.DelegateType;
var blocks = new Blocks(methodInfo.methodDef); var blocks = new Blocks(methodInfo.methodDef);
foreach (var block in blocks.MethodBlocks.getAllBlocks()) foreach (var block in blocks.MethodBlocks.GetAllBlocks())
update(block, newMethodInfo); Update(block, newMethodInfo);
IList<Instruction> allInstructions; IList<Instruction> allInstructions;
IList<ExceptionHandler> allExceptionHandlers; IList<ExceptionHandler> allExceptionHandlers;
blocks.getCode(out allInstructions, out allExceptionHandlers); blocks.GetCode(out allInstructions, out allExceptionHandlers);
newMethodInfo.delegateInstance = codeGenerator.generate(allInstructions, allExceptionHandlers); newMethodInfo.delegateInstance = codeGenerator.Generate(allInstructions, allExceptionHandlers);
} }
static Instruction create(OpCode opcode, object operand) { static Instruction Create(OpCode opcode, object operand) {
return new Instruction { return new Instruction {
OpCode = opcode, OpCode = opcode,
Operand = operand, Operand = operand,
@ -215,17 +215,17 @@ namespace AssemblyData.methodsrewriter {
} }
// Inserts ldarg THIS, and returns number of instructions inserted at 'i' // Inserts ldarg THIS, and returns number of instructions inserted at 'i'
int insertLoadThis(Block block, int i) { int InsertLoadThis(Block block, int i) {
block.insert(i, create(OpCodes.Ldarg, new Operand(Operand.Type.ThisArg))); block.Insert(i, Create(OpCodes.Ldarg, new Operand(Operand.Type.ThisArg)));
return 1; return 1;
} }
int insertCallOurMethod(Block block, int i, string methodName) { int InsertCallOurMethod(Block block, int i, string methodName) {
block.insert(i, create(OpCodes.Call, new Operand(Operand.Type.OurMethod, methodName))); block.Insert(i, Create(OpCodes.Call, new Operand(Operand.Type.OurMethod, methodName)));
return 1; return 1;
} }
void update(Block block, NewMethodInfo currentMethodInfo) { void Update(Block block, NewMethodInfo currentMethodInfo) {
var instrs = block.Instructions; var instrs = block.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
var instr = instrs[i]; var instr = instrs[i];
@ -233,14 +233,14 @@ namespace AssemblyData.methodsrewriter {
var ctor = (IMethod)instr.Operand; var ctor = (IMethod)instr.Operand;
var ctorTypeFullName = ctor.DeclaringType.FullName; var ctorTypeFullName = ctor.DeclaringType.FullName;
if (ctorTypeFullName == "System.Diagnostics.StackTrace") { if (ctorTypeFullName == "System.Diagnostics.StackTrace") {
insertLoadThis(block, i + 1); InsertLoadThis(block, i + 1);
insertCallOurMethod(block, i + 2, "static_rtFixStackTrace"); InsertCallOurMethod(block, i + 2, "static_RtFixStackTrace");
i += 2; i += 2;
continue; continue;
} }
else if (ctorTypeFullName == "System.Diagnostics.StackFrame") { else if (ctorTypeFullName == "System.Diagnostics.StackFrame") {
insertLoadThis(block, i + 1); InsertLoadThis(block, i + 1);
insertCallOurMethod(block, i + 2, "static_rtFixStackFrame"); InsertCallOurMethod(block, i + 2, "static_RtFixStackFrame");
i += 2; i += 2;
continue; continue;
} }
@ -251,67 +251,67 @@ namespace AssemblyData.methodsrewriter {
if (calledMethod.DeclaringType.DefinitionAssembly.IsCorLib()) { if (calledMethod.DeclaringType.DefinitionAssembly.IsCorLib()) {
var calledMethodFullName = calledMethod.FullName; var calledMethodFullName = calledMethod.FullName;
if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetAssembly(System.Type)") { if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetAssembly(System.Type)") {
block.replace(i, 1, OpCodes.Nop.ToInstruction()); block.Replace(i, 1, OpCodes.Nop.ToInstruction());
insertLoadThis(block, i + 1); InsertLoadThis(block, i + 1);
insertCallOurMethod(block, i + 2, "static_rtGetAssembly_TypeArg"); InsertCallOurMethod(block, i + 2, "static_RtGetAssembly_TypeArg");
i += 2; i += 2;
continue; continue;
} }
else if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetCallingAssembly()" || else if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetCallingAssembly()" ||
calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetEntryAssembly()" || calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetEntryAssembly()" ||
calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetExecutingAssembly()") { calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetExecutingAssembly()") {
block.replace(i, 1, OpCodes.Nop.ToInstruction()); block.Replace(i, 1, OpCodes.Nop.ToInstruction());
insertLoadThis(block, i + 1); InsertLoadThis(block, i + 1);
block.insert(i + 2, OpCodes.Ldc_I4.ToInstruction(currentMethodInfo.delegateIndex)); block.Insert(i + 2, OpCodes.Ldc_I4.ToInstruction(currentMethodInfo.delegateIndex));
insertCallOurMethod(block, i + 3, "rtGetAssembly"); InsertCallOurMethod(block, i + 3, "RtGetAssembly");
i += 3; i += 3;
continue; continue;
} }
} }
var method = Resolver.getMethod((IMethod)instr.Operand); var method = Resolver.GetMethod((IMethod)instr.Operand);
if (method != null) { if (method != null) {
createMethod(method.methodBase); CreateMethod(method.methodBase);
var newMethodInfo = realMethodToNewMethod[method.methodBase]; var newMethodInfo = realMethodToNewMethod[method.methodBase];
block.replace(i, 1, OpCodes.Nop.ToInstruction()); block.Replace(i, 1, OpCodes.Nop.ToInstruction());
int n = i + 1; int n = i + 1;
// Pop all pushed args to a temp array // Pop all pushed args to a temp array
var mparams = getParameters(method.methodDef); var mparams = GetParameters(method.methodDef);
if (mparams.Count > 0) { if (mparams.Count > 0) {
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(mparams.Count)); block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(mparams.Count));
var objectType = method.methodDef.DeclaringType.Module.CorLibTypes.Object; var objectType = method.methodDef.DeclaringType.Module.CorLibTypes.Object;
block.insert(n++, OpCodes.Newarr.ToInstruction(objectType)); block.Insert(n++, OpCodes.Newarr.ToInstruction(objectType));
block.insert(n++, create(OpCodes.Stloc, new Operand(Operand.Type.TempObjArray))); block.Insert(n++, Create(OpCodes.Stloc, new Operand(Operand.Type.TempObjArray)));
for (int j = mparams.Count - 1; j >= 0; j--) { for (int j = mparams.Count - 1; j >= 0; j--) {
var argType = mparams[j]; var argType = mparams[j];
if (argType.RemovePinnedAndModifiers().IsValueType) if (argType.RemovePinnedAndModifiers().IsValueType)
block.insert(n++, OpCodes.Box.ToInstruction(((TypeDefOrRefSig)argType).TypeDefOrRef)); block.Insert(n++, OpCodes.Box.ToInstruction(((TypeDefOrRefSig)argType).TypeDefOrRef));
block.insert(n++, create(OpCodes.Stloc, new Operand(Operand.Type.TempObj))); block.Insert(n++, Create(OpCodes.Stloc, new Operand(Operand.Type.TempObj)));
block.insert(n++, create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray))); block.Insert(n++, Create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray)));
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(j)); block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(j));
block.insert(n++, create(OpCodes.Ldloc, new Operand(Operand.Type.TempObj))); block.Insert(n++, Create(OpCodes.Ldloc, new Operand(Operand.Type.TempObj)));
block.insert(n++, OpCodes.Stelem_Ref.ToInstruction()); block.Insert(n++, OpCodes.Stelem_Ref.ToInstruction());
} }
} }
// Push delegate instance // Push delegate instance
insertLoadThis(block, n++); InsertLoadThis(block, n++);
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(newMethodInfo.delegateIndex)); block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(newMethodInfo.delegateIndex));
insertCallOurMethod(block, n++, "rtGetDelegateInstance"); InsertCallOurMethod(block, n++, "RtGetDelegateInstance");
block.insert(n++, create(OpCodes.Castclass, new Operand(Operand.Type.ReflectionType, newMethodInfo.delegateType))); block.Insert(n++, Create(OpCodes.Castclass, new Operand(Operand.Type.ReflectionType, newMethodInfo.delegateType)));
// Push all popped args // Push all popped args
if (mparams.Count > 0) { if (mparams.Count > 0) {
for (int j = 0; j < mparams.Count; j++) { for (int j = 0; j < mparams.Count; j++) {
block.insert(n++, create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray))); block.Insert(n++, Create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray)));
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(j)); block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(j));
block.insert(n++, OpCodes.Ldelem_Ref.ToInstruction()); block.Insert(n++, OpCodes.Ldelem_Ref.ToInstruction());
var argType = mparams[j]; var argType = mparams[j];
if (argType.RemovePinnedAndModifiers().IsValueType) if (argType.RemovePinnedAndModifiers().IsValueType)
block.insert(n++, OpCodes.Unbox_Any.ToInstruction(((TypeDefOrRefSig)argType).TypeDefOrRef)); block.Insert(n++, OpCodes.Unbox_Any.ToInstruction(((TypeDefOrRefSig)argType).TypeDefOrRef));
else { else {
// Don't cast it to its correct type. This will sometimes cause // Don't cast it to its correct type. This will sometimes cause
// an exception in some EF obfuscated assembly since we'll be // an exception in some EF obfuscated assembly since we'll be
@ -322,8 +322,8 @@ namespace AssemblyData.methodsrewriter {
} }
} }
insertLoadThis(block, n++); InsertLoadThis(block, n++);
block.insert(n++, create(OpCodes.Call, new Operand(Operand.Type.NewMethod, method.methodBase))); block.Insert(n++, Create(OpCodes.Call, new Operand(Operand.Type.NewMethod, method.methodBase)));
i = n - 1; i = n - 1;
continue; continue;
} }
@ -331,48 +331,48 @@ namespace AssemblyData.methodsrewriter {
} }
} }
static IList<TypeSig> getParameters(MethodDef method) { static IList<TypeSig> GetParameters(MethodDef method) {
var list = new List<TypeSig>(method.Parameters.Count); var list = new List<TypeSig>(method.Parameters.Count);
for (int i = 0; i < method.Parameters.Count; i++) for (int i = 0; i < method.Parameters.Count; i++)
list.Add(method.Parameters[i].Type); list.Add(method.Parameters[i].Type);
return list; return list;
} }
static FieldInfo getStackTraceStackFramesField() { static FieldInfo GgetStackTraceStackFramesField() {
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
return ResolverUtils.getFieldThrow(typeof(StackTrace), typeof(StackFrame[]), flags, "Could not find StackTrace's frames (StackFrame[]) field"); return ResolverUtils.GetFieldThrow(typeof(StackTrace), typeof(StackFrame[]), flags, "Could not find StackTrace's frames (StackFrame[]) field");
} }
static FieldInfo getStackFrameMethodField() { static FieldInfo GetStackFrameMethodField() {
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
return ResolverUtils.getFieldThrow(typeof(StackFrame), typeof(MethodBase), flags, "Could not find StackFrame's method (MethodBase) field"); return ResolverUtils.GetFieldThrow(typeof(StackFrame), typeof(MethodBase), flags, "Could not find StackFrame's method (MethodBase) field");
} }
static void writeMethodBase(StackFrame frame, MethodBase method) { static void WriteMethodBase(StackFrame frame, MethodBase method) {
var methodField = getStackFrameMethodField(); var methodField = GetStackFrameMethodField();
methodField.SetValue(frame, method); methodField.SetValue(frame, method);
if (frame.GetMethod() != method) if (frame.GetMethod() != method)
throw new ApplicationException(string.Format("Could not set new method: {0}", method)); throw new ApplicationException(string.Format("Could not set new method: {0}", method));
} }
NewMethodInfo getNewMethodInfo(string name) { NewMethodInfo GetNewMethodInfo(string name) {
NewMethodInfo info; NewMethodInfo info;
delegateNameToNewMethodInfo.TryGetValue(name, out info); delegateNameToNewMethodInfo.TryGetValue(name, out info);
return info; return info;
} }
// Called after the StackTrace ctor has been called. // Called after the StackTrace ctor has been called.
static StackTrace static_rtFixStackTrace(StackTrace stackTrace, MethodsRewriter self) { static StackTrace static_RtFixStackTrace(StackTrace stackTrace, MethodsRewriter self) {
return self.rtFixStackTrace(stackTrace); return self.RtFixStackTrace(stackTrace);
} }
StackTrace rtFixStackTrace(StackTrace stackTrace) { StackTrace RtFixStackTrace(StackTrace stackTrace) {
var framesField = getStackTraceStackFramesField(); var framesField = GgetStackTraceStackFramesField();
var frames = (StackFrame[])framesField.GetValue(stackTrace); var frames = (StackFrame[])framesField.GetValue(stackTrace);
var newFrames = new List<StackFrame>(frames.Length); var newFrames = new List<StackFrame>(frames.Length);
foreach (var frame in frames) { foreach (var frame in frames) {
fixStackFrame(frame); FixStackFrame(frame);
newFrames.Add(frame); newFrames.Add(frame);
} }
@ -380,52 +380,52 @@ namespace AssemblyData.methodsrewriter {
return stackTrace; return stackTrace;
} }
static StackFrame static_rtFixStackFrame(StackFrame stackFrame, MethodsRewriter self) { static StackFrame static_RtFixStackFrame(StackFrame stackFrame, MethodsRewriter self) {
return self.rtFixStackFrame(stackFrame); return self.RtFixStackFrame(stackFrame);
} }
StackFrame rtFixStackFrame(StackFrame frame) { StackFrame RtFixStackFrame(StackFrame frame) {
fixStackFrame(frame); FixStackFrame(frame);
return frame; return frame;
} }
void fixStackFrame(StackFrame frame) { void FixStackFrame(StackFrame frame) {
var method = frame.GetMethod(); var method = frame.GetMethod();
var info = getNewMethodInfo(method.Name); var info = GetNewMethodInfo(method.Name);
if (info == null) if (info == null)
return; return;
MethodBase stackMethod; MethodBase stackMethod;
if (newStackMethodDict.TryGetValue(info, out stackMethod)) { if (newStackMethodDict.TryGetValue(info, out stackMethod)) {
writeMethodBase(frame, stackMethod); WriteMethodBase(frame, stackMethod);
} }
else if (info.isRewrittenMethod(method.Name)) { else if (info.IsRewrittenMethod(method.Name)) {
// Write random method from the same module // Write random method from the same module
writeMethodBase(frame, methodsFinder.getMethod(info.oldMethod.Module)); WriteMethodBase(frame, methodsFinder.GetMethod(info.oldMethod.Module));
} }
else if (info.isDelegateMethod(method.Name)) { else if (info.IsDelegateMethod(method.Name)) {
// Write original method // Write original method
writeMethodBase(frame, info.oldMethod); WriteMethodBase(frame, info.oldMethod);
} }
else else
throw new ApplicationException("BUG: Shouldn't be here"); throw new ApplicationException("BUG: Shouldn't be here");
} }
// Called when the code calls GetCallingAssembly(), GetEntryAssembly(), or GetExecutingAssembly() // Called when the code calls GetCallingAssembly(), GetEntryAssembly(), or GetExecutingAssembly()
Assembly rtGetAssembly(int delegateIndex) { Assembly RtGetAssembly(int delegateIndex) {
return newMethodInfos[delegateIndex].oldMethod.Module.Assembly; return newMethodInfos[delegateIndex].oldMethod.Module.Assembly;
} }
// Called when the code calls GetAssembly(Type) // Called when the code calls GetAssembly(Type)
static Assembly static_rtGetAssembly_TypeArg(Type type, MethodsRewriter self) { static Assembly static_RtGetAssembly_TypeArg(Type type, MethodsRewriter self) {
return self.rtGetAssembly_TypeArg(type); return self.RtGetAssembly_TypeArg(type);
} }
Assembly rtGetAssembly_TypeArg(Type type) { Assembly RtGetAssembly_TypeArg(Type type) {
return Assembly.GetAssembly(type); return Assembly.GetAssembly(type);
} }
Delegate rtGetDelegateInstance(int delegateIndex) { Delegate RtGetDelegateInstance(int delegateIndex) {
return newMethodInfos[delegateIndex].delegateInstance; return newMethodInfos[delegateIndex].delegateInstance;
} }
} }

View File

@ -28,7 +28,7 @@ namespace AssemblyData.methodsrewriter {
static Dictionary<string, AssemblyResolver> assemblyResolvers = new Dictionary<string, AssemblyResolver>(StringComparer.Ordinal); static Dictionary<string, AssemblyResolver> assemblyResolvers = new Dictionary<string, AssemblyResolver>(StringComparer.Ordinal);
static Dictionary<Module, MModule> modules = new Dictionary<Module, MModule>(); static Dictionary<Module, MModule> modules = new Dictionary<Module, MModule>();
public static MModule loadAssembly(Module module) { public static MModule LoadAssembly(Module module) {
MModule info; MModule info;
if (modules.TryGetValue(module, out info)) if (modules.TryGetValue(module, out info))
return info; return info;
@ -38,7 +38,7 @@ namespace AssemblyData.methodsrewriter {
return info; return info;
} }
static MModule getModule(ModuleDef moduleDef) { static MModule GetModule(ModuleDef moduleDef) {
foreach (var mm in modules.Values) { foreach (var mm in modules.Values) {
if (mm.moduleDef == moduleDef) if (mm.moduleDef == moduleDef)
return mm; return mm;
@ -46,7 +46,7 @@ namespace AssemblyData.methodsrewriter {
return null; return null;
} }
static MModule getModule(AssemblyRef asmRef) { static MModule GetModule(AssemblyRef asmRef) {
foreach (var mm in modules.Values) { foreach (var mm in modules.Values) {
var asm = mm.moduleDef.Assembly; var asm = mm.moduleDef.Assembly;
if (asm != null && asm.FullName == asmRef.FullName) if (asm != null && asm.FullName == asmRef.FullName)
@ -55,83 +55,83 @@ namespace AssemblyData.methodsrewriter {
return null; return null;
} }
public static MModule getModule(IScope scope) { public static MModule GetModule(IScope scope) {
if (scope.ScopeType == ScopeType.ModuleDef) if (scope.ScopeType == ScopeType.ModuleDef)
return getModule((ModuleDef)scope); return GetModule((ModuleDef)scope);
else if (scope.ScopeType == ScopeType.AssemblyRef) else if (scope.ScopeType == ScopeType.AssemblyRef)
return getModule((AssemblyRef)scope); return GetModule((AssemblyRef)scope);
return null; return null;
} }
public static MType getType(IType typeRef) { public static MType GetType(IType typeRef) {
if (typeRef == null) if (typeRef == null)
return null; return null;
var module = getModule(typeRef.Scope); var module = GetModule(typeRef.Scope);
if (module != null) if (module != null)
return module.getType(typeRef); return module.GetType(typeRef);
return null; return null;
} }
public static MMethod getMethod(IMethod methodRef) { public static MMethod GetMethod(IMethod methodRef) {
if (methodRef == null) if (methodRef == null)
return null; return null;
var module = getModule(methodRef.DeclaringType.Scope); var module = GetModule(methodRef.DeclaringType.Scope);
if (module != null) if (module != null)
return module.getMethod(methodRef); return module.GetMethod(methodRef);
return null; return null;
} }
public static MField getField(IField fieldRef) { public static MField GetField(IField fieldRef) {
if (fieldRef == null) if (fieldRef == null)
return null; return null;
var module = getModule(fieldRef.DeclaringType.Scope); var module = GetModule(fieldRef.DeclaringType.Scope);
if (module != null) if (module != null)
return module.getField(fieldRef); return module.GetField(fieldRef);
return null; return null;
} }
public static object getRtObject(ITokenOperand memberRef) { public static object GetRtObject(ITokenOperand memberRef) {
if (memberRef == null) if (memberRef == null)
return null; return null;
var tdr = memberRef as ITypeDefOrRef; var tdr = memberRef as ITypeDefOrRef;
if (tdr != null) if (tdr != null)
return getRtType(tdr); return GetRtType(tdr);
var field = memberRef as IField; var field = memberRef as IField;
if (field != null && field.FieldSig != null) if (field != null && field.FieldSig != null)
return getRtField(field); return GetRtField(field);
var method = memberRef as IMethod; var method = memberRef as IMethod;
if (method != null && method.MethodSig != null) if (method != null && method.MethodSig != null)
return getRtMethod(method); return GetRtMethod(method);
throw new ApplicationException(string.Format("Unknown MemberRef: {0}", memberRef)); throw new ApplicationException(string.Format("Unknown MemberRef: {0}", memberRef));
} }
public static Type getRtType(IType typeRef) { public static Type GetRtType(IType typeRef) {
var mtype = getType(typeRef); var mtype = GetType(typeRef);
if (mtype != null) if (mtype != null)
return mtype.type; return mtype.type;
return Resolver.resolve(typeRef); return Resolver.Resolve(typeRef);
} }
public static FieldInfo getRtField(IField fieldRef) { public static FieldInfo GetRtField(IField fieldRef) {
var mfield = getField(fieldRef); var mfield = GetField(fieldRef);
if (mfield != null) if (mfield != null)
return mfield.fieldInfo; return mfield.fieldInfo;
return Resolver.resolve(fieldRef); return Resolver.Resolve(fieldRef);
} }
public static MethodBase getRtMethod(IMethod methodRef) { public static MethodBase GetRtMethod(IMethod methodRef) {
var mmethod = getMethod(methodRef); var mmethod = GetMethod(methodRef);
if (mmethod != null) if (mmethod != null)
return mmethod.methodBase; return mmethod.methodBase;
return Resolver.resolve(methodRef); return Resolver.Resolve(methodRef);
} }
static AssemblyResolver getAssemblyResolver(ITypeDefOrRef type) { static AssemblyResolver GetAssemblyResolver(ITypeDefOrRef type) {
var asmName = type.DefinitionAssembly.FullName; var asmName = type.DefinitionAssembly.FullName;
AssemblyResolver resolver; AssemblyResolver resolver;
if (!assemblyResolvers.TryGetValue(asmName, out resolver)) if (!assemblyResolvers.TryGetValue(asmName, out resolver))
@ -139,38 +139,38 @@ namespace AssemblyData.methodsrewriter {
return resolver; return resolver;
} }
static Type resolve(IType typeRef) { static Type Resolve(IType typeRef) {
if (typeRef == null) if (typeRef == null)
return null; return null;
var scopeType = typeRef.ScopeType; var scopeType = typeRef.ScopeType;
var resolver = getAssemblyResolver(scopeType); var resolver = GetAssemblyResolver(scopeType);
var resolvedType = resolver.resolve(scopeType); var resolvedType = resolver.Resolve(scopeType);
if (resolvedType != null) if (resolvedType != null)
return fixType(typeRef, resolvedType); return FixType(typeRef, resolvedType);
throw new ApplicationException(string.Format("Could not resolve type {0} ({1:X8}) in assembly {2}", typeRef, typeRef.MDToken.Raw, resolver)); throw new ApplicationException(string.Format("Could not resolve type {0} ({1:X8}) in assembly {2}", typeRef, typeRef.MDToken.Raw, resolver));
} }
static FieldInfo resolve(IField fieldRef) { static FieldInfo Resolve(IField fieldRef) {
if (fieldRef == null) if (fieldRef == null)
return null; return null;
var resolver = getAssemblyResolver(fieldRef.DeclaringType); var resolver = GetAssemblyResolver(fieldRef.DeclaringType);
var fieldInfo = resolver.resolve(fieldRef); var fieldInfo = resolver.Resolve(fieldRef);
if (fieldInfo != null) if (fieldInfo != null)
return fieldInfo; return fieldInfo;
throw new ApplicationException(string.Format("Could not resolve field {0} ({1:X8}) in assembly {2}", fieldRef, fieldRef.MDToken.Raw, resolver)); throw new ApplicationException(string.Format("Could not resolve field {0} ({1:X8}) in assembly {2}", fieldRef, fieldRef.MDToken.Raw, resolver));
} }
static MethodBase resolve(IMethod methodRef) { static MethodBase Resolve(IMethod methodRef) {
if (methodRef == null) if (methodRef == null)
return null; return null;
var resolver = getAssemblyResolver(methodRef.DeclaringType); var resolver = GetAssemblyResolver(methodRef.DeclaringType);
var methodBase = resolver.resolve(methodRef); var methodBase = resolver.Resolve(methodRef);
if (methodBase != null) if (methodBase != null)
return methodBase; return methodBase;
throw new ApplicationException(string.Format("Could not resolve method {0} ({1:X8}) in assembly {2}", methodRef, methodRef.MDToken.Raw, resolver)); throw new ApplicationException(string.Format("Could not resolve method {0} ({1:X8}) in assembly {2}", methodRef, methodRef.MDToken.Raw, resolver));
} }
static Type fixType(IType typeRef, Type type) { static Type FixType(IType typeRef, Type type) {
var sig = typeRef as TypeSig; var sig = typeRef as TypeSig;
if (sig == null) { if (sig == null) {
var ts = typeRef as TypeSpec; var ts = typeRef as TypeSpec;
@ -203,7 +203,7 @@ namespace AssemblyData.methodsrewriter {
var arg = git.GenericArguments[i]; var arg = git.GenericArguments[i];
if (!(arg is GenericSig)) if (!(arg is GenericSig))
isGenericTypeDef = false; isGenericTypeDef = false;
args[i] = Resolver.resolve(arg); args[i] = Resolver.Resolve(arg);
} }
if (!isGenericTypeDef) if (!isGenericTypeDef)
type = type.MakeGenericType(args); type = type.MakeGenericType(args);

View File

@ -25,27 +25,27 @@ using de4dot.blocks;
namespace AssemblyData.methodsrewriter { namespace AssemblyData.methodsrewriter {
static class ResolverUtils { static class ResolverUtils {
public static bool compareTypes(Type a, IType b) { public static bool CompareTypes(Type a, IType b) {
return new SigComparer().Equals(a, b); return new SigComparer().Equals(a, b);
} }
public static bool compareFields(FieldInfo a, IField b) { public static bool CompareFields(FieldInfo a, IField b) {
return new SigComparer().Equals(a, b); return new SigComparer().Equals(a, b);
} }
public static bool hasThis(MethodBase method) { public static bool HasThis(MethodBase method) {
return (method.CallingConvention & CallingConventions.HasThis) != 0; return (method.CallingConvention & CallingConventions.HasThis) != 0;
} }
public static bool explicitThis(MethodBase method) { public static bool ExplicitThis(MethodBase method) {
return (method.CallingConvention & CallingConventions.ExplicitThis) != 0; return (method.CallingConvention & CallingConventions.ExplicitThis) != 0;
} }
public static bool compareMethods(MethodBase a, IMethod b) { public static bool CompareMethods(MethodBase a, IMethod b) {
return new SigComparer().Equals(a, b); return new SigComparer().Equals(a, b);
} }
public static Type getReturnType(MethodBase methodBase) { public static Type GetReturnType(MethodBase methodBase) {
var methodInfo = methodBase as MethodInfo; var methodInfo = methodBase as MethodInfo;
if (methodInfo != null) if (methodInfo != null)
return methodInfo.ReturnType; return methodInfo.ReturnType;
@ -57,7 +57,7 @@ namespace AssemblyData.methodsrewriter {
throw new ApplicationException(string.Format("Could not figure out return type: {0} ({1:X8})", methodBase, methodBase.MetadataToken)); throw new ApplicationException(string.Format("Could not figure out return type: {0} ({1:X8})", methodBase, methodBase.MetadataToken));
} }
public static Type[] getGenericArguments(MethodBase methodBase) { public static Type[] GetGenericArguments(MethodBase methodBase) {
try { try {
return methodBase.GetGenericArguments(); return methodBase.GetGenericArguments();
} }
@ -66,7 +66,7 @@ namespace AssemblyData.methodsrewriter {
} }
} }
public static IEnumerable<MethodBase> getMethodBases(Type type, BindingFlags flags) { public static IEnumerable<MethodBase> GetMethodBases(Type type, BindingFlags flags) {
if (type.TypeInitializer != null) if (type.TypeInitializer != null)
yield return type.TypeInitializer; yield return type.TypeInitializer;
foreach (var ctor in type.GetConstructors(flags)) foreach (var ctor in type.GetConstructors(flags))
@ -96,7 +96,7 @@ namespace AssemblyData.methodsrewriter {
} }
static Dictionary<CachedMemberInfo, FieldInfo> cachedFieldInfos = new Dictionary<CachedMemberInfo, FieldInfo>(); static Dictionary<CachedMemberInfo, FieldInfo> cachedFieldInfos = new Dictionary<CachedMemberInfo, FieldInfo>();
public static FieldInfo getField(Type type, Type fieldType, BindingFlags flags) { public static FieldInfo GetField(Type type, Type fieldType, BindingFlags flags) {
var key = new CachedMemberInfo(type, fieldType); var key = new CachedMemberInfo(type, fieldType);
FieldInfo fieldInfo; FieldInfo fieldInfo;
if (cachedFieldInfos.TryGetValue(key, out fieldInfo)) if (cachedFieldInfos.TryGetValue(key, out fieldInfo))
@ -111,14 +111,14 @@ namespace AssemblyData.methodsrewriter {
return null; return null;
} }
public static FieldInfo getFieldThrow(Type type, Type fieldType, BindingFlags flags, string msg) { public static FieldInfo GetFieldThrow(Type type, Type fieldType, BindingFlags flags, string msg) {
var info = getField(type, fieldType, flags); var info = GetField(type, fieldType, flags);
if (info != null) if (info != null)
return info; return info;
throw new ApplicationException(msg); throw new ApplicationException(msg);
} }
public static List<FieldInfo> getFields(Type type, Type fieldType, BindingFlags flags) { public static List<FieldInfo> GetFields(Type type, Type fieldType, BindingFlags flags) {
var list = new List<FieldInfo>(); var list = new List<FieldInfo>();
foreach (var field in type.GetFields(flags)) { foreach (var field in type.GetFields(flags)) {
if (field.FieldType == fieldType) if (field.FieldType == fieldType)
@ -127,7 +127,7 @@ namespace AssemblyData.methodsrewriter {
return list; return list;
} }
public static Type makeInstanceType(Type type, ITypeDefOrRef typeRef) { public static Type MakeInstanceType(Type type, ITypeDefOrRef typeRef) {
var ts = typeRef as TypeSpec; var ts = typeRef as TypeSpec;
if (ts == null) if (ts == null)
return type; return type;
@ -140,7 +140,7 @@ namespace AssemblyData.methodsrewriter {
var arg = git.GenericArguments[i]; var arg = git.GenericArguments[i];
if (!(arg is GenericSig)) if (!(arg is GenericSig))
isTypeDef = false; isTypeDef = false;
types[i] = Resolver.getRtType(arg); types[i] = Resolver.GetRtType(arg);
} }
if (isTypeDef) if (isTypeDef)
return type; return type;

View File

@ -30,27 +30,27 @@ namespace AssemblyData.methodsrewriter {
Dictionary<string, List<FieldInfo>> fields; Dictionary<string, List<FieldInfo>> fields;
public TypeInstanceResolver(Type type, ITypeDefOrRef typeRef) { public TypeInstanceResolver(Type type, ITypeDefOrRef typeRef) {
this.type = ResolverUtils.makeInstanceType(type, typeRef); this.type = ResolverUtils.MakeInstanceType(type, typeRef);
} }
public FieldInfo resolve(IField fieldRef) { public FieldInfo Resolve(IField fieldRef) {
initFields(); InitFields();
List<FieldInfo> list; List<FieldInfo> list;
if (!fields.TryGetValue(fieldRef.Name.String, out list)) if (!fields.TryGetValue(fieldRef.Name.String, out list))
return null; return null;
fieldRef = GenericArgsSubstitutor.create(fieldRef, fieldRef.DeclaringType.TryGetGenericInstSig()); fieldRef = GenericArgsSubstitutor.Create(fieldRef, fieldRef.DeclaringType.TryGetGenericInstSig());
foreach (var field in list) { foreach (var field in list) {
if (ResolverUtils.compareFields(field, fieldRef)) if (ResolverUtils.CompareFields(field, fieldRef))
return field; return field;
} }
return null; return null;
} }
void initFields() { void InitFields() {
if (fields != null) if (fields != null)
return; return;
fields = new Dictionary<string, List<FieldInfo>>(StringComparer.Ordinal); fields = new Dictionary<string, List<FieldInfo>>(StringComparer.Ordinal);
@ -64,30 +64,30 @@ namespace AssemblyData.methodsrewriter {
} }
} }
public MethodBase resolve(IMethod methodRef) { public MethodBase Resolve(IMethod methodRef) {
initMethods(); InitMethods();
List<MethodBase> list; List<MethodBase> list;
if (!methods.TryGetValue(methodRef.Name.String, out list)) if (!methods.TryGetValue(methodRef.Name.String, out list))
return null; return null;
methodRef = GenericArgsSubstitutor.create(methodRef, methodRef.DeclaringType.TryGetGenericInstSig()); methodRef = GenericArgsSubstitutor.Create(methodRef, methodRef.DeclaringType.TryGetGenericInstSig());
foreach (var method in list) { foreach (var method in list) {
if (ResolverUtils.compareMethods(method, methodRef)) if (ResolverUtils.CompareMethods(method, methodRef))
return method; return method;
} }
return null; return null;
} }
void initMethods() { void InitMethods() {
if (methods != null) if (methods != null)
return; return;
methods = new Dictionary<string, List<MethodBase>>(StringComparer.Ordinal); methods = new Dictionary<string, List<MethodBase>>(StringComparer.Ordinal);
var flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; var flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
foreach (var method in ResolverUtils.getMethodBases(type, flags)) { foreach (var method in ResolverUtils.GetMethodBases(type, flags)) {
List<MethodBase> list; List<MethodBase> list;
if (!methods.TryGetValue(method.Name, out list)) if (!methods.TryGetValue(method.Name, out list))
methods[method.Name] = list = new List<MethodBase>(); methods[method.Name] = list = new List<MethodBase>();

View File

@ -32,19 +32,19 @@ namespace AssemblyData.methodsrewriter {
this.type = type; this.type = type;
} }
TypeInstanceResolver getTypeInstance(ITypeDefOrRef typeRef) { TypeInstanceResolver GetTypeInstance(ITypeDefOrRef typeRef) {
TypeInstanceResolver instance; TypeInstanceResolver instance;
if (!typeRefToInstance.TryGetValue(typeRef, out instance)) if (!typeRefToInstance.TryGetValue(typeRef, out instance))
typeRefToInstance[typeRef] = instance = new TypeInstanceResolver(type, typeRef); typeRefToInstance[typeRef] = instance = new TypeInstanceResolver(type, typeRef);
return instance; return instance;
} }
public FieldInfo resolve(IField fieldRef) { public FieldInfo Resolve(IField fieldRef) {
return getTypeInstance(fieldRef.DeclaringType).resolve(fieldRef); return GetTypeInstance(fieldRef.DeclaringType).Resolve(fieldRef);
} }
public MethodBase resolve(IMethod methodRef) { public MethodBase Resolve(IMethod methodRef) {
return getTypeInstance(methodRef.DeclaringType).resolve(methodRef); return GetTypeInstance(methodRef.DeclaringType).Resolve(methodRef);
} }
} }
} }

View File

@ -20,7 +20,7 @@
namespace AssemblyServer_CLR20_x64 { namespace AssemblyServer_CLR20_x64 {
class Program { class Program {
static int Main(string[] args) { static int Main(string[] args) {
return AssemblyServer.Start.main(args); return AssemblyServer.Start.Main2(args);
} }
} }
} }

View File

@ -20,7 +20,7 @@
namespace AssemblyServer_CLR20 { namespace AssemblyServer_CLR20 {
class Program { class Program {
static int Main(string[] args) { static int Main(string[] args) {
return AssemblyServer.Start.main(args); return AssemblyServer.Start.Main2(args);
} }
} }
} }

View File

@ -20,7 +20,7 @@
namespace AssemblyServer_CLR40_x64 { namespace AssemblyServer_CLR40_x64 {
class Program { class Program {
static int Main(string[] args) { static int Main(string[] args) {
return AssemblyServer.Start.main(args); return AssemblyServer.Start.Main2(args);
} }
} }
} }

View File

@ -20,7 +20,7 @@
namespace AssemblyServer_CLR40 { namespace AssemblyServer_CLR40 {
class Program { class Program {
static int Main(string[] args) { static int Main(string[] args) {
return AssemblyServer.Start.main(args); return AssemblyServer.Start.Main2(args);
} }
} }
} }

View File

@ -20,7 +20,7 @@
namespace AssemblyServer_x64 { namespace AssemblyServer_x64 {
class Program { class Program {
static int Main(string[] args) { static int Main(string[] args) {
return AssemblyServer.Start.main(args); return AssemblyServer.Start.Main2(args);
} }
} }
} }

View File

@ -20,7 +20,7 @@
namespace AssemblyServer_x86 { namespace AssemblyServer_x86 {
class Program { class Program {
static int Main(string[] args) { static int Main(string[] args) {
return AssemblyServer.Start.main(args); return AssemblyServer.Start.Main2(args);
} }
} }
} }

View File

@ -52,7 +52,7 @@ namespace de4dot.blocks {
public Instr FirstInstr { public Instr FirstInstr {
get { get {
if (instructions.Count == 0) if (instructions.Count == 0)
add(new Instr(OpCodes.Nop.ToInstruction())); Add(new Instr(OpCodes.Nop.ToInstruction()));
return instructions[0]; return instructions[0];
} }
} }
@ -60,16 +60,16 @@ namespace de4dot.blocks {
public Instr LastInstr { public Instr LastInstr {
get { get {
if (instructions.Count == 0) if (instructions.Count == 0)
add(new Instr(OpCodes.Nop.ToInstruction())); Add(new Instr(OpCodes.Nop.ToInstruction()));
return instructions[instructions.Count - 1]; return instructions[instructions.Count - 1];
} }
} }
public void add(Instr instr) { public void Add(Instr instr) {
instructions.Add(instr); instructions.Add(instr);
} }
public void insert(int index, Instruction instr) { public void Insert(int index, Instruction instr) {
instructions.Insert(index, new Instr(instr)); instructions.Insert(index, new Instr(instr));
} }
@ -78,8 +78,8 @@ namespace de4dot.blocks {
} }
// If last instr is a br/br.s, removes it and replaces it with a fall through // If last instr is a br/br.s, removes it and replaces it with a fall through
public void removeLastBr() { public void RemoveLastBr() {
if (!LastInstr.isBr()) if (!LastInstr.IsBr())
return; return;
if (fallThrough != null || (LastInstr.Operand != null && (targets == null || targets.Count != 1))) if (fallThrough != null || (LastInstr.Operand != null && (targets == null || targets.Count != 1)))
@ -89,111 +89,111 @@ namespace de4dot.blocks {
instructions.RemoveAt(instructions.Count - 1); instructions.RemoveAt(instructions.Count - 1);
} }
public void replace(int index, int num, Instruction instruction) { public void Replace(int index, int num, Instruction instruction) {
if (num <= 0) if (num <= 0)
throw new ArgumentOutOfRangeException("num"); throw new ArgumentOutOfRangeException("num");
remove(index, num); Remove(index, num);
instructions.Insert(index, new Instr(instruction)); instructions.Insert(index, new Instr(instruction));
} }
public void remove(int index, int num) { public void Remove(int index, int num) {
if (index + num > instructions.Count) if (index + num > instructions.Count)
throw new ApplicationException("Overflow"); throw new ApplicationException("Overflow");
if (num > 0 && index + num == instructions.Count && LastInstr.isConditionalBranch()) if (num > 0 && index + num == instructions.Count && LastInstr.IsConditionalBranch())
disconnectFromFallThroughAndTargets(); DisconnectFromFallThroughAndTargets();
instructions.RemoveRange(index, num); instructions.RemoveRange(index, num);
} }
public void remove(IEnumerable<int> indexes) { public void Remove(IEnumerable<int> indexes) {
var instrsToDelete = new List<int>(Utils.unique(indexes)); var instrsToDelete = new List<int>(Utils.Unique(indexes));
instrsToDelete.Sort(); instrsToDelete.Sort();
instrsToDelete.Reverse(); instrsToDelete.Reverse();
foreach (var index in instrsToDelete) foreach (var index in instrsToDelete)
remove(index, 1); Remove(index, 1);
} }
// Replace the last instructions with a branch to target // Replace the last instructions with a branch to target
public void replaceLastInstrsWithBranch(int numInstrs, Block target) { public void ReplaceLastInstrsWithBranch(int numInstrs, Block target) {
if (numInstrs < 0 || numInstrs > instructions.Count) if (numInstrs < 0 || numInstrs > instructions.Count)
throw new ApplicationException("Invalid numInstrs to replace with branch"); throw new ApplicationException("Invalid numInstrs to replace with branch");
if (target == null) if (target == null)
throw new ApplicationException("Invalid new target, it's null"); throw new ApplicationException("Invalid new target, it's null");
disconnectFromFallThroughAndTargets(); DisconnectFromFallThroughAndTargets();
if (numInstrs > 0) if (numInstrs > 0)
instructions.RemoveRange(instructions.Count - numInstrs, numInstrs); instructions.RemoveRange(instructions.Count - numInstrs, numInstrs);
fallThrough = target; fallThrough = target;
target.sources.Add(this); target.sources.Add(this);
} }
public void replaceLastNonBranchWithBranch(int numInstrs, Block target) { public void ReplaceLastNonBranchWithBranch(int numInstrs, Block target) {
if (LastInstr.isBr()) if (LastInstr.IsBr())
numInstrs++; numInstrs++;
replaceLastInstrsWithBranch(numInstrs, target); ReplaceLastInstrsWithBranch(numInstrs, target);
} }
public void replaceBccWithBranch(bool isTaken) { public void ReplaceBccWithBranch(bool isTaken) {
Block target = isTaken ? targets[0] : fallThrough; Block target = isTaken ? targets[0] : fallThrough;
replaceLastInstrsWithBranch(1, target); ReplaceLastInstrsWithBranch(1, target);
} }
public void replaceSwitchWithBranch(Block target) { public void ReplaceSwitchWithBranch(Block target) {
if (LastInstr.OpCode.Code != Code.Switch) if (LastInstr.OpCode.Code != Code.Switch)
throw new ApplicationException("Last instruction is not a switch"); throw new ApplicationException("Last instruction is not a switch");
replaceLastInstrsWithBranch(1, target); ReplaceLastInstrsWithBranch(1, target);
} }
public void setNewFallThrough(Block newFallThrough) { public void SetNewFallThrough(Block newFallThrough) {
disconnectFromFallThrough(); DisconnectFromFallThrough();
fallThrough = newFallThrough; fallThrough = newFallThrough;
newFallThrough.sources.Add(this); newFallThrough.sources.Add(this);
} }
public void setNewTarget(int index, Block newTarget) { public void SetNewTarget(int index, Block newTarget) {
disconnectFromBlock(targets[index]); DisconnectFromBlock(targets[index]);
targets[index] = newTarget; targets[index] = newTarget;
newTarget.sources.Add(this); newTarget.sources.Add(this);
} }
public void removeDeadBlock() { public void RemoveDeadBlock() {
if (sources.Count != 0) if (sources.Count != 0)
throw new ApplicationException("Trying to remove a non-dead block"); throw new ApplicationException("Trying to remove a non-dead block");
removeGuaranteedDeadBlock(); RemoveGuaranteedDeadBlock();
} }
// Removes a block that has been guaranteed to be dead. This method won't verify // Removes a block that has been guaranteed to be dead. This method won't verify
// that it really is dead. // that it really is dead.
public void removeGuaranteedDeadBlock() { public void RemoveGuaranteedDeadBlock() {
disconnectFromFallThroughAndTargets(); DisconnectFromFallThroughAndTargets();
Parent = null; Parent = null;
} }
void disconnectFromFallThroughAndTargets() { void DisconnectFromFallThroughAndTargets() {
disconnectFromFallThrough(); DisconnectFromFallThrough();
disconnectFromTargets(); DisconnectFromTargets();
} }
void disconnectFromFallThrough() { void DisconnectFromFallThrough() {
if (fallThrough != null) { if (fallThrough != null) {
disconnectFromBlock(fallThrough); DisconnectFromBlock(fallThrough);
fallThrough = null; fallThrough = null;
} }
} }
void disconnectFromTargets() { void DisconnectFromTargets() {
if (targets != null) { if (targets != null) {
foreach (var target in targets) foreach (var target in targets)
disconnectFromBlock(target); DisconnectFromBlock(target);
targets = null; targets = null;
} }
} }
void disconnectFromBlock(Block target) { void DisconnectFromBlock(Block target) {
if (!target.sources.Remove(this)) if (!target.sources.Remove(this))
throw new ApplicationException("Could not remove the block from its target block"); throw new ApplicationException("Could not remove the block from its target block");
} }
public int countTargets() { public int CountTargets() {
int count = fallThrough != null ? 1 : 0; int count = fallThrough != null ? 1 : 0;
if (targets != null) if (targets != null)
count += targets.Count; count += targets.Count;
@ -201,8 +201,8 @@ namespace de4dot.blocks {
} }
// Returns the target iff it has only ONE target. Else it returns null. // Returns the target iff it has only ONE target. Else it returns null.
public Block getOnlyTarget() { public Block GetOnlyTarget() {
if (countTargets() != 1) if (CountTargets() != 1)
return null; return null;
if (fallThrough != null) if (fallThrough != null)
return fallThrough; return fallThrough;
@ -210,7 +210,7 @@ namespace de4dot.blocks {
} }
// Returns all targets. FallThrough (if not null) is always returned first! // Returns all targets. FallThrough (if not null) is always returned first!
public IEnumerable<Block> getTargets() { public IEnumerable<Block> GetTargets() {
if (fallThrough != null) if (fallThrough != null)
yield return fallThrough; yield return fallThrough;
if (targets != null) { if (targets != null) {
@ -220,52 +220,52 @@ namespace de4dot.blocks {
} }
// Returns true iff other is the only block in Sources // Returns true iff other is the only block in Sources
public bool isOnlySource(Block other) { public bool IsOnlySource(Block other) {
return sources.Count == 1 && sources[0] == other; return sources.Count == 1 && sources[0] == other;
} }
// Returns true if we can merge other with this // Returns true if we can merge other with this
public bool canMerge(Block other) { public bool CanMerge(Block other) {
return canAppend(other) && other.isOnlySource(this); return CanAppend(other) && other.IsOnlySource(this);
} }
// Merge two blocks into one // Merge two blocks into one
public void merge(Block other) { public void Merge(Block other) {
if (!canMerge(other)) if (!CanMerge(other))
throw new ApplicationException("Can't merge the two blocks!"); throw new ApplicationException("Can't merge the two blocks!");
append(other); Append(other);
other.disconnectFromFallThroughAndTargets(); other.DisconnectFromFallThroughAndTargets();
other.Parent = null; other.Parent = null;
} }
public bool canAppend(Block other) { public bool CanAppend(Block other) {
if (other == null || other == this || getOnlyTarget() != other) if (other == null || other == this || GetOnlyTarget() != other)
return false; return false;
// If it's eg. a leave, then don't merge them since it clears the stack. // If it's eg. a leave, then don't merge them since it clears the stack.
return LastInstr.isBr() || Instr.isFallThrough(LastInstr.OpCode); return LastInstr.IsBr() || Instr.IsFallThrough(LastInstr.OpCode);
} }
public void append(Block other) { public void Append(Block other) {
if (!canAppend(other)) if (!CanAppend(other))
throw new ApplicationException("Can't append the block!"); throw new ApplicationException("Can't append the block!");
removeLastBr(); // Get rid of last br/br.s if present RemoveLastBr(); // Get rid of last br/br.s if present
var newInstructions = new List<Instr>(instructions.Count + other.instructions.Count); var newInstructions = new List<Instr>(instructions.Count + other.instructions.Count);
addInstructions(newInstructions, instructions, false); AddInstructions(newInstructions, instructions, false);
addInstructions(newInstructions, other.instructions, true); AddInstructions(newInstructions, other.instructions, true);
instructions = newInstructions; instructions = newInstructions;
disconnectFromFallThroughAndTargets(); DisconnectFromFallThroughAndTargets();
if (other.targets != null) if (other.targets != null)
targets = new List<Block>(other.targets); targets = new List<Block>(other.targets);
else else
targets = null; targets = null;
fallThrough = other.fallThrough; fallThrough = other.fallThrough;
updateSources(); UpdateSources();
} }
void addInstructions(IList<Instr> dest, IList<Instr> instrs, bool clone) { void AddInstructions(IList<Instr> dest, IList<Instr> instrs, bool clone) {
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
var instr = instrs[i]; var instr = instrs[i];
if (instr.OpCode != OpCodes.Nop) if (instr.OpCode != OpCodes.Nop)
@ -275,7 +275,7 @@ namespace de4dot.blocks {
// Update each target's Sources property. Must only be called if this isn't in the // Update each target's Sources property. Must only be called if this isn't in the
// Sources list! // Sources list!
public void updateSources() { public void UpdateSources() {
if (fallThrough != null) if (fallThrough != null)
fallThrough.sources.Add(this); fallThrough.sources.Add(this);
if (targets != null) { if (targets != null) {
@ -285,30 +285,30 @@ namespace de4dot.blocks {
} }
// Returns true if it falls through // Returns true if it falls through
public bool isFallThrough() { public bool IsFallThrough() {
return targets == null && fallThrough != null; return targets == null && fallThrough != null;
} }
public bool canFlipConditionalBranch() { public bool CanFlipConditionalBranch() {
return LastInstr.canFlipConditionalBranch(); return LastInstr.CanFlipConditionalBranch();
} }
public void flipConditionalBranch() { public void FlipConditionalBranch() {
if (fallThrough == null || targets == null || targets.Count != 1) if (fallThrough == null || targets == null || targets.Count != 1)
throw new ApplicationException("Invalid bcc block state"); throw new ApplicationException("Invalid bcc block state");
LastInstr.flipConditonalBranch(); LastInstr.FlipConditonalBranch();
var oldFallThrough = fallThrough; var oldFallThrough = fallThrough;
fallThrough = targets[0]; fallThrough = targets[0];
targets[0] = oldFallThrough; targets[0] = oldFallThrough;
} }
// Returns true if it's a conditional branch // Returns true if it's a conditional branch
public bool isConditionalBranch() { public bool IsConditionalBranch() {
return LastInstr.isConditionalBranch(); return LastInstr.IsConditionalBranch();
} }
public bool isNopBlock() { public bool IsNopBlock() {
if (!isFallThrough()) if (!IsFallThrough())
return false; return false;
foreach (var instr in instructions) { foreach (var instr in instructions) {
if (instr.OpCode.Code != Code.Nop) if (instr.OpCode.Code != Code.Nop)

View File

@ -42,28 +42,28 @@ namespace de4dot.blocks {
public Blocks(MethodDef method) { public Blocks(MethodDef method) {
this.method = method; this.method = method;
updateBlocks(); UpdateBlocks();
} }
public void updateBlocks() { public void UpdateBlocks() {
var body = method.Body; var body = method.Body;
locals = body.Variables; locals = body.Variables;
methodBlocks = new InstructionListParser(body.Instructions, body.ExceptionHandlers).parse(); methodBlocks = new InstructionListParser(body.Instructions, body.ExceptionHandlers).Parse();
} }
IEnumerable<ScopeBlock> getAllScopeBlocks(ScopeBlock scopeBlock) { IEnumerable<ScopeBlock> GetAllScopeBlocks(ScopeBlock scopeBlock) {
var list = new List<ScopeBlock>(); var list = new List<ScopeBlock>();
list.Add(scopeBlock); list.Add(scopeBlock);
list.AddRange(scopeBlock.getAllScopeBlocks()); list.AddRange(scopeBlock.GetAllScopeBlocks());
return list; return list;
} }
public int removeDeadBlocks() { public int RemoveDeadBlocks() {
return new DeadBlocksRemover(methodBlocks).remove(); return new DeadBlocksRemover(methodBlocks).Remove();
} }
public void getCode(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers) { public void GetCode(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers) {
new CodeGenerator(methodBlocks).getCode(out allInstructions, out allExceptionHandlers); new CodeGenerator(methodBlocks).GetCode(out allInstructions, out allExceptionHandlers);
} }
struct LocalVariableInfo { struct LocalVariableInfo {
@ -75,12 +75,12 @@ namespace de4dot.blocks {
} }
} }
public int optimizeLocals() { public int OptimizeLocals() {
if (locals.Count == 0) if (locals.Count == 0)
return 0; return 0;
var usedLocals = new Dictionary<Local, List<LocalVariableInfo>>(); var usedLocals = new Dictionary<Local, List<LocalVariableInfo>>();
foreach (var block in methodBlocks.getAllBlocks()) { foreach (var block in methodBlocks.GetAllBlocks()) {
for (int i = 0; i < block.Instructions.Count; i++) { for (int i = 0; i < block.Instructions.Count; i++) {
var instr = block.Instructions[i]; var instr = block.Instructions[i];
Local local; Local local;
@ -97,7 +97,7 @@ namespace de4dot.blocks {
case Code.Stloc_1: case Code.Stloc_1:
case Code.Stloc_2: case Code.Stloc_2:
case Code.Stloc_3: case Code.Stloc_3:
local = Instr.getLocalVar(locals, instr); local = Instr.GetLocalVar(locals, instr);
break; break;
case Code.Ldloca_S: case Code.Ldloca_S:
@ -129,7 +129,7 @@ namespace de4dot.blocks {
newLocals.Add(local); newLocals.Add(local);
newLocalsDict[local] = true; newLocalsDict[local] = true;
foreach (var info in usedLocals[local]) foreach (var info in usedLocals[local])
info.block.Instructions[info.index] = new Instr(optimizeLocalInstr(info.block.Instructions[info.index], local, (uint)newIndex)); info.block.Instructions[info.index] = new Instr(OptimizeLocalInstr(info.block.Instructions[info.index], local, (uint)newIndex));
} }
// We can't remove all locals. Locals that reference another assembly will // We can't remove all locals. Locals that reference another assembly will
@ -162,7 +162,7 @@ namespace de4dot.blocks {
return numRemoved; return numRemoved;
} }
static Instruction optimizeLocalInstr(Instr instr, Local local, uint newIndex) { static Instruction OptimizeLocalInstr(Instr instr, Local local, uint newIndex) {
switch (instr.OpCode.Code) { switch (instr.OpCode.Code) {
case Code.Ldloc: case Code.Ldloc:
case Code.Ldloc_S: case Code.Ldloc_S:
@ -211,11 +211,11 @@ namespace de4dot.blocks {
} }
} }
public void repartitionBlocks() { public void RepartitionBlocks() {
mergeNopBlocks(); MergeNopBlocks();
foreach (var scopeBlock in getAllScopeBlocks(methodBlocks)) { foreach (var scopeBlock in GetAllScopeBlocks(methodBlocks)) {
try { try {
scopeBlock.repartitionBlocks(); scopeBlock.RepartitionBlocks();
} }
catch (NullReferenceException) { catch (NullReferenceException) {
//TODO: Send this message to the log //TODO: Send this message to the log
@ -225,12 +225,12 @@ namespace de4dot.blocks {
} }
} }
void mergeNopBlocks() { void MergeNopBlocks() {
var allBlocks = methodBlocks.getAllBlocks(); var allBlocks = methodBlocks.GetAllBlocks();
var nopBlocks = new Dictionary<Block, bool>(); var nopBlocks = new Dictionary<Block, bool>();
foreach (var nopBlock in allBlocks) { foreach (var nopBlock in allBlocks) {
if (nopBlock.isNopBlock()) if (nopBlock.IsNopBlock())
nopBlocks[nopBlock] = true; nopBlocks[nopBlock] = true;
} }
@ -243,18 +243,18 @@ namespace de4dot.blocks {
foreach (var block in allBlocks) { foreach (var block in allBlocks) {
Block nopBlockTarget; Block nopBlockTarget;
nopBlockTarget = getNopBlockTarget(nopBlocks, block, block.FallThrough); nopBlockTarget = GetNopBlockTarget(nopBlocks, block, block.FallThrough);
if (nopBlockTarget != null) { if (nopBlockTarget != null) {
block.setNewFallThrough(nopBlockTarget); block.SetNewFallThrough(nopBlockTarget);
changed = true; changed = true;
} }
if (block.Targets != null) { if (block.Targets != null) {
for (int targetIndex = 0; targetIndex < block.Targets.Count; targetIndex++) { for (int targetIndex = 0; targetIndex < block.Targets.Count; targetIndex++) {
nopBlockTarget = getNopBlockTarget(nopBlocks, block, block.Targets[targetIndex]); nopBlockTarget = GetNopBlockTarget(nopBlocks, block, block.Targets[targetIndex]);
if (nopBlockTarget == null) if (nopBlockTarget == null)
continue; continue;
block.setNewTarget(targetIndex, nopBlockTarget); block.SetNewTarget(targetIndex, nopBlockTarget);
changed = true; changed = true;
} }
} }
@ -265,10 +265,10 @@ namespace de4dot.blocks {
} }
foreach (var nopBlock in nopBlocks.Keys) foreach (var nopBlock in nopBlocks.Keys)
nopBlock.Parent.removeDeadBlock(nopBlock); nopBlock.Parent.RemoveDeadBlock(nopBlock);
} }
static Block getNopBlockTarget(Dictionary<Block, bool> nopBlocks, Block source, Block nopBlock) { static Block GetNopBlockTarget(Dictionary<Block, bool> nopBlocks, Block source, Block nopBlock) {
if (nopBlock == null || !nopBlocks.ContainsKey(nopBlock) || source == nopBlock.FallThrough) if (nopBlock == null || !nopBlocks.ContainsKey(nopBlock) || source == nopBlock.FallThrough)
return null; return null;
if (nopBlock.Parent.BaseBlocks[0] == nopBlock) if (nopBlock.Parent.BaseBlocks[0] == nopBlock)

View File

@ -34,7 +34,7 @@ namespace de4dot.blocks {
this.baseBlock = baseBlock; this.baseBlock = baseBlock;
} }
public bool visited() { public bool Visited() {
return dfsNumber >= 0; return dfsNumber >= 0;
} }
@ -62,7 +62,7 @@ namespace de4dot.blocks {
this.skipFirstBlock = skipFirstBlock; this.skipFirstBlock = skipFirstBlock;
} }
public List<BaseBlock> sort() { public List<BaseBlock> Sort() {
if (validBlocks.Count == 0) if (validBlocks.Count == 0)
return new List<BaseBlock>(); return new List<BaseBlock>();
if (skipFirstBlock) if (skipFirstBlock)
@ -77,14 +77,14 @@ namespace de4dot.blocks {
var finalList = new List<BaseBlock>(validBlocks.Count); var finalList = new List<BaseBlock>(validBlocks.Count);
if (firstBlock is Block) { if (firstBlock is Block) {
foreach (var target in getTargets(firstBlock)) { foreach (var target in GetTargets(firstBlock)) {
visit(target); Visit(target);
finalList.AddRange(sorted); finalList.AddRange(sorted);
sorted.Clear(); sorted.Clear();
} }
} }
foreach (var bb in validBlocks) { foreach (var bb in validBlocks) {
visit(bb); Visit(bb);
finalList.AddRange(sorted); finalList.AddRange(sorted);
sorted.Clear(); sorted.Clear();
} }
@ -103,19 +103,19 @@ namespace de4dot.blocks {
return finalList; return finalList;
} }
void visit(BaseBlock bb) { void Visit(BaseBlock bb) {
var info = getInfo(bb); var info = GetInfo(bb);
if (info == null) if (info == null)
return; return;
if (info.baseBlock == firstBlock) if (info.baseBlock == firstBlock)
return; return;
if (info.visited()) if (info.Visited())
return; return;
visit(info); Visit(info);
} }
BlockInfo getInfo(BaseBlock baseBlock) { BlockInfo GetInfo(BaseBlock baseBlock) {
baseBlock = scopeBlock.toChild(baseBlock); baseBlock = scopeBlock.ToChild(baseBlock);
if (baseBlock == null) if (baseBlock == null)
return null; return null;
BlockInfo info; BlockInfo info;
@ -123,54 +123,54 @@ namespace de4dot.blocks {
return info; return info;
} }
List<BaseBlock> getTargets(BaseBlock baseBlock) { List<BaseBlock> GetTargets(BaseBlock baseBlock) {
var list = new List<BaseBlock>(); var list = new List<BaseBlock>();
if (baseBlock is Block) { if (baseBlock is Block) {
var block = (Block)baseBlock; var block = (Block)baseBlock;
addTargets(list, block.getTargets()); AddTargets(list, block.GetTargets());
} }
else if (baseBlock is TryBlock) else if (baseBlock is TryBlock)
addTargets(list, (TryBlock)baseBlock); AddTargets(list, (TryBlock)baseBlock);
else if (baseBlock is TryHandlerBlock) else if (baseBlock is TryHandlerBlock)
addTargets(list, (TryHandlerBlock)baseBlock); AddTargets(list, (TryHandlerBlock)baseBlock);
else else
addTargets(list, (ScopeBlock)baseBlock); AddTargets(list, (ScopeBlock)baseBlock);
return list; return list;
} }
void addTargets(List<BaseBlock> dest, TryBlock tryBlock) { void AddTargets(List<BaseBlock> dest, TryBlock tryBlock) {
addTargets(dest, (ScopeBlock)tryBlock); AddTargets(dest, (ScopeBlock)tryBlock);
foreach (var tryHandlerBlock in tryBlock.TryHandlerBlocks) { foreach (var tryHandlerBlock in tryBlock.TryHandlerBlocks) {
dest.Add(tryHandlerBlock); dest.Add(tryHandlerBlock);
addTargets(dest, tryHandlerBlock); AddTargets(dest, tryHandlerBlock);
} }
} }
void addTargets(List<BaseBlock> dest, TryHandlerBlock tryHandlerBlock) { void AddTargets(List<BaseBlock> dest, TryHandlerBlock tryHandlerBlock) {
addTargets(dest, (ScopeBlock)tryHandlerBlock); AddTargets(dest, (ScopeBlock)tryHandlerBlock);
dest.Add(tryHandlerBlock.FilterHandlerBlock); dest.Add(tryHandlerBlock.FilterHandlerBlock);
addTargets(dest, tryHandlerBlock.FilterHandlerBlock); AddTargets(dest, tryHandlerBlock.FilterHandlerBlock);
dest.Add(tryHandlerBlock.HandlerBlock); dest.Add(tryHandlerBlock.HandlerBlock);
addTargets(dest, tryHandlerBlock.HandlerBlock); AddTargets(dest, tryHandlerBlock.HandlerBlock);
} }
void addTargets(List<BaseBlock> dest, ScopeBlock scopeBlock) { void AddTargets(List<BaseBlock> dest, ScopeBlock scopeBlock) {
foreach (var block in scopeBlock.getAllBlocks()) foreach (var block in scopeBlock.GetAllBlocks())
addTargets(dest, block.getTargets()); AddTargets(dest, block.GetTargets());
} }
void addTargets(List<BaseBlock> dest, IEnumerable<Block> source) { void AddTargets(List<BaseBlock> dest, IEnumerable<Block> source) {
var list = new List<Block>(source); var list = new List<Block>(source);
list.Reverse(); list.Reverse();
foreach (var block in list) foreach (var block in list)
dest.Add(block); dest.Add(block);
} }
void visit(BlockInfo info) { void Visit(BlockInfo info) {
if (info.baseBlock == firstBlock) if (info.baseBlock == firstBlock)
throw new ApplicationException("Can't visit firstBlock"); throw new ApplicationException("Can't visit firstBlock");
stack.Push(info); stack.Push(info);
@ -179,15 +179,15 @@ namespace de4dot.blocks {
info.low = dfsNumber; info.low = dfsNumber;
dfsNumber++; dfsNumber++;
foreach (var tmp in getTargets(info.baseBlock)) { foreach (var tmp in GetTargets(info.baseBlock)) {
var targetInfo = getInfo(tmp); var targetInfo = GetInfo(tmp);
if (targetInfo == null) if (targetInfo == null)
continue; continue;
if (targetInfo.baseBlock == firstBlock) if (targetInfo.baseBlock == firstBlock)
continue; continue;
if (!targetInfo.visited()) { if (!targetInfo.Visited()) {
visit(targetInfo); Visit(targetInfo);
info.low = Math.Min(info.low, targetInfo.low); info.low = Math.Min(info.low, targetInfo.low);
} }
else if (targetInfo.onStack) else if (targetInfo.onStack)
@ -206,8 +206,8 @@ namespace de4dot.blocks {
} }
if (sccBlocks.Count > 1) { if (sccBlocks.Count > 1) {
sccBlocks.Reverse(); sccBlocks.Reverse();
var result = new Sorter(scopeBlock, sccBlocks, true).sort(); var result = new Sorter(scopeBlock, sccBlocks, true).Sort();
sortLoopBlock(result); SortLoopBlock(result);
sorted.InsertRange(0, result); sorted.InsertRange(0, result);
} }
else { else {
@ -215,12 +215,12 @@ namespace de4dot.blocks {
} }
} }
void sortLoopBlock(List<BaseBlock> list) { void SortLoopBlock(List<BaseBlock> list) {
// Some popular decompilers sometimes produce bad output unless the loop condition // Some popular decompilers sometimes produce bad output unless the loop condition
// checker block is at the end of the loop. Eg., they may use a while loop when // checker block is at the end of the loop. Eg., they may use a while loop when
// it's really a for/foreach loop. // it's really a for/foreach loop.
var loopStart = getLoopStartBlock(list); var loopStart = GetLoopStartBlock(list);
if (loopStart == null) if (loopStart == null)
return; return;
@ -229,7 +229,7 @@ namespace de4dot.blocks {
list.Add(loopStart); list.Add(loopStart);
} }
Block getLoopStartBlock(List<BaseBlock> list) { Block GetLoopStartBlock(List<BaseBlock> list) {
var loopBlocks = new Dictionary<Block, bool>(list.Count); var loopBlocks = new Dictionary<Block, bool>(list.Count);
foreach (var bb in list) { foreach (var bb in list) {
var block = bb as Block; var block = bb as Block;
@ -268,9 +268,9 @@ namespace de4dot.blocks {
this.scopeBlock = scopeBlock; this.scopeBlock = scopeBlock;
} }
public List<BaseBlock> sort() { public List<BaseBlock> Sort() {
var sorted = new Sorter(scopeBlock, scopeBlock.BaseBlocks, false).sort(); var sorted = new Sorter(scopeBlock, scopeBlock.BaseBlocks, false).Sort();
return new ForwardScanOrder(scopeBlock, sorted).fix(); return new ForwardScanOrder(scopeBlock, sorted).Fix();
} }
} }
} }

View File

@ -67,11 +67,11 @@ namespace de4dot.blocks {
this.methodBlocks = methodBlocks; this.methodBlocks = methodBlocks;
} }
public void getCode(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers) { public void GetCode(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers) {
fixEmptyBlocks(); FixEmptyBlocks();
layOutBlocks(); LayOutBlocks();
sortExceptions(); SortExceptions();
layOutInstructions(out allInstructions, out allExceptionHandlers); LayOutInstructions(out allInstructions, out allExceptionHandlers);
allInstructions.SimplifyBranches(); allInstructions.SimplifyBranches();
allInstructions.OptimizeBranches(); allInstructions.OptimizeBranches();
@ -87,7 +87,7 @@ namespace de4dot.blocks {
} }
} }
void layOutInstructions(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers) { void LayOutInstructions(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers) {
allInstructions = new List<Instruction>(); allInstructions = new List<Instruction>();
allExceptionHandlers = new List<ExceptionHandler>(); allExceptionHandlers = new List<ExceptionHandler>();
@ -103,20 +103,20 @@ namespace de4dot.blocks {
var targets = new List<Instr>(); var targets = new List<Instr>();
foreach (var target in block.Targets) foreach (var target in block.Targets)
targets.Add(target.FirstInstr); targets.Add(target.FirstInstr);
block.LastInstr.updateTargets(targets); block.LastInstr.UpdateTargets(targets);
} }
allInstructions.Add(block.LastInstr.Instruction); allInstructions.Add(block.LastInstr.Instruction);
var next = i + 1 < blocks.Count ? blocks[i + 1] : null; var next = i + 1 < blocks.Count ? blocks[i + 1] : null;
// If eg. ble next, then change it to bgt XYZ and fall through to next. // If eg. ble next, then change it to bgt XYZ and fall through to next.
if (block.Targets != null && block.canFlipConditionalBranch() && block.Targets[0] == next) { if (block.Targets != null && block.CanFlipConditionalBranch() && block.Targets[0] == next) {
block.flipConditionalBranch(); block.FlipConditionalBranch();
block.LastInstr.updateTargets(new List<Instr> { block.Targets[0].FirstInstr }); block.LastInstr.UpdateTargets(new List<Instr> { block.Targets[0].FirstInstr });
} }
else if (block.FallThrough != null && block.FallThrough != next) { else if (block.FallThrough != null && block.FallThrough != next) {
var instr = new Instr(OpCodes.Br.ToInstruction(block.FallThrough.FirstInstr.Instruction)); var instr = new Instr(OpCodes.Br.ToInstruction(block.FallThrough.FirstInstr.Instruction));
instr.updateTargets(new List<Instr> { block.FallThrough.FirstInstr }); instr.UpdateTargets(new List<Instr> { block.FallThrough.FirstInstr });
allInstructions.Add(instr.Instruction); allInstructions.Add(instr.Instruction);
} }
@ -126,25 +126,25 @@ namespace de4dot.blocks {
} }
foreach (var ex in exceptions) { foreach (var ex in exceptions) {
var tryStart = getBlockInfo(blockInfos, ex.tryStart).start; var tryStart = GetBlockInfo(blockInfos, ex.tryStart).start;
var tryEnd = getBlockInfo(blockInfos, ex.tryEnd).end; var tryEnd = GetBlockInfo(blockInfos, ex.tryEnd).end;
var filterStart = ex.filterStart == -1 ? -1 : getBlockInfo(blockInfos, ex.filterStart).start; var filterStart = ex.filterStart == -1 ? -1 : GetBlockInfo(blockInfos, ex.filterStart).start;
var handlerStart = getBlockInfo(blockInfos, ex.handlerStart).start; var handlerStart = GetBlockInfo(blockInfos, ex.handlerStart).start;
var handlerEnd = getBlockInfo(blockInfos, ex.handlerEnd).end; var handlerEnd = GetBlockInfo(blockInfos, ex.handlerEnd).end;
var eh = new ExceptionHandler(ex.handlerType); var eh = new ExceptionHandler(ex.handlerType);
eh.CatchType = ex.catchType; eh.CatchType = ex.catchType;
eh.TryStart = getInstruction(allInstructions, tryStart); eh.TryStart = GetInstruction(allInstructions, tryStart);
eh.TryEnd = getInstruction(allInstructions, tryEnd + 1); eh.TryEnd = GetInstruction(allInstructions, tryEnd + 1);
eh.FilterStart = filterStart == -1 ? null : getInstruction(allInstructions, filterStart); eh.FilterStart = filterStart == -1 ? null : GetInstruction(allInstructions, filterStart);
eh.HandlerStart = getInstruction(allInstructions, handlerStart); eh.HandlerStart = GetInstruction(allInstructions, handlerStart);
eh.HandlerEnd = getInstruction(allInstructions, handlerEnd + 1); eh.HandlerEnd = GetInstruction(allInstructions, handlerEnd + 1);
allExceptionHandlers.Add(eh); allExceptionHandlers.Add(eh);
} }
} }
static BlockInfo getBlockInfo(List<BlockInfo> blockInfos, int index) { static BlockInfo GetBlockInfo(List<BlockInfo> blockInfos, int index) {
if (index >= blockInfos.Count) if (index >= blockInfos.Count)
index = blockInfos.Count - 1; index = blockInfos.Count - 1;
if (index < 0) if (index < 0)
@ -152,13 +152,13 @@ namespace de4dot.blocks {
return blockInfos[index]; return blockInfos[index];
} }
static Instruction getInstruction(IList<Instruction> allInstructions, int i) { static Instruction GetInstruction(IList<Instruction> allInstructions, int i) {
if (i < allInstructions.Count) if (i < allInstructions.Count)
return allInstructions[i]; return allInstructions[i];
return null; return null;
} }
void sortExceptions() { void SortExceptions() {
exceptions.Sort((a, b) => { exceptions.Sort((a, b) => {
// Make sure nested try blocks are sorted before the outer try block. // Make sure nested try blocks are sorted before the outer try block.
if (a.tryStart > b.tryStart) return -1; // a could be nested, but b is not if (a.tryStart > b.tryStart) return -1; // a could be nested, but b is not
@ -184,8 +184,8 @@ namespace de4dot.blocks {
}); });
} }
void fixEmptyBlocks() { void FixEmptyBlocks() {
foreach (var block in methodBlocks.getAllBlocks()) { foreach (var block in methodBlocks.GetAllBlocks()) {
if (block.Instructions.Count == 0) { if (block.Instructions.Count == 0) {
block.Instructions.Add(new Instr(OpCodes.Nop.ToInstruction())); block.Instructions.Add(new Instr(OpCodes.Nop.ToInstruction()));
} }
@ -193,12 +193,12 @@ namespace de4dot.blocks {
} }
// Write all blocks to the blocks list // Write all blocks to the blocks list
void layOutBlocks() { void LayOutBlocks() {
if (methodBlocks.BaseBlocks.Count == 0) if (methodBlocks.BaseBlocks.Count == 0)
return; return;
stateStack.Push(new BlockState(methodBlocks)); stateStack.Push(new BlockState(methodBlocks));
processBaseBlocks(methodBlocks.BaseBlocks, (block) => { ProcessBaseBlocks(methodBlocks.BaseBlocks, (block) => {
return block.LastInstr.OpCode == OpCodes.Ret; return block.LastInstr.OpCode == OpCodes.Ret;
}); });
@ -212,7 +212,7 @@ namespace de4dot.blocks {
} }
} }
void processBaseBlocks(List<BaseBlock> lb, Func<Block, bool> placeLast) { void ProcessBaseBlocks(List<BaseBlock> lb, Func<Block, bool> placeLast) {
var bbs = new List<BaseBlock>(); var bbs = new List<BaseBlock>();
int lastIndex = -1; int lastIndex = -1;
for (int i = 0; i < lb.Count; i++) { for (int i = 0; i < lb.Count; i++) {
@ -228,22 +228,22 @@ namespace de4dot.blocks {
bbs.Add(block); bbs.Add(block);
} }
foreach (var bb in bbs) foreach (var bb in bbs)
doBaseBlock(bb); DoBaseBlock(bb);
} }
// Returns the BaseBlock's ScopeBlock. The return value is either current ScopeBlock, // Returns the BaseBlock's ScopeBlock. The return value is either current ScopeBlock,
// the ScopeBlock one step below current (current one's child), or null. // the ScopeBlock one step below current (current one's child), or null.
ScopeBlock getScopeBlock(BaseBlock bb) { ScopeBlock GetScopeBlock(BaseBlock bb) {
BlockState current = stateStack.Peek(); BlockState current = stateStack.Peek();
if (current.scopeBlock.isOurBaseBlock(bb)) if (current.scopeBlock.IsOurBaseBlock(bb))
return current.scopeBlock; return current.scopeBlock;
return (ScopeBlock)current.scopeBlock.toChild(bb); return (ScopeBlock)current.scopeBlock.ToChild(bb);
} }
void doBaseBlock(BaseBlock bb) { void DoBaseBlock(BaseBlock bb) {
BlockState current = stateStack.Peek(); BlockState current = stateStack.Peek();
ScopeBlock newOne = getScopeBlock(bb); ScopeBlock newOne = GetScopeBlock(bb);
if (newOne == null) if (newOne == null)
return; // Not a BaseBlock somewhere inside this ScopeBlock return; // Not a BaseBlock somewhere inside this ScopeBlock
if (newOne != current.scopeBlock) if (newOne != current.scopeBlock)
@ -257,13 +257,13 @@ namespace de4dot.blocks {
visited[bb] = true; visited[bb] = true;
if (bb is Block) if (bb is Block)
doBlock(bb as Block); DoBlock(bb as Block);
else if (bb is TryBlock) else if (bb is TryBlock)
doTryBlock(bb as TryBlock); DoTryBlock(bb as TryBlock);
else if (bb is FilterHandlerBlock) else if (bb is FilterHandlerBlock)
doFilterHandlerBlock(bb as FilterHandlerBlock); DoFilterHandlerBlock(bb as FilterHandlerBlock);
else if (bb is HandlerBlock) else if (bb is HandlerBlock)
doHandlerBlock(bb as HandlerBlock); DoHandlerBlock(bb as HandlerBlock);
else if (bb is TryHandlerBlock) { else if (bb is TryHandlerBlock) {
// The try handler block is usually after the try block, but sometimes it isn't... // The try handler block is usually after the try block, but sometimes it isn't...
// Handle that case here. // Handle that case here.
@ -274,14 +274,14 @@ namespace de4dot.blocks {
throw new ApplicationException("Invalid block found"); throw new ApplicationException("Invalid block found");
} }
void doBlock(Block block) { void DoBlock(Block block) {
blocks.Add(block); blocks.Add(block);
} }
void doTryBlock(TryBlock tryBlock) { void DoTryBlock(TryBlock tryBlock) {
var tryStart = blocks.Count; var tryStart = blocks.Count;
stateStack.Push(new BlockState(tryBlock)); stateStack.Push(new BlockState(tryBlock));
processBaseBlocks(tryBlock.BaseBlocks, (block) => { ProcessBaseBlocks(tryBlock.BaseBlocks, (block) => {
return block.LastInstr.OpCode == OpCodes.Leave || return block.LastInstr.OpCode == OpCodes.Leave ||
block.LastInstr.OpCode == OpCodes.Leave_S; block.LastInstr.OpCode == OpCodes.Leave_S;
}); });
@ -298,10 +298,10 @@ namespace de4dot.blocks {
var filterStart = blocks.Count; var filterStart = blocks.Count;
if (handlerBlock.FilterHandlerBlock.BaseBlocks != null) if (handlerBlock.FilterHandlerBlock.BaseBlocks != null)
doBaseBlock(handlerBlock.FilterHandlerBlock); DoBaseBlock(handlerBlock.FilterHandlerBlock);
var handlerStart = blocks.Count; var handlerStart = blocks.Count;
doBaseBlock(handlerBlock.HandlerBlock); DoBaseBlock(handlerBlock.HandlerBlock);
var handlerEnd = blocks.Count - 1; var handlerEnd = blocks.Count - 1;
exceptions.Add(new ExceptionInfo(tryStart, tryEnd, filterStart, handlerStart, handlerEnd, handlerBlock.CatchType, handlerBlock.HandlerType)); exceptions.Add(new ExceptionInfo(tryStart, tryEnd, filterStart, handlerStart, handlerEnd, handlerBlock.CatchType, handlerBlock.HandlerType));
@ -310,17 +310,17 @@ namespace de4dot.blocks {
} }
} }
void doFilterHandlerBlock(FilterHandlerBlock filterHandlerBlock) { void DoFilterHandlerBlock(FilterHandlerBlock filterHandlerBlock) {
stateStack.Push(new BlockState(filterHandlerBlock)); stateStack.Push(new BlockState(filterHandlerBlock));
processBaseBlocks(filterHandlerBlock.BaseBlocks, (block) => { ProcessBaseBlocks(filterHandlerBlock.BaseBlocks, (block) => {
return block.LastInstr.OpCode == OpCodes.Endfilter; // MUST end with endfilter! return block.LastInstr.OpCode == OpCodes.Endfilter; // MUST end with endfilter!
}); });
stateStack.Pop(); stateStack.Pop();
} }
void doHandlerBlock(HandlerBlock handlerBlock) { void DoHandlerBlock(HandlerBlock handlerBlock) {
stateStack.Push(new BlockState(handlerBlock)); stateStack.Push(new BlockState(handlerBlock));
processBaseBlocks(handlerBlock.BaseBlocks, (block) => { ProcessBaseBlocks(handlerBlock.BaseBlocks, (block) => {
return block.LastInstr.OpCode == OpCodes.Endfinally || return block.LastInstr.OpCode == OpCodes.Endfinally ||
block.LastInstr.OpCode == OpCodes.Leave || block.LastInstr.OpCode == OpCodes.Leave ||
block.LastInstr.OpCode == OpCodes.Leave_S; block.LastInstr.OpCode == OpCodes.Leave_S;

View File

@ -32,10 +32,10 @@ namespace de4dot.blocks {
this.methodBlocks = methodBlocks; this.methodBlocks = methodBlocks;
} }
public int remove() { public int Remove() {
addScopeBlock(methodBlocks); AddScopeBlock(methodBlocks);
processAll(); ProcessAll();
return removeDeadBlocks(); return RemoveDeadBlocks();
} }
class ScopeBlockInfo { class ScopeBlockInfo {
@ -46,12 +46,12 @@ namespace de4dot.blocks {
} }
} }
int removeDeadBlocks() { int RemoveDeadBlocks() {
int numDeadBlocks = 0; int numDeadBlocks = 0;
var infos = new Dictionary<ScopeBlock, ScopeBlockInfo>(); var infos = new Dictionary<ScopeBlock, ScopeBlockInfo>();
var deadBlocksDict = new Dictionary<BaseBlock, bool>(); var deadBlocksDict = new Dictionary<BaseBlock, bool>();
foreach (var baseBlock in findDeadBlocks()) { foreach (var baseBlock in FindDeadBlocks()) {
deadBlocksDict[baseBlock] = true; deadBlocksDict[baseBlock] = true;
ScopeBlock parent = baseBlock.Parent; ScopeBlock parent = baseBlock.Parent;
ScopeBlockInfo info; ScopeBlockInfo info;
@ -62,15 +62,15 @@ namespace de4dot.blocks {
} }
foreach (var info in infos.Values) foreach (var info in infos.Values)
info.scopeBlock.removeAllDeadBlocks(info.deadBlocks, deadBlocksDict); info.scopeBlock.RemoveAllDeadBlocks(info.deadBlocks, deadBlocksDict);
return numDeadBlocks; return numDeadBlocks;
} }
IList<BaseBlock> findDeadBlocks() { IList<BaseBlock> FindDeadBlocks() {
var deadBlocks = new List<BaseBlock>(); var deadBlocks = new List<BaseBlock>();
foreach (var bb in methodBlocks.getAllBaseBlocks()) { foreach (var bb in methodBlocks.GetAllBaseBlocks()) {
if (!checkedBaseBlocks.ContainsKey(bb)) if (!checkedBaseBlocks.ContainsKey(bb))
deadBlocks.Add(bb); deadBlocks.Add(bb);
} }
@ -78,66 +78,66 @@ namespace de4dot.blocks {
return deadBlocks; return deadBlocks;
} }
void addScopeBlock(ScopeBlock scopeBlock) { void AddScopeBlock(ScopeBlock scopeBlock) {
scopeBlocksToCheck.Push(scopeBlock); scopeBlocksToCheck.Push(scopeBlock);
} }
void processAll() { void ProcessAll() {
bool didSomething; bool didSomething;
do { do {
didSomething = false; didSomething = false;
while (baseBlocksToCheck.Count > 0) { while (baseBlocksToCheck.Count > 0) {
processBaseBlock(baseBlocksToCheck.Pop()); ProcessBaseBlock(baseBlocksToCheck.Pop());
didSomething = true; didSomething = true;
} }
while (scopeBlocksToCheck.Count > 0) { while (scopeBlocksToCheck.Count > 0) {
processScopeBlock(scopeBlocksToCheck.Pop()); ProcessScopeBlock(scopeBlocksToCheck.Pop());
didSomething = true; didSomething = true;
} }
} while (didSomething); } while (didSomething);
} }
void processBaseBlock(BaseBlock baseBlock) { void ProcessBaseBlock(BaseBlock baseBlock) {
if (baseBlock == null || checkedBaseBlocks.ContainsKey(baseBlock)) if (baseBlock == null || checkedBaseBlocks.ContainsKey(baseBlock))
return; return;
checkedBaseBlocks[baseBlock] = true; checkedBaseBlocks[baseBlock] = true;
if (baseBlock is Block) { if (baseBlock is Block) {
var block = (Block)baseBlock; var block = (Block)baseBlock;
foreach (var block2 in block.getTargets()) foreach (var block2 in block.GetTargets())
addBaseBlock(block2); AddBaseBlock(block2);
} }
else if (baseBlock is ScopeBlock) { else if (baseBlock is ScopeBlock) {
var scopeBlock = (ScopeBlock)baseBlock; var scopeBlock = (ScopeBlock)baseBlock;
addScopeBlock(scopeBlock); AddScopeBlock(scopeBlock);
if (scopeBlock.BaseBlocks != null && scopeBlock.BaseBlocks.Count > 0) if (scopeBlock.BaseBlocks != null && scopeBlock.BaseBlocks.Count > 0)
addBaseBlock(scopeBlock.BaseBlocks[0]); AddBaseBlock(scopeBlock.BaseBlocks[0]);
} }
else else
throw new ApplicationException(string.Format("Unknown BaseBlock type {0}", baseBlock.GetType())); throw new ApplicationException(string.Format("Unknown BaseBlock type {0}", baseBlock.GetType()));
} }
// Add a block to be processed later, including all its enclosing ScopeBlocks. // Add a block to be processed later, including all its enclosing ScopeBlocks.
void addBaseBlock(BaseBlock baseBlock) { void AddBaseBlock(BaseBlock baseBlock) {
for (BaseBlock bb = baseBlock; bb != null; bb = bb.Parent) for (BaseBlock bb = baseBlock; bb != null; bb = bb.Parent)
baseBlocksToCheck.Push(bb); baseBlocksToCheck.Push(bb);
} }
void processScopeBlock(ScopeBlock scopeBlock) { void ProcessScopeBlock(ScopeBlock scopeBlock) {
if (scopeBlock == null || checkedScopeBlocks.ContainsKey(scopeBlock)) if (scopeBlock == null || checkedScopeBlocks.ContainsKey(scopeBlock))
return; return;
checkedScopeBlocks[scopeBlock] = true; checkedScopeBlocks[scopeBlock] = true;
addBaseBlock(scopeBlock); AddBaseBlock(scopeBlock);
if (scopeBlock is TryBlock) { if (scopeBlock is TryBlock) {
var tryBlock = (TryBlock)scopeBlock; var tryBlock = (TryBlock)scopeBlock;
foreach (var handler in tryBlock.TryHandlerBlocks) foreach (var handler in tryBlock.TryHandlerBlocks)
addScopeBlock(handler); AddScopeBlock(handler);
} }
else if (scopeBlock is TryHandlerBlock) { else if (scopeBlock is TryHandlerBlock) {
var tryHandlerBlock = (TryHandlerBlock)scopeBlock; var tryHandlerBlock = (TryHandlerBlock)scopeBlock;
addScopeBlock(tryHandlerBlock.FilterHandlerBlock); AddScopeBlock(tryHandlerBlock.FilterHandlerBlock);
addScopeBlock(tryHandlerBlock.HandlerBlock); AddScopeBlock(tryHandlerBlock.HandlerBlock);
} }
} }
} }

View File

@ -35,18 +35,18 @@ namespace de4dot.blocks {
public class CallCounter { public class CallCounter {
Dictionary<IMethod, int> calls = new Dictionary<IMethod, int>(MethodEqualityComparer.CompareDeclaringTypes); Dictionary<IMethod, int> calls = new Dictionary<IMethod, int>(MethodEqualityComparer.CompareDeclaringTypes);
public void add(IMethod calledMethod) { public void Add(IMethod calledMethod) {
int count; int count;
calls.TryGetValue(calledMethod, out count); calls.TryGetValue(calledMethod, out count);
calls[calledMethod] = count + 1; calls[calledMethod] = count + 1;
} }
public IMethod most() { public IMethod Most() {
int numCalls; int numCalls;
return most(out numCalls); return Most(out numCalls);
} }
public IMethod most(out int numCalls) { public IMethod Most(out int numCalls) {
IMethod method = null; IMethod method = null;
int callCount = 0; int callCount = 0;
foreach (var key in calls.Keys) { foreach (var key in calls.Keys) {
@ -61,15 +61,15 @@ namespace de4dot.blocks {
} }
public static class DotNetUtils { public static class DotNetUtils {
public static TypeDef getModuleType(ModuleDef module) { public static TypeDef GetModuleType(ModuleDef module) {
return module.GlobalType; return module.GlobalType;
} }
public static MethodDef getModuleTypeCctor(ModuleDef module) { public static MethodDef GetModuleTypeCctor(ModuleDef module) {
return module.GlobalType.FindStaticConstructor(); return module.GlobalType.FindStaticConstructor();
} }
public static bool isEmpty(MethodDef method) { public static bool IsEmpty(MethodDef method) {
if (method.Body == null) if (method.Body == null)
return false; return false;
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
@ -80,18 +80,18 @@ namespace de4dot.blocks {
return true; return true;
} }
public static bool isEmptyObfuscated(MethodDef method) { public static bool IsEmptyObfuscated(MethodDef method) {
if (method.Body == null) if (method.Body == null)
return false; return false;
int index = 0; int index = 0;
var instr = getInstruction(method.Body.Instructions, ref index); var instr = GetInstruction(method.Body.Instructions, ref index);
if (instr == null || instr.OpCode.Code != Code.Ret) if (instr == null || instr.OpCode.Code != Code.Ret)
return false; return false;
return true; return true;
} }
public static FieldDef findFieldType(TypeDef typeDef, string typeName, bool isStatic) { public static FieldDef FindFieldType(TypeDef typeDef, string typeName, bool isStatic) {
if (typeDef == null) if (typeDef == null)
return null; return null;
foreach (var field in typeDef.Fields) { foreach (var field in typeDef.Fields) {
@ -101,11 +101,11 @@ namespace de4dot.blocks {
return null; return null;
} }
public static IEnumerable<MethodDef> findMethods(IEnumerable<MethodDef> methods, string returnType, string[] argsTypes) { public static IEnumerable<MethodDef> FindMethods(IEnumerable<MethodDef> methods, string returnType, string[] argsTypes) {
return findMethods(methods, returnType, argsTypes, true); return FindMethods(methods, returnType, argsTypes, true);
} }
public static IEnumerable<MethodDef> findMethods(IEnumerable<MethodDef> methods, string returnType, string[] argsTypes, bool isStatic) { public static IEnumerable<MethodDef> FindMethods(IEnumerable<MethodDef> methods, string returnType, string[] argsTypes, bool isStatic) {
foreach (var method in methods) { foreach (var method in methods) {
var sig = method.MethodSig; var sig = method.MethodSig;
if (sig == null || !method.HasBody || !sig.IsDefault) if (sig == null || !method.HasBody || !sig.IsDefault)
@ -125,32 +125,32 @@ namespace de4dot.blocks {
} }
} }
public static bool isDelegate(IType type) { public static bool IsDelegate(IType type) {
if (type == null) if (type == null)
return false; return false;
var fn = type.FullName; var fn = type.FullName;
return fn == "System.Delegate" || fn == "System.MulticastDelegate"; return fn == "System.Delegate" || fn == "System.MulticastDelegate";
} }
public static bool derivesFromDelegate(TypeDef type) { public static bool DerivesFromDelegate(TypeDef type) {
return type != null && isDelegate(type.BaseType); return type != null && IsDelegate(type.BaseType);
} }
public static bool isMethod(IMethod method, string returnType, string parameters) { public static bool IsMethod(IMethod method, string returnType, string parameters) {
return method != null && method.FullName == returnType + " " + method.DeclaringType.FullName + "::" + method.Name + parameters; return method != null && method.FullName == returnType + " " + method.DeclaringType.FullName + "::" + method.Name + parameters;
} }
public static string getDllName(string dll) { public static string GetDllName(string dll) {
if (dll.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) if (dll.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
return dll.Substring(0, dll.Length - 4); return dll.Substring(0, dll.Length - 4);
return dll; return dll;
} }
public static bool hasPinvokeMethod(TypeDef type, string methodName) { public static bool HasPinvokeMethod(TypeDef type, string methodName) {
return getPInvokeMethod(type, methodName) != null; return GetPInvokeMethod(type, methodName) != null;
} }
public static MethodDef getPInvokeMethod(TypeDef type, string methodName) { public static MethodDef GetPInvokeMethod(TypeDef type, string methodName) {
if (type == null) if (type == null)
return null; return null;
UTF8String mname = methodName; UTF8String mname = methodName;
@ -163,69 +163,69 @@ namespace de4dot.blocks {
return null; return null;
} }
public static MethodDef getPInvokeMethod(TypeDef type, string dll, string funcName) { public static MethodDef GetPInvokeMethod(TypeDef type, string dll, string funcName) {
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (isPinvokeMethod(method, dll, funcName)) if (IsPinvokeMethod(method, dll, funcName))
return method; return method;
} }
return null; return null;
} }
public static bool isPinvokeMethod(MethodDef method, string dll, string funcName) { public static bool IsPinvokeMethod(MethodDef method, string dll, string funcName) {
if (method == null) if (method == null)
return false; return false;
if (method.ImplMap == null || method.ImplMap.Name.String != funcName) if (method.ImplMap == null || method.ImplMap.Name.String != funcName)
return false; return false;
return getDllName(dll).Equals(getDllName(method.ImplMap.Module.Name.String), StringComparison.OrdinalIgnoreCase); return GetDllName(dll).Equals(GetDllName(method.ImplMap.Module.Name.String), StringComparison.OrdinalIgnoreCase);
} }
public static MethodDef getMethod(ModuleDefMD module, IMethod method) { public static MethodDef GetMethod(ModuleDefMD module, IMethod method) {
if (method == null) if (method == null)
return null; return null;
return getMethod(module, method, method.DeclaringType); return GetMethod(module, method, method.DeclaringType);
} }
public static MethodDef getMethod2(ModuleDefMD module, IMethod method) { public static MethodDef GetMethod2(ModuleDefMD module, IMethod method) {
if (method == null) if (method == null)
return null; return null;
if (method is MethodDef) if (method is MethodDef)
return (MethodDef)method; return (MethodDef)method;
var git = method.DeclaringType.TryGetGenericInstSig(); var git = method.DeclaringType.TryGetGenericInstSig();
var dt = git == null ? method.DeclaringType : git.GenericType.TypeDefOrRef; var dt = git == null ? method.DeclaringType : git.GenericType.TypeDefOrRef;
return getMethod(module, method, dt); return GetMethod(module, method, dt);
} }
static MethodDef getMethod(ModuleDefMD module, IMethod method, ITypeDefOrRef declaringType) { static MethodDef GetMethod(ModuleDefMD module, IMethod method, ITypeDefOrRef declaringType) {
if (method == null) if (method == null)
return null; return null;
if (method is MethodDef) if (method is MethodDef)
return (MethodDef)method; return (MethodDef)method;
return getMethod(getType(module, declaringType), method); return GetMethod(GetType(module, declaringType), method);
} }
public static MethodDef getMethod(TypeDef type, string returnType, string parameters) { public static MethodDef GetMethod(TypeDef type, string returnType, string parameters) {
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (isMethod(method, returnType, parameters)) if (IsMethod(method, returnType, parameters))
return method; return method;
} }
return null; return null;
} }
public static MethodDef getMethod2(ModuleDef module, IMethod method) { public static MethodDef GetMethod2(ModuleDef module, IMethod method) {
if (method == null) if (method == null)
return null; return null;
return getMethod(module, method, method.DeclaringType.ScopeType); return GetMethod(module, method, method.DeclaringType.ScopeType);
} }
public static TypeDef getType(ModuleDef module, TypeSig type) { public static TypeDef GetType(ModuleDef module, TypeSig type) {
type = type.RemovePinnedAndModifiers(); type = type.RemovePinnedAndModifiers();
var tdr = type as TypeDefOrRefSig; var tdr = type as TypeDefOrRefSig;
if (tdr == null) if (tdr == null)
return null; return null;
return getType(module, tdr.TypeDefOrRef); return GetType(module, tdr.TypeDefOrRef);
} }
public static TypeDef getType(ModuleDef module, ITypeDefOrRef type) { public static TypeDef GetType(ModuleDef module, ITypeDefOrRef type) {
var td = type as TypeDef; var td = type as TypeDef;
if (td == null) { if (td == null) {
var tr = type as TypeRef; var tr = type as TypeRef;
@ -239,15 +239,15 @@ namespace de4dot.blocks {
return td != null && td.Module == module ? td : null; return td != null && td.Module == module ? td : null;
} }
static MethodDef getMethod(ModuleDef module, IMethod method, ITypeDefOrRef declaringType) { static MethodDef GetMethod(ModuleDef module, IMethod method, ITypeDefOrRef declaringType) {
if (method == null) if (method == null)
return null; return null;
if (method is MethodDef) if (method is MethodDef)
return (MethodDef)method; return (MethodDef)method;
return getMethod(getType(module, declaringType), method); return GetMethod(GetType(module, declaringType), method);
} }
public static MethodDef getMethod(TypeDef type, IMethod methodRef) { public static MethodDef GetMethod(TypeDef type, IMethod methodRef) {
if (type == null || methodRef == null) if (type == null || methodRef == null)
return null; return null;
if (methodRef is MethodDef) if (methodRef is MethodDef)
@ -255,7 +255,7 @@ namespace de4dot.blocks {
return type.FindMethod(methodRef.Name, methodRef.MethodSig); return type.FindMethod(methodRef.Name, methodRef.MethodSig);
} }
public static IEnumerable<MethodDef> getNormalMethods(TypeDef type) { public static IEnumerable<MethodDef> GetNormalMethods(TypeDef type) {
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (method.HasImplMap) if (method.HasImplMap)
continue; continue;
@ -266,15 +266,15 @@ namespace de4dot.blocks {
} }
} }
public static FieldDef getField(ModuleDef module, IField field) { public static FieldDef GetField(ModuleDef module, IField field) {
if (field == null) if (field == null)
return null; return null;
if (field is FieldDef) if (field is FieldDef)
return (FieldDef)field; return (FieldDef)field;
return getField(getType(module, field.DeclaringType), field); return GetField(GetType(module, field.DeclaringType), field);
} }
public static FieldDef getField(TypeDef type, IField fieldRef) { public static FieldDef GetField(TypeDef type, IField fieldRef) {
if (type == null || fieldRef == null) if (type == null || fieldRef == null)
return null; return null;
if (fieldRef is FieldDef) if (fieldRef is FieldDef)
@ -282,7 +282,7 @@ namespace de4dot.blocks {
return type.FindField(fieldRef.Name, fieldRef.FieldSig); return type.FindField(fieldRef.Name, fieldRef.FieldSig);
} }
public static FieldDef getField(TypeDef type, string typeFullName) { public static FieldDef GetField(TypeDef type, string typeFullName) {
if (type == null) if (type == null)
return null; return null;
foreach (var field in type.Fields) { foreach (var field in type.Fields) {
@ -292,7 +292,7 @@ namespace de4dot.blocks {
return null; return null;
} }
public static IEnumerable<IMethod> getMethodCalls(MethodDef method) { public static IEnumerable<IMethod> GetMethodCalls(MethodDef method) {
var list = new List<IMethod>(); var list = new List<IMethod>();
if (method.HasBody) { if (method.HasBody) {
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
@ -304,7 +304,7 @@ namespace de4dot.blocks {
return list; return list;
} }
public static bool hasString(MethodDef method, string s) { public static bool HasString(MethodDef method, string s) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return false; return false;
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
@ -314,7 +314,7 @@ namespace de4dot.blocks {
return false; return false;
} }
public static IList<string> getCodeStrings(MethodDef method) { public static IList<string> GetCodeStrings(MethodDef method) {
var strings = new List<string>(); var strings = new List<string>();
if (method != null && method.Body != null) { if (method != null && method.Body != null) {
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
@ -325,17 +325,17 @@ namespace de4dot.blocks {
return strings; return strings;
} }
public static Resource getResource(ModuleDef module, string name) { public static Resource GetResource(ModuleDef module, string name) {
return getResource(module, new List<string> { name }); return GetResource(module, new List<string> { name });
} }
public static Resource getResource(ModuleDef module, IEnumerable<string> strings) { public static Resource GetResource(ModuleDef module, IEnumerable<string> strings) {
if (!module.HasResources) if (!module.HasResources)
return null; return null;
var resources = module.Resources; var resources = module.Resources;
foreach (var tmp in strings) { foreach (var tmp in strings) {
var resourceName = removeFromNullChar(tmp); var resourceName = RemoveFromNullChar(tmp);
if (resourceName == null) if (resourceName == null)
continue; continue;
UTF8String name = resourceName; UTF8String name = resourceName;
@ -348,7 +348,7 @@ namespace de4dot.blocks {
return null; return null;
} }
static string removeFromNullChar(string s) { static string RemoveFromNullChar(string s) {
int index = s.IndexOf((char)0); int index = s.IndexOf((char)0);
if (index < 0) if (index < 0)
return s; return s;
@ -356,7 +356,7 @@ namespace de4dot.blocks {
} }
// Copies most things but not everything // Copies most things but not everything
public static MethodDef clone(MethodDef method) { public static MethodDef Clone(MethodDef method) {
var newMethod = new MethodDefUser(method.Name, method.MethodSig, method.ImplAttributes, method.Attributes); var newMethod = new MethodDefUser(method.Name, method.MethodSig, method.ImplAttributes, method.Attributes);
newMethod.Rid = method.Rid; newMethod.Rid = method.Rid;
newMethod.DeclaringType2 = method.DeclaringType; newMethod.DeclaringType2 = method.DeclaringType;
@ -369,11 +369,11 @@ namespace de4dot.blocks {
newMethod.GenericParameters.Add(newGp); newMethod.GenericParameters.Add(newGp);
} }
newMethod.Body = new CilBody(); newMethod.Body = new CilBody();
copyBodyFromTo(method, newMethod); CopyBodyFromTo(method, newMethod);
return newMethod; return newMethod;
} }
public static void copyBody(MethodDef method, out IList<Instruction> instructions, out IList<ExceptionHandler> exceptionHandlers) { public static void CopyBody(MethodDef method, out IList<Instruction> instructions, out IList<ExceptionHandler> exceptionHandlers) {
if (method == null || !method.HasBody) { if (method == null || !method.HasBody) {
instructions = new List<Instruction>(); instructions = new List<Instruction>();
exceptionHandlers = new List<ExceptionHandler>(); exceptionHandlers = new List<ExceptionHandler>();
@ -384,7 +384,7 @@ namespace de4dot.blocks {
var oldExHandlers = method.Body.ExceptionHandlers; var oldExHandlers = method.Body.ExceptionHandlers;
instructions = new List<Instruction>(oldInstrs.Count); instructions = new List<Instruction>(oldInstrs.Count);
exceptionHandlers = new List<ExceptionHandler>(oldExHandlers.Count); exceptionHandlers = new List<ExceptionHandler>(oldExHandlers.Count);
var oldToIndex = Utils.createObjectToIndexDictionary(oldInstrs); var oldToIndex = Utils.CreateObjectToIndexDictionary(oldInstrs);
foreach (var oldInstr in oldInstrs) foreach (var oldInstr in oldInstrs)
instructions.Add(oldInstr.Clone()); instructions.Add(oldInstr.Clone());
@ -404,24 +404,24 @@ namespace de4dot.blocks {
foreach (var oldEx in oldExHandlers) { foreach (var oldEx in oldExHandlers) {
var newEx = new ExceptionHandler(oldEx.HandlerType) { var newEx = new ExceptionHandler(oldEx.HandlerType) {
TryStart = getInstruction(instructions, oldToIndex, oldEx.TryStart), TryStart = GetInstruction(instructions, oldToIndex, oldEx.TryStart),
TryEnd = getInstruction(instructions, oldToIndex, oldEx.TryEnd), TryEnd = GetInstruction(instructions, oldToIndex, oldEx.TryEnd),
FilterStart = getInstruction(instructions, oldToIndex, oldEx.FilterStart), FilterStart = GetInstruction(instructions, oldToIndex, oldEx.FilterStart),
HandlerStart = getInstruction(instructions, oldToIndex, oldEx.HandlerStart), HandlerStart = GetInstruction(instructions, oldToIndex, oldEx.HandlerStart),
HandlerEnd = getInstruction(instructions, oldToIndex, oldEx.HandlerEnd), HandlerEnd = GetInstruction(instructions, oldToIndex, oldEx.HandlerEnd),
CatchType = oldEx.CatchType, CatchType = oldEx.CatchType,
}; };
exceptionHandlers.Add(newEx); exceptionHandlers.Add(newEx);
} }
} }
static Instruction getInstruction(IList<Instruction> instructions, IDictionary<Instruction, int> instructionToIndex, Instruction instruction) { static Instruction GetInstruction(IList<Instruction> instructions, IDictionary<Instruction, int> instructionToIndex, Instruction instruction) {
if (instruction == null) if (instruction == null)
return null; return null;
return instructions[instructionToIndex[instruction]]; return instructions[instructionToIndex[instruction]];
} }
public static void restoreBody(MethodDef method, IEnumerable<Instruction> instructions, IEnumerable<ExceptionHandler> exceptionHandlers) { public static void RestoreBody(MethodDef method, IEnumerable<Instruction> instructions, IEnumerable<ExceptionHandler> exceptionHandlers) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return; return;
@ -436,19 +436,19 @@ namespace de4dot.blocks {
bodyExceptionHandlers.Add(eh); bodyExceptionHandlers.Add(eh);
} }
public static void copyBodyFromTo(MethodDef fromMethod, MethodDef toMethod) { public static void CopyBodyFromTo(MethodDef fromMethod, MethodDef toMethod) {
if (fromMethod == toMethod) if (fromMethod == toMethod)
return; return;
IList<Instruction> instructions; IList<Instruction> instructions;
IList<ExceptionHandler> exceptionHandlers; IList<ExceptionHandler> exceptionHandlers;
copyBody(fromMethod, out instructions, out exceptionHandlers); CopyBody(fromMethod, out instructions, out exceptionHandlers);
restoreBody(toMethod, instructions, exceptionHandlers); RestoreBody(toMethod, instructions, exceptionHandlers);
copyLocalsFromTo(fromMethod, toMethod); CopyLocalsFromTo(fromMethod, toMethod);
updateInstructionOperands(fromMethod, toMethod); UpdateInstructionOperands(fromMethod, toMethod);
} }
static void copyLocalsFromTo(MethodDef fromMethod, MethodDef toMethod) { static void CopyLocalsFromTo(MethodDef fromMethod, MethodDef toMethod) {
var fromBody = fromMethod.Body; var fromBody = fromMethod.Body;
var toBody = toMethod.Body; var toBody = toMethod.Body;
@ -457,7 +457,7 @@ namespace de4dot.blocks {
toBody.Variables.Add(new Local(local.Type)); toBody.Variables.Add(new Local(local.Type));
} }
static void updateInstructionOperands(MethodDef fromMethod, MethodDef toMethod) { static void UpdateInstructionOperands(MethodDef fromMethod, MethodDef toMethod) {
var fromBody = fromMethod.Body; var fromBody = fromMethod.Body;
var toBody = toMethod.Body; var toBody = toMethod.Body;
@ -481,7 +481,7 @@ namespace de4dot.blocks {
} }
} }
public static string getCustomArgAsString(CustomAttribute cattr, int arg) { public static string GetCustomArgAsString(CustomAttribute cattr, int arg) {
if (cattr == null || arg >= cattr.ConstructorArguments.Count) if (cattr == null || arg >= cattr.ConstructorArguments.Count)
return null; return null;
var carg = cattr.ConstructorArguments[arg]; var carg = cattr.ConstructorArguments[arg];
@ -490,7 +490,7 @@ namespace de4dot.blocks {
return UTF8String.ToSystemStringOrEmpty((UTF8String)carg.Value); return UTF8String.ToSystemStringOrEmpty((UTF8String)carg.Value);
} }
public static IEnumerable<MethodDef> getCalledMethods(ModuleDef module, MethodDef method) { public static IEnumerable<MethodDef> GetCalledMethods(ModuleDef module, MethodDef method) {
if (method != null && method.HasBody) { if (method != null && method.HasBody) {
foreach (var call in method.Body.Instructions) { foreach (var call in method.Body.Instructions) {
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt) if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
@ -498,15 +498,15 @@ namespace de4dot.blocks {
var methodRef = call.Operand as IMethod; var methodRef = call.Operand as IMethod;
if (methodRef == null) if (methodRef == null)
continue; continue;
var type = getType(module, methodRef.DeclaringType); var type = GetType(module, methodRef.DeclaringType);
var methodDef = getMethod(type, methodRef); var methodDef = GetMethod(type, methodRef);
if (methodDef != null) if (methodDef != null)
yield return methodDef; yield return methodDef;
} }
} }
} }
public static IList<Instruction> getInstructions(IList<Instruction> instructions, int i, params OpCode[] opcodes) { public static IList<Instruction> GetInstructions(IList<Instruction> instructions, int i, params OpCode[] opcodes) {
if (i + opcodes.Length > instructions.Count) if (i + opcodes.Length > instructions.Count)
return null; return null;
if (opcodes.Length == 0) if (opcodes.Length == 0)
@ -524,25 +524,25 @@ namespace de4dot.blocks {
return list; return list;
} }
public static bool hasReturnValue(IMethod method) { public static bool HasReturnValue(IMethod method) {
if (method == null || method.MethodSig == null || method.MethodSig.RetType == null) if (method == null || method.MethodSig == null || method.MethodSig.RetType == null)
return false; return false;
return method.MethodSig.RetType.RemovePinnedAndModifiers().ElementType != ElementType.Void; return method.MethodSig.RetType.RemovePinnedAndModifiers().ElementType != ElementType.Void;
} }
public static Parameter getParameter(IList<Parameter> parameters, int index) { public static Parameter GetParameter(IList<Parameter> parameters, int index) {
if (0 <= index && index < parameters.Count) if (0 <= index && index < parameters.Count)
return parameters[index]; return parameters[index];
return null; return null;
} }
public static TypeSig getArg(IList<TypeSig> args, int index) { public static TypeSig GetArg(IList<TypeSig> args, int index) {
if (0 <= index && index < args.Count) if (0 <= index && index < args.Count)
return args[index]; return args[index];
return null; return null;
} }
public static List<TypeSig> getArgs(IMethod method) { public static List<TypeSig> GetArgs(IMethod method) {
var sig = method.MethodSig; var sig = method.MethodSig;
var args = new List<TypeSig>(sig.Params.Count + 1); var args = new List<TypeSig>(sig.Params.Count + 1);
if (sig.ImplicitThis) if (sig.ImplicitThis)
@ -552,7 +552,7 @@ namespace de4dot.blocks {
return args; return args;
} }
public static int getArgsCount(IMethod method) { public static int GetArgsCount(IMethod method) {
var sig = method.MethodSig; var sig = method.MethodSig;
if (sig == null) if (sig == null)
return 0; return 0;
@ -562,22 +562,22 @@ namespace de4dot.blocks {
return count; return count;
} }
public static IList<TypeSig> replaceGenericParameters(GenericInstSig typeOwner, MethodSpec methodOwner, IList<TypeSig> types) { public static IList<TypeSig> ReplaceGenericParameters(GenericInstSig typeOwner, MethodSpec methodOwner, IList<TypeSig> types) {
if (typeOwner == null && methodOwner == null) if (typeOwner == null && methodOwner == null)
return types; return types;
for (int i = 0; i < types.Count; i++) for (int i = 0; i < types.Count; i++)
types[i] = getGenericArgument(typeOwner, methodOwner, types[i]); types[i] = GetGenericArgument(typeOwner, methodOwner, types[i]);
return types; return types;
} }
public static TypeSig getGenericArgument(GenericInstSig typeOwner, MethodSpec methodOwner, TypeSig type) { public static TypeSig GetGenericArgument(GenericInstSig typeOwner, MethodSpec methodOwner, TypeSig type) {
var typeArgs = typeOwner == null ? null : typeOwner.GenericArguments; var typeArgs = typeOwner == null ? null : typeOwner.GenericArguments;
var genMethodArgs = methodOwner == null || methodOwner.GenericInstMethodSig == null ? var genMethodArgs = methodOwner == null || methodOwner.GenericInstMethodSig == null ?
null : methodOwner.GenericInstMethodSig.GenericArguments; null : methodOwner.GenericInstMethodSig.GenericArguments;
return GenericArgsSubstitutor.create(type, typeArgs, genMethodArgs); return GenericArgsSubstitutor.Create(type, typeArgs, genMethodArgs);
} }
public static Instruction getInstruction(IList<Instruction> instructions, ref int index) { public static Instruction GetInstruction(IList<Instruction> instructions, ref int index) {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
if (index < 0 || index >= instructions.Count) if (index < 0 || index >= instructions.Count)
return null; return null;
@ -596,7 +596,7 @@ namespace de4dot.blocks {
return null; return null;
} }
public static TypeDefOrRefSig findOrCreateTypeRef(ModuleDef module, AssemblyRef asmRef, string ns, string name, bool isValueType) { public static TypeDefOrRefSig FindOrCreateTypeRef(ModuleDef module, AssemblyRef asmRef, string ns, string name, bool isValueType) {
var typeRef = module.UpdateRowId(new TypeRefUser(module, ns, name, asmRef)); var typeRef = module.UpdateRowId(new TypeRefUser(module, ns, name, asmRef));
if (isValueType) if (isValueType)
return new ValueTypeSig(typeRef); return new ValueTypeSig(typeRef);
@ -604,7 +604,7 @@ namespace de4dot.blocks {
return new ClassSig(typeRef); return new ClassSig(typeRef);
} }
public static FrameworkType getFrameworkType(ModuleDefMD module) { public static FrameworkType GetFrameworkType(ModuleDefMD module) {
foreach (var modRef in module.GetAssemblyRefs()) { foreach (var modRef in module.GetAssemblyRefs()) {
if (modRef.Name != "mscorlib") if (modRef.Name != "mscorlib")
continue; continue;
@ -627,7 +627,7 @@ namespace de4dot.blocks {
return FrameworkType.Unknown; return FrameworkType.Unknown;
} }
public static int getMethodCalls(MethodDef method, string methodFullName) { public static int GetMethodCalls(MethodDef method, string methodFullName) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return 0; return 0;
@ -645,7 +645,7 @@ namespace de4dot.blocks {
return count; return count;
} }
public static bool callsMethod(MethodDef method, string methodFullName) { public static bool CallsMethod(MethodDef method, string methodFullName) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return false; return false;
@ -662,25 +662,25 @@ namespace de4dot.blocks {
return false; return false;
} }
public static bool callsMethod(MethodDef method, string returnType, string parameters) { public static bool CallsMethod(MethodDef method, string returnType, string parameters) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return false; return false;
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt && instr.OpCode.Code != Code.Newobj) if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt && instr.OpCode.Code != Code.Newobj)
continue; continue;
if (isMethod(instr.Operand as IMethod, returnType, parameters)) if (IsMethod(instr.Operand as IMethod, returnType, parameters))
return true; return true;
} }
return false; return false;
} }
public static IList<Instruction> getArgPushes(IList<Instruction> instrs, int index) { public static IList<Instruction> GetArgPushes(IList<Instruction> instrs, int index) {
return getArgPushes(instrs, ref index); return GetArgPushes(instrs, ref index);
} }
public static IList<Instruction> getArgPushes(IList<Instruction> instrs, ref int index) { public static IList<Instruction> GetArgPushes(IList<Instruction> instrs, ref int index) {
if (index < 0 || index >= instrs.Count) if (index < 0 || index >= instrs.Count)
return null; return null;
var startInstr = instrs[index]; var startInstr = instrs[index];
@ -707,7 +707,7 @@ namespace de4dot.blocks {
if (pops != 0) { if (pops != 0) {
index++; index++;
if (getArgPushes(instrs, ref index) == null) if (GetArgPushes(instrs, ref index) == null)
return null; return null;
} }
} }

View File

@ -31,21 +31,21 @@ namespace de4dot.blocks {
get { return methods.Count; } get { return methods.Count; }
} }
public void add(uint token, DumpedMethod info) { public void Add(uint token, DumpedMethod info) {
methods[token] = info; methods[token] = info;
} }
public DumpedMethod get(MethodDef method) { public DumpedMethod Get(MethodDef method) {
return get(method.MDToken.ToUInt32()); return Get(method.MDToken.ToUInt32());
} }
public DumpedMethod get(uint token) { public DumpedMethod Get(uint token) {
DumpedMethod dm; DumpedMethod dm;
methods.TryGetValue(token, out dm); methods.TryGetValue(token, out dm);
return dm; return dm;
} }
public void add(DumpedMethod dm) { public void Add(DumpedMethod dm) {
if (MDToken.ToTable(dm.token) != Table.Method || MDToken.ToRID(dm.token) == 0) if (MDToken.ToTable(dm.token) != Table.Method || MDToken.ToRID(dm.token) == 0)
throw new ArgumentException("Invalid token"); throw new ArgumentException("Invalid token");
methods[dm.token] = dm; methods[dm.token] = dm;

View File

@ -41,7 +41,7 @@ namespace de4dot.blocks {
this.stackStart = stackStart; this.stackStart = stackStart;
} }
public void calculateStackUsage() { public void CalculateStackUsage() {
Block block = baseBlock as Block; Block block = baseBlock as Block;
if (block == null) { if (block == null) {
stackEnd = stackStart; stackEnd = stackStart;
@ -60,17 +60,17 @@ namespace de4dot.blocks {
this.sorted = sorted; this.sorted = sorted;
} }
public List<BaseBlock> fix() { public List<BaseBlock> Fix() {
createBlockInfos(); CreateBlockInfos();
createNewList(); CreateNewList();
return newList; return newList;
} }
void createBlockInfos() { void CreateBlockInfos() {
int firstBlockStackStart = scopeBlock is TryHandlerBlock ? 1 : 0; int firstBlockStackStart = scopeBlock is TryHandlerBlock ? 1 : 0;
foreach (var bb in getStartBlocks()) { foreach (var bb in GetStartBlocks()) {
int stackStart = ReferenceEquals(bb, sorted[0]) ? firstBlockStackStart : 0; int stackStart = ReferenceEquals(bb, sorted[0]) ? firstBlockStackStart : 0;
scanBaseBlock(bb, stackStart); ScanBaseBlock(bb, stackStart);
} }
// One reason for this to fail is if there are still dead blocks left. Could also // One reason for this to fail is if there are still dead blocks left. Could also
@ -79,29 +79,29 @@ namespace de4dot.blocks {
throw new ApplicationException(string.Format("Didn't add all blocks: {0} vs {1}", blockInfos.Count, sorted.Count)); throw new ApplicationException(string.Format("Didn't add all blocks: {0} vs {1}", blockInfos.Count, sorted.Count));
} }
IEnumerable<BaseBlock> getStartBlocks() { IEnumerable<BaseBlock> GetStartBlocks() {
if (sorted.Count > 0) { if (sorted.Count > 0) {
yield return sorted[0]; yield return sorted[0];
foreach (var bb in sorted) { foreach (var bb in sorted) {
if (ReferenceEquals(bb, sorted[0])) if (ReferenceEquals(bb, sorted[0]))
continue; continue;
var block = bb as Block; var block = bb as Block;
if (block == null || block.Sources == null || isOneSourceInAnotherScopeBlock(block)) if (block == null || block.Sources == null || IsOneSourceInAnotherScopeBlock(block))
yield return bb; yield return bb;
} }
} }
} }
bool isOneSourceInAnotherScopeBlock(Block block) { bool IsOneSourceInAnotherScopeBlock(Block block) {
foreach (var source in block.Sources) { foreach (var source in block.Sources) {
if (!scopeBlock.isOurBaseBlock(source)) if (!scopeBlock.IsOurBaseBlock(source))
return true; return true;
} }
return false; return false;
} }
void scanBaseBlock(BaseBlock bb, int stackStart) { void ScanBaseBlock(BaseBlock bb, int stackStart) {
if (blockInfos.ContainsKey(bb) || !scopeBlock.isOurBaseBlock(bb)) if (blockInfos.ContainsKey(bb) || !scopeBlock.IsOurBaseBlock(bb))
return; return;
var blockInfo = new BlockInfo(bb, stackStart); var blockInfo = new BlockInfo(bb, stackStart);
@ -115,38 +115,38 @@ namespace de4dot.blocks {
return; return;
} }
blockInfo.calculateStackUsage(); blockInfo.CalculateStackUsage();
foreach (var target in block.getTargets()) foreach (var target in block.GetTargets())
scanBaseBlock(target, blockInfo.stackEnd); ScanBaseBlock(target, blockInfo.stackEnd);
} }
void createNewList() { void CreateNewList() {
newList = new List<BaseBlock>(sorted.Count); newList = new List<BaseBlock>(sorted.Count);
foreach (var bb in sorted) foreach (var bb in sorted)
addToNewList(bb); AddToNewList(bb);
if (newList.Count != sorted.Count) if (newList.Count != sorted.Count)
throw new ApplicationException(string.Format("Too many/few blocks after sorting: {0} vs {1}", newList.Count, sorted.Count)); throw new ApplicationException(string.Format("Too many/few blocks after sorting: {0} vs {1}", newList.Count, sorted.Count));
if (newList.Count > 0 && !ReferenceEquals(newList[0], sorted[0])) if (newList.Count > 0 && !ReferenceEquals(newList[0], sorted[0]))
throw new ApplicationException("Start block is not first block after sorting"); throw new ApplicationException("Start block is not first block after sorting");
} }
void addToNewList(BaseBlock bb) { void AddToNewList(BaseBlock bb) {
if (inNewList.ContainsKey(bb) || !scopeBlock.isOurBaseBlock(bb)) if (inNewList.ContainsKey(bb) || !scopeBlock.IsOurBaseBlock(bb))
return; return;
inNewList[bb] = false; inNewList[bb] = false;
var blockInfo = blockInfos[bb]; var blockInfo = blockInfos[bb];
var block = bb as Block; var block = bb as Block;
if (blockInfo.stackStart == 0 || ReferenceEquals(bb, sorted[0]) || if (blockInfo.stackStart == 0 || ReferenceEquals(bb, sorted[0]) ||
block == null || block.Sources == null || isInNewList(block.Sources)) { block == null || block.Sources == null || IsInNewList(block.Sources)) {
} }
else { else {
foreach (var source in block.Sources) { foreach (var source in block.Sources) {
if (!scopeBlock.isOurBaseBlock(source)) if (!scopeBlock.IsOurBaseBlock(source))
continue; continue;
int oldCount = newList.Count; int oldCount = newList.Count;
addToNewList(source); // Make sure it's before this block AddToNewList(source); // Make sure it's before this block
if (oldCount != newList.Count) if (oldCount != newList.Count)
break; break;
} }
@ -156,7 +156,7 @@ namespace de4dot.blocks {
newList.Add(bb); newList.Add(bb);
} }
bool isInNewList(IEnumerable<Block> blocks) { bool IsInNewList(IEnumerable<Block> blocks) {
foreach (var block in blocks) { foreach (var block in blocks) {
if (inNewList.ContainsKey(block) && inNewList[block]) if (inNewList.ContainsKey(block) && inNewList[block])
return true; return true;

View File

@ -26,115 +26,115 @@ namespace de4dot.blocks {
IList<TypeSig> genericMethodArgs; IList<TypeSig> genericMethodArgs;
bool updated; bool updated;
public static ITypeDefOrRef create(ITypeDefOrRef type, GenericInstSig git) { public static ITypeDefOrRef Create(ITypeDefOrRef type, GenericInstSig git) {
if (git == null) if (git == null)
return type; return type;
return create(type, git.GenericArguments); return Create(type, git.GenericArguments);
} }
public static ITypeDefOrRef create(ITypeDefOrRef type, IList<TypeSig> genericArgs) { public static ITypeDefOrRef Create(ITypeDefOrRef type, IList<TypeSig> genericArgs) {
if (genericArgs == null || genericArgs.Count == 0) if (genericArgs == null || genericArgs.Count == 0)
return type; return type;
var ts = type as TypeSpec; var ts = type as TypeSpec;
if (ts == null) if (ts == null)
return type; return type;
var newSig = create(ts.TypeSig, genericArgs); var newSig = Create(ts.TypeSig, genericArgs);
return newSig == ts.TypeSig ? type : new TypeSpecUser(newSig); return newSig == ts.TypeSig ? type : new TypeSpecUser(newSig);
} }
public static TypeSig create(TypeSig type, IList<TypeSig> genericArgs) { public static TypeSig Create(TypeSig type, IList<TypeSig> genericArgs) {
if (type == null || genericArgs == null || genericArgs.Count == 0) if (type == null || genericArgs == null || genericArgs.Count == 0)
return type; return type;
return new GenericArgsSubstitutor(genericArgs).create(type); return new GenericArgsSubstitutor(genericArgs).Create(type);
} }
public static TypeSig create(TypeSig type, IList<TypeSig> genericArgs, IList<TypeSig> genericMethodArgs) { public static TypeSig Create(TypeSig type, IList<TypeSig> genericArgs, IList<TypeSig> genericMethodArgs) {
if (type == null || ((genericArgs == null || genericArgs.Count == 0) && if (type == null || ((genericArgs == null || genericArgs.Count == 0) &&
(genericMethodArgs == null || genericMethodArgs.Count == 0))) (genericMethodArgs == null || genericMethodArgs.Count == 0)))
return type; return type;
return new GenericArgsSubstitutor(genericArgs, genericMethodArgs).create(type); return new GenericArgsSubstitutor(genericArgs, genericMethodArgs).Create(type);
} }
public static IField create(IField field, GenericInstSig git) { public static IField Create(IField field, GenericInstSig git) {
if (git == null) if (git == null)
return field; return field;
return create(field, git.GenericArguments); return Create(field, git.GenericArguments);
} }
public static IField create(IField field, IList<TypeSig> genericArgs) { public static IField Create(IField field, IList<TypeSig> genericArgs) {
if (field == null || genericArgs == null || genericArgs.Count == 0) if (field == null || genericArgs == null || genericArgs.Count == 0)
return field; return field;
var newSig = create(field.FieldSig, genericArgs); var newSig = Create(field.FieldSig, genericArgs);
if (newSig == field.FieldSig) if (newSig == field.FieldSig)
return field; return field;
var module = field.DeclaringType != null ? field.DeclaringType.Module : null; var module = field.DeclaringType != null ? field.DeclaringType.Module : null;
return new MemberRefUser(module, field.Name, newSig, field.DeclaringType); return new MemberRefUser(module, field.Name, newSig, field.DeclaringType);
} }
public static FieldSig create(FieldSig sig, GenericInstSig git) { public static FieldSig Create(FieldSig sig, GenericInstSig git) {
if (git == null) if (git == null)
return sig; return sig;
return create(sig, git.GenericArguments); return Create(sig, git.GenericArguments);
} }
public static FieldSig create(FieldSig sig, IList<TypeSig> genericArgs) { public static FieldSig Create(FieldSig sig, IList<TypeSig> genericArgs) {
if (sig == null || genericArgs == null || genericArgs.Count == 0) if (sig == null || genericArgs == null || genericArgs.Count == 0)
return sig; return sig;
return new GenericArgsSubstitutor(genericArgs).create(sig); return new GenericArgsSubstitutor(genericArgs).Create(sig);
} }
public static IMethod create(IMethod method, GenericInstSig git) { public static IMethod Create(IMethod method, GenericInstSig git) {
if (git == null) if (git == null)
return method; return method;
var mdr = method as IMethodDefOrRef; var mdr = method as IMethodDefOrRef;
if (mdr != null) if (mdr != null)
return create(mdr, git); return Create(mdr, git);
var ms = method as MethodSpec; var ms = method as MethodSpec;
if (ms != null) if (ms != null)
return create(ms, git); return Create(ms, git);
return method; return method;
} }
public static MethodSpec create(MethodSpec method, GenericInstSig git) { public static MethodSpec Create(MethodSpec method, GenericInstSig git) {
if (method == null || git == null) if (method == null || git == null)
return method; return method;
var newMethod = create(method.Method, git); var newMethod = Create(method.Method, git);
var newInst = create(method.GenericInstMethodSig, git); var newInst = Create(method.GenericInstMethodSig, git);
bool updated = newMethod != method.Method || newInst != method.GenericInstMethodSig; bool updated = newMethod != method.Method || newInst != method.GenericInstMethodSig;
return updated ? new MethodSpecUser(newMethod, newInst) : method; return updated ? new MethodSpecUser(newMethod, newInst) : method;
} }
public static GenericInstMethodSig create(GenericInstMethodSig sig, GenericInstSig git) { public static GenericInstMethodSig Create(GenericInstMethodSig sig, GenericInstSig git) {
if (git == null) if (git == null)
return sig; return sig;
return create(sig, git.GenericArguments); return Create(sig, git.GenericArguments);
} }
public static GenericInstMethodSig create(GenericInstMethodSig sig, IList<TypeSig> genericArgs) { public static GenericInstMethodSig Create(GenericInstMethodSig sig, IList<TypeSig> genericArgs) {
if (sig == null || genericArgs == null || genericArgs.Count == 0) if (sig == null || genericArgs == null || genericArgs.Count == 0)
return sig; return sig;
return new GenericArgsSubstitutor(genericArgs).create(sig); return new GenericArgsSubstitutor(genericArgs).Create(sig);
} }
public static IMethodDefOrRef create(IMethodDefOrRef method, GenericInstSig git) { public static IMethodDefOrRef Create(IMethodDefOrRef method, GenericInstSig git) {
if (git == null) if (git == null)
return method; return method;
return create(method, git.GenericArguments); return Create(method, git.GenericArguments);
} }
public static IMethodDefOrRef create(IMethodDefOrRef method, IList<TypeSig> genericArgs) { public static IMethodDefOrRef Create(IMethodDefOrRef method, IList<TypeSig> genericArgs) {
return create(method, genericArgs, null); return Create(method, genericArgs, null);
} }
public static IMethodDefOrRef create(IMethodDefOrRef method, GenericInstSig git, IList<TypeSig> genericMethodArgs) { public static IMethodDefOrRef Create(IMethodDefOrRef method, GenericInstSig git, IList<TypeSig> genericMethodArgs) {
return create(method, git == null ? null : git.GenericArguments, genericMethodArgs); return Create(method, git == null ? null : git.GenericArguments, genericMethodArgs);
} }
// Creates a new method but keeps declaring type as is // Creates a new method but keeps declaring type as is
public static IMethodDefOrRef create(IMethodDefOrRef method, IList<TypeSig> genericArgs, IList<TypeSig> genericMethodArgs) { public static IMethodDefOrRef Create(IMethodDefOrRef method, IList<TypeSig> genericArgs, IList<TypeSig> genericMethodArgs) {
if (method == null) if (method == null)
return method; return method;
if ((genericArgs == null || genericArgs.Count == 0) && (genericMethodArgs == null || genericMethodArgs.Count == 0)) if ((genericArgs == null || genericArgs.Count == 0) && (genericMethodArgs == null || genericMethodArgs.Count == 0))
@ -144,7 +144,7 @@ namespace de4dot.blocks {
if (sig == null) if (sig == null)
return method; return method;
var newSig = new GenericArgsSubstitutor(genericArgs, genericMethodArgs).create(sig); var newSig = new GenericArgsSubstitutor(genericArgs, genericMethodArgs).Create(sig);
if (newSig == sig) if (newSig == sig)
return method; return method;
@ -163,12 +163,12 @@ namespace de4dot.blocks {
this.updated = false; this.updated = false;
} }
TypeSig create(TypeSig type) { TypeSig Create(TypeSig type) {
var newType = create2(type); var newType = Create2(type);
return updated ? newType : type; return updated ? newType : type;
} }
TypeSig create2(TypeSig type) { TypeSig Create2(TypeSig type) {
if (type == null) if (type == null)
return type; return type;
TypeSig result; TypeSig result;
@ -197,11 +197,11 @@ namespace de4dot.blocks {
break; break;
case ElementType.Ptr: case ElementType.Ptr:
result = new PtrSig(create2(type.Next)); result = new PtrSig(Create2(type.Next));
break; break;
case ElementType.ByRef: case ElementType.ByRef:
result = new ByRefSig(create2(type.Next)); result = new ByRefSig(Create2(type.Next));
break; break;
case ElementType.Array: case ElementType.Array:
@ -210,11 +210,11 @@ namespace de4dot.blocks {
break; break;
case ElementType.SZArray: case ElementType.SZArray:
result = new SZArraySig(create2(type.Next)); result = new SZArraySig(Create2(type.Next));
break; break;
case ElementType.Pinned: case ElementType.Pinned:
result = new PinnedSig(create2(type.Next)); result = new PinnedSig(Create2(type.Next));
break; break;
case ElementType.ValueType: case ElementType.ValueType:
@ -244,9 +244,9 @@ namespace de4dot.blocks {
case ElementType.GenericInst: case ElementType.GenericInst:
var gis = (GenericInstSig)type; var gis = (GenericInstSig)type;
var newGis = new GenericInstSig(create2(gis.GenericType) as ClassOrValueTypeSig, gis.GenericArguments.Count); var newGis = new GenericInstSig(Create2(gis.GenericType) as ClassOrValueTypeSig, gis.GenericArguments.Count);
for (int i = 0; i < gis.GenericArguments.Count; i++) for (int i = 0; i < gis.GenericArguments.Count; i++)
newGis.GenericArguments.Add(create2(gis.GenericArguments[i])); newGis.GenericArguments.Add(Create2(gis.GenericArguments[i]));
result = newGis; result = newGis;
break; break;
@ -267,7 +267,7 @@ namespace de4dot.blocks {
break; break;
case ElementType.FnPtr: case ElementType.FnPtr:
result = new FnPtrSig(create(((FnPtrSig)type).MethodSig)); result = new FnPtrSig(Create(((FnPtrSig)type).MethodSig));
break; break;
case ElementType.End: case ElementType.End:
@ -282,31 +282,31 @@ namespace de4dot.blocks {
return result; return result;
} }
MethodSig create(MethodSig sig) { MethodSig Create(MethodSig sig) {
if (sig == null) if (sig == null)
return sig; return sig;
var newSig = new MethodSig(sig.GetCallingConvention()); var newSig = new MethodSig(sig.GetCallingConvention());
newSig.RetType = create2(sig.RetType); newSig.RetType = Create2(sig.RetType);
for (int i = 0; i < sig.Params.Count; i++) for (int i = 0; i < sig.Params.Count; i++)
newSig.Params.Add(create2(sig.Params[i])); newSig.Params.Add(Create2(sig.Params[i]));
newSig.GenParamCount = sig.GenParamCount; newSig.GenParamCount = sig.GenParamCount;
if (sig.ParamsAfterSentinel != null) { if (sig.ParamsAfterSentinel != null) {
newSig.ParamsAfterSentinel = new List<TypeSig>(); newSig.ParamsAfterSentinel = new List<TypeSig>();
for (int i = 0; i < sig.ParamsAfterSentinel.Count; i++) for (int i = 0; i < sig.ParamsAfterSentinel.Count; i++)
newSig.ParamsAfterSentinel.Add(create2(sig.ParamsAfterSentinel[i])); newSig.ParamsAfterSentinel.Add(Create2(sig.ParamsAfterSentinel[i]));
} }
return updated ? newSig : sig; return updated ? newSig : sig;
} }
GenericInstMethodSig create(GenericInstMethodSig sig) { GenericInstMethodSig Create(GenericInstMethodSig sig) {
var newSig = new GenericInstMethodSig(); var newSig = new GenericInstMethodSig();
for (int i = 0; i < sig.GenericArguments.Count; i++) for (int i = 0; i < sig.GenericArguments.Count; i++)
newSig.GenericArguments.Add(create2(sig.GenericArguments[i])); newSig.GenericArguments.Add(Create2(sig.GenericArguments[i]));
return updated ? newSig : sig; return updated ? newSig : sig;
} }
FieldSig create(FieldSig sig) { FieldSig Create(FieldSig sig) {
var newSig = new FieldSig(create2(sig.Type)); var newSig = new FieldSig(Create2(sig.Type));
return updated ? newSig : sig; return updated ? newSig : sig;
} }
} }

View File

@ -44,11 +44,11 @@ namespace de4dot.blocks {
// Returns the variable or null if it's not a ldloc/stloc instruction. It does not return // Returns the variable or null if it's not a ldloc/stloc instruction. It does not return
// a local variable if it's a ldloca/ldloca.s instruction. // a local variable if it's a ldloca/ldloca.s instruction.
public static Local getLocalVar(IList<Local> locals, Instr instr) { public static Local GetLocalVar(IList<Local> locals, Instr instr) {
return instr.Instruction.GetLocal(locals); return instr.Instruction.GetLocal(locals);
} }
static public bool isFallThrough(OpCode opCode) { static public bool IsFallThrough(OpCode opCode) {
switch (opCode.FlowControl) { switch (opCode.FlowControl) {
case FlowControl.Call: case FlowControl.Call:
return opCode != OpCodes.Jmp; return opCode != OpCodes.Jmp;
@ -61,7 +61,7 @@ namespace de4dot.blocks {
} }
// Returns true if the instruction only pushes one value onto the stack and pops nothing // Returns true if the instruction only pushes one value onto the stack and pops nothing
public bool isSimpleLoad() { public bool IsSimpleLoad() {
switch (OpCode.Code) { switch (OpCode.Code) {
case Code.Ldarg: case Code.Ldarg:
case Code.Ldarg_S: case Code.Ldarg_S:
@ -103,55 +103,55 @@ namespace de4dot.blocks {
} }
} }
public bool isLdcI4() { public bool IsLdcI4() {
return instruction.IsLdcI4(); return instruction.IsLdcI4();
} }
public int getLdcI4Value() { public int GetLdcI4Value() {
return instruction.GetLdcI4Value(); return instruction.GetLdcI4Value();
} }
public bool isLdarg() { public bool IsLdarg() {
return instruction.IsLdarg(); return instruction.IsLdarg();
} }
public bool isStloc() { public bool IsStloc() {
return instruction.IsStloc(); return instruction.IsStloc();
} }
public bool isLdloc() { public bool IsLdloc() {
return instruction.IsLdloc(); return instruction.IsLdloc();
} }
public bool isNop() { public bool IsNop() {
return OpCode == OpCodes.Nop; return OpCode == OpCodes.Nop;
} }
public bool isPop() { public bool IsPop() {
return OpCode == OpCodes.Pop; return OpCode == OpCodes.Pop;
} }
public bool isLeave() { public bool IsLeave() {
return instruction.IsLeave(); return instruction.IsLeave();
} }
public bool isBr() { public bool IsBr() {
return instruction.IsBr(); return instruction.IsBr();
} }
public bool isBrfalse() { public bool IsBrfalse() {
return instruction.IsBrfalse(); return instruction.IsBrfalse();
} }
public bool isBrtrue() { public bool IsBrtrue() {
return instruction.IsBrtrue(); return instruction.IsBrtrue();
} }
public bool isConditionalBranch() { public bool IsConditionalBranch() {
return instruction.IsConditionalBranch(); return instruction.IsConditionalBranch();
} }
public bool getFlippedBranchOpCode(out OpCode opcode) { public bool GetFlippedBranchOpCode(out OpCode opcode) {
switch (OpCode.Code) { switch (OpCode.Code) {
case Code.Bge: opcode = OpCodes.Blt; return true; case Code.Bge: opcode = OpCodes.Blt; return true;
case Code.Bge_S: opcode = OpCodes.Blt_S; return true; case Code.Bge_S: opcode = OpCodes.Blt_S; return true;
@ -190,20 +190,20 @@ namespace de4dot.blocks {
} }
} }
public void flipConditonalBranch() { public void FlipConditonalBranch() {
OpCode opcode; OpCode opcode;
if (!getFlippedBranchOpCode(out opcode)) if (!GetFlippedBranchOpCode(out opcode))
throw new ApplicationException("Can't flip conditional since it's not a supported conditional instruction"); throw new ApplicationException("Can't flip conditional since it's not a supported conditional instruction");
instruction.OpCode = opcode; instruction.OpCode = opcode;
} }
// Returns true if we can flip a conditional branch // Returns true if we can flip a conditional branch
public bool canFlipConditionalBranch() { public bool CanFlipConditionalBranch() {
OpCode opcode; OpCode opcode;
return getFlippedBranchOpCode(out opcode); return GetFlippedBranchOpCode(out opcode);
} }
public void updateTargets(List<Instr> targets) { public void UpdateTargets(List<Instr> targets) {
switch (OpCode.OperandType) { switch (OpCode.OperandType) {
case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineBrTarget:
case OperandType.InlineBrTarget: case OperandType.InlineBrTarget:

View File

@ -33,44 +33,44 @@ namespace de4dot.blocks {
this.exceptionHandlers = exceptionHandlers; this.exceptionHandlers = exceptionHandlers;
this.branches = new Dictionary<int, List<int>>(); this.branches = new Dictionary<int, List<int>>();
createInstrToIndex(); CreateInstrToIndex();
createBranches(); CreateBranches();
createExceptionBranches(); CreateExceptionBranches();
} }
void createInstrToIndex() { void CreateInstrToIndex() {
instrToIndex = new Dictionary<Instruction, int>(); instrToIndex = new Dictionary<Instruction, int>();
for (int i = 0; i < instructions.Count; i++) for (int i = 0; i < instructions.Count; i++)
instrToIndex[instructions[i]] = i; instrToIndex[instructions[i]] = i;
} }
List<int> getBranchTargetList(int index) { List<int> GetBranchTargetList(int index) {
List<int> targetsList; List<int> targetsList;
if (!branches.TryGetValue(index, out targetsList)) if (!branches.TryGetValue(index, out targetsList))
branches[index] = targetsList = new List<int>(); branches[index] = targetsList = new List<int>();
return targetsList; return targetsList;
} }
void markAsBranchTarget(Instruction instr) { void MarkAsBranchTarget(Instruction instr) {
if (instr == null) if (instr == null)
return; return;
int index = instrToIndex[instr]; int index = instrToIndex[instr];
getBranchTargetList(index); // Just create the list GetBranchTargetList(index); // Just create the list
} }
void createExceptionBranches() { void CreateExceptionBranches() {
foreach (var eh in exceptionHandlers) { foreach (var eh in exceptionHandlers) {
markAsBranchTarget(eh.TryStart); MarkAsBranchTarget(eh.TryStart);
markAsBranchTarget(eh.TryEnd); MarkAsBranchTarget(eh.TryEnd);
markAsBranchTarget(eh.FilterStart); MarkAsBranchTarget(eh.FilterStart);
markAsBranchTarget(eh.HandlerStart); MarkAsBranchTarget(eh.HandlerStart);
markAsBranchTarget(eh.HandlerEnd); MarkAsBranchTarget(eh.HandlerEnd);
} }
} }
void createBranches() { void CreateBranches() {
for (int i = 0; i < instructions.Count; i++) { for (int i = 0; i < instructions.Count; i++) {
var instr = instructions[i]; var instr = instructions[i];
@ -113,13 +113,13 @@ namespace de4dot.blocks {
targets.Add(i + 1); targets.Add(i + 1);
for (int j = 0; j < targets.Count; j++) { for (int j = 0; j < targets.Count; j++) {
int targetIndex = targets[j]; int targetIndex = targets[j];
getBranchTargetList(targetIndex).Add(i); GetBranchTargetList(targetIndex).Add(i);
} }
} }
} }
} }
void findBlocks(List<Block> instrToBlock, List<Block> allBlocks) { void FindBlocks(List<Block> instrToBlock, List<Block> allBlocks) {
Block block = null; Block block = null;
for (var i = 0; i < instructions.Count; i++) { for (var i = 0; i < instructions.Count; i++) {
List<int> branchSources; List<int> branchSources;
@ -128,7 +128,7 @@ namespace de4dot.blocks {
allBlocks.Add(block); allBlocks.Add(block);
} }
block.add(new Instr(this.instructions[i])); block.Add(new Instr(this.instructions[i]));
instrToBlock.Add(block); instrToBlock.Add(block);
} }
} }
@ -136,7 +136,7 @@ namespace de4dot.blocks {
// Fix all branches so they now point to a Block, and not an Instruction. The // Fix all branches so they now point to a Block, and not an Instruction. The
// block's Targets field is updated, not the Instruction's Operand field. // block's Targets field is updated, not the Instruction's Operand field.
// Also update Block.FallThrough with next Block if last instr falls through. // Also update Block.FallThrough with next Block if last instr falls through.
void fixBranchTargets(List<Block> instrToBlock, List<Block> allBlocks) { void FixBranchTargets(List<Block> instrToBlock, List<Block> allBlocks) {
for (var i = 0; i < allBlocks.Count; i++) { for (var i = 0; i < allBlocks.Count; i++) {
var block = allBlocks[i]; var block = allBlocks[i];
var lastInstr = block.LastInstr; var lastInstr = block.LastInstr;
@ -160,15 +160,15 @@ namespace de4dot.blocks {
break; break;
} }
if (i + 1 < allBlocks.Count && Instr.isFallThrough(lastInstr.OpCode)) if (i + 1 < allBlocks.Count && Instr.IsFallThrough(lastInstr.OpCode))
block.FallThrough = allBlocks[i + 1]; block.FallThrough = allBlocks[i + 1];
} }
} }
// Updates the sources field of each block // Updates the sources field of each block
void fixBlockSources(List<Block> allBlocks) { void FixBlockSources(List<Block> allBlocks) {
foreach (var block in allBlocks) { foreach (var block in allBlocks) {
block.updateSources(); block.UpdateSources();
} }
} }
@ -195,7 +195,7 @@ namespace de4dot.blocks {
} }
} }
List<List<ExceptionHandler>> getSortedExceptionInfos() { List<List<ExceptionHandler>> GetSortedExceptionInfos() {
var exInfos = new Dictionary<EHInfo, List<ExceptionHandler>>(); var exInfos = new Dictionary<EHInfo, List<ExceptionHandler>>();
foreach (var eh in exceptionHandlers) { foreach (var eh in exceptionHandlers) {
List<ExceptionHandler> handlers; List<ExceptionHandler> handlers;
@ -220,8 +220,8 @@ namespace de4dot.blocks {
// Same start instruction. The nested one is the one that ends earliest, // Same start instruction. The nested one is the one that ends earliest,
// so it should be sorted before the outer one. // so it should be sorted before the outer one.
ai = getInstrIndex(a[0].TryEnd); ai = GetInstrIndex(a[0].TryEnd);
bi = getInstrIndex(b[0].TryEnd); bi = GetInstrIndex(b[0].TryEnd);
if (ai < bi) return -1; if (ai < bi) return -1;
if (ai > bi) return 1; if (ai > bi) return 1;
@ -245,7 +245,7 @@ namespace de4dot.blocks {
List<BaseBlockInfo> blocksLeft = new List<BaseBlockInfo>(); List<BaseBlockInfo> blocksLeft = new List<BaseBlockInfo>();
public void add(BaseBlock bb, int start, int end) { public void Add(BaseBlock bb, int start, int end) {
if (start < 0 || end < 0 || end < start) if (start < 0 || end < 0 || end < start)
throw new ApplicationException("Invalid start and/or end index"); throw new ApplicationException("Invalid start and/or end index");
if (blocksLeft.Count != 0) { if (blocksLeft.Count != 0) {
@ -256,7 +256,7 @@ namespace de4dot.blocks {
blocksLeft.Add(new BaseBlockInfo(start, end, bb)); blocksLeft.Add(new BaseBlockInfo(start, end, bb));
} }
int findStart(int instrIndex) { int FindStart(int instrIndex) {
for (int i = 0; i < blocksLeft.Count; i++) { for (int i = 0; i < blocksLeft.Count; i++) {
if (blocksLeft[i].startInstr == instrIndex) if (blocksLeft[i].startInstr == instrIndex)
return i; return i;
@ -264,7 +264,7 @@ namespace de4dot.blocks {
throw new ApplicationException("Could not find start BaseBlockInfo"); throw new ApplicationException("Could not find start BaseBlockInfo");
} }
int findEnd(int instrIndex) { int FindEnd(int instrIndex) {
for (int i = 0; i < blocksLeft.Count; i++) { for (int i = 0; i < blocksLeft.Count; i++) {
if (blocksLeft[i].endInstr == instrIndex) if (blocksLeft[i].endInstr == instrIndex)
return i; return i;
@ -272,14 +272,14 @@ namespace de4dot.blocks {
throw new ApplicationException("Could not find end BaseBlockInfo"); throw new ApplicationException("Could not find end BaseBlockInfo");
} }
List<BaseBlock> getBlocks(int startInstr, int endInstr, out int startIndex, out int endIndex) { List<BaseBlock> GetBlocks(int startInstr, int endInstr, out int startIndex, out int endIndex) {
if (endInstr < startInstr || startInstr < 0 || endInstr < 0) if (endInstr < startInstr || startInstr < 0 || endInstr < 0)
throw new ApplicationException("Invalid startInstr and/or endInstr"); throw new ApplicationException("Invalid startInstr and/or endInstr");
var rv = new List<BaseBlock>(); var rv = new List<BaseBlock>();
startIndex = findStart(startInstr); startIndex = FindStart(startInstr);
endIndex = findEnd(endInstr); endIndex = FindEnd(endInstr);
for (int i = startIndex; i <= endIndex; i++) for (int i = startIndex; i <= endIndex; i++)
rv.Add(blocksLeft[i].baseBlock); rv.Add(blocksLeft[i].baseBlock);
@ -288,13 +288,13 @@ namespace de4dot.blocks {
} }
// Replace the BaseBlocks with a new BaseBlock, returning the old ones. // Replace the BaseBlocks with a new BaseBlock, returning the old ones.
public List<BaseBlock> replace(int startInstr, int endInstr, ScopeBlock bb) { public List<BaseBlock> Replace(int startInstr, int endInstr, ScopeBlock bb) {
if (endInstr < startInstr) if (endInstr < startInstr)
return new List<BaseBlock>(); return new List<BaseBlock>();
int startIndex, endIndex; int startIndex, endIndex;
var rv = getBlocks(startInstr, endInstr, out startIndex, out endIndex); var rv = GetBlocks(startInstr, endInstr, out startIndex, out endIndex);
updateParent(rv, bb); UpdateParent(rv, bb);
var bbi = new BaseBlockInfo(blocksLeft[startIndex].startInstr, blocksLeft[endIndex].endInstr, bb); var bbi = new BaseBlockInfo(blocksLeft[startIndex].startInstr, blocksLeft[endIndex].endInstr, bb);
blocksLeft.RemoveRange(startIndex, endIndex - startIndex + 1); blocksLeft.RemoveRange(startIndex, endIndex - startIndex + 1);
@ -303,78 +303,78 @@ namespace de4dot.blocks {
return rv; return rv;
} }
public List<BaseBlock> getBlocks(ScopeBlock parent) { public List<BaseBlock> GetBlocks(ScopeBlock parent) {
if (blocksLeft.Count == 0) if (blocksLeft.Count == 0)
return new List<BaseBlock>(); return new List<BaseBlock>();
int startIndex, endIndex; int startIndex, endIndex;
var lb = getBlocks(0, blocksLeft[blocksLeft.Count - 1].endInstr, out startIndex, out endIndex); var lb = GetBlocks(0, blocksLeft[blocksLeft.Count - 1].endInstr, out startIndex, out endIndex);
return updateParent(lb, parent); return UpdateParent(lb, parent);
} }
List<BaseBlock> updateParent(List<BaseBlock> lb, ScopeBlock parent) { List<BaseBlock> UpdateParent(List<BaseBlock> lb, ScopeBlock parent) {
foreach (var bb in lb) foreach (var bb in lb)
bb.Parent = parent; bb.Parent = parent;
return lb; return lb;
} }
} }
BaseBlocksList createBaseBlockList(List<Block> allBlocks, List<List<ExceptionHandler>> exSorted) { BaseBlocksList CreateBaseBlockList(List<Block> allBlocks, List<List<ExceptionHandler>> exSorted) {
var bbl = new BaseBlocksList(); var bbl = new BaseBlocksList();
foreach (var block in allBlocks) { foreach (var block in allBlocks) {
int start = instrToIndex[block.FirstInstr.Instruction]; int start = instrToIndex[block.FirstInstr.Instruction];
int end = instrToIndex[block.LastInstr.Instruction]; int end = instrToIndex[block.LastInstr.Instruction];
bbl.add(block, start, end); bbl.Add(block, start, end);
} }
foreach (var exHandlers in exSorted) { foreach (var exHandlers in exSorted) {
var tryBlock = new TryBlock(); var tryBlock = new TryBlock();
var tryStart = instrToIndex[exHandlers[0].TryStart]; var tryStart = instrToIndex[exHandlers[0].TryStart];
var tryEnd = getInstrIndex(exHandlers[0].TryEnd) - 1; var tryEnd = GetInstrIndex(exHandlers[0].TryEnd) - 1;
tryBlock.BaseBlocks = bbl.replace(tryStart, tryEnd, tryBlock); tryBlock.BaseBlocks = bbl.Replace(tryStart, tryEnd, tryBlock);
foreach (var exHandler in exHandlers) { foreach (var exHandler in exHandlers) {
var tryHandlerBlock = new TryHandlerBlock(exHandler); var tryHandlerBlock = new TryHandlerBlock(exHandler);
tryBlock.addTryHandler(tryHandlerBlock); tryBlock.AddTryHandler(tryHandlerBlock);
int filterStart = -1, handlerStart = -1, handlerEnd = -1; int filterStart = -1, handlerStart = -1, handlerEnd = -1;
if (exHandler.FilterStart != null) { if (exHandler.FilterStart != null) {
filterStart = instrToIndex[exHandler.FilterStart]; filterStart = instrToIndex[exHandler.FilterStart];
var end = instrToIndex[exHandler.HandlerStart] - 1; var end = instrToIndex[exHandler.HandlerStart] - 1;
tryHandlerBlock.FilterHandlerBlock.BaseBlocks = bbl.replace(filterStart, end, tryHandlerBlock.FilterHandlerBlock); tryHandlerBlock.FilterHandlerBlock.BaseBlocks = bbl.Replace(filterStart, end, tryHandlerBlock.FilterHandlerBlock);
} }
handlerStart = instrToIndex[exHandler.HandlerStart]; handlerStart = instrToIndex[exHandler.HandlerStart];
handlerEnd = getInstrIndex(exHandler.HandlerEnd) - 1; handlerEnd = GetInstrIndex(exHandler.HandlerEnd) - 1;
tryHandlerBlock.HandlerBlock.BaseBlocks = bbl.replace(handlerStart, handlerEnd, tryHandlerBlock.HandlerBlock); tryHandlerBlock.HandlerBlock.BaseBlocks = bbl.Replace(handlerStart, handlerEnd, tryHandlerBlock.HandlerBlock);
tryHandlerBlock.BaseBlocks = bbl.replace(filterStart == -1 ? handlerStart : filterStart, handlerEnd, tryHandlerBlock); tryHandlerBlock.BaseBlocks = bbl.Replace(filterStart == -1 ? handlerStart : filterStart, handlerEnd, tryHandlerBlock);
} }
} }
return bbl; return bbl;
} }
int getInstrIndex(Instruction instruction) { int GetInstrIndex(Instruction instruction) {
if (instruction == null) if (instruction == null)
return instructions.Count; return instructions.Count;
return instrToIndex[instruction]; return instrToIndex[instruction];
} }
public MethodBlocks parse() { public MethodBlocks Parse() {
var instrToBlock = new List<Block>(instructions.Count); var instrToBlock = new List<Block>(instructions.Count);
var allBlocks = new List<Block>(); var allBlocks = new List<Block>();
findBlocks(instrToBlock, allBlocks); FindBlocks(instrToBlock, allBlocks);
fixBranchTargets(instrToBlock, allBlocks); FixBranchTargets(instrToBlock, allBlocks);
fixBlockSources(allBlocks); FixBlockSources(allBlocks);
var exSorted = getSortedExceptionInfos(); var exSorted = GetSortedExceptionInfos();
var bbl = createBaseBlockList(allBlocks, exSorted); var bbl = CreateBaseBlockList(allBlocks, exSorted);
foreach (var block in allBlocks) foreach (var block in allBlocks)
block.removeLastBr(); block.RemoveLastBr();
var mb = new MethodBlocks(); var mb = new MethodBlocks();
mb.BaseBlocks = bbl.getBlocks(mb); mb.BaseBlocks = bbl.GetBlocks(mb);
return mb; return mb;
} }
} }

View File

@ -32,23 +32,23 @@ namespace de4dot.blocks {
get { return tokenToValue.Count; } get { return tokenToValue.Count; }
} }
public IEnumerable<TypeDef> getKeys() { public IEnumerable<TypeDef> GetKeys() {
return tokenToKey.Values; return tokenToKey.Values;
} }
public IEnumerable<TValue> getValues() { public IEnumerable<TValue> GetValues() {
return tokenToValue.Values; return tokenToValue.Values;
} }
ScopeAndTokenKey getTokenKey(TypeDef typeDef) { ScopeAndTokenKey GetTokenKey(TypeDef typeDef) {
return new ScopeAndTokenKey(typeDef); return new ScopeAndTokenKey(typeDef);
} }
public TValue find(IType typeRef) { public TValue Find(IType typeRef) {
TValue value; TValue value;
var typeDef = typeRef as TypeDef; var typeDef = typeRef as TypeDef;
if (typeDef != null) if (typeDef != null)
tokenToValue.TryGetValue(getTokenKey(typeDef), out value); tokenToValue.TryGetValue(GetTokenKey(typeDef), out value);
else if (typeRef != null) else if (typeRef != null)
refToValue.TryGetValue(typeRef, out value); refToValue.TryGetValue(typeRef, out value);
else else
@ -56,23 +56,23 @@ namespace de4dot.blocks {
return value; return value;
} }
public TValue findAny(IType type) { public TValue FindAny(IType type) {
TValue value; TValue value;
var typeDef = type as TypeDef; var typeDef = type as TypeDef;
if (typeDef != null && tokenToValue.TryGetValue(getTokenKey(typeDef), out value)) if (typeDef != null && tokenToValue.TryGetValue(GetTokenKey(typeDef), out value))
return value; return value;
refToValue.TryGetValue(type, out value); refToValue.TryGetValue(type, out value);
return value; return value;
} }
public void add(TypeDef typeDef, TValue value) { public void Add(TypeDef typeDef, TValue value) {
var tokenKey = getTokenKey(typeDef); var tokenKey = GetTokenKey(typeDef);
tokenToValue[tokenKey] = value; tokenToValue[tokenKey] = value;
tokenToKey[tokenKey] = typeDef; tokenToKey[tokenKey] = typeDef;
if (!refToValue.ContainsKey(typeDef) || if (!refToValue.ContainsKey(typeDef) ||
getAccessibilityOrder(typeDef) < getAccessibilityOrder(refToKey[typeDef])) { GetAccessibilityOrder(typeDef) < GetAccessibilityOrder(refToKey[typeDef])) {
refToKey[typeDef] = typeDef; refToKey[typeDef] = typeDef;
refToValue[typeDef] = value; refToValue[typeDef] = value;
} }
@ -89,11 +89,11 @@ namespace de4dot.blocks {
60, // NestedFamANDAssem 60, // NestedFamANDAssem
30, // NestedFamORAssem 30, // NestedFamORAssem
}; };
static int getAccessibilityOrder(TypeDef typeDef) { static int GetAccessibilityOrder(TypeDef typeDef) {
return accessibilityOrder[(int)typeDef.Attributes & 7]; return accessibilityOrder[(int)typeDef.Attributes & 7];
} }
public void onTypesRenamed() { public void OnTypesRenamed() {
var newTypeRefToValue = new Dictionary<IType, TValue>(refToValue.Count); var newTypeRefToValue = new Dictionary<IType, TValue>(refToValue.Count);
foreach (var kvp in refToValue) foreach (var kvp in refToValue)
newTypeRefToValue[kvp.Key] = kvp.Value; newTypeRefToValue[kvp.Key] = kvp.Value;
@ -111,48 +111,48 @@ namespace de4dot.blocks {
get { return tokenToValue.Count; } get { return tokenToValue.Count; }
} }
public IEnumerable<FieldDef> getKeys() { public IEnumerable<FieldDef> GetKeys() {
return tokenToKey.Values; return tokenToKey.Values;
} }
public IEnumerable<TValue> getValues() { public IEnumerable<TValue> GetValues() {
return tokenToValue.Values; return tokenToValue.Values;
} }
ScopeAndTokenKey getTokenKey(FieldDef fieldDef) { ScopeAndTokenKey GetTokenKey(FieldDef fieldDef) {
return new ScopeAndTokenKey(fieldDef); return new ScopeAndTokenKey(fieldDef);
} }
internal abstract IFieldRefKey getRefKey(IField fieldRef); internal abstract IFieldRefKey GetRefKey(IField fieldRef);
public TValue find(IField fieldRef) { public TValue Find(IField fieldRef) {
TValue value; TValue value;
var fieldDef = fieldRef as FieldDef; var fieldDef = fieldRef as FieldDef;
if (fieldDef != null) if (fieldDef != null)
tokenToValue.TryGetValue(getTokenKey(fieldDef), out value); tokenToValue.TryGetValue(GetTokenKey(fieldDef), out value);
else else
refToValue.TryGetValue(getRefKey(fieldRef), out value); refToValue.TryGetValue(GetRefKey(fieldRef), out value);
return value; return value;
} }
public TValue findAny(IField fieldRef) { public TValue FindAny(IField fieldRef) {
TValue value; TValue value;
var fieldDef = fieldRef as FieldDef; var fieldDef = fieldRef as FieldDef;
if (fieldDef != null && tokenToValue.TryGetValue(getTokenKey(fieldDef), out value)) if (fieldDef != null && tokenToValue.TryGetValue(GetTokenKey(fieldDef), out value))
return value; return value;
refToValue.TryGetValue(getRefKey(fieldRef), out value); refToValue.TryGetValue(GetRefKey(fieldRef), out value);
return value; return value;
} }
public void add(FieldDef fieldDef, TValue value) { public void Add(FieldDef fieldDef, TValue value) {
var tokenKey = getTokenKey(fieldDef); var tokenKey = GetTokenKey(fieldDef);
tokenToValue[tokenKey] = value; tokenToValue[tokenKey] = value;
tokenToKey[tokenKey] = fieldDef; tokenToKey[tokenKey] = fieldDef;
var refKey = getRefKey(fieldDef); var refKey = GetRefKey(fieldDef);
if (!refToValue.ContainsKey(refKey) || if (!refToValue.ContainsKey(refKey) ||
getAccessibilityOrder(fieldDef) < getAccessibilityOrder(refToKey[refKey])) { GetAccessibilityOrder(fieldDef) < GetAccessibilityOrder(refToKey[refKey])) {
refToKey[refKey] = fieldDef; refToKey[refKey] = fieldDef;
refToValue[refKey] = value; refToValue[refKey] = value;
} }
@ -169,26 +169,26 @@ namespace de4dot.blocks {
0, // Public 0, // Public
70, // <reserved> 70, // <reserved>
}; };
static int getAccessibilityOrder(FieldDef fieldDef) { static int GetAccessibilityOrder(FieldDef fieldDef) {
return accessibilityOrder[(int)fieldDef.Attributes & 7]; return accessibilityOrder[(int)fieldDef.Attributes & 7];
} }
public void onTypesRenamed() { public void OnTypesRenamed() {
var newFieldRefToDef = new Dictionary<IFieldRefKey, TValue>(refToValue.Count); var newFieldRefToDef = new Dictionary<IFieldRefKey, TValue>(refToValue.Count);
foreach (var kvp in refToValue) foreach (var kvp in refToValue)
newFieldRefToDef[getRefKey((FieldDef)kvp.Key.FieldRef)] = kvp.Value; newFieldRefToDef[GetRefKey((FieldDef)kvp.Key.FieldRef)] = kvp.Value;
refToValue = newFieldRefToDef; refToValue = newFieldRefToDef;
} }
} }
public class FieldDefDict<TValue> : FieldDefDictBase<TValue> { public class FieldDefDict<TValue> : FieldDefDictBase<TValue> {
internal override IFieldRefKey getRefKey(IField fieldRef) { internal override IFieldRefKey GetRefKey(IField fieldRef) {
return new FieldRefKey(fieldRef); return new FieldRefKey(fieldRef);
} }
} }
public class FieldDefAndDeclaringTypeDict<TValue> : FieldDefDictBase<TValue> { public class FieldDefAndDeclaringTypeDict<TValue> : FieldDefDictBase<TValue> {
internal override IFieldRefKey getRefKey(IField fieldRef) { internal override IFieldRefKey GetRefKey(IField fieldRef) {
return new FieldRefAndDeclaringTypeKey(fieldRef); return new FieldRefAndDeclaringTypeKey(fieldRef);
} }
} }
@ -203,48 +203,48 @@ namespace de4dot.blocks {
get { return tokenToValue.Count; } get { return tokenToValue.Count; }
} }
public IEnumerable<MethodDef> getKeys() { public IEnumerable<MethodDef> GetKeys() {
return tokenToKey.Values; return tokenToKey.Values;
} }
public IEnumerable<TValue> getValues() { public IEnumerable<TValue> GetValues() {
return tokenToValue.Values; return tokenToValue.Values;
} }
ScopeAndTokenKey getTokenKey(MethodDef methodDef) { ScopeAndTokenKey GetTokenKey(MethodDef methodDef) {
return new ScopeAndTokenKey(methodDef); return new ScopeAndTokenKey(methodDef);
} }
internal abstract IMethodRefKey getRefKey(IMethod methodRef); internal abstract IMethodRefKey GetRefKey(IMethod methodRef);
public TValue find(IMethod methodRef) { public TValue Find(IMethod methodRef) {
TValue value; TValue value;
var methodDef = methodRef as MethodDef; var methodDef = methodRef as MethodDef;
if (methodDef != null) if (methodDef != null)
tokenToValue.TryGetValue(getTokenKey(methodDef), out value); tokenToValue.TryGetValue(GetTokenKey(methodDef), out value);
else else
refToValue.TryGetValue(getRefKey(methodRef), out value); refToValue.TryGetValue(GetRefKey(methodRef), out value);
return value; return value;
} }
public TValue findAny(IMethod methodRef) { public TValue FindAny(IMethod methodRef) {
TValue value; TValue value;
var methodDef = methodRef as MethodDef; var methodDef = methodRef as MethodDef;
if (methodDef != null && tokenToValue.TryGetValue(getTokenKey(methodDef), out value)) if (methodDef != null && tokenToValue.TryGetValue(GetTokenKey(methodDef), out value))
return value; return value;
refToValue.TryGetValue(getRefKey(methodRef), out value); refToValue.TryGetValue(GetRefKey(methodRef), out value);
return value; return value;
} }
public void add(MethodDef methodDef, TValue value) { public void Add(MethodDef methodDef, TValue value) {
var tokenKey = getTokenKey(methodDef); var tokenKey = GetTokenKey(methodDef);
tokenToValue[tokenKey] = value; tokenToValue[tokenKey] = value;
tokenToKey[tokenKey] = methodDef; tokenToKey[tokenKey] = methodDef;
var refKey = getRefKey(methodDef); var refKey = GetRefKey(methodDef);
if (!refToValue.ContainsKey(refKey) || if (!refToValue.ContainsKey(refKey) ||
getAccessibilityOrder(methodDef) < getAccessibilityOrder(refToKey[refKey])) { GetAccessibilityOrder(methodDef) < GetAccessibilityOrder(refToKey[refKey])) {
refToKey[refKey] = methodDef; refToKey[refKey] = methodDef;
refToValue[refKey] = value; refToValue[refKey] = value;
} }
@ -261,26 +261,26 @@ namespace de4dot.blocks {
0, // Public 0, // Public
70, // <reserved> 70, // <reserved>
}; };
static int getAccessibilityOrder(MethodDef methodDef) { static int GetAccessibilityOrder(MethodDef methodDef) {
return accessibilityOrder[(int)methodDef.Attributes & 7]; return accessibilityOrder[(int)methodDef.Attributes & 7];
} }
public void onTypesRenamed() { public void OnTypesRenamed() {
var newFieldRefToDef = new Dictionary<IMethodRefKey, TValue>(refToValue.Count); var newFieldRefToDef = new Dictionary<IMethodRefKey, TValue>(refToValue.Count);
foreach (var kvp in refToValue) foreach (var kvp in refToValue)
newFieldRefToDef[getRefKey((MethodDef)kvp.Key.MethodRef)] = kvp.Value; newFieldRefToDef[GetRefKey((MethodDef)kvp.Key.MethodRef)] = kvp.Value;
refToValue = newFieldRefToDef; refToValue = newFieldRefToDef;
} }
} }
public class MethodDefDict<TValue> : MethodDefDictBase<TValue> { public class MethodDefDict<TValue> : MethodDefDictBase<TValue> {
internal override IMethodRefKey getRefKey(IMethod methodRef) { internal override IMethodRefKey GetRefKey(IMethod methodRef) {
return new MethodRefKey(methodRef); return new MethodRefKey(methodRef);
} }
} }
public class MethodDefAndDeclaringTypeDict<TValue> : MethodDefDictBase<TValue> { public class MethodDefAndDeclaringTypeDict<TValue> : MethodDefDictBase<TValue> {
internal override IMethodRefKey getRefKey(IMethod methodRef) { internal override IMethodRefKey GetRefKey(IMethod methodRef) {
return new MethodRefAndDeclaringTypeKey(methodRef); return new MethodRefAndDeclaringTypeKey(methodRef);
} }
} }
@ -294,59 +294,59 @@ namespace de4dot.blocks {
get { return tokenToValue.Count; } get { return tokenToValue.Count; }
} }
public IEnumerable<EventDef> getKeys() { public IEnumerable<EventDef> GetKeys() {
return tokenToKey.Values; return tokenToKey.Values;
} }
public IEnumerable<TValue> getValues() { public IEnumerable<TValue> GetValues() {
return tokenToValue.Values; return tokenToValue.Values;
} }
ScopeAndTokenKey getTokenKey(EventDef eventRef) { ScopeAndTokenKey GetTokenKey(EventDef eventRef) {
return new ScopeAndTokenKey(eventRef); return new ScopeAndTokenKey(eventRef);
} }
internal abstract IEventRefKey getRefKey(EventDef eventRef); internal abstract IEventRefKey GetRefKey(EventDef eventRef);
public TValue find(EventDef eventRef) { public TValue Find(EventDef eventRef) {
TValue value; TValue value;
tokenToValue.TryGetValue(getTokenKey(eventRef), out value); tokenToValue.TryGetValue(GetTokenKey(eventRef), out value);
return value; return value;
} }
public TValue findAny(EventDef eventRef) { public TValue FindAny(EventDef eventRef) {
TValue value; TValue value;
if (tokenToValue.TryGetValue(getTokenKey(eventRef), out value)) if (tokenToValue.TryGetValue(GetTokenKey(eventRef), out value))
return value; return value;
refToValue.TryGetValue(getRefKey(eventRef), out value); refToValue.TryGetValue(GetRefKey(eventRef), out value);
return value; return value;
} }
public void add(EventDef eventDef, TValue value) { public void Add(EventDef eventDef, TValue value) {
var tokenKey = getTokenKey(eventDef); var tokenKey = GetTokenKey(eventDef);
tokenToValue[tokenKey] = value; tokenToValue[tokenKey] = value;
tokenToKey[tokenKey] = eventDef; tokenToKey[tokenKey] = eventDef;
refToValue[getRefKey(eventDef)] = value; refToValue[GetRefKey(eventDef)] = value;
} }
public void onTypesRenamed() { public void OnTypesRenamed() {
var newFieldRefToDef = new Dictionary<IEventRefKey, TValue>(refToValue.Count); var newFieldRefToDef = new Dictionary<IEventRefKey, TValue>(refToValue.Count);
foreach (var kvp in refToValue) foreach (var kvp in refToValue)
newFieldRefToDef[getRefKey((EventDef)kvp.Key.EventDef)] = kvp.Value; newFieldRefToDef[GetRefKey((EventDef)kvp.Key.EventDef)] = kvp.Value;
refToValue = newFieldRefToDef; refToValue = newFieldRefToDef;
} }
} }
public class EventDefDict<TValue> : EventDefDictBase<TValue> { public class EventDefDict<TValue> : EventDefDictBase<TValue> {
internal override IEventRefKey getRefKey(EventDef eventRef) { internal override IEventRefKey GetRefKey(EventDef eventRef) {
return new EventRefKey(eventRef); return new EventRefKey(eventRef);
} }
} }
public class EventDefAndDeclaringTypeDict<TValue> : EventDefDictBase<TValue> { public class EventDefAndDeclaringTypeDict<TValue> : EventDefDictBase<TValue> {
internal override IEventRefKey getRefKey(EventDef eventRef) { internal override IEventRefKey GetRefKey(EventDef eventRef) {
return new EventRefAndDeclaringTypeKey(eventRef); return new EventRefAndDeclaringTypeKey(eventRef);
} }
} }
@ -360,59 +360,59 @@ namespace de4dot.blocks {
get { return tokenToValue.Count; } get { return tokenToValue.Count; }
} }
public IEnumerable<PropertyDef> getKeys() { public IEnumerable<PropertyDef> GetKeys() {
return tokenToKey.Values; return tokenToKey.Values;
} }
public IEnumerable<TValue> getValues() { public IEnumerable<TValue> GetValues() {
return tokenToValue.Values; return tokenToValue.Values;
} }
ScopeAndTokenKey getTokenKey(PropertyDef propertyRef) { ScopeAndTokenKey GetTokenKey(PropertyDef propertyRef) {
return new ScopeAndTokenKey(propertyRef); return new ScopeAndTokenKey(propertyRef);
} }
internal abstract IPropertyRefKey getRefKey(PropertyDef propertyRef); internal abstract IPropertyRefKey GetRefKey(PropertyDef propertyRef);
public TValue find(PropertyDef propRef) { public TValue Find(PropertyDef propRef) {
TValue value; TValue value;
tokenToValue.TryGetValue(getTokenKey(propRef), out value); tokenToValue.TryGetValue(GetTokenKey(propRef), out value);
return value; return value;
} }
public TValue findAny(PropertyDef propRef) { public TValue FindAny(PropertyDef propRef) {
TValue value; TValue value;
if (tokenToValue.TryGetValue(getTokenKey(propRef), out value)) if (tokenToValue.TryGetValue(GetTokenKey(propRef), out value))
return value; return value;
refToValue.TryGetValue(getRefKey(propRef), out value); refToValue.TryGetValue(GetRefKey(propRef), out value);
return value; return value;
} }
public void add(PropertyDef propDef, TValue value) { public void Add(PropertyDef propDef, TValue value) {
var tokenKey = getTokenKey(propDef); var tokenKey = GetTokenKey(propDef);
tokenToValue[tokenKey] = value; tokenToValue[tokenKey] = value;
tokenToKey[tokenKey] = propDef; tokenToKey[tokenKey] = propDef;
refToValue[getRefKey(propDef)] = value; refToValue[GetRefKey(propDef)] = value;
} }
public void onTypesRenamed() { public void OnTypesRenamed() {
var newFieldRefToDef = new Dictionary<IPropertyRefKey, TValue>(refToValue.Count); var newFieldRefToDef = new Dictionary<IPropertyRefKey, TValue>(refToValue.Count);
foreach (var kvp in refToValue) foreach (var kvp in refToValue)
newFieldRefToDef[getRefKey((PropertyDef)kvp.Key.PropertyDef)] = kvp.Value; newFieldRefToDef[GetRefKey((PropertyDef)kvp.Key.PropertyDef)] = kvp.Value;
refToValue = newFieldRefToDef; refToValue = newFieldRefToDef;
} }
} }
public class PropertyDefDict<TValue> : PropertyDefDictBase<TValue> { public class PropertyDefDict<TValue> : PropertyDefDictBase<TValue> {
internal override IPropertyRefKey getRefKey(PropertyDef propRef) { internal override IPropertyRefKey GetRefKey(PropertyDef propRef) {
return new PropertyRefKey(propRef); return new PropertyRefKey(propRef);
} }
} }
public class PropertyDefAndDeclaringTypeDict<TValue> : PropertyDefDictBase<TValue> { public class PropertyDefAndDeclaringTypeDict<TValue> : PropertyDefDictBase<TValue> {
internal override IPropertyRefKey getRefKey(PropertyDef propRef) { internal override IPropertyRefKey GetRefKey(PropertyDef propRef) {
return new PropertyRefAndDeclaringTypeKey(propRef); return new PropertyRefAndDeclaringTypeKey(propRef);
} }
} }
@ -467,16 +467,16 @@ namespace de4dot.blocks {
return true; return true;
if (a == null || b == null) if (a == null || b == null)
return false; return false;
return getCanonicalizedScopeName(a) == getCanonicalizedScopeName(b); return GetCanonicalizedScopeName(a) == GetCanonicalizedScopeName(b);
} }
static int GetHashCode(IScope a) { static int GetHashCode(IScope a) {
if (a == null) if (a == null)
return 0; return 0;
return getCanonicalizedScopeName(a).GetHashCode(); return GetCanonicalizedScopeName(a).GetHashCode();
} }
static string getAssemblyName(IScope a) { static string GetAssemblyName(IScope a) {
switch (a.ScopeType) { switch (a.ScopeType) {
case ScopeType.AssemblyRef: case ScopeType.AssemblyRef:
return ((AssemblyRef)a).Name.String; return ((AssemblyRef)a).Name.String;
@ -489,10 +489,10 @@ namespace de4dot.blocks {
return null; return null;
} }
static string getCanonicalizedScopeName(IScope a) { static string GetCanonicalizedScopeName(IScope a) {
if (a == null) if (a == null)
return string.Empty; return string.Empty;
var asmName = getAssemblyName(a); var asmName = GetAssemblyName(a);
if (asmName != null) { if (asmName != null) {
// The version number should be ignored. Older code may reference an old version of // The version number should be ignored. Older code may reference an old version of
// the assembly, but if the newer one has been loaded, that one is used. // the assembly, but if the newer one has been loaded, that one is used.

View File

@ -32,52 +32,52 @@ namespace de4dot.blocks {
set { baseBlocks = value; } set { baseBlocks = value; }
} }
public IEnumerable<BaseBlock> getBaseBlocks() { public IEnumerable<BaseBlock> GetBaseBlocks() {
if (baseBlocks != null) { if (baseBlocks != null) {
foreach (var bb in baseBlocks) foreach (var bb in baseBlocks)
yield return bb; yield return bb;
} }
} }
public List<BaseBlock> getAllBaseBlocks() { public List<BaseBlock> GetAllBaseBlocks() {
return getTheBlocks(new List<BaseBlock>()); return GetTheBlocks(new List<BaseBlock>());
} }
public List<Block> getAllBlocks() { public List<Block> GetAllBlocks() {
return getTheBlocks(new List<Block>()); return GetTheBlocks(new List<Block>());
} }
public List<Block> getAllBlocks(List<Block> allBlocks) { public List<Block> GetAllBlocks(List<Block> allBlocks) {
allBlocks.Clear(); allBlocks.Clear();
return getTheBlocks(allBlocks); return GetTheBlocks(allBlocks);
} }
public List<ScopeBlock> getAllScopeBlocks() { public List<ScopeBlock> GetAllScopeBlocks() {
return getTheBlocks(new List<ScopeBlock>()); return GetTheBlocks(new List<ScopeBlock>());
} }
public List<T> getTheBlocks<T>(List<T> list) where T : BaseBlock { public List<T> GetTheBlocks<T>(List<T> list) where T : BaseBlock {
addBlocks(list, this); AddBlocks(list, this);
return list; return list;
} }
void addBlocks<T>(IList<T> list, ScopeBlock scopeBlock) where T : BaseBlock { void AddBlocks<T>(IList<T> list, ScopeBlock scopeBlock) where T : BaseBlock {
foreach (var bb in scopeBlock.getBaseBlocks()) { foreach (var bb in scopeBlock.GetBaseBlocks()) {
T t = bb as T; T t = bb as T;
if (t != null) if (t != null)
list.Add(t); list.Add(t);
if (bb is ScopeBlock) if (bb is ScopeBlock)
addBlocks(list, (ScopeBlock)bb); AddBlocks(list, (ScopeBlock)bb);
} }
} }
List<Block> findBlocks() { List<Block> FindBlocks() {
return findBlocks(null); return FindBlocks(null);
} }
List<Block> findBlocks(Func<Block, bool> blockChecker) { List<Block> FindBlocks(Func<Block, bool> blockChecker) {
var blocks = new List<Block>(); var blocks = new List<Block>();
foreach (var bb in getBaseBlocks()) { foreach (var bb in GetBaseBlocks()) {
Block block = bb as Block; Block block = bb as Block;
if (block != null && (blockChecker == null || blockChecker(block))) if (block != null && (blockChecker == null || blockChecker(block)))
blocks.Add(block); blocks.Add(block);
@ -85,7 +85,7 @@ namespace de4dot.blocks {
return blocks; return blocks;
} }
internal bool getLdcValue(Instr instr, out int value) { internal bool GetLdcValue(Instr instr, out int value) {
if (Code.Ldc_I4_0 <= instr.OpCode.Code && instr.OpCode.Code <= Code.Ldc_I4_8) if (Code.Ldc_I4_0 <= instr.OpCode.Code && instr.OpCode.Code <= Code.Ldc_I4_8)
value = instr.OpCode.Code - Code.Ldc_I4_0; value = instr.OpCode.Code - Code.Ldc_I4_0;
else if (instr.OpCode.Code == Code.Ldc_I4) else if (instr.OpCode.Code == Code.Ldc_I4)
@ -103,18 +103,18 @@ namespace de4dot.blocks {
// Remove the block if it's a dead block. If it has refs to other dead blocks, those // Remove the block if it's a dead block. If it has refs to other dead blocks, those
// are also removed. // are also removed.
public void removeDeadBlock(Block block) { public void RemoveDeadBlock(Block block) {
removeDeadBlocks(new List<Block> { block }); RemoveDeadBlocks(new List<Block> { block });
} }
// Remove all dead blocks we can find // Remove all dead blocks we can find
public void removeDeadBlocks() { public void RemoveDeadBlocks() {
removeDeadBlocks(findBlocks()); RemoveDeadBlocks(FindBlocks());
} }
// Remove the blocks if they're dead blocks. If they have refs to other dead blocks, // Remove the blocks if they're dead blocks. If they have refs to other dead blocks,
// those are also removed. // those are also removed.
public void removeDeadBlocks(List<Block> blocks) { public void RemoveDeadBlocks(List<Block> blocks) {
while (blocks.Count != 0) { while (blocks.Count != 0) {
var block = blocks[blocks.Count - 1]; var block = blocks[blocks.Count - 1];
blocks.RemoveAt(blocks.Count - 1); blocks.RemoveAt(blocks.Count - 1);
@ -122,7 +122,7 @@ namespace de4dot.blocks {
continue; // Not dead continue; // Not dead
if (block == baseBlocks[0]) if (block == baseBlocks[0])
continue; // It's the start of this block fence so must be present continue; // It's the start of this block fence so must be present
if (!isOurBaseBlock(block)) if (!IsOurBaseBlock(block))
continue; // Some other ScopeBlock owns it, eg. first instr of an exception handler continue; // Some other ScopeBlock owns it, eg. first instr of an exception handler
// It's a dead block we can delete! // It's a dead block we can delete!
@ -131,27 +131,27 @@ namespace de4dot.blocks {
blocks.Add(block.FallThrough); blocks.Add(block.FallThrough);
if (block.Targets != null) if (block.Targets != null)
blocks.AddRange(block.Targets); blocks.AddRange(block.Targets);
block.removeDeadBlock(); block.RemoveDeadBlock();
if (!baseBlocks.Remove(block)) if (!baseBlocks.Remove(block))
throw new ApplicationException("Could not remove dead block from baseBlocks"); throw new ApplicationException("Could not remove dead block from baseBlocks");
} }
} }
public bool isOurBaseBlock(BaseBlock bb) { public bool IsOurBaseBlock(BaseBlock bb) {
return bb != null && bb.Parent == this; return bb != null && bb.Parent == this;
} }
// For each block, if it has only one target, and the target has only one source, then // For each block, if it has only one target, and the target has only one source, then
// merge them into one block. // merge them into one block.
public int mergeBlocks() { public int MergeBlocks() {
int mergedBlocks = 0; int mergedBlocks = 0;
var blocks = findBlocks(); var blocks = FindBlocks();
for (int i = 0; i < blocks.Count; i++) { for (int i = 0; i < blocks.Count; i++) {
var block = blocks[i]; var block = blocks[i];
var target = block.getOnlyTarget(); var target = block.GetOnlyTarget();
if (!isOurBaseBlock(target)) if (!IsOurBaseBlock(target))
continue; // Only merge blocks we own! continue; // Only merge blocks we own!
if (!block.canMerge(target)) if (!block.CanMerge(target))
continue; // Can't merge them! continue; // Can't merge them!
if (target == baseBlocks[0]) if (target == baseBlocks[0])
continue; // The first one has an implicit source (eg. start of method or exception handler) continue; // The first one has an implicit source (eg. start of method or exception handler)
@ -160,7 +160,7 @@ namespace de4dot.blocks {
if (targetIndex < 0) if (targetIndex < 0)
throw new ApplicationException("Could not remove target block from blocks"); throw new ApplicationException("Could not remove target block from blocks");
blocks.RemoveAt(targetIndex); blocks.RemoveAt(targetIndex);
block.merge(target); block.Merge(target);
if (!baseBlocks.Remove(target)) if (!baseBlocks.Remove(target))
throw new ApplicationException("Could not remove merged block from baseBlocks"); throw new ApplicationException("Could not remove merged block from baseBlocks");
if (targetIndex < i) if (targetIndex < i)
@ -174,20 +174,20 @@ namespace de4dot.blocks {
// If bb is in baseBlocks (a direct child), return bb. If bb is a BaseBlock in a // If bb is in baseBlocks (a direct child), return bb. If bb is a BaseBlock in a
// ScopeBlock that is a direct child, then return that ScopeBlock. Else return null. // ScopeBlock that is a direct child, then return that ScopeBlock. Else return null.
public BaseBlock toChild(BaseBlock bb) { public BaseBlock ToChild(BaseBlock bb) {
if (isOurBaseBlock(bb)) if (IsOurBaseBlock(bb))
return bb; return bb;
for (var sb = bb.Parent; sb != null; sb = sb.Parent) { for (var sb = bb.Parent; sb != null; sb = sb.Parent) {
if (isOurBaseBlock(sb)) if (IsOurBaseBlock(sb))
return sb; return sb;
} }
return null; return null;
} }
internal void repartitionBlocks() { internal void RepartitionBlocks() {
var newBaseBlocks = new BlocksSorter(this).sort(); var newBaseBlocks = new BlocksSorter(this).Sort();
const bool insane = true; const bool insane = true;
if (insane) { if (insane) {
@ -206,7 +206,7 @@ namespace de4dot.blocks {
// Removes the TryBlock and all its TryHandlerBlocks. The code inside the try block // Removes the TryBlock and all its TryHandlerBlocks. The code inside the try block
// is not removed. // is not removed.
public void removeTryBlock(TryBlock tryBlock) { public void RemoveTryBlock(TryBlock tryBlock) {
int tryBlockIndex = baseBlocks.IndexOf(tryBlock); int tryBlockIndex = baseBlocks.IndexOf(tryBlock);
if (tryBlockIndex < 0) if (tryBlockIndex < 0)
throw new ApplicationException("Can't remove the TryBlock since it's not this ScopeBlock's TryBlock"); throw new ApplicationException("Can't remove the TryBlock since it's not this ScopeBlock's TryBlock");
@ -220,15 +220,15 @@ namespace de4dot.blocks {
// Get removed blocks and make sure they're not referenced by remaining code // Get removed blocks and make sure they're not referenced by remaining code
var removedBlocks = new List<Block>(); var removedBlocks = new List<Block>();
foreach (var handler in tryBlock.TryHandlerBlocks) foreach (var handler in tryBlock.TryHandlerBlocks)
handler.getTheBlocks(removedBlocks); handler.GetTheBlocks(removedBlocks);
if (!verifyNoExternalRefs(removedBlocks)) if (!VerifyNoExternalRefs(removedBlocks))
throw new ApplicationException("Removed blocks are referenced by remaining code"); throw new ApplicationException("Removed blocks are referenced by remaining code");
removeAllDeadBlocks(Utils.convert<TryHandlerBlock, BaseBlock>(tryBlock.TryHandlerBlocks)); RemoveAllDeadBlocks(Utils.Convert<TryHandlerBlock, BaseBlock>(tryBlock.TryHandlerBlocks));
} }
// Returns true if no external blocks references the blocks // Returns true if no external blocks references the blocks
static bool verifyNoExternalRefs(IList<Block> removedBlocks) { static bool VerifyNoExternalRefs(IList<Block> removedBlocks) {
var removedDict = new Dictionary<Block, bool>(); var removedDict = new Dictionary<Block, bool>();
foreach (var removedBlock in removedBlocks) foreach (var removedBlock in removedBlocks)
removedDict[removedBlock] = true; removedDict[removedBlock] = true;
@ -243,13 +243,13 @@ namespace de4dot.blocks {
} }
// Remove all blocks in deadBlocks. They're guaranteed to be dead. // Remove all blocks in deadBlocks. They're guaranteed to be dead.
void removeAllDeadBlocks(IEnumerable<BaseBlock> deadBlocks) { void RemoveAllDeadBlocks(IEnumerable<BaseBlock> deadBlocks) {
removeAllDeadBlocks(deadBlocks, null); RemoveAllDeadBlocks(deadBlocks, null);
} }
// Remove all blocks in deadBlocks. They're guaranteed to be dead. deadBlocksDict is // Remove all blocks in deadBlocks. They're guaranteed to be dead. deadBlocksDict is
// a dictionary of all dead blocks (even those not in this ScopeBlock). // a dictionary of all dead blocks (even those not in this ScopeBlock).
internal void removeAllDeadBlocks(IEnumerable<BaseBlock> deadBlocks, Dictionary<BaseBlock, bool> deadBlocksDict) { internal void RemoveAllDeadBlocks(IEnumerable<BaseBlock> deadBlocks, Dictionary<BaseBlock, bool> deadBlocksDict) {
// Verify that all the blocks really are dead. If all their source blocks are // Verify that all the blocks really are dead. If all their source blocks are
// dead, then they are dead. // dead, then they are dead.
@ -260,7 +260,7 @@ namespace de4dot.blocks {
allDeadBlocks.Add(bb as Block); allDeadBlocks.Add(bb as Block);
else if (bb is ScopeBlock) { else if (bb is ScopeBlock) {
var sb = (ScopeBlock)bb; var sb = (ScopeBlock)bb;
allDeadBlocks.AddRange(sb.getAllBlocks()); allDeadBlocks.AddRange(sb.GetAllBlocks());
} }
else else
throw new ApplicationException(string.Format("Unknown BaseBlock type {0}", bb.GetType())); throw new ApplicationException(string.Format("Unknown BaseBlock type {0}", bb.GetType()));
@ -278,20 +278,20 @@ namespace de4dot.blocks {
} }
foreach (var block in allDeadBlocks) foreach (var block in allDeadBlocks)
block.removeGuaranteedDeadBlock(); block.RemoveGuaranteedDeadBlock();
foreach (var bb in deadBlocks) { foreach (var bb in deadBlocks) {
if (!baseBlocks.Remove(bb)) if (!baseBlocks.Remove(bb))
throw new ApplicationException("Could not remove dead base block from baseBlocks"); throw new ApplicationException("Could not remove dead base block from baseBlocks");
} }
} }
public void removeGuaranteedDeadBlock(Block block) { public void RemoveGuaranteedDeadBlock(Block block) {
if (!baseBlocks.Remove(block)) if (!baseBlocks.Remove(block))
throw new ApplicationException("Could not remove dead block"); throw new ApplicationException("Could not remove dead block");
block.removeGuaranteedDeadBlock(); block.RemoveGuaranteedDeadBlock();
} }
public void add(Block block) { public void Add(Block block) {
if (block.Parent != null) if (block.Parent != null)
throw new ApplicationException("Block already has a parent"); throw new ApplicationException("Block already has a parent");
baseBlocks.Add(block); baseBlocks.Add(block);

View File

@ -31,7 +31,7 @@ namespace de4dot.blocks {
get { return handlerBlocks; } get { return handlerBlocks; }
} }
public void addTryHandler(TryHandlerBlock tryHandlerBlock) { public void AddTryHandler(TryHandlerBlock tryHandlerBlock) {
handlerBlocks.Add(tryHandlerBlock); handlerBlocks.Add(tryHandlerBlock);
} }
} }

View File

@ -47,21 +47,21 @@ namespace de4dot.blocks {
} }
static class Utils { static class Utils {
public static IDictionary<T, int> createObjectToIndexDictionary<T>(IList<T> objs) { public static IDictionary<T, int> CreateObjectToIndexDictionary<T>(IList<T> objs) {
var dict = new Dictionary<T, int>(); var dict = new Dictionary<T, int>();
for (int i = 0; i < objs.Count; i++) for (int i = 0; i < objs.Count; i++)
dict[objs[i]] = i; dict[objs[i]] = i;
return dict; return dict;
} }
public static List<TOut> convert<TIn, TOut>(IEnumerable<TIn> list) where TIn : TOut { public static List<TOut> Convert<TIn, TOut>(IEnumerable<TIn> list) where TIn : TOut {
var olist = new List<TOut>(); var olist = new List<TOut>();
foreach (var l in list) foreach (var l in list)
olist.Add(l); olist.Add(l);
return olist; return olist;
} }
public static IEnumerable<T> unique<T>(IEnumerable<T> values) { public static IEnumerable<T> Unique<T>(IEnumerable<T> values) {
// HashSet is only available in .NET 3.5 and later. // HashSet is only available in .NET 3.5 and later.
var dict = new Dictionary<T, bool>(); var dict = new Dictionary<T, bool>();
foreach (var val in values) foreach (var val in values)

View File

@ -31,11 +31,11 @@ namespace de4dot.blocks.cflow {
branchEmulator = new BranchEmulator(instructionEmulator, this); branchEmulator = new BranchEmulator(instructionEmulator, this);
} }
protected override bool deobfuscate(Block block) { protected override bool Deobfuscate(Block block) {
this.block = block; this.block = block;
if (!block.LastInstr.isConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch) if (!block.LastInstr.IsConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch)
return false; return false;
instructionEmulator.init(blocks); instructionEmulator.Initialize(blocks);
var instructions = block.Instructions; var instructions = block.Instructions;
if (instructions.Count == 0) if (instructions.Count == 0)
@ -43,7 +43,7 @@ namespace de4dot.blocks.cflow {
try { try {
for (int i = 0; i < instructions.Count - 1; i++) { for (int i = 0; i < instructions.Count - 1; i++) {
var instr = instructions[i].Instruction; var instr = instructions[i].Instruction;
instructionEmulator.emulate(instr); instructionEmulator.Emulate(instr);
} }
} }
catch (NullReferenceException) { catch (NullReferenceException) {
@ -51,28 +51,28 @@ namespace de4dot.blocks.cflow {
return false; return false;
} }
return branchEmulator.emulate(block.LastInstr.Instruction); return branchEmulator.Emulate(block.LastInstr.Instruction);
} }
void popPushedArgs(int stackArgs) { void PopPushedArgs(int stackArgs) {
// Pop the arguments to the bcc instruction. The dead code remover will get rid of the // Pop the arguments to the bcc instruction. The dead code remover will get rid of the
// pop and any pushed arguments. Insert the pops just before the bcc instr. // pop and any pushed arguments. Insert the pops just before the bcc instr.
for (int i = 0; i < stackArgs; i++) for (int i = 0; i < stackArgs; i++)
block.insert(block.Instructions.Count - 1, OpCodes.Pop.ToInstruction()); block.Insert(block.Instructions.Count - 1, OpCodes.Pop.ToInstruction());
} }
void IBranchHandler.handleNormal(int stackArgs, bool isTaken) { void IBranchHandler.HandleNormal(int stackArgs, bool isTaken) {
popPushedArgs(stackArgs); PopPushedArgs(stackArgs);
block.replaceBccWithBranch(isTaken); block.ReplaceBccWithBranch(isTaken);
} }
bool IBranchHandler.handleSwitch(Int32Value switchIndex) { bool IBranchHandler.HandleSwitch(Int32Value switchIndex) {
var target = CflowUtils.getSwitchTarget(block.Targets, block.FallThrough, switchIndex); var target = CflowUtils.GetSwitchTarget(block.Targets, block.FallThrough, switchIndex);
if (target == null) if (target == null)
return false; return false;
popPushedArgs(1); PopPushedArgs(1);
block.replaceSwitchWithBranch(target); block.ReplaceSwitchWithBranch(target);
return true; return true;
} }
} }

View File

@ -27,17 +27,17 @@ namespace de4dot.blocks.cflow {
public bool ExecuteOnNoChange { get; set; } public bool ExecuteOnNoChange { get; set; }
public virtual void deobfuscateBegin(Blocks blocks) { public virtual void DeobfuscateBegin(Blocks blocks) {
this.blocks = blocks; this.blocks = blocks;
} }
public bool deobfuscate(List<Block> allBlocks) { public bool Deobfuscate(List<Block> allBlocks) {
init(allBlocks); Initialize(allBlocks);
bool changed = false; bool changed = false;
foreach (var block in allBlocks) { foreach (var block in allBlocks) {
try { try {
changed |= deobfuscate(block); changed |= Deobfuscate(block);
} }
catch (NullReferenceException) { catch (NullReferenceException) {
// Here if eg. invalid metadata token in a call instruction (operand is null) // Here if eg. invalid metadata token in a call instruction (operand is null)
@ -46,10 +46,10 @@ namespace de4dot.blocks.cflow {
return changed; return changed;
} }
protected virtual void init(List<Block> allBlocks) { protected virtual void Initialize(List<Block> allBlocks) {
this.allBlocks = allBlocks; this.allBlocks = allBlocks;
} }
protected abstract bool deobfuscate(Block block); protected abstract bool Deobfuscate(Block block);
} }
} }

View File

@ -28,15 +28,15 @@ namespace de4dot.blocks.cflow {
List<IBlocksDeobfuscator> ourBlocksDeobfuscators = new List<IBlocksDeobfuscator>(); List<IBlocksDeobfuscator> ourBlocksDeobfuscators = new List<IBlocksDeobfuscator>();
public BlocksCflowDeobfuscator() { public BlocksCflowDeobfuscator() {
init(); Initialize();
} }
public BlocksCflowDeobfuscator(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscator) { public BlocksCflowDeobfuscator(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscator) {
init(); Initialize();
add(blocksDeobfuscator); Add(blocksDeobfuscator);
} }
void init() { void Initialize() {
ourBlocksDeobfuscators.Add(new BlockCflowDeobfuscator { ExecuteOnNoChange = false }); ourBlocksDeobfuscators.Add(new BlockCflowDeobfuscator { ExecuteOnNoChange = false });
ourBlocksDeobfuscators.Add(new SwitchCflowDeobfuscator { ExecuteOnNoChange = false }); ourBlocksDeobfuscators.Add(new SwitchCflowDeobfuscator { ExecuteOnNoChange = false });
ourBlocksDeobfuscators.Add(new DeadStoreRemover { ExecuteOnNoChange = false }); ourBlocksDeobfuscators.Add(new DeadStoreRemover { ExecuteOnNoChange = false });
@ -46,73 +46,73 @@ namespace de4dot.blocks.cflow {
ourBlocksDeobfuscators.Add(new DupBlockCflowDeobfuscator { ExecuteOnNoChange = true }); ourBlocksDeobfuscators.Add(new DupBlockCflowDeobfuscator { ExecuteOnNoChange = true });
} }
public void add(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscators) { public void Add(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscators) {
foreach (var bd in blocksDeobfuscators) foreach (var bd in blocksDeobfuscators)
add(bd); Add(bd);
} }
public void add(IBlocksDeobfuscator blocksDeobfuscator) { public void Add(IBlocksDeobfuscator blocksDeobfuscator) {
if (blocksDeobfuscator != null) if (blocksDeobfuscator != null)
userBlocksDeobfuscators.Add(blocksDeobfuscator); userBlocksDeobfuscators.Add(blocksDeobfuscator);
} }
public void init(Blocks blocks) { public void Initialize(Blocks blocks) {
this.blocks = blocks; this.blocks = blocks;
} }
public void deobfuscate() { public void Deobfuscate() {
bool changed; bool changed;
int iterations = -1; int iterations = -1;
deobfuscateBegin(userBlocksDeobfuscators); DeobfuscateBegin(userBlocksDeobfuscators);
deobfuscateBegin(ourBlocksDeobfuscators); DeobfuscateBegin(ourBlocksDeobfuscators);
do { do {
iterations++; iterations++;
changed = false; changed = false;
removeDeadBlocks(); RemoveDeadBlocks();
mergeBlocks(); MergeBlocks();
blocks.MethodBlocks.getAllBlocks(allBlocks); blocks.MethodBlocks.GetAllBlocks(allBlocks);
if (iterations == 0) if (iterations == 0)
changed |= fixDotfuscatorLoop(); changed |= FixDotfuscatorLoop();
changed |= deobfuscate(userBlocksDeobfuscators, allBlocks); changed |= Deobfuscate(userBlocksDeobfuscators, allBlocks);
changed |= deobfuscate(ourBlocksDeobfuscators, allBlocks); changed |= Deobfuscate(ourBlocksDeobfuscators, allBlocks);
changed |= deobfuscateNoChange(changed, userBlocksDeobfuscators, allBlocks); changed |= DeobfuscateNoChange(changed, userBlocksDeobfuscators, allBlocks);
changed |= deobfuscateNoChange(changed, ourBlocksDeobfuscators, allBlocks); changed |= DeobfuscateNoChange(changed, ourBlocksDeobfuscators, allBlocks);
} while (changed); } while (changed);
} }
void deobfuscateBegin(IEnumerable<IBlocksDeobfuscator> bds) { void DeobfuscateBegin(IEnumerable<IBlocksDeobfuscator> bds) {
foreach (var bd in bds) foreach (var bd in bds)
bd.deobfuscateBegin(blocks); bd.DeobfuscateBegin(blocks);
} }
bool deobfuscate(IEnumerable<IBlocksDeobfuscator> bds, List<Block> allBlocks) { bool Deobfuscate(IEnumerable<IBlocksDeobfuscator> bds, List<Block> allBlocks) {
bool changed = false; bool changed = false;
foreach (var bd in bds) { foreach (var bd in bds) {
if (bd.ExecuteOnNoChange) if (bd.ExecuteOnNoChange)
continue; continue;
changed |= bd.deobfuscate(allBlocks); changed |= bd.Deobfuscate(allBlocks);
} }
return changed; return changed;
} }
bool deobfuscateNoChange(bool changed, IEnumerable<IBlocksDeobfuscator> bds, List<Block> allBlocks) { bool DeobfuscateNoChange(bool changed, IEnumerable<IBlocksDeobfuscator> bds, List<Block> allBlocks) {
foreach (var bd in bds) { foreach (var bd in bds) {
if (changed) if (changed)
break; break;
if (!bd.ExecuteOnNoChange) if (!bd.ExecuteOnNoChange)
continue; continue;
changed |= bd.deobfuscate(allBlocks); changed |= bd.Deobfuscate(allBlocks);
} }
return changed; return changed;
} }
// Hack for old Dotfuscator // Hack for old Dotfuscator
bool fixDotfuscatorLoop() { bool FixDotfuscatorLoop() {
/* /*
blk1: blk1:
... ...
@ -136,7 +136,7 @@ namespace de4dot.blocks.cflow {
continue; continue;
if (instructions[1].OpCode.Code != Code.Dup) if (instructions[1].OpCode.Code != Code.Dup)
continue; continue;
if (!instructions[2].isLdcI4()) if (!instructions[2].IsLdcI4())
continue; continue;
if (instructions[3].OpCode.Code != Code.Sub && instructions[3].OpCode.Code != Code.Add) if (instructions[3].OpCode.Code != Code.Sub && instructions[3].OpCode.Code != Code.Add)
continue; continue;
@ -148,32 +148,32 @@ namespace de4dot.blocks.cflow {
var prev = block.Sources[0]; var prev = block.Sources[0];
if (prev == block) if (prev == block)
prev = block.Sources[1]; prev = block.Sources[1];
if (prev == null || !prev.LastInstr.isLdcI4()) if (prev == null || !prev.LastInstr.IsLdcI4())
continue; continue;
var next = block.FallThrough; var next = block.FallThrough;
if (next.FirstInstr.OpCode.Code != Code.Pop) if (next.FirstInstr.OpCode.Code != Code.Pop)
continue; continue;
block.replaceLastInstrsWithBranch(5, next); block.ReplaceLastInstrsWithBranch(5, next);
changed = true; changed = true;
} }
return changed; return changed;
} }
bool removeDeadBlocks() { bool RemoveDeadBlocks() {
return new DeadBlocksRemover(blocks.MethodBlocks).remove() > 0; return new DeadBlocksRemover(blocks.MethodBlocks).Remove() > 0;
} }
bool mergeBlocks() { bool MergeBlocks() {
bool changed = false; bool changed = false;
foreach (var scopeBlock in getAllScopeBlocks(blocks.MethodBlocks)) foreach (var scopeBlock in GetAllScopeBlocks(blocks.MethodBlocks))
changed |= scopeBlock.mergeBlocks() > 0; changed |= scopeBlock.MergeBlocks() > 0;
return changed; return changed;
} }
IEnumerable<ScopeBlock> getAllScopeBlocks(ScopeBlock scopeBlock) { IEnumerable<ScopeBlock> GetAllScopeBlocks(ScopeBlock scopeBlock) {
var list = new List<ScopeBlock>(); var list = new List<ScopeBlock>();
list.Add(scopeBlock); list.Add(scopeBlock);
list.AddRange(scopeBlock.getAllScopeBlocks()); list.AddRange(scopeBlock.GetAllScopeBlocks());
return list; return list;
} }
} }

View File

@ -22,10 +22,10 @@ using dnlib.DotNet.Emit;
namespace de4dot.blocks.cflow { namespace de4dot.blocks.cflow {
public interface IBranchHandler { public interface IBranchHandler {
// stackArgs is the number of args used by the branch instruction (1 or 2) // stackArgs is the number of args used by the branch instruction (1 or 2)
void handleNormal(int stackArgs, bool isTaken); void HandleNormal(int stackArgs, bool isTaken);
// Returns true if the switch target was found (even if it was the fall-through) // Returns true if the switch target was found (even if it was the fall-through)
bool handleSwitch(Int32Value switchIndex); bool HandleSwitch(Int32Value switchIndex);
} }
public class BranchEmulator { public class BranchEmulator {
@ -37,216 +37,216 @@ namespace de4dot.blocks.cflow {
this.branchHandler = branchHandler; this.branchHandler = branchHandler;
} }
public bool emulate(Instruction instr) { public bool Emulate(Instruction instr) {
switch (instr.OpCode.Code) { switch (instr.OpCode.Code) {
case Code.Br: case Code.Br:
case Code.Br_S: return emulate_Br(); case Code.Br_S: return Emulate_Br();
case Code.Beq: case Code.Beq:
case Code.Beq_S: return emulate_Beq(); case Code.Beq_S: return Emulate_Beq();
case Code.Bge: case Code.Bge:
case Code.Bge_S: return emulate_Bge(); case Code.Bge_S: return Emulate_Bge();
case Code.Bge_Un: case Code.Bge_Un:
case Code.Bge_Un_S: return emulate_Bge_Un(); case Code.Bge_Un_S: return Emulate_Bge_Un();
case Code.Bgt: case Code.Bgt:
case Code.Bgt_S: return emulate_Bgt(); case Code.Bgt_S: return Emulate_Bgt();
case Code.Bgt_Un: case Code.Bgt_Un:
case Code.Bgt_Un_S: return emulate_Bgt_Un(); case Code.Bgt_Un_S: return Emulate_Bgt_Un();
case Code.Ble: case Code.Ble:
case Code.Ble_S: return emulate_Ble(); case Code.Ble_S: return Emulate_Ble();
case Code.Ble_Un: case Code.Ble_Un:
case Code.Ble_Un_S: return emulate_Ble_Un(); case Code.Ble_Un_S: return Emulate_Ble_Un();
case Code.Blt: case Code.Blt:
case Code.Blt_S: return emulate_Blt(); case Code.Blt_S: return Emulate_Blt();
case Code.Blt_Un: case Code.Blt_Un:
case Code.Blt_Un_S: return emulate_Blt_Un(); case Code.Blt_Un_S: return Emulate_Blt_Un();
case Code.Bne_Un: case Code.Bne_Un:
case Code.Bne_Un_S: return emulate_Bne_Un(); case Code.Bne_Un_S: return Emulate_Bne_Un();
case Code.Brfalse: case Code.Brfalse:
case Code.Brfalse_S:return emulate_Brfalse(); case Code.Brfalse_S:return Emulate_Brfalse();
case Code.Brtrue: case Code.Brtrue:
case Code.Brtrue_S: return emulate_Brtrue(); case Code.Brtrue_S: return Emulate_Brtrue();
case Code.Switch: return emulate_Switch(); case Code.Switch: return Emulate_Switch();
default: default:
return false; return false;
} }
} }
bool emulateBranch(int stackArgs, Bool3 cond) { bool EmulateBranch(int stackArgs, Bool3 cond) {
if (cond == Bool3.Unknown) if (cond == Bool3.Unknown)
return false; return false;
return emulateBranch(stackArgs, cond == Bool3.True); return EmulateBranch(stackArgs, cond == Bool3.True);
} }
bool emulateBranch(int stackArgs, bool isTaken) { bool EmulateBranch(int stackArgs, bool isTaken) {
branchHandler.handleNormal(stackArgs, isTaken); branchHandler.HandleNormal(stackArgs, isTaken);
return true; return true;
} }
bool emulate_Br() { bool Emulate_Br() {
return emulateBranch(0, true); return EmulateBranch(0, true);
} }
bool emulate_Beq() { bool Emulate_Beq() {
var val2 = instructionEmulator.pop(); var val2 = instructionEmulator.Pop();
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32() && val2.isInt32()) if (val1.IsInt32() && val2.IsInt32())
return emulateBranch(2, Int32Value.compareEq((Int32Value)val1, (Int32Value)val2)); return EmulateBranch(2, Int32Value.CompareEq((Int32Value)val1, (Int32Value)val2));
else if (val1.isInt64() && val2.isInt64()) else if (val1.IsInt64() && val2.IsInt64())
return emulateBranch(2, Int64Value.compareEq((Int64Value)val1, (Int64Value)val2)); return EmulateBranch(2, Int64Value.CompareEq((Int64Value)val1, (Int64Value)val2));
else if (val1.isNull() && val2.isNull()) else if (val1.IsNull() && val2.IsNull())
return emulateBranch(2, true); return EmulateBranch(2, true);
else else
return false; return false;
} }
bool emulate_Bne_Un() { bool Emulate_Bne_Un() {
var val2 = instructionEmulator.pop(); var val2 = instructionEmulator.Pop();
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32() && val2.isInt32()) if (val1.IsInt32() && val2.IsInt32())
return emulateBranch(2, Int32Value.compareNeq((Int32Value)val1, (Int32Value)val2)); return EmulateBranch(2, Int32Value.CompareNeq((Int32Value)val1, (Int32Value)val2));
else if (val1.isInt64() && val2.isInt64()) else if (val1.IsInt64() && val2.IsInt64())
return emulateBranch(2, Int64Value.compareNeq((Int64Value)val1, (Int64Value)val2)); return EmulateBranch(2, Int64Value.CompareNeq((Int64Value)val1, (Int64Value)val2));
else if (val1.isNull() && val2.isNull()) else if (val1.IsNull() && val2.IsNull())
return emulateBranch(2, false); return EmulateBranch(2, false);
else else
return false; return false;
} }
bool emulate_Bge() { bool Emulate_Bge() {
var val2 = instructionEmulator.pop(); var val2 = instructionEmulator.Pop();
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32() && val2.isInt32()) if (val1.IsInt32() && val2.IsInt32())
return emulateBranch(2, Int32Value.compareGe((Int32Value)val1, (Int32Value)val2)); return EmulateBranch(2, Int32Value.CompareGe((Int32Value)val1, (Int32Value)val2));
else if (val1.isInt64() && val2.isInt64()) else if (val1.IsInt64() && val2.IsInt64())
return emulateBranch(2, Int64Value.compareGe((Int64Value)val1, (Int64Value)val2)); return EmulateBranch(2, Int64Value.CompareGe((Int64Value)val1, (Int64Value)val2));
else else
return false; return false;
} }
bool emulate_Bge_Un() { bool Emulate_Bge_Un() {
var val2 = instructionEmulator.pop(); var val2 = instructionEmulator.Pop();
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32() && val2.isInt32()) if (val1.IsInt32() && val2.IsInt32())
return emulateBranch(2, Int32Value.compareGe_Un((Int32Value)val1, (Int32Value)val2)); return EmulateBranch(2, Int32Value.CompareGe_Un((Int32Value)val1, (Int32Value)val2));
else if (val1.isInt64() && val2.isInt64()) else if (val1.IsInt64() && val2.IsInt64())
return emulateBranch(2, Int64Value.compareGe_Un((Int64Value)val1, (Int64Value)val2)); return EmulateBranch(2, Int64Value.CompareGe_Un((Int64Value)val1, (Int64Value)val2));
else else
return false; return false;
} }
bool emulate_Bgt() { bool Emulate_Bgt() {
var val2 = instructionEmulator.pop(); var val2 = instructionEmulator.Pop();
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32() && val2.isInt32()) if (val1.IsInt32() && val2.IsInt32())
return emulateBranch(2, Int32Value.compareGt((Int32Value)val1, (Int32Value)val2)); return EmulateBranch(2, Int32Value.CompareGt((Int32Value)val1, (Int32Value)val2));
else if (val1.isInt64() && val2.isInt64()) else if (val1.IsInt64() && val2.IsInt64())
return emulateBranch(2, Int64Value.compareGt((Int64Value)val1, (Int64Value)val2)); return EmulateBranch(2, Int64Value.CompareGt((Int64Value)val1, (Int64Value)val2));
else else
return false; return false;
} }
bool emulate_Bgt_Un() { bool Emulate_Bgt_Un() {
var val2 = instructionEmulator.pop(); var val2 = instructionEmulator.Pop();
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32() && val2.isInt32()) if (val1.IsInt32() && val2.IsInt32())
return emulateBranch(2, Int32Value.compareGt_Un((Int32Value)val1, (Int32Value)val2)); return EmulateBranch(2, Int32Value.CompareGt_Un((Int32Value)val1, (Int32Value)val2));
else if (val1.isInt64() && val2.isInt64()) else if (val1.IsInt64() && val2.IsInt64())
return emulateBranch(2, Int64Value.compareGt_Un((Int64Value)val1, (Int64Value)val2)); return EmulateBranch(2, Int64Value.CompareGt_Un((Int64Value)val1, (Int64Value)val2));
else else
return false; return false;
} }
bool emulate_Ble() { bool Emulate_Ble() {
var val2 = instructionEmulator.pop(); var val2 = instructionEmulator.Pop();
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32() && val2.isInt32()) if (val1.IsInt32() && val2.IsInt32())
return emulateBranch(2, Int32Value.compareLe((Int32Value)val1, (Int32Value)val2)); return EmulateBranch(2, Int32Value.CompareLe((Int32Value)val1, (Int32Value)val2));
else if (val1.isInt64() && val2.isInt64()) else if (val1.IsInt64() && val2.IsInt64())
return emulateBranch(2, Int64Value.compareLe((Int64Value)val1, (Int64Value)val2)); return EmulateBranch(2, Int64Value.CompareLe((Int64Value)val1, (Int64Value)val2));
else else
return false; return false;
} }
bool emulate_Ble_Un() { bool Emulate_Ble_Un() {
var val2 = instructionEmulator.pop(); var val2 = instructionEmulator.Pop();
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32() && val2.isInt32()) if (val1.IsInt32() && val2.IsInt32())
return emulateBranch(2, Int32Value.compareLe_Un((Int32Value)val1, (Int32Value)val2)); return EmulateBranch(2, Int32Value.CompareLe_Un((Int32Value)val1, (Int32Value)val2));
else if (val1.isInt64() && val2.isInt64()) else if (val1.IsInt64() && val2.IsInt64())
return emulateBranch(2, Int64Value.compareLe_Un((Int64Value)val1, (Int64Value)val2)); return EmulateBranch(2, Int64Value.CompareLe_Un((Int64Value)val1, (Int64Value)val2));
else else
return false; return false;
} }
bool emulate_Blt() { bool Emulate_Blt() {
var val2 = instructionEmulator.pop(); var val2 = instructionEmulator.Pop();
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32() && val2.isInt32()) if (val1.IsInt32() && val2.IsInt32())
return emulateBranch(2, Int32Value.compareLt((Int32Value)val1, (Int32Value)val2)); return EmulateBranch(2, Int32Value.CompareLt((Int32Value)val1, (Int32Value)val2));
else if (val1.isInt64() && val2.isInt64()) else if (val1.IsInt64() && val2.IsInt64())
return emulateBranch(2, Int64Value.compareLt((Int64Value)val1, (Int64Value)val2)); return EmulateBranch(2, Int64Value.CompareLt((Int64Value)val1, (Int64Value)val2));
else else
return false; return false;
} }
bool emulate_Blt_Un() { bool Emulate_Blt_Un() {
var val2 = instructionEmulator.pop(); var val2 = instructionEmulator.Pop();
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32() && val2.isInt32()) if (val1.IsInt32() && val2.IsInt32())
return emulateBranch(2, Int32Value.compareLt_Un((Int32Value)val1, (Int32Value)val2)); return EmulateBranch(2, Int32Value.CompareLt_Un((Int32Value)val1, (Int32Value)val2));
else if (val1.isInt64() && val2.isInt64()) else if (val1.IsInt64() && val2.IsInt64())
return emulateBranch(2, Int64Value.compareLt_Un((Int64Value)val1, (Int64Value)val2)); return EmulateBranch(2, Int64Value.CompareLt_Un((Int64Value)val1, (Int64Value)val2));
else else
return false; return false;
} }
bool emulate_Brfalse() { bool Emulate_Brfalse() {
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32()) if (val1.IsInt32())
return emulateBranch(1, Int32Value.compareFalse((Int32Value)val1)); return EmulateBranch(1, Int32Value.CompareFalse((Int32Value)val1));
else if (val1.isInt64()) else if (val1.IsInt64())
return emulateBranch(1, Int64Value.compareFalse((Int64Value)val1)); return EmulateBranch(1, Int64Value.CompareFalse((Int64Value)val1));
else if (val1.isNull()) else if (val1.IsNull())
return emulateBranch(1, true); return EmulateBranch(1, true);
else if (val1.isObject() || val1.isString()) else if (val1.IsObject() || val1.IsString())
return emulateBranch(1, false); return EmulateBranch(1, false);
else else
return false; return false;
} }
bool emulate_Brtrue() { bool Emulate_Brtrue() {
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (val1.isInt32()) if (val1.IsInt32())
return emulateBranch(1, Int32Value.compareTrue((Int32Value)val1)); return EmulateBranch(1, Int32Value.CompareTrue((Int32Value)val1));
else if (val1.isInt64()) else if (val1.IsInt64())
return emulateBranch(1, Int64Value.compareTrue((Int64Value)val1)); return EmulateBranch(1, Int64Value.CompareTrue((Int64Value)val1));
else if (val1.isNull()) else if (val1.IsNull())
return emulateBranch(1, false); return EmulateBranch(1, false);
else if (val1.isObject() || val1.isString()) else if (val1.IsObject() || val1.IsString())
return emulateBranch(1, true); return EmulateBranch(1, true);
else else
return false; return false;
} }
bool emulate_Switch() { bool Emulate_Switch() {
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (!val1.isInt32()) if (!val1.IsInt32())
return false; return false;
return branchHandler.handleSwitch((Int32Value)val1); return branchHandler.HandleSwitch((Int32Value)val1);
} }
} }
} }

View File

@ -31,19 +31,19 @@ namespace de4dot.blocks.cflow {
} }
public CachedCflowDeobfuscator(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscators) { public CachedCflowDeobfuscator(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscators) {
add(blocksDeobfuscators); Add(blocksDeobfuscators);
} }
public void add(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscators) { public void Add(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscators) {
foreach (var bd in blocksDeobfuscators) foreach (var bd in blocksDeobfuscators)
cflowDeobfuscator.add(bd); cflowDeobfuscator.Add(bd);
} }
public void add(IBlocksDeobfuscator blocksDeobfuscator) { public void Add(IBlocksDeobfuscator blocksDeobfuscator) {
cflowDeobfuscator.add(blocksDeobfuscator); cflowDeobfuscator.Add(blocksDeobfuscator);
} }
public MethodDef deobfuscate(MethodDef method) { public MethodDef Deobfuscate(MethodDef method) {
MethodDef deobfuscatedMethod; MethodDef deobfuscatedMethod;
if (deobfuscated.TryGetValue(method, out deobfuscatedMethod)) if (deobfuscated.TryGetValue(method, out deobfuscatedMethod))
return deobfuscatedMethod; return deobfuscatedMethod;
@ -53,22 +53,22 @@ namespace de4dot.blocks.cflow {
return method; return method;
} }
deobfuscatedMethod = DotNetUtils.clone(method); deobfuscatedMethod = DotNetUtils.Clone(method);
deobfuscated[method] = deobfuscatedMethod; deobfuscated[method] = deobfuscatedMethod;
var blocks = new Blocks(deobfuscatedMethod); var blocks = new Blocks(deobfuscatedMethod);
deobfuscate(blocks); Deobfuscate(blocks);
IList<Instruction> allInstructions; IList<Instruction> allInstructions;
IList<ExceptionHandler> allExceptionHandlers; IList<ExceptionHandler> allExceptionHandlers;
blocks.getCode(out allInstructions, out allExceptionHandlers); blocks.GetCode(out allInstructions, out allExceptionHandlers);
DotNetUtils.restoreBody(deobfuscatedMethod, allInstructions, allExceptionHandlers); DotNetUtils.RestoreBody(deobfuscatedMethod, allInstructions, allExceptionHandlers);
return deobfuscatedMethod; return deobfuscatedMethod;
} }
void deobfuscate(Blocks blocks) { void Deobfuscate(Blocks blocks) {
cflowDeobfuscator.init(blocks); cflowDeobfuscator.Initialize(blocks);
cflowDeobfuscator.deobfuscate(); cflowDeobfuscator.Deobfuscate();
} }
} }
} }

View File

@ -29,30 +29,30 @@ namespace de4dot.blocks.cflow {
} }
public CflowDeobfuscator(IBlocksDeobfuscator blocksDeobfuscator) { public CflowDeobfuscator(IBlocksDeobfuscator blocksDeobfuscator) {
cflowDeobfuscator.add(blocksDeobfuscator); cflowDeobfuscator.Add(blocksDeobfuscator);
} }
public void deobfuscate(MethodDef method) { public void Deobfuscate(MethodDef method) {
deobfuscate(method, (blocks) => { Deobfuscate(method, (blocks) => {
cflowDeobfuscator.init(blocks); cflowDeobfuscator.Initialize(blocks);
cflowDeobfuscator.deobfuscate(); cflowDeobfuscator.Deobfuscate();
}); });
} }
static bool hasNonEmptyBody(MethodDef method) { static bool HasNonEmptyBody(MethodDef method) {
return method.Body != null && method.Body.Instructions.Count > 0; return method.Body != null && method.Body.Instructions.Count > 0;
} }
void deobfuscate(MethodDef method, Action<Blocks> handler) { void Deobfuscate(MethodDef method, Action<Blocks> handler) {
if (hasNonEmptyBody(method)) { if (HasNonEmptyBody(method)) {
var blocks = new Blocks(method); var blocks = new Blocks(method);
handler(blocks); handler(blocks);
IList<Instruction> allInstructions; IList<Instruction> allInstructions;
IList<ExceptionHandler> allExceptionHandlers; IList<ExceptionHandler> allExceptionHandlers;
blocks.getCode(out allInstructions, out allExceptionHandlers); blocks.GetCode(out allInstructions, out allExceptionHandlers);
DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers); DotNetUtils.RestoreBody(method, allInstructions, allExceptionHandlers);
} }
} }
} }

View File

@ -21,8 +21,8 @@ using System.Collections.Generic;
namespace de4dot.blocks.cflow { namespace de4dot.blocks.cflow {
static class CflowUtils { static class CflowUtils {
public static Block getSwitchTarget(IList<Block> targets, Block fallThrough, Int32Value intValue) { public static Block GetSwitchTarget(IList<Block> targets, Block fallThrough, Int32Value intValue) {
if (!intValue.allBitsValid()) if (!intValue.AllBitsValid())
return null; return null;
int index = intValue.value; int index = intValue.value;

View File

@ -29,15 +29,15 @@ namespace de4dot.blocks.cflow {
InstructionEmulator instructionEmulator = new InstructionEmulator(); InstructionEmulator instructionEmulator = new InstructionEmulator();
IList<Parameter> args; IList<Parameter> args;
protected override void init(List<Block> allBlocks) { protected override void Initialize(List<Block> allBlocks) {
base.init(allBlocks); base.Initialize(allBlocks);
args = blocks.Method.Parameters; args = blocks.Method.Parameters;
} }
protected override bool deobfuscate(Block block) { protected override bool Deobfuscate(Block block) {
bool changed = false; bool changed = false;
instructionEmulator.init(blocks); instructionEmulator.Initialize(blocks);
var instrs = block.Instructions; var instrs = block.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
var instr = instrs[i]; var instr = instrs[i];
@ -49,7 +49,7 @@ namespace de4dot.blocks.cflow {
case Code.Ldarg_2: case Code.Ldarg_2:
case Code.Ldarg_3: case Code.Ldarg_3:
case Code.Ldarg_S: case Code.Ldarg_S:
changed |= fixLoadInstruction(block, i, instructionEmulator.getArg(instr.Instruction.GetParameter(args))); changed |= FixLoadInstruction(block, i, instructionEmulator.GetArg(instr.Instruction.GetParameter(args)));
break; break;
case Code.Ldloc: case Code.Ldloc:
@ -58,22 +58,22 @@ namespace de4dot.blocks.cflow {
case Code.Ldloc_2: case Code.Ldloc_2:
case Code.Ldloc_3: case Code.Ldloc_3:
case Code.Ldloc_S: case Code.Ldloc_S:
changed |= fixLoadInstruction(block, i, instructionEmulator.getLocal(instr.Instruction.GetLocal(blocks.Locals))); changed |= FixLoadInstruction(block, i, instructionEmulator.GetLocal(instr.Instruction.GetLocal(blocks.Locals)));
break; break;
case Code.Ldarga: case Code.Ldarga:
case Code.Ldarga_S: case Code.Ldarga_S:
instructionEmulator.makeArgUnknown((Parameter)instr.Operand); instructionEmulator.MakeArgUnknown((Parameter)instr.Operand);
break; break;
case Code.Ldloca: case Code.Ldloca:
case Code.Ldloca_S: case Code.Ldloca_S:
instructionEmulator.makeLocalUnknown((Local)instr.Operand); instructionEmulator.MakeLocalUnknown((Local)instr.Operand);
break; break;
} }
try { try {
instructionEmulator.emulate(instr.Instruction); instructionEmulator.Emulate(instr.Instruction);
} }
catch (NullReferenceException) { catch (NullReferenceException) {
// Here if eg. invalid metadata token in a call instruction (operand is null) // Here if eg. invalid metadata token in a call instruction (operand is null)
@ -84,17 +84,17 @@ namespace de4dot.blocks.cflow {
return changed; return changed;
} }
bool fixLoadInstruction(Block block, int index, Value value) { bool FixLoadInstruction(Block block, int index, Value value) {
if (value.isInt32()) { if (value.IsInt32()) {
var intValue = (Int32Value)value; var intValue = (Int32Value)value;
if (!intValue.allBitsValid()) if (!intValue.AllBitsValid())
return false; return false;
block.Instructions[index] = new Instr(Instruction.CreateLdcI4(intValue.value)); block.Instructions[index] = new Instr(Instruction.CreateLdcI4(intValue.value));
return true; return true;
} }
else if (value.isInt64()) { else if (value.IsInt64()) {
var intValue = (Int64Value)value; var intValue = (Int64Value)value;
if (!intValue.allBitsValid()) if (!intValue.AllBitsValid())
return false; return false;
block.Instructions[index] = new Instr(OpCodes.Ldc_I8.ToInstruction(intValue.value)); block.Instructions[index] = new Instr(OpCodes.Ldc_I8.ToInstruction(intValue.value));
return true; return true;

View File

@ -27,7 +27,7 @@ namespace de4dot.blocks.cflow {
List<int> allDeadInstructions = new List<int>(); List<int> allDeadInstructions = new List<int>();
InstructionExpressionFinder instructionExpressionFinder = new InstructionExpressionFinder(); InstructionExpressionFinder instructionExpressionFinder = new InstructionExpressionFinder();
protected override bool deobfuscate(Block block) { protected override bool Deobfuscate(Block block) {
allDeadInstructions.Clear(); allDeadInstructions.Clear();
bool changed = false; bool changed = false;
@ -56,10 +56,10 @@ namespace de4dot.blocks.cflow {
case Code.Leave_S: case Code.Leave_S:
case Code.Endfinally: case Code.Endfinally:
case Code.Pop: case Code.Pop:
instructionExpressionFinder.init(block, false); instructionExpressionFinder.Initialize(block, false);
if (!instructionExpressionFinder.find(i)) if (!instructionExpressionFinder.Find(i))
continue; continue;
if (!okInstructions(block, instructionExpressionFinder.DeadInstructions)) if (!OkInstructions(block, instructionExpressionFinder.DeadInstructions))
continue; continue;
allDeadInstructions.AddRange(instructionExpressionFinder.DeadInstructions); allDeadInstructions.AddRange(instructionExpressionFinder.DeadInstructions);
break; break;
@ -70,14 +70,14 @@ namespace de4dot.blocks.cflow {
} }
if (allDeadInstructions.Count > 0) { if (allDeadInstructions.Count > 0) {
block.remove(allDeadInstructions); block.Remove(allDeadInstructions);
changed = true; changed = true;
} }
return changed; return changed;
} }
bool okInstructions(Block block, IEnumerable<int> indexes) { bool OkInstructions(Block block, IEnumerable<int> indexes) {
foreach (var index in indexes) { foreach (var index in indexes) {
var instr = block.Instructions[index]; var instr = block.Instructions[index];
switch (instr.OpCode.Code) { switch (instr.OpCode.Code) {
@ -318,27 +318,27 @@ namespace de4dot.blocks.cflow {
get { return deadInstructions; } get { return deadInstructions; }
} }
public void init(Block block, bool methodHasReturnValue) { public void Initialize(Block block, bool methodHasReturnValue) {
deadInstructions.Clear(); deadInstructions.Clear();
this.block = block; this.block = block;
this.methodHasReturnValue = methodHasReturnValue; this.methodHasReturnValue = methodHasReturnValue;
} }
public bool find(int index) { public bool Find(int index) {
return find(ref index, true); return Find(ref index, true);
} }
bool find(ref int index, bool addIt) { bool Find(ref int index, bool addIt) {
if (index < 0) if (index < 0)
return false; return false;
var startInstr = block.Instructions[index]; var startInstr = block.Instructions[index];
int startInstrPushes, startInstrPops; int startInstrPushes, startInstrPops;
calculateStackUsage(startInstr.Instruction, false, out startInstrPushes, out startInstrPops); CalculateStackUsage(startInstr.Instruction, false, out startInstrPushes, out startInstrPops);
// Don't add it if it clears the stack (eg. leave) // Don't add it if it clears the stack (eg. leave)
if (addIt && startInstrPops >= 0) if (addIt && startInstrPops >= 0)
addIndex(index); AddIndex(index);
if (startInstrPops == 0) if (startInstrPops == 0)
return true; return true;
@ -349,19 +349,19 @@ namespace de4dot.blocks.cflow {
break; break;
int pushes, pops; int pushes, pops;
calculateStackUsage(instr.Instruction, methodHasReturnValue, out pushes, out pops); CalculateStackUsage(instr.Instruction, methodHasReturnValue, out pushes, out pops);
if (pops < 0) if (pops < 0)
break; // eg. leave break; // eg. leave
index--; index--;
if (pops > 0) { // if instr uses any args if (pops > 0) { // if instr uses any args
bool otherExpr = pops > 0 && pushes == 0; bool otherExpr = pops > 0 && pushes == 0;
if (!find(ref index, addIt && !otherExpr)) if (!Find(ref index, addIt && !otherExpr))
break; break;
} }
else if (pushes != 0 || pops != 0) { else if (pushes != 0 || pops != 0) {
if (addIt) if (addIt)
addIndex(index); AddIndex(index);
} }
if (pushes > 0 && startInstrPops >= 0) { if (pushes > 0 && startInstrPops >= 0) {
if (pushes > startInstrPops) if (pushes > startInstrPops)
@ -373,12 +373,12 @@ namespace de4dot.blocks.cflow {
return startInstrPops <= 0; return startInstrPops <= 0;
} }
void addIndex(int index) { void AddIndex(int index) {
deadInstructions.Add(index); deadInstructions.Add(index);
} }
} }
static void calculateStackUsage(Instruction instr, bool methodHasReturnValue, out int pushes, out int pops) { static void CalculateStackUsage(Instruction instr, bool methodHasReturnValue, out int pushes, out int pops) {
instr.CalculateStackUsage(false, out pushes, out pops); instr.CalculateStackUsage(false, out pushes, out pops);
} }
} }

View File

@ -41,16 +41,16 @@ namespace de4dot.blocks.cflow {
public bool ExecuteOnNoChange { get; set; } public bool ExecuteOnNoChange { get; set; }
public void deobfuscateBegin(Blocks blocks) { public void DeobfuscateBegin(Blocks blocks) {
this.blocks = blocks; this.blocks = blocks;
} }
public bool deobfuscate(List<Block> allBlocks) { public bool Deobfuscate(List<Block> allBlocks) {
this.allBlocks = allBlocks; this.allBlocks = allBlocks;
return remove(); return Remove();
} }
bool remove() { bool Remove() {
if (blocks.Locals.Count == 0) if (blocks.Locals.Count == 0)
return false; return false;
@ -61,7 +61,7 @@ namespace de4dot.blocks.cflow {
deadLocals.Add(false); deadLocals.Add(false);
} }
findLoadStores(); FindLoadStores();
bool deadStores = false; bool deadStores = false;
for (int i = 0; i < blocks.Locals.Count; i++) { for (int i = 0; i < blocks.Locals.Count; i++) {
@ -74,10 +74,10 @@ namespace de4dot.blocks.cflow {
if (!deadStores) if (!deadStores)
return false; return false;
return removeDeadStores(); return RemoveDeadStores();
} }
void findLoadStores() { void FindLoadStores() {
foreach (var block in allBlocks) { foreach (var block in allBlocks) {
foreach (var instr in block.Instructions) { foreach (var instr in block.Instructions) {
Local local; Local local;
@ -89,7 +89,7 @@ namespace de4dot.blocks.cflow {
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 = Instr.getLocalVar(blocks.Locals, instr); local = Instr.GetLocalVar(blocks.Locals, instr);
flags = AccessFlags.Read; flags = AccessFlags.Read;
break; break;
@ -99,7 +99,7 @@ namespace de4dot.blocks.cflow {
case Code.Stloc_1: case Code.Stloc_1:
case Code.Stloc_2: case Code.Stloc_2:
case Code.Stloc_3: case Code.Stloc_3:
local = Instr.getLocalVar(blocks.Locals, instr); local = Instr.GetLocalVar(blocks.Locals, instr);
flags = AccessFlags.Write; flags = AccessFlags.Write;
break; break;
@ -122,7 +122,7 @@ namespace de4dot.blocks.cflow {
} }
} }
bool removeDeadStores() { bool RemoveDeadStores() {
bool changed = false; bool changed = false;
foreach (var block in allBlocks) { foreach (var block in allBlocks) {
var instructions = block.Instructions; var instructions = block.Instructions;
@ -136,7 +136,7 @@ namespace de4dot.blocks.cflow {
case Code.Stloc_1: case Code.Stloc_1:
case Code.Stloc_2: case Code.Stloc_2:
case Code.Stloc_3: case Code.Stloc_3:
local = Instr.getLocalVar(blocks.Locals, instr); local = Instr.GetLocalVar(blocks.Locals, instr);
break; break;
default: default:

View File

@ -25,22 +25,22 @@ namespace de4dot.blocks.cflow {
// If a block is just a dup followed by a bcc, try to append the block // If a block is just a dup followed by a bcc, try to append the block
// to all its sources. Will fix some SA assemblies. // to all its sources. Will fix some SA assemblies.
class DupBlockCflowDeobfuscator : BlockDeobfuscator { class DupBlockCflowDeobfuscator : BlockDeobfuscator {
protected override bool deobfuscate(Block block) { protected override bool Deobfuscate(Block block) {
if (block.Instructions.Count != 2) if (block.Instructions.Count != 2)
return false; return false;
if (block.Instructions[0].OpCode.Code != Code.Dup) if (block.Instructions[0].OpCode.Code != Code.Dup)
return false; return false;
if (!block.LastInstr.isConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch) if (!block.LastInstr.IsConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch)
return false; return false;
bool modified = false; bool modified = false;
foreach (var source in new List<Block>(block.Sources)) { foreach (var source in new List<Block>(block.Sources)) {
if (source.getOnlyTarget() != block) if (source.GetOnlyTarget() != block)
continue; continue;
if (!source.canAppend(block)) if (!source.CanAppend(block))
continue; continue;
source.append(block); source.Append(block);
modified = true; modified = true;
} }
return modified; return modified;

View File

@ -23,9 +23,9 @@ namespace de4dot.blocks.cflow {
public interface IBlocksDeobfuscator { public interface IBlocksDeobfuscator {
bool ExecuteOnNoChange { get; } bool ExecuteOnNoChange { get; }
void deobfuscateBegin(Blocks blocks); void DeobfuscateBegin(Blocks blocks);
// Returns true if something was updated // Returns true if something was updated
bool deobfuscate(List<Block> allBlocks); bool Deobfuscate(List<Block> allBlocks);
} }
} }

View File

@ -21,6 +21,6 @@ using dnlib.DotNet;
namespace de4dot.blocks.cflow { namespace de4dot.blocks.cflow {
public interface ICflowDeobfuscator { public interface ICflowDeobfuscator {
void deobfuscate(MethodDef method); void Deobfuscate(MethodDef method);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -40,75 +40,75 @@ namespace de4dot.blocks.cflow {
this.validMask = validMask; this.validMask = validMask;
} }
public bool hasUnknownBits() { public bool HasUnknownBits() {
return validMask != NO_UNKNOWN_BITS; return validMask != NO_UNKNOWN_BITS;
} }
public bool allBitsValid() { public bool AllBitsValid() {
return !hasUnknownBits(); return !HasUnknownBits();
} }
bool isBitValid(int n) { bool IsBitValid(int n) {
return isBitValid(validMask, n); return IsBitValid(validMask, n);
} }
static bool isBitValid(uint validMask, int n) { static bool IsBitValid(uint validMask, int n) {
return (validMask & (1U << n)) != 0; return (validMask & (1U << n)) != 0;
} }
public static Int32Value createUnknownBool() { public static Int32Value CreateUnknownBool() {
return new Int32Value(0, NO_UNKNOWN_BITS << 1); return new Int32Value(0, NO_UNKNOWN_BITS << 1);
} }
public static Int32Value createUnknownUInt8() { public static Int32Value CreateUnknownUInt8() {
return new Int32Value(0, NO_UNKNOWN_BITS << 8); return new Int32Value(0, NO_UNKNOWN_BITS << 8);
} }
public static Int32Value createUnknownUInt16() { public static Int32Value CreateUnknownUInt16() {
return new Int32Value(0, NO_UNKNOWN_BITS << 16); return new Int32Value(0, NO_UNKNOWN_BITS << 16);
} }
public static Int32Value createUnknown() { public static Int32Value CreateUnknown() {
return new Int32Value(0, 0U); return new Int32Value(0, 0U);
} }
public bool isZero() { public bool IsZero() {
return hasValue(0); return HasValue(0);
} }
public bool isNonZero() { public bool IsNonZero() {
return (value & validMask) != 0; return (value & validMask) != 0;
} }
public bool hasValue(int value) { public bool HasValue(int value) {
return allBitsValid() && this.value == value; return AllBitsValid() && this.value == value;
} }
public bool hasValue(uint value) { public bool HasValue(uint value) {
return hasValue((int)value); return HasValue((int)value);
} }
public Int32Value toBoolean() { public Int32Value ToBoolean() {
if (isNonZero()) if (IsNonZero())
return new Int32Value(1, NO_UNKNOWN_BITS); return new Int32Value(1, NO_UNKNOWN_BITS);
if (isZero()) if (IsZero())
return this; return this;
return createUnknownBool(); return CreateUnknownBool();
} }
public Int32Value toInt8() { public Int32Value ToInt8() {
return Conv_I1(this); return Conv_I1(this);
} }
public Int32Value toUInt8() { public Int32Value ToUInt8() {
return Conv_U1(this); return Conv_U1(this);
} }
public Int32Value toInt16() { public Int32Value ToInt16() {
return Conv_I2(this); return Conv_I2(this);
} }
public Int32Value toUInt16() { public Int32Value ToUInt16() {
return Conv_U2(this); return Conv_U2(this);
} }
@ -140,7 +140,7 @@ namespace de4dot.blocks.cflow {
public static Int32Value Conv_I1(int value, uint validMask) { public static Int32Value Conv_I1(int value, uint validMask) {
value = (int)(sbyte)value; value = (int)(sbyte)value;
if (isBitValid(validMask, 7)) if (IsBitValid(validMask, 7))
validMask |= NO_UNKNOWN_BITS << 8; validMask |= NO_UNKNOWN_BITS << 8;
else else
validMask &= ~(NO_UNKNOWN_BITS << 8); validMask &= ~(NO_UNKNOWN_BITS << 8);
@ -179,7 +179,7 @@ namespace de4dot.blocks.cflow {
public static Int32Value Conv_I2(int value, uint validMask) { public static Int32Value Conv_I2(int value, uint validMask) {
value = (int)(short)value; value = (int)(short)value;
if (isBitValid(validMask, 15)) if (IsBitValid(validMask, 15))
validMask |= NO_UNKNOWN_BITS << 16; validMask |= NO_UNKNOWN_BITS << 16;
else else
validMask &= ~(NO_UNKNOWN_BITS << 16); validMask &= ~(NO_UNKNOWN_BITS << 16);
@ -215,97 +215,97 @@ namespace de4dot.blocks.cflow {
} }
public static Int32Value Add(Int32Value a, Int32Value b) { public static Int32Value Add(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return new Int32Value(a.value + b.value); return new Int32Value(a.value + b.value);
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
return new Int32Value(a.value << 1, (a.validMask << 1) | 1); return new Int32Value(a.value << 1, (a.validMask << 1) | 1);
return createUnknown(); return CreateUnknown();
} }
public static Int32Value Sub(Int32Value a, Int32Value b) { public static Int32Value Sub(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return new Int32Value(a.value - b.value); return new Int32Value(a.value - b.value);
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
return zero; return zero;
return createUnknown(); return CreateUnknown();
} }
public static Int32Value Mul(Int32Value a, Int32Value b) { public static Int32Value Mul(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return new Int32Value(a.value * b.value); return new Int32Value(a.value * b.value);
if (a.isZero() || b.isZero()) if (a.IsZero() || b.IsZero())
return zero; return zero;
if (a.hasValue(1)) if (a.HasValue(1))
return b; return b;
if (b.hasValue(1)) if (b.HasValue(1))
return a; return a;
return createUnknown(); return CreateUnknown();
} }
public static Int32Value Div(Int32Value a, Int32Value b) { public static Int32Value Div(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) { if (a.AllBitsValid() && b.AllBitsValid()) {
try { try {
return new Int32Value(a.value / b.value); return new Int32Value(a.value / b.value);
} }
catch (ArithmeticException) { catch (ArithmeticException) {
return createUnknown(); return CreateUnknown();
} }
} }
if (ReferenceEquals(a, b) && a.isNonZero()) if (ReferenceEquals(a, b) && a.IsNonZero())
return one; return one;
if (b.hasValue(1)) if (b.HasValue(1))
return a; return a;
return createUnknown(); return CreateUnknown();
} }
public static Int32Value Div_Un(Int32Value a, Int32Value b) { public static Int32Value Div_Un(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) { if (a.AllBitsValid() && b.AllBitsValid()) {
try { try {
return new Int32Value((int)((uint)a.value / (uint)b.value)); return new Int32Value((int)((uint)a.value / (uint)b.value));
} }
catch (ArithmeticException) { catch (ArithmeticException) {
return createUnknown(); return CreateUnknown();
} }
} }
if (ReferenceEquals(a, b) && a.isNonZero()) if (ReferenceEquals(a, b) && a.IsNonZero())
return one; return one;
if (b.hasValue(1)) if (b.HasValue(1))
return a; return a;
return createUnknown(); return CreateUnknown();
} }
public static Int32Value Rem(Int32Value a, Int32Value b) { public static Int32Value Rem(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) { if (a.AllBitsValid() && b.AllBitsValid()) {
try { try {
return new Int32Value(a.value % b.value); return new Int32Value(a.value % b.value);
} }
catch (ArithmeticException) { catch (ArithmeticException) {
return createUnknown(); return CreateUnknown();
} }
} }
if ((ReferenceEquals(a, b) && a.isNonZero()) || b.hasValue(1)) if ((ReferenceEquals(a, b) && a.IsNonZero()) || b.HasValue(1))
return zero; return zero;
return createUnknown(); return CreateUnknown();
} }
public static Int32Value Rem_Un(Int32Value a, Int32Value b) { public static Int32Value Rem_Un(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) { if (a.AllBitsValid() && b.AllBitsValid()) {
try { try {
return new Int32Value((int)((uint)a.value % (uint)b.value)); return new Int32Value((int)((uint)a.value % (uint)b.value));
} }
catch (ArithmeticException) { catch (ArithmeticException) {
return createUnknown(); return CreateUnknown();
} }
} }
if ((ReferenceEquals(a, b) && a.isNonZero()) || b.hasValue(1)) if ((ReferenceEquals(a, b) && a.IsNonZero()) || b.HasValue(1))
return zero; return zero;
return createUnknown(); return CreateUnknown();
} }
public static Int32Value Neg(Int32Value a) { public static Int32Value Neg(Int32Value a) {
if (a.allBitsValid()) if (a.AllBitsValid())
return new Int32Value(-a.value); return new Int32Value(-a.value);
return createUnknown(); return CreateUnknown();
} }
public static Int32Value And(Int32Value a, Int32Value b) { public static Int32Value And(Int32Value a, Int32Value b) {
@ -333,38 +333,38 @@ namespace de4dot.blocks.cflow {
} }
public static Int32Value Shl(Int32Value a, Int32Value b) { public static Int32Value Shl(Int32Value a, Int32Value b) {
if (b.hasUnknownBits()) if (b.HasUnknownBits())
return createUnknown(); return CreateUnknown();
if (b.value == 0) if (b.value == 0)
return a; return a;
if (b.value < 0 || b.value >= sizeof(int) * 8) if (b.value < 0 || b.value >= sizeof(int) * 8)
return createUnknown(); return CreateUnknown();
int shift = b.value; int shift = b.value;
uint validMask = (a.validMask << shift) | (uint.MaxValue >> (sizeof(int) * 8 - shift)); uint validMask = (a.validMask << shift) | (uint.MaxValue >> (sizeof(int) * 8 - shift));
return new Int32Value(a.value << shift, validMask); return new Int32Value(a.value << shift, validMask);
} }
public static Int32Value Shr(Int32Value a, Int32Value b) { public static Int32Value Shr(Int32Value a, Int32Value b) {
if (b.hasUnknownBits()) if (b.HasUnknownBits())
return createUnknown(); return CreateUnknown();
if (b.value == 0) if (b.value == 0)
return a; return a;
if (b.value < 0 || b.value >= sizeof(int) * 8) if (b.value < 0 || b.value >= sizeof(int) * 8)
return createUnknown(); return CreateUnknown();
int shift = b.value; int shift = b.value;
uint validMask = a.validMask >> shift; uint validMask = a.validMask >> shift;
if (a.isBitValid(sizeof(int) * 8 - 1)) if (a.IsBitValid(sizeof(int) * 8 - 1))
validMask |= (uint.MaxValue << (sizeof(int) * 8 - shift)); validMask |= (uint.MaxValue << (sizeof(int) * 8 - shift));
return new Int32Value(a.value >> shift, validMask); return new Int32Value(a.value >> shift, validMask);
} }
public static Int32Value Shr_Un(Int32Value a, Int32Value b) { public static Int32Value Shr_Un(Int32Value a, Int32Value b) {
if (b.hasUnknownBits()) if (b.HasUnknownBits())
return createUnknown(); return CreateUnknown();
if (b.value == 0) if (b.value == 0)
return a; return a;
if (b.value < 0 || b.value >= sizeof(int) * 8) if (b.value < 0 || b.value >= sizeof(int) * 8)
return createUnknown(); return CreateUnknown();
int shift = b.value; int shift = b.value;
uint validMask = (a.validMask >> shift) | (uint.MaxValue << (sizeof(int) * 8 - shift)); uint validMask = (a.validMask >> shift) | (uint.MaxValue << (sizeof(int) * 8 - shift));
return new Int32Value((int)((uint)a.value >> shift), validMask); return new Int32Value((int)((uint)a.value >> shift), validMask);
@ -374,32 +374,32 @@ namespace de4dot.blocks.cflow {
switch (b) { switch (b) {
case Bool3.False: return zero; case Bool3.False: return zero;
case Bool3.True: return one; case Bool3.True: return one;
default: return createUnknownBool(); default: return CreateUnknownBool();
} }
} }
public static Int32Value Ceq(Int32Value a, Int32Value b) { public static Int32Value Ceq(Int32Value a, Int32Value b) {
return create(compareEq(a, b)); return create(CompareEq(a, b));
} }
public static Int32Value Cgt(Int32Value a, Int32Value b) { public static Int32Value Cgt(Int32Value a, Int32Value b) {
return create(compareGt(a, b)); return create(CompareGt(a, b));
} }
public static Int32Value Cgt_Un(Int32Value a, Int32Value b) { public static Int32Value Cgt_Un(Int32Value a, Int32Value b) {
return create(compareGt_Un(a, b)); return create(CompareGt_Un(a, b));
} }
public static Int32Value Clt(Int32Value a, Int32Value b) { public static Int32Value Clt(Int32Value a, Int32Value b) {
return create(compareLt(a, b)); return create(CompareLt(a, b));
} }
public static Int32Value Clt_Un(Int32Value a, Int32Value b) { public static Int32Value Clt_Un(Int32Value a, Int32Value b) {
return create(compareLt_Un(a, b)); return create(CompareLt_Un(a, b));
} }
public static Bool3 compareEq(Int32Value a, Int32Value b) { public static Bool3 CompareEq(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value == b.value ? Bool3.True : Bool3.False; return a.value == b.value ? Bool3.True : Bool3.False;
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
return Bool3.True; return Bool3.True;
@ -408,8 +408,8 @@ namespace de4dot.blocks.cflow {
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareNeq(Int32Value a, Int32Value b) { public static Bool3 CompareNeq(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value != b.value ? Bool3.True : Bool3.False; return a.value != b.value ? Bool3.True : Bool3.False;
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
return Bool3.False; return Bool3.False;
@ -418,96 +418,96 @@ namespace de4dot.blocks.cflow {
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareGt(Int32Value a, Int32Value b) { public static Bool3 CompareGt(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value > b.value ? Bool3.True : Bool3.False; return a.value > b.value ? Bool3.True : Bool3.False;
if (a.hasValue(int.MinValue)) if (a.HasValue(int.MinValue))
return Bool3.False; // min > x => false return Bool3.False; // min > x => false
if (b.hasValue(int.MaxValue)) if (b.HasValue(int.MaxValue))
return Bool3.False; // x > max => false return Bool3.False; // x > max => false
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareGt_Un(Int32Value a, Int32Value b) { public static Bool3 CompareGt_Un(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return (uint)a.value > (uint)b.value ? Bool3.True : Bool3.False; return (uint)a.value > (uint)b.value ? Bool3.True : Bool3.False;
if (a.hasValue(uint.MinValue)) if (a.HasValue(uint.MinValue))
return Bool3.False; // min > x => false return Bool3.False; // min > x => false
if (b.hasValue(uint.MaxValue)) if (b.HasValue(uint.MaxValue))
return Bool3.False; // x > max => false return Bool3.False; // x > max => false
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareGe(Int32Value a, Int32Value b) { public static Bool3 CompareGe(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value >= b.value ? Bool3.True : Bool3.False; return a.value >= b.value ? Bool3.True : Bool3.False;
if (a.hasValue(int.MaxValue)) if (a.HasValue(int.MaxValue))
return Bool3.True; // max >= x => true return Bool3.True; // max >= x => true
if (b.hasValue(int.MinValue)) if (b.HasValue(int.MinValue))
return Bool3.True; // x >= min => true return Bool3.True; // x >= min => true
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareGe_Un(Int32Value a, Int32Value b) { public static Bool3 CompareGe_Un(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return (uint)a.value >= (uint)b.value ? Bool3.True : Bool3.False; return (uint)a.value >= (uint)b.value ? Bool3.True : Bool3.False;
if (a.hasValue(uint.MaxValue)) if (a.HasValue(uint.MaxValue))
return Bool3.True; // max >= x => true return Bool3.True; // max >= x => true
if (b.hasValue(uint.MinValue)) if (b.HasValue(uint.MinValue))
return Bool3.True; // x >= min => true return Bool3.True; // x >= min => true
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareLe(Int32Value a, Int32Value b) { public static Bool3 CompareLe(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value <= b.value ? Bool3.True : Bool3.False; return a.value <= b.value ? Bool3.True : Bool3.False;
if (a.hasValue(int.MinValue)) if (a.HasValue(int.MinValue))
return Bool3.True; // min <= x => true return Bool3.True; // min <= x => true
if (b.hasValue(int.MaxValue)) if (b.HasValue(int.MaxValue))
return Bool3.True; // x <= max => true return Bool3.True; // x <= max => true
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareLe_Un(Int32Value a, Int32Value b) { public static Bool3 CompareLe_Un(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return (uint)a.value <= (uint)b.value ? Bool3.True : Bool3.False; return (uint)a.value <= (uint)b.value ? Bool3.True : Bool3.False;
if (a.hasValue(uint.MinValue)) if (a.HasValue(uint.MinValue))
return Bool3.True; // min <= x => true return Bool3.True; // min <= x => true
if (b.hasValue(uint.MaxValue)) if (b.HasValue(uint.MaxValue))
return Bool3.True; // x <= max => true return Bool3.True; // x <= max => true
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareLt(Int32Value a, Int32Value b) { public static Bool3 CompareLt(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value < b.value ? Bool3.True : Bool3.False; return a.value < b.value ? Bool3.True : Bool3.False;
if (a.hasValue(int.MaxValue)) if (a.HasValue(int.MaxValue))
return Bool3.False; // max < x => false return Bool3.False; // max < x => false
if (b.hasValue(int.MinValue)) if (b.HasValue(int.MinValue))
return Bool3.False; // x < min => false return Bool3.False; // x < min => false
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareLt_Un(Int32Value a, Int32Value b) { public static Bool3 CompareLt_Un(Int32Value a, Int32Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return (uint)a.value < (uint)b.value ? Bool3.True : Bool3.False; return (uint)a.value < (uint)b.value ? Bool3.True : Bool3.False;
if (a.hasValue(uint.MaxValue)) if (a.HasValue(uint.MaxValue))
return Bool3.False; // max < x => false return Bool3.False; // max < x => false
if (b.hasValue(uint.MinValue)) if (b.HasValue(uint.MinValue))
return Bool3.False; // x < min => false return Bool3.False; // x < min => false
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareTrue(Int32Value a) { public static Bool3 CompareTrue(Int32Value a) {
if (a.allBitsValid()) if (a.AllBitsValid())
return a.value != 0 ? Bool3.True : Bool3.False; return a.value != 0 ? Bool3.True : Bool3.False;
if ((a.value & a.validMask) != 0) if ((a.value & a.validMask) != 0)
return Bool3.True; return Bool3.True;
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareFalse(Int32Value a) { public static Bool3 CompareFalse(Int32Value a) {
if (a.allBitsValid()) if (a.AllBitsValid())
return a.value == 0 ? Bool3.True : Bool3.False; return a.value == 0 ? Bool3.True : Bool3.False;
if ((a.value & a.validMask) != 0) if ((a.value & a.validMask) != 0)
return Bool3.False; return Bool3.False;
@ -515,7 +515,7 @@ namespace de4dot.blocks.cflow {
} }
public override string ToString() { public override string ToString() {
if (allBitsValid()) if (AllBitsValid())
return value.ToString(); return value.ToString();
return string.Format("0x{0:X8}({1:X8})", value, validMask); return string.Format("0x{0:X8}({1:X8})", value, validMask);
} }

View File

@ -40,40 +40,40 @@ namespace de4dot.blocks.cflow {
this.validMask = validMask; this.validMask = validMask;
} }
bool hasUnknownBits() { bool HasUnknownBits() {
return validMask != NO_UNKNOWN_BITS; return validMask != NO_UNKNOWN_BITS;
} }
public bool allBitsValid() { public bool AllBitsValid() {
return !hasUnknownBits(); return !HasUnknownBits();
} }
bool isBitValid(int n) { bool IsBitValid(int n) {
return isBitValid(validMask, n); return IsBitValid(validMask, n);
} }
static bool isBitValid(ulong validMask, int n) { static bool IsBitValid(ulong validMask, int n) {
return (validMask & (1UL << n)) != 0; return (validMask & (1UL << n)) != 0;
} }
public static Int64Value createUnknown() { public static Int64Value CreateUnknown() {
return new Int64Value(0, 0UL); return new Int64Value(0, 0UL);
} }
public bool isZero() { public bool IsZero() {
return hasValue(0); return HasValue(0);
} }
public bool isNonZero() { public bool IsNonZero() {
return ((ulong)value & validMask) != 0; return ((ulong)value & validMask) != 0;
} }
public bool hasValue(long value) { public bool HasValue(long value) {
return allBitsValid() && this.value == value; return AllBitsValid() && this.value == value;
} }
public bool hasValue(ulong value) { public bool HasValue(ulong value) {
return hasValue((long)value); return HasValue((long)value);
} }
public static Int64Value Conv_U8(Int32Value a) { public static Int64Value Conv_U8(Int32Value a) {
@ -93,7 +93,7 @@ namespace de4dot.blocks.cflow {
public static Int64Value Conv_I8(Int32Value a) { public static Int64Value Conv_I8(Int32Value a) {
long value = a.value; long value = a.value;
ulong validMask = a.validMask; ulong validMask = a.validMask;
if (isBitValid(validMask, 31)) if (IsBitValid(validMask, 31))
validMask |= NO_UNKNOWN_BITS << 32; validMask |= NO_UNKNOWN_BITS << 32;
else else
validMask &= ~(NO_UNKNOWN_BITS << 32); validMask &= ~(NO_UNKNOWN_BITS << 32);
@ -109,97 +109,97 @@ namespace de4dot.blocks.cflow {
} }
public static Int64Value Add(Int64Value a, Int64Value b) { public static Int64Value Add(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return new Int64Value(a.value + b.value); return new Int64Value(a.value + b.value);
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
return new Int64Value(a.value << 1, (a.validMask << 1) | 1); return new Int64Value(a.value << 1, (a.validMask << 1) | 1);
return createUnknown(); return CreateUnknown();
} }
public static Int64Value Sub(Int64Value a, Int64Value b) { public static Int64Value Sub(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return new Int64Value(a.value - b.value); return new Int64Value(a.value - b.value);
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
return zero; return zero;
return createUnknown(); return CreateUnknown();
} }
public static Int64Value Mul(Int64Value a, Int64Value b) { public static Int64Value Mul(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return new Int64Value(a.value * b.value); return new Int64Value(a.value * b.value);
if (a.isZero() || b.isZero()) if (a.IsZero() || b.IsZero())
return zero; return zero;
if (a.hasValue(1)) if (a.HasValue(1))
return b; return b;
if (b.hasValue(1)) if (b.HasValue(1))
return a; return a;
return createUnknown(); return CreateUnknown();
} }
public static Int64Value Div(Int64Value a, Int64Value b) { public static Int64Value Div(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) { if (a.AllBitsValid() && b.AllBitsValid()) {
try { try {
return new Int64Value(a.value / b.value); return new Int64Value(a.value / b.value);
} }
catch (ArithmeticException) { catch (ArithmeticException) {
return createUnknown(); return CreateUnknown();
} }
} }
if (ReferenceEquals(a, b) && a.isNonZero()) if (ReferenceEquals(a, b) && a.IsNonZero())
return one; return one;
if (b.hasValue(1)) if (b.HasValue(1))
return a; return a;
return createUnknown(); return CreateUnknown();
} }
public static Int64Value Div_Un(Int64Value a, Int64Value b) { public static Int64Value Div_Un(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) { if (a.AllBitsValid() && b.AllBitsValid()) {
try { try {
return new Int64Value((long)((ulong)a.value / (ulong)b.value)); return new Int64Value((long)((ulong)a.value / (ulong)b.value));
} }
catch (ArithmeticException) { catch (ArithmeticException) {
return createUnknown(); return CreateUnknown();
} }
} }
if (ReferenceEquals(a, b) && a.isNonZero()) if (ReferenceEquals(a, b) && a.IsNonZero())
return one; return one;
if (b.hasValue(1)) if (b.HasValue(1))
return a; return a;
return createUnknown(); return CreateUnknown();
} }
public static Int64Value Rem(Int64Value a, Int64Value b) { public static Int64Value Rem(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) { if (a.AllBitsValid() && b.AllBitsValid()) {
try { try {
return new Int64Value(a.value % b.value); return new Int64Value(a.value % b.value);
} }
catch (ArithmeticException) { catch (ArithmeticException) {
return createUnknown(); return CreateUnknown();
} }
} }
if ((ReferenceEquals(a, b) && a.isNonZero()) || b.hasValue(1)) if ((ReferenceEquals(a, b) && a.IsNonZero()) || b.HasValue(1))
return zero; return zero;
return createUnknown(); return CreateUnknown();
} }
public static Int64Value Rem_Un(Int64Value a, Int64Value b) { public static Int64Value Rem_Un(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) { if (a.AllBitsValid() && b.AllBitsValid()) {
try { try {
return new Int64Value((long)((ulong)a.value % (ulong)b.value)); return new Int64Value((long)((ulong)a.value % (ulong)b.value));
} }
catch (ArithmeticException) { catch (ArithmeticException) {
return createUnknown(); return CreateUnknown();
} }
} }
if ((ReferenceEquals(a, b) && a.isNonZero()) || b.hasValue(1)) if ((ReferenceEquals(a, b) && a.IsNonZero()) || b.HasValue(1))
return zero; return zero;
return createUnknown(); return CreateUnknown();
} }
public static Int64Value Neg(Int64Value a) { public static Int64Value Neg(Int64Value a) {
if (a.allBitsValid()) if (a.AllBitsValid())
return new Int64Value(-a.value); return new Int64Value(-a.value);
return createUnknown(); return CreateUnknown();
} }
public static Int64Value And(Int64Value a, Int64Value b) { public static Int64Value And(Int64Value a, Int64Value b) {
@ -227,73 +227,73 @@ namespace de4dot.blocks.cflow {
} }
public static Int64Value Shl(Int64Value a, Int32Value b) { public static Int64Value Shl(Int64Value a, Int32Value b) {
if (b.hasUnknownBits()) if (b.HasUnknownBits())
return createUnknown(); return CreateUnknown();
if (b.value == 0) if (b.value == 0)
return a; return a;
if (b.value < 0 || b.value >= sizeof(long) * 8) if (b.value < 0 || b.value >= sizeof(long) * 8)
return createUnknown(); return CreateUnknown();
int shift = b.value; int shift = b.value;
ulong validMask = (a.validMask << shift) | (ulong.MaxValue >> (sizeof(long) * 8 - shift)); ulong validMask = (a.validMask << shift) | (ulong.MaxValue >> (sizeof(long) * 8 - shift));
return new Int64Value(a.value << shift, validMask); return new Int64Value(a.value << shift, validMask);
} }
public static Int64Value Shr(Int64Value a, Int32Value b) { public static Int64Value Shr(Int64Value a, Int32Value b) {
if (b.hasUnknownBits()) if (b.HasUnknownBits())
return createUnknown(); return CreateUnknown();
if (b.value == 0) if (b.value == 0)
return a; return a;
if (b.value < 0 || b.value >= sizeof(long) * 8) if (b.value < 0 || b.value >= sizeof(long) * 8)
return createUnknown(); return CreateUnknown();
int shift = b.value; int shift = b.value;
ulong validMask = a.validMask >> shift; ulong validMask = a.validMask >> shift;
if (a.isBitValid(sizeof(long) * 8 - 1)) if (a.IsBitValid(sizeof(long) * 8 - 1))
validMask |= (ulong.MaxValue << (sizeof(long) * 8 - shift)); validMask |= (ulong.MaxValue << (sizeof(long) * 8 - shift));
return new Int64Value(a.value >> shift, validMask); return new Int64Value(a.value >> shift, validMask);
} }
public static Int64Value Shr_Un(Int64Value a, Int32Value b) { public static Int64Value Shr_Un(Int64Value a, Int32Value b) {
if (b.hasUnknownBits()) if (b.HasUnknownBits())
return createUnknown(); return CreateUnknown();
if (b.value == 0) if (b.value == 0)
return a; return a;
if (b.value < 0 || b.value >= sizeof(long) * 8) if (b.value < 0 || b.value >= sizeof(long) * 8)
return createUnknown(); return CreateUnknown();
int shift = b.value; int shift = b.value;
ulong validMask = (a.validMask >> shift) | (ulong.MaxValue << (sizeof(long) * 8 - shift)); ulong validMask = (a.validMask >> shift) | (ulong.MaxValue << (sizeof(long) * 8 - shift));
return new Int64Value((long)((ulong)a.value >> shift), validMask); return new Int64Value((long)((ulong)a.value >> shift), validMask);
} }
static Int32Value create(Bool3 b) { static Int32Value Create(Bool3 b) {
switch (b) { switch (b) {
case Bool3.False: return Int32Value.zero; case Bool3.False: return Int32Value.zero;
case Bool3.True: return Int32Value.one; case Bool3.True: return Int32Value.one;
default: return Int32Value.createUnknownBool(); default: return Int32Value.CreateUnknownBool();
} }
} }
public static Int32Value Ceq(Int64Value a, Int64Value b) { public static Int32Value Ceq(Int64Value a, Int64Value b) {
return create(compareEq(a, b)); return Create(CompareEq(a, b));
} }
public static Int32Value Cgt(Int64Value a, Int64Value b) { public static Int32Value Cgt(Int64Value a, Int64Value b) {
return create(compareGt(a, b)); return Create(CompareGt(a, b));
} }
public static Int32Value Cgt_Un(Int64Value a, Int64Value b) { public static Int32Value Cgt_Un(Int64Value a, Int64Value b) {
return create(compareGt_Un(a, b)); return Create(CompareGt_Un(a, b));
} }
public static Int32Value Clt(Int64Value a, Int64Value b) { public static Int32Value Clt(Int64Value a, Int64Value b) {
return create(compareLt(a, b)); return Create(CompareLt(a, b));
} }
public static Int32Value Clt_Un(Int64Value a, Int64Value b) { public static Int32Value Clt_Un(Int64Value a, Int64Value b) {
return create(compareLt_Un(a, b)); return Create(CompareLt_Un(a, b));
} }
public static Bool3 compareEq(Int64Value a, Int64Value b) { public static Bool3 CompareEq(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value == b.value ? Bool3.True : Bool3.False; return a.value == b.value ? Bool3.True : Bool3.False;
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
return Bool3.True; return Bool3.True;
@ -302,8 +302,8 @@ namespace de4dot.blocks.cflow {
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareNeq(Int64Value a, Int64Value b) { public static Bool3 CompareNeq(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value != b.value ? Bool3.True : Bool3.False; return a.value != b.value ? Bool3.True : Bool3.False;
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
return Bool3.False; return Bool3.False;
@ -312,96 +312,96 @@ namespace de4dot.blocks.cflow {
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareGt(Int64Value a, Int64Value b) { public static Bool3 CompareGt(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value > b.value ? Bool3.True : Bool3.False; return a.value > b.value ? Bool3.True : Bool3.False;
if (a.hasValue(long.MinValue)) if (a.HasValue(long.MinValue))
return Bool3.False; // min > x => false return Bool3.False; // min > x => false
if (b.hasValue(long.MaxValue)) if (b.HasValue(long.MaxValue))
return Bool3.False; // x > max => false return Bool3.False; // x > max => false
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareGt_Un(Int64Value a, Int64Value b) { public static Bool3 CompareGt_Un(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return (ulong)a.value > (ulong)b.value ? Bool3.True : Bool3.False; return (ulong)a.value > (ulong)b.value ? Bool3.True : Bool3.False;
if (a.hasValue(ulong.MinValue)) if (a.HasValue(ulong.MinValue))
return Bool3.False; // min > x => false return Bool3.False; // min > x => false
if (b.hasValue(ulong.MaxValue)) if (b.HasValue(ulong.MaxValue))
return Bool3.False; // x > max => false return Bool3.False; // x > max => false
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareGe(Int64Value a, Int64Value b) { public static Bool3 CompareGe(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value >= b.value ? Bool3.True : Bool3.False; return a.value >= b.value ? Bool3.True : Bool3.False;
if (a.hasValue(long.MaxValue)) if (a.HasValue(long.MaxValue))
return Bool3.True; // max >= x => true return Bool3.True; // max >= x => true
if (b.hasValue(long.MinValue)) if (b.HasValue(long.MinValue))
return Bool3.True; // x >= min => true return Bool3.True; // x >= min => true
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareGe_Un(Int64Value a, Int64Value b) { public static Bool3 CompareGe_Un(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return (ulong)a.value >= (ulong)b.value ? Bool3.True : Bool3.False; return (ulong)a.value >= (ulong)b.value ? Bool3.True : Bool3.False;
if (a.hasValue(ulong.MaxValue)) if (a.HasValue(ulong.MaxValue))
return Bool3.True; // max >= x => true return Bool3.True; // max >= x => true
if (b.hasValue(ulong.MinValue)) if (b.HasValue(ulong.MinValue))
return Bool3.True; // x >= min => true return Bool3.True; // x >= min => true
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareLe(Int64Value a, Int64Value b) { public static Bool3 CompareLe(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value <= b.value ? Bool3.True : Bool3.False; return a.value <= b.value ? Bool3.True : Bool3.False;
if (a.hasValue(long.MinValue)) if (a.HasValue(long.MinValue))
return Bool3.True; // min <= x => true return Bool3.True; // min <= x => true
if (b.hasValue(long.MaxValue)) if (b.HasValue(long.MaxValue))
return Bool3.True; // x <= max => true return Bool3.True; // x <= max => true
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareLe_Un(Int64Value a, Int64Value b) { public static Bool3 CompareLe_Un(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return (ulong)a.value <= (ulong)b.value ? Bool3.True : Bool3.False; return (ulong)a.value <= (ulong)b.value ? Bool3.True : Bool3.False;
if (a.hasValue(ulong.MinValue)) if (a.HasValue(ulong.MinValue))
return Bool3.True; // min <= x => true return Bool3.True; // min <= x => true
if (b.hasValue(ulong.MaxValue)) if (b.HasValue(ulong.MaxValue))
return Bool3.True; // x <= max => true return Bool3.True; // x <= max => true
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareLt(Int64Value a, Int64Value b) { public static Bool3 CompareLt(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return a.value < b.value ? Bool3.True : Bool3.False; return a.value < b.value ? Bool3.True : Bool3.False;
if (a.hasValue(long.MaxValue)) if (a.HasValue(long.MaxValue))
return Bool3.False; // max < x => false return Bool3.False; // max < x => false
if (b.hasValue(long.MinValue)) if (b.HasValue(long.MinValue))
return Bool3.False; // x < min => false return Bool3.False; // x < min => false
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareLt_Un(Int64Value a, Int64Value b) { public static Bool3 CompareLt_Un(Int64Value a, Int64Value b) {
if (a.allBitsValid() && b.allBitsValid()) if (a.AllBitsValid() && b.AllBitsValid())
return (ulong)a.value < (ulong)b.value ? Bool3.True : Bool3.False; return (ulong)a.value < (ulong)b.value ? Bool3.True : Bool3.False;
if (a.hasValue(ulong.MaxValue)) if (a.HasValue(ulong.MaxValue))
return Bool3.False; // max < x => false return Bool3.False; // max < x => false
if (b.hasValue(ulong.MinValue)) if (b.HasValue(ulong.MinValue))
return Bool3.False; // x < min => false return Bool3.False; // x < min => false
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareTrue(Int64Value a) { public static Bool3 CompareTrue(Int64Value a) {
if (a.allBitsValid()) if (a.AllBitsValid())
return a.value != 0 ? Bool3.True : Bool3.False; return a.value != 0 ? Bool3.True : Bool3.False;
if (((ulong)a.value & a.validMask) != 0) if (((ulong)a.value & a.validMask) != 0)
return Bool3.True; return Bool3.True;
return Bool3.Unknown; return Bool3.Unknown;
} }
public static Bool3 compareFalse(Int64Value a) { public static Bool3 CompareFalse(Int64Value a) {
if (a.allBitsValid()) if (a.AllBitsValid())
return a.value == 0 ? Bool3.True : Bool3.False; return a.value == 0 ? Bool3.True : Bool3.False;
if (((ulong)a.value & a.validMask) != 0) if (((ulong)a.value & a.validMask) != 0)
return Bool3.False; return Bool3.False;
@ -409,7 +409,7 @@ namespace de4dot.blocks.cflow {
} }
public override string ToString() { public override string ToString() {
if (allBitsValid()) if (AllBitsValid())
return value.ToString(); return value.ToString();
return string.Format("0x{0:X8}L({1:X8})", value, validMask); return string.Format("0x{0:X8}L({1:X8})", value, validMask);
} }

View File

@ -29,18 +29,18 @@ namespace de4dot.blocks.cflow {
this.inlineInstanceMethods = inlineInstanceMethods; this.inlineInstanceMethods = inlineInstanceMethods;
} }
protected override bool deobfuscateInternal() { protected override bool DeobfuscateInternal() {
bool changed = false; bool changed = false;
var instructions = block.Instructions; var instructions = block.Instructions;
for (int i = 0; i < instructions.Count; i++) { for (int i = 0; i < instructions.Count; i++) {
var instr = instructions[i].Instruction; var instr = instructions[i].Instruction;
if (instr.OpCode.Code == Code.Call) if (instr.OpCode.Code == Code.Call)
changed |= inlineMethod(instr, i); changed |= InlineMethod(instr, i);
} }
return changed; return changed;
} }
protected virtual bool canInline(MethodDef method) { protected virtual bool CanInline(MethodDef method) {
if (method.GenericParameters.Count > 0) if (method.GenericParameters.Count > 0)
return false; return false;
if (method == blocks.Method) if (method == blocks.Method)
@ -55,19 +55,19 @@ namespace de4dot.blocks.cflow {
return inlineInstanceMethods; return inlineInstanceMethods;
} }
bool inlineMethod(Instruction callInstr, int instrIndex) { bool InlineMethod(Instruction callInstr, int instrIndex) {
var methodToInline = callInstr.Operand as MethodDef; var methodToInline = callInstr.Operand as MethodDef;
if (methodToInline == null) if (methodToInline == null)
return false; return false;
if (!canInline(methodToInline)) if (!CanInline(methodToInline))
return false; return false;
var body = methodToInline.Body; var body = methodToInline.Body;
if (body == null) if (body == null)
return false; return false;
int index = 0; int index = 0;
var instr = DotNetUtils.getInstruction(body.Instructions, ref index); var instr = DotNetUtils.GetInstruction(body.Instructions, ref index);
if (instr == null) if (instr == null)
return false; return false;
@ -83,7 +83,7 @@ namespace de4dot.blocks.cflow {
case Code.Call: case Code.Call:
case Code.Callvirt: case Code.Callvirt:
case Code.Newobj: case Code.Newobj:
return inlineOtherMethod(instrIndex, methodToInline, instr, index); return InlineOtherMethod(instrIndex, methodToInline, instr, index);
case Code.Ldc_I4: case Code.Ldc_I4:
case Code.Ldc_I4_0: case Code.Ldc_I4_0:
@ -106,17 +106,17 @@ namespace de4dot.blocks.cflow {
case Code.Ldtoken: case Code.Ldtoken:
case Code.Ldsfld: case Code.Ldsfld:
case Code.Ldsflda: case Code.Ldsflda:
return inlineLoadMethod(instrIndex, methodToInline, instr, index); return InlineLoadMethod(instrIndex, methodToInline, instr, index);
default: default:
return false; return false;
} }
} }
protected override bool isCompatibleType(int paramIndex, IType origType, IType newType) { protected override bool IsCompatibleType(int paramIndex, IType origType, IType newType) {
if (new SigComparer(SigComparerOptions.IgnoreModifiers).Equals(origType, newType)) if (new SigComparer(SigComparerOptions.IgnoreModifiers).Equals(origType, newType))
return true; return true;
if (isValueType(newType) || isValueType(origType)) if (IsValueType(newType) || IsValueType(origType))
return false; return false;
return newType.FullName == "System.Object"; return newType.FullName == "System.Object";
} }

View File

@ -33,24 +33,24 @@ namespace de4dot.blocks.cflow {
public bool ExecuteOnNoChange { get; set; } public bool ExecuteOnNoChange { get; set; }
public void deobfuscateBegin(Blocks blocks) { public void DeobfuscateBegin(Blocks blocks) {
this.blocks = blocks; this.blocks = blocks;
iteration = 0; iteration = 0;
} }
public bool deobfuscate(List<Block> allBlocks) { public bool Deobfuscate(List<Block> allBlocks) {
if (iteration++ >= MAX_ITERATIONS) if (iteration++ >= MAX_ITERATIONS)
return false; return false;
bool changed = false; bool changed = false;
foreach (var block in allBlocks) { foreach (var block in allBlocks) {
this.block = block; this.block = block;
changed |= deobfuscateInternal(); changed |= DeobfuscateInternal();
} }
return changed; return changed;
} }
protected abstract bool deobfuscateInternal(); protected abstract bool DeobfuscateInternal();
protected class InstructionPatcher { protected class InstructionPatcher {
readonly int patchIndex; readonly int patchIndex;
@ -64,53 +64,53 @@ namespace de4dot.blocks.cflow {
this.clonedInstr = new Instr(lastInstr.Clone()); this.clonedInstr = new Instr(lastInstr.Clone());
} }
public void patch(Block block) { public void Patch(Block block) {
block.Instructions[patchIndex] = clonedInstr; block.Instructions[patchIndex] = clonedInstr;
} }
} }
protected bool inlineLoadMethod(int patchIndex, MethodDef methodToInline, Instruction loadInstr, int instrIndex) { protected bool InlineLoadMethod(int patchIndex, MethodDef methodToInline, Instruction loadInstr, int instrIndex) {
if (!isReturn(methodToInline, instrIndex)) if (!IsReturn(methodToInline, instrIndex))
return false; return false;
int methodArgsCount = DotNetUtils.getArgsCount(methodToInline); int methodArgsCount = DotNetUtils.GetArgsCount(methodToInline);
for (int i = 0; i < methodArgsCount; i++) for (int i = 0; i < methodArgsCount; i++)
block.insert(patchIndex++, OpCodes.Pop.ToInstruction()); block.Insert(patchIndex++, OpCodes.Pop.ToInstruction());
block.Instructions[patchIndex] = new Instr(loadInstr.Clone()); block.Instructions[patchIndex] = new Instr(loadInstr.Clone());
return true; return true;
} }
protected bool inlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) { protected bool InlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) {
return inlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0); return InlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0);
} }
protected bool inlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) { protected bool InlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
return patchMethod(methodToInline, tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, popLastArgs)); return PatchMethod(methodToInline, TryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, popLastArgs));
} }
protected bool patchMethod(MethodDef methodToInline, InstructionPatcher patcher) { protected bool PatchMethod(MethodDef methodToInline, InstructionPatcher patcher) {
if (patcher == null) if (patcher == null)
return false; return false;
if (!isReturn(methodToInline, patcher.afterIndex)) if (!IsReturn(methodToInline, patcher.afterIndex))
return false; return false;
patcher.patch(block); patcher.Patch(block);
return true; return true;
} }
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) { protected InstructionPatcher TryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) {
return tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0); return TryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0);
} }
protected virtual Instruction onAfterLoadArg(MethodDef methodToInline, Instruction instr, ref int instrIndex) { protected virtual Instruction OnAfterLoadArg(MethodDef methodToInline, Instruction instr, ref int instrIndex) {
return instr; return instr;
} }
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) { protected InstructionPatcher TryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
int loadIndex = 0; int loadIndex = 0;
int methodArgsCount = DotNetUtils.getArgsCount(methodToInline); int methodArgsCount = DotNetUtils.GetArgsCount(methodToInline);
bool foundLdarga = false; bool foundLdarga = false;
while (instr != null && loadIndex < methodArgsCount) { while (instr != null && loadIndex < methodArgsCount) {
bool isLdarg = true; bool isLdarg = true;
@ -136,8 +136,8 @@ namespace de4dot.blocks.cflow {
if (instr.GetParameterIndex() != loadIndex) if (instr.GetParameterIndex() != loadIndex)
return null; return null;
loadIndex++; loadIndex++;
instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex); instr = DotNetUtils.GetInstruction(methodToInline.Body.Instructions, ref instrIndex);
instr = onAfterLoadArg(methodToInline, instr, ref instrIndex); instr = OnAfterLoadArg(methodToInline, instr, ref instrIndex);
} }
if (instr == null || loadIndex != methodArgsCount - popLastArgs) if (instr == null || loadIndex != methodArgsCount - popLastArgs)
return null; return null;
@ -150,13 +150,13 @@ namespace de4dot.blocks.cflow {
if (calledMethod == null) if (calledMethod == null)
return null; return null;
if (!isCompatibleType(-1, calledMethod.MethodSig.RetType, methodToInline.MethodSig.RetType)) if (!IsCompatibleType(-1, calledMethod.MethodSig.RetType, methodToInline.MethodSig.RetType))
return null; return null;
if (!checkSameMethods(calledMethod, methodToInline, popLastArgs)) if (!CheckSameMethods(calledMethod, methodToInline, popLastArgs))
return null; return null;
if (!hasAccessTo(instr.Operand)) if (!HasAccessTo(instr.Operand))
return null; return null;
return new InstructionPatcher(patchIndex, instrIndex, callInstr); return new InstructionPatcher(patchIndex, instrIndex, callInstr);
@ -169,19 +169,19 @@ namespace de4dot.blocks.cflow {
if (ctor == null) if (ctor == null)
return null; return null;
if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodSig.RetType)) if (!IsCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodSig.RetType))
return null; return null;
var methodArgs = methodToInline.Parameters; var methodArgs = methodToInline.Parameters;
var calledMethodArgs = DotNetUtils.getArgs(ctor); var calledMethodArgs = DotNetUtils.GetArgs(ctor);
if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count) if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count)
return null; return null;
for (int i = 1; i < calledMethodArgs.Count; i++) { for (int i = 1; i < calledMethodArgs.Count; i++) {
if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1].Type)) if (!IsCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1].Type))
return null; return null;
} }
if (!hasAccessTo(instr.Operand)) if (!HasAccessTo(instr.Operand))
return null; return null;
return new InstructionPatcher(patchIndex, instrIndex, newobjInstr); return new InstructionPatcher(patchIndex, instrIndex, newobjInstr);
@ -192,7 +192,7 @@ namespace de4dot.blocks.cflow {
if (methodArgsCount != 1) if (methodArgsCount != 1)
return null; return null;
if (!hasAccessTo(instr.Operand)) if (!HasAccessTo(instr.Operand))
return null; return null;
return new InstructionPatcher(patchIndex, instrIndex, ldInstr); return new InstructionPatcher(patchIndex, instrIndex, ldInstr);
@ -201,36 +201,36 @@ namespace de4dot.blocks.cflow {
return null; return null;
} }
bool hasAccessTo(object operand) { bool HasAccessTo(object operand) {
if (operand == null) if (operand == null)
return false; return false;
accessChecker.UserType = blocks.Method.DeclaringType; accessChecker.UserType = blocks.Method.DeclaringType;
return accessChecker.CanAccess(operand) ?? getDefaultAccessResult(); return accessChecker.CanAccess(operand) ?? GetDefaultAccessResult();
} }
protected virtual bool getDefaultAccessResult() { protected virtual bool GetDefaultAccessResult() {
return true; return true;
} }
protected virtual bool isReturn(MethodDef methodToInline, int instrIndex) { protected virtual bool IsReturn(MethodDef methodToInline, int instrIndex) {
var instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex); var instr = DotNetUtils.GetInstruction(methodToInline.Body.Instructions, ref instrIndex);
return instr != null && instr.OpCode.Code == Code.Ret; return instr != null && instr.OpCode.Code == Code.Ret;
} }
protected bool checkSameMethods(IMethod method, MethodDef methodToInline) { protected bool CheckSameMethods(IMethod method, MethodDef methodToInline) {
return checkSameMethods(method, methodToInline, 0); return CheckSameMethods(method, methodToInline, 0);
} }
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.ImplicitThis; bool hasImplicitThis = method.MethodSig.ImplicitThis;
if (methodToInlineArgs.Count - ignoreLastMethodToInlineArgs != methodArgs.Count) if (methodToInlineArgs.Count - ignoreLastMethodToInlineArgs != methodArgs.Count)
return false; return false;
for (int i = 0; i < methodArgs.Count; i++) { for (int i = 0; i < methodArgs.Count; i++) {
var methodArg = methodArgs[i]; var methodArg = methodArgs[i];
var methodToInlineArg = getArgType(methodToInline, methodToInlineArgs[i].Type); var methodToInlineArg = GetArgType(methodToInline, methodToInlineArgs[i].Type);
if (!isCompatibleType(i, methodArg, methodToInlineArg)) { if (!IsCompatibleType(i, methodArg, methodToInlineArg)) {
if (i != 0 || !hasImplicitThis) if (i != 0 || !hasImplicitThis)
return false; return false;
if (!isCompatibleValueThisPtr(methodArg, methodToInlineArg)) if (!isCompatibleValueThisPtr(methodArg, methodToInlineArg))
@ -241,7 +241,7 @@ namespace de4dot.blocks.cflow {
return true; return true;
} }
static TypeSig getArgType(MethodDef method, TypeSig arg) { static TypeSig GetArgType(MethodDef method, TypeSig arg) {
if (arg.GetElementType() != ElementType.MVar) if (arg.GetElementType() != ElementType.MVar)
return arg; return arg;
var mvar = (GenericMVar)arg; var mvar = (GenericMVar)arg;
@ -254,7 +254,7 @@ namespace de4dot.blocks.cflow {
return arg; return arg;
} }
protected virtual bool isCompatibleType(int paramIndex, IType origType, IType newType) { protected virtual bool IsCompatibleType(int paramIndex, IType origType, IType newType) {
return new SigComparer().Equals(origType, newType); return new SigComparer().Equals(origType, newType);
} }
@ -262,12 +262,12 @@ namespace de4dot.blocks.cflow {
var newByRef = newType as ByRefSig; var newByRef = newType as ByRefSig;
if (newByRef == null) if (newByRef == null)
return false; return false;
if (!isValueType(newByRef.Next) || !isValueType(origType)) if (!IsValueType(newByRef.Next) || !IsValueType(origType))
return false; return false;
return new SigComparer().Equals(origType, newByRef.Next); return new SigComparer().Equals(origType, newByRef.Next);
} }
protected static bool isValueType(IType type) { protected static bool IsValueType(IType type) {
if (type == null) if (type == null)
return false; return false;
var ts = type as TypeSig; var ts = type as TypeSig;

View File

@ -26,12 +26,12 @@ namespace de4dot.blocks.cflow {
class StLdlocFixer : BlockDeobfuscator { class StLdlocFixer : BlockDeobfuscator {
IList<Local> locals; IList<Local> locals;
protected override void init(List<Block> allBlocks) { protected override void Initialize(List<Block> allBlocks) {
base.init(allBlocks); base.Initialize(allBlocks);
locals = blocks.Locals; locals = blocks.Locals;
} }
protected override bool deobfuscate(Block block) { protected override bool Deobfuscate(Block block) {
bool changed = false; bool changed = false;
var instructions = block.Instructions; var instructions = block.Instructions;
for (int i = 0; i < instructions.Count; i++) { for (int i = 0; i < instructions.Count; i++) {
@ -47,12 +47,12 @@ namespace de4dot.blocks.cflow {
case Code.Stloc_3: case Code.Stloc_3:
if (i + 1 >= instructions.Count) if (i + 1 >= instructions.Count)
break; break;
if (!instructions[i + 1].isLdloc()) if (!instructions[i + 1].IsLdloc())
break; break;
var local = Instr.getLocalVar(locals, instr); var local = Instr.GetLocalVar(locals, instr);
if (local.Type.ElementType != ElementType.Boolean) if (local.Type.ElementType != ElementType.Boolean)
continue; continue;
if (local != Instr.getLocalVar(locals, instructions[i + 1])) if (local != Instr.GetLocalVar(locals, instructions[i + 1]))
break; break;
instructions[i] = new Instr(OpCodes.Dup.ToInstruction()); instructions[i] = new Instr(OpCodes.Dup.ToInstruction());
instructions[i + 1] = instr; instructions[i + 1] = instr;

View File

@ -26,50 +26,50 @@ namespace de4dot.blocks.cflow {
class SwitchCflowDeobfuscator : BlockDeobfuscator { class SwitchCflowDeobfuscator : BlockDeobfuscator {
InstructionEmulator instructionEmulator = new InstructionEmulator(); InstructionEmulator instructionEmulator = new InstructionEmulator();
protected override bool deobfuscate(Block switchBlock) { protected override bool Deobfuscate(Block switchBlock) {
if (switchBlock.LastInstr.OpCode.Code != Code.Switch) if (switchBlock.LastInstr.OpCode.Code != Code.Switch)
return false; return false;
if (isSwitchTopOfStack(switchBlock) && deobfuscateTos(switchBlock)) if (IsSwitchTopOfStack(switchBlock) && DeobfuscateTOS(switchBlock))
return true; return true;
if (isLdlocBranch(switchBlock, true) && deobfuscateLdloc(switchBlock)) if (IsLdlocBranch(switchBlock, true) && DeobfuscateLdloc(switchBlock))
return true; return true;
if (isStLdlocBranch(switchBlock, true) && deobfuscateStLdloc(switchBlock)) if (IsStLdlocBranch(switchBlock, true) && DeobfuscateStLdloc(switchBlock))
return true; return true;
if (isSwitchType1(switchBlock) && deobfuscateType1(switchBlock)) if (IsSwitchType1(switchBlock) && DeobfuscateType1(switchBlock))
return true; return true;
if (isSwitchType2(switchBlock) && deobfuscateType2(switchBlock)) if (IsSwitchType2(switchBlock) && DeobfuscateType2(switchBlock))
return true; return true;
if (switchBlock.FirstInstr.isLdloc() && fixSwitchBranch(switchBlock)) if (switchBlock.FirstInstr.IsLdloc() && FixSwitchBranch(switchBlock))
return true; return true;
return false; return false;
} }
static bool isSwitchTopOfStack(Block switchBlock) { static bool IsSwitchTopOfStack(Block switchBlock) {
return switchBlock.Instructions.Count == 1; return switchBlock.Instructions.Count == 1;
} }
static bool isLdlocBranch(Block switchBlock, bool isSwitch) { static bool IsLdlocBranch(Block switchBlock, bool isSwitch) {
int numInstrs = 1 + (isSwitch ? 1 : 0); int numInstrs = 1 + (isSwitch ? 1 : 0);
return switchBlock.Instructions.Count == numInstrs && switchBlock.Instructions[0].isLdloc(); return switchBlock.Instructions.Count == numInstrs && switchBlock.Instructions[0].IsLdloc();
} }
static bool isSwitchType1(Block switchBlock) { static bool IsSwitchType1(Block switchBlock) {
return switchBlock.FirstInstr.isLdloc(); return switchBlock.FirstInstr.IsLdloc();
} }
bool isSwitchType2(Block switchBlock) { bool IsSwitchType2(Block switchBlock) {
Local local = null; Local local = null;
foreach (var instr in switchBlock.Instructions) { foreach (var instr in switchBlock.Instructions) {
if (!instr.isLdloc()) if (!instr.IsLdloc())
continue; continue;
local = Instr.getLocalVar(blocks.Locals, instr); local = Instr.GetLocalVar(blocks.Locals, instr);
break; break;
} }
if (local == null) if (local == null)
@ -79,12 +79,12 @@ namespace de4dot.blocks.cflow {
var instrs = source.Instructions; var instrs = source.Instructions;
for (int i = 1; i < instrs.Count; i++) { for (int i = 1; i < instrs.Count; i++) {
var ldci4 = instrs[i - 1]; var ldci4 = instrs[i - 1];
if (!ldci4.isLdcI4()) if (!ldci4.IsLdcI4())
continue; continue;
var stloc = instrs[i]; var stloc = instrs[i];
if (!stloc.isStloc()) if (!stloc.IsStloc())
continue; continue;
if (Instr.getLocalVar(blocks.Locals, stloc) != local) if (Instr.GetLocalVar(blocks.Locals, stloc) != local)
continue; continue;
return true; return true;
@ -94,29 +94,29 @@ namespace de4dot.blocks.cflow {
return false; return false;
} }
bool isStLdlocBranch(Block switchBlock, bool isSwitch) { bool IsStLdlocBranch(Block switchBlock, bool isSwitch) {
int numInstrs = 2 + (isSwitch ? 1 : 0); int numInstrs = 2 + (isSwitch ? 1 : 0);
return switchBlock.Instructions.Count == numInstrs && return switchBlock.Instructions.Count == numInstrs &&
switchBlock.Instructions[0].isStloc() && switchBlock.Instructions[0].IsStloc() &&
switchBlock.Instructions[1].isLdloc() && switchBlock.Instructions[1].IsLdloc() &&
Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[0]) == Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[1]); Instr.GetLocalVar(blocks.Locals, switchBlock.Instructions[0]) == Instr.GetLocalVar(blocks.Locals, switchBlock.Instructions[1]);
} }
bool deobfuscateTos(Block switchBlock) { bool DeobfuscateTOS(Block switchBlock) {
bool changed = false; bool changed = false;
if (switchBlock.Targets == null) if (switchBlock.Targets == null)
return changed; return changed;
var targets = new List<Block>(switchBlock.Targets); var targets = new List<Block>(switchBlock.Targets);
changed |= deobfuscateTos(targets, switchBlock.FallThrough, switchBlock); changed |= DeobfuscateTOS(targets, switchBlock.FallThrough, switchBlock);
return changed; return changed;
} }
bool deobfuscateLdloc(Block switchBlock) { bool DeobfuscateLdloc(Block switchBlock) {
bool changed = false; bool changed = false;
var switchVariable = Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[0]); var switchVariable = Instr.GetLocalVar(blocks.Locals, switchBlock.Instructions[0]);
if (switchVariable == null) if (switchVariable == null)
return changed; return changed;
@ -124,15 +124,15 @@ namespace de4dot.blocks.cflow {
return changed; return changed;
var targets = new List<Block>(switchBlock.Targets); var targets = new List<Block>(switchBlock.Targets);
changed |= deobfuscateLdloc(targets, switchBlock.FallThrough, switchBlock, switchVariable); changed |= DeobfuscateLdloc(targets, switchBlock.FallThrough, switchBlock, switchVariable);
return changed; return changed;
} }
bool deobfuscateStLdloc(Block switchBlock) { bool DeobfuscateStLdloc(Block switchBlock) {
bool changed = false; bool changed = false;
var switchVariable = Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[0]); var switchVariable = Instr.GetLocalVar(blocks.Locals, switchBlock.Instructions[0]);
if (switchVariable == null) if (switchVariable == null)
return changed; return changed;
@ -140,7 +140,7 @@ namespace de4dot.blocks.cflow {
return changed; return changed;
var targets = new List<Block>(switchBlock.Targets); var targets = new List<Block>(switchBlock.Targets);
changed |= deobfuscateStLdloc(targets, switchBlock.FallThrough, switchBlock); changed |= DeobfuscateStLdloc(targets, switchBlock.FallThrough, switchBlock);
return changed; return changed;
} }
@ -153,19 +153,19 @@ namespace de4dot.blocks.cflow {
// stloc N // stloc N
// ldloc N // ldloc N
// switch (......) // switch (......)
bool deobfuscateStLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block) { bool DeobfuscateStLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block) {
bool changed = false; bool changed = false;
foreach (var source in new List<Block>(block.Sources)) { foreach (var source in new List<Block>(block.Sources)) {
if (!isBranchBlock(source)) if (!isBranchBlock(source))
continue; continue;
instructionEmulator.init(blocks); instructionEmulator.Initialize(blocks);
instructionEmulator.emulate(source.Instructions); instructionEmulator.Emulate(source.Instructions);
var target = getSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.pop()); var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.Pop());
if (target == null) if (target == null)
continue; continue;
source.replaceLastNonBranchWithBranch(0, target); source.ReplaceLastNonBranchWithBranch(0, target);
source.add(new Instr(OpCodes.Pop.ToInstruction())); source.Add(new Instr(OpCodes.Pop.ToInstruction()));
changed = true; changed = true;
} }
return changed; return changed;
@ -179,32 +179,32 @@ namespace de4dot.blocks.cflow {
// swblk: // swblk:
// ldloc N // ldloc N
// switch (......) // switch (......)
bool deobfuscateLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block, Local switchVariable) { bool DeobfuscateLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block, Local switchVariable) {
bool changed = false; bool changed = false;
foreach (var source in new List<Block>(block.Sources)) { foreach (var source in new List<Block>(block.Sources)) {
if (isBranchBlock(source)) { if (isBranchBlock(source)) {
instructionEmulator.init(blocks); instructionEmulator.Initialize(blocks);
instructionEmulator.emulate(source.Instructions); instructionEmulator.Emulate(source.Instructions);
var target = getSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.getLocal(switchVariable)); var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.GetLocal(switchVariable));
if (target == null) if (target == null)
continue; continue;
source.replaceLastNonBranchWithBranch(0, target); source.ReplaceLastNonBranchWithBranch(0, target);
changed = true; changed = true;
} }
else if (isBccBlock(source)) { else if (IsBccBlock(source)) {
instructionEmulator.init(blocks); instructionEmulator.Initialize(blocks);
instructionEmulator.emulate(source.Instructions); instructionEmulator.Emulate(source.Instructions);
var target = getSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.getLocal(switchVariable)); var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.GetLocal(switchVariable));
if (target == null) if (target == null)
continue; continue;
if (source.Targets[0] == block) { if (source.Targets[0] == block) {
source.setNewTarget(0, target); source.SetNewTarget(0, target);
changed = true; changed = true;
} }
if (source.FallThrough == block) { if (source.FallThrough == block) {
source.setNewFallThrough(target); source.SetNewFallThrough(target);
changed = true; changed = true;
} }
} }
@ -218,21 +218,21 @@ namespace de4dot.blocks.cflow {
// br swblk // br swblk
// swblk: // swblk:
// switch (......) // switch (......)
bool deobfuscateTos(IList<Block> switchTargets, Block switchFallThrough, Block block) { bool DeobfuscateTOS(IList<Block> switchTargets, Block switchFallThrough, Block block) {
bool changed = false; bool changed = false;
foreach (var source in new List<Block>(block.Sources)) { foreach (var source in new List<Block>(block.Sources)) {
if (!isBranchBlock(source)) if (!isBranchBlock(source))
continue; continue;
instructionEmulator.init(blocks); instructionEmulator.Initialize(blocks);
instructionEmulator.emulate(source.Instructions); instructionEmulator.Emulate(source.Instructions);
var target = getSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.pop()); var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.Pop());
if (target == null) { if (target == null) {
changed |= deobfuscateTos_Ldloc(switchTargets, switchFallThrough, source); changed |= DeobfuscateTos_Ldloc(switchTargets, switchFallThrough, source);
} }
else { else {
source.replaceLastNonBranchWithBranch(0, target); source.ReplaceLastNonBranchWithBranch(0, target);
source.add(new Instr(OpCodes.Pop.ToInstruction())); source.Add(new Instr(OpCodes.Pop.ToInstruction()));
changed = true; changed = true;
} }
} }
@ -245,15 +245,15 @@ namespace de4dot.blocks.cflow {
// stloc N // stloc N
// ldloc N // ldloc N
// br swblk // br swblk
bool deobfuscateTos_Ldloc(IList<Block> switchTargets, Block switchFallThrough, Block block) { bool DeobfuscateTos_Ldloc(IList<Block> switchTargets, Block switchFallThrough, Block block) {
if (isLdlocBranch(block, false)) { if (IsLdlocBranch(block, false)) {
var switchVariable = Instr.getLocalVar(blocks.Locals, block.Instructions[0]); var switchVariable = Instr.GetLocalVar(blocks.Locals, block.Instructions[0]);
if (switchVariable == null) if (switchVariable == null)
return false; return false;
return deobfuscateLdloc(switchTargets, switchFallThrough, block, switchVariable); return DeobfuscateLdloc(switchTargets, switchFallThrough, block, switchVariable);
} }
else if (isStLdlocBranch(block, false)) else if (IsStLdlocBranch(block, false))
return deobfuscateStLdloc(switchTargets, switchFallThrough, block); return DeobfuscateStLdloc(switchTargets, switchFallThrough, block);
return false; return false;
} }
@ -273,7 +273,7 @@ namespace de4dot.blocks.cflow {
} }
} }
static bool isBccBlock(Block block) { static bool IsBccBlock(Block block) {
if (block.Targets == null || block.Targets.Count != 1) if (block.Targets == null || block.Targets.Count != 1)
return false; return false;
if (block.FallThrough == null) if (block.FallThrough == null)
@ -309,91 +309,91 @@ namespace de4dot.blocks.cflow {
} }
} }
bool deobfuscateType1(Block switchBlock) { bool DeobfuscateType1(Block switchBlock) {
Block target; Block target;
if (!emulateGetTarget(switchBlock, out target) || target != null) if (!EmulateGetTarget(switchBlock, out target) || target != null)
return false; return false;
bool changed = false; bool changed = false;
foreach (var source in new List<Block>(switchBlock.Sources)) { foreach (var source in new List<Block>(switchBlock.Sources)) {
if (!source.canAppend(switchBlock)) if (!source.CanAppend(switchBlock))
continue; continue;
if (!willHaveKnownTarget(switchBlock, source)) if (!WillHaveKnownTarget(switchBlock, source))
continue; continue;
source.append(switchBlock); source.Append(switchBlock);
changed = true; changed = true;
} }
return changed; return changed;
} }
bool deobfuscateType2(Block switchBlock) { bool DeobfuscateType2(Block switchBlock) {
bool changed = false; bool changed = false;
var bccSources = new List<Block>(); var bccSources = new List<Block>();
foreach (var source in new List<Block>(switchBlock.Sources)) { foreach (var source in new List<Block>(switchBlock.Sources)) {
if (source.LastInstr.isConditionalBranch()) { if (source.LastInstr.IsConditionalBranch()) {
bccSources.Add(source); bccSources.Add(source);
continue; continue;
} }
if (!source.canAppend(switchBlock)) if (!source.CanAppend(switchBlock))
continue; continue;
if (!willHaveKnownTarget(switchBlock, source)) if (!WillHaveKnownTarget(switchBlock, source))
continue; continue;
source.append(switchBlock); source.Append(switchBlock);
changed = true; changed = true;
} }
foreach (var bccSource in bccSources) { foreach (var bccSource in bccSources) {
if (!willHaveKnownTarget(switchBlock, bccSource)) if (!WillHaveKnownTarget(switchBlock, bccSource))
continue; continue;
var consts = getBccLocalConstants(bccSource); var consts = GetBccLocalConstants(bccSource);
if (consts.Count == 0) if (consts.Count == 0)
continue; continue;
var newFallThrough = createBlock(consts, bccSource.FallThrough); var newFallThrough = CreateBlock(consts, bccSource.FallThrough);
var newTarget = createBlock(consts, bccSource.Targets[0]); var newTarget = CreateBlock(consts, bccSource.Targets[0]);
var oldFallThrough = bccSource.FallThrough; var oldFallThrough = bccSource.FallThrough;
var oldTarget = bccSource.Targets[0]; var oldTarget = bccSource.Targets[0];
bccSource.setNewFallThrough(newFallThrough); bccSource.SetNewFallThrough(newFallThrough);
bccSource.setNewTarget(0, newTarget); bccSource.SetNewTarget(0, newTarget);
newFallThrough.setNewFallThrough(oldFallThrough); newFallThrough.SetNewFallThrough(oldFallThrough);
newTarget.setNewFallThrough(oldTarget); newTarget.SetNewFallThrough(oldTarget);
changed = true; changed = true;
} }
return changed; return changed;
} }
static Block createBlock(Dictionary<Local, int> consts, Block fallThrough) { static Block CreateBlock(Dictionary<Local, int> consts, Block fallThrough) {
var block = new Block(); var block = new Block();
foreach (var kv in consts) { foreach (var kv in consts) {
block.Instructions.Add(new Instr(Instruction.CreateLdcI4(kv.Value))); block.Instructions.Add(new Instr(Instruction.CreateLdcI4(kv.Value)));
block.Instructions.Add(new Instr(OpCodes.Stloc.ToInstruction(kv.Key))); block.Instructions.Add(new Instr(OpCodes.Stloc.ToInstruction(kv.Key)));
} }
fallThrough.Parent.add(block); fallThrough.Parent.Add(block);
return block; return block;
} }
Dictionary<Local, int> getBccLocalConstants(Block block) { Dictionary<Local, int> GetBccLocalConstants(Block block) {
var dict = new Dictionary<Local, int>(); var dict = new Dictionary<Local, int>();
var instrs = block.Instructions; var instrs = block.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
var instr = instrs[i]; var instr = instrs[i];
if (instr.isStloc()) { if (instr.IsStloc()) {
var local = Instr.getLocalVar(blocks.Locals, instr); var local = Instr.GetLocalVar(blocks.Locals, instr);
if (local == null) if (local == null)
continue; continue;
var ldci4 = i == 0 ? null : instrs[i - 1]; var ldci4 = i == 0 ? null : instrs[i - 1];
if (ldci4 == null || !ldci4.isLdcI4()) if (ldci4 == null || !ldci4.IsLdcI4())
dict.Remove(local); dict.Remove(local);
else else
dict[local] = ldci4.getLdcI4Value(); dict[local] = ldci4.GetLdcI4Value();
} }
else if (instr.isLdloc()) { else if (instr.IsLdloc()) {
var local = Instr.getLocalVar(blocks.Locals, instr); var local = Instr.GetLocalVar(blocks.Locals, instr);
if (local != null) if (local != null)
dict.Remove(local); dict.Remove(local);
} }
@ -406,47 +406,47 @@ namespace de4dot.blocks.cflow {
return dict; return dict;
} }
bool emulateGetTarget(Block switchBlock, out Block target) { bool EmulateGetTarget(Block switchBlock, out Block target) {
instructionEmulator.init(blocks); instructionEmulator.Initialize(blocks);
try { try {
instructionEmulator.emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1); instructionEmulator.Emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1);
} }
catch (NullReferenceException) { catch (NullReferenceException) {
// Here if eg. invalid metadata token in a call instruction (operand is null) // Here if eg. invalid metadata token in a call instruction (operand is null)
target = null; target = null;
return false; return false;
} }
target = getTarget(switchBlock); target = GetTarget(switchBlock);
return true; return true;
} }
bool willHaveKnownTarget(Block switchBlock, Block source) { bool WillHaveKnownTarget(Block switchBlock, Block source) {
instructionEmulator.init(blocks); instructionEmulator.Initialize(blocks);
try { try {
instructionEmulator.emulate(source.Instructions); instructionEmulator.Emulate(source.Instructions);
instructionEmulator.emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1); instructionEmulator.Emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1);
} }
catch (NullReferenceException) { catch (NullReferenceException) {
// Here if eg. invalid metadata token in a call instruction (operand is null) // Here if eg. invalid metadata token in a call instruction (operand is null)
return false; return false;
} }
return getTarget(switchBlock) != null; return GetTarget(switchBlock) != null;
} }
Block getTarget(Block switchBlock) { Block GetTarget(Block switchBlock) {
var val1 = instructionEmulator.pop(); var val1 = instructionEmulator.Pop();
if (!val1.isInt32()) if (!val1.IsInt32())
return null; return null;
return CflowUtils.getSwitchTarget(switchBlock.Targets, switchBlock.FallThrough, (Int32Value)val1); return CflowUtils.GetSwitchTarget(switchBlock.Targets, switchBlock.FallThrough, (Int32Value)val1);
} }
static Block getSwitchTarget(IList<Block> targets, Block fallThrough, Value value) { static Block GetSwitchTarget(IList<Block> targets, Block fallThrough, Value value) {
if (!value.isInt32()) if (!value.IsInt32())
return null; return null;
return CflowUtils.getSwitchTarget(targets, fallThrough, (Int32Value)value); return CflowUtils.GetSwitchTarget(targets, fallThrough, (Int32Value)value);
} }
static bool fixSwitchBranch(Block switchBlock) { static bool FixSwitchBranch(Block switchBlock) {
// Code: // Code:
// blk1: // blk1:
// ldc.i4 XXX // ldc.i4 XXX
@ -467,11 +467,11 @@ namespace de4dot.blocks.cflow {
foreach (var commonSource in new List<Block>(switchBlock.Sources)) { foreach (var commonSource in new List<Block>(switchBlock.Sources)) {
if (commonSource.Instructions.Count != 1) if (commonSource.Instructions.Count != 1)
continue; continue;
if (!commonSource.FirstInstr.isStloc()) if (!commonSource.FirstInstr.IsStloc())
continue; continue;
foreach (var blk in new List<Block>(commonSource.Sources)) { foreach (var blk in new List<Block>(commonSource.Sources)) {
if (blk.canAppend(commonSource)) { if (blk.CanAppend(commonSource)) {
blk.append(commonSource); blk.Append(commonSource);
changed = true; changed = true;
} }
} }

View File

@ -38,35 +38,35 @@ namespace de4dot.blocks.cflow {
public abstract class Value { public abstract class Value {
public readonly ValueType valueType; public readonly ValueType valueType;
public bool isUnknown() { public bool IsUnknown() {
return valueType == ValueType.Unknown; return valueType == ValueType.Unknown;
} }
public bool isNull() { public bool IsNull() {
return valueType == ValueType.Null; return valueType == ValueType.Null;
} }
public bool isObject() { public bool IsObject() {
return valueType == ValueType.Object; return valueType == ValueType.Object;
} }
public bool isBoxed() { public bool IsBoxed() {
return valueType == ValueType.Boxed; return valueType == ValueType.Boxed;
} }
public bool isInt32() { public bool IsInt32() {
return valueType == ValueType.Int32; return valueType == ValueType.Int32;
} }
public bool isInt64() { public bool IsInt64() {
return valueType == ValueType.Int64; return valueType == ValueType.Int64;
} }
public bool isReal8() { public bool IsReal8() {
return valueType == ValueType.Real8; return valueType == ValueType.Real8;
} }
public bool isString() { public bool IsString() {
return valueType == ValueType.String; return valueType == ValueType.String;
} }

View File

@ -29,43 +29,43 @@ namespace de4dot.blocks.cflow {
get { return stack.Count; } get { return stack.Count; }
} }
public void init() { public void Initialize() {
stack.Clear(); stack.Clear();
} }
public void clear() { public void Clear() {
stack.Clear(); stack.Clear();
} }
public void push(Value value) { public void Push(Value value) {
stack.Add(value); stack.Add(value);
} }
public Value peek() { public Value Peek() {
if (stack.Count == 0) if (stack.Count == 0)
return new UnknownValue(); return new UnknownValue();
return stack[stack.Count - 1]; return stack[stack.Count - 1];
} }
public Value pop() { public Value Pop() {
Value value = peek(); Value value = Peek();
if (stack.Count != 0) if (stack.Count != 0)
stack.RemoveAt(stack.Count - 1); stack.RemoveAt(stack.Count - 1);
return value; return value;
} }
public void push(int count) { public void Push(int count) {
if (count < 0) if (count < 0)
throw new ArgumentOutOfRangeException("count"); throw new ArgumentOutOfRangeException("count");
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
pushUnknown(); PushUnknown();
} }
public void pushUnknown() { public void PushUnknown() {
push(new UnknownValue()); Push(new UnknownValue());
} }
public void pop(int count) { public void Pop(int count) {
if (count < 0) if (count < 0)
throw new ArgumentOutOfRangeException("count"); throw new ArgumentOutOfRangeException("count");
if (count >= stack.Count) if (count >= stack.Count)
@ -74,8 +74,8 @@ namespace de4dot.blocks.cflow {
stack.RemoveRange(stack.Count - count, count); stack.RemoveRange(stack.Count - count, count);
} }
public void copyTop() { public void CopyTop() {
push(peek()); Push(Peek());
} }
public override string ToString() { public override string ToString() {

View File

@ -20,7 +20,7 @@
namespace de4dot_x64 { namespace de4dot_x64 {
class Program { class Program {
static int Main(string[] args) { static int Main(string[] args) {
return de4dot.cui.Program.main(args); return de4dot.cui.Program.Main2(args);
} }
} }
} }

View File

@ -43,13 +43,13 @@ namespace de4dot.code.AssemblyClient {
this.loader = loader; this.loader = loader;
} }
public void connect() { public void Connect() {
loader.loadServer(); loader.LoadServer();
service = loader.createService(); service = loader.CreateService();
serverLoadedTime = DateTime.UtcNow; serverLoadedTime = DateTime.UtcNow;
} }
public void waitConnected() { public void WaitConnected() {
// If we don't wait here, we'll sometimes get stuck in doNothing(). Make sure the // If we don't wait here, we'll sometimes get stuck in doNothing(). Make sure the
// server has had time to start... This only seems to be needed when starting a // server has had time to start... This only seems to be needed when starting a
// server in a different process, though. // server in a different process, though.
@ -61,7 +61,7 @@ namespace de4dot.code.AssemblyClient {
var startTime = DateTime.UtcNow; var startTime = DateTime.UtcNow;
while (true) { while (true) {
try { try {
service.doNothing(); service.DoNothing();
break; break;
} }
catch (RemotingException) { catch (RemotingException) {
@ -77,7 +77,7 @@ namespace de4dot.code.AssemblyClient {
public void Dispose() { public void Dispose() {
if (service != null) { if (service != null) {
try { try {
service.exit(); service.Exit();
} }
catch (RemotingException) { catch (RemotingException) {
// Couldn't connect // Couldn't connect

View File

@ -21,17 +21,17 @@ using dnlib.DotNet;
namespace de4dot.code.AssemblyClient { namespace de4dot.code.AssemblyClient {
public interface IAssemblyClientFactory { public interface IAssemblyClientFactory {
IAssemblyClient create(); IAssemblyClient Create();
} }
public class SameAppDomainAssemblyClientFactory : IAssemblyClientFactory { public class SameAppDomainAssemblyClientFactory : IAssemblyClientFactory {
public IAssemblyClient create() { public IAssemblyClient Create() {
return new AssemblyClient(new SameAppDomainAssemblyServerLoader()); return new AssemblyClient(new SameAppDomainAssemblyServerLoader());
} }
} }
public class NewAppDomainAssemblyClientFactory : IAssemblyClientFactory { public class NewAppDomainAssemblyClientFactory : IAssemblyClientFactory {
public IAssemblyClient create() { public IAssemblyClient Create() {
return new AssemblyClient(new NewAppDomainAssemblyServerLoader()); return new AssemblyClient(new NewAppDomainAssemblyServerLoader());
} }
} }
@ -47,15 +47,15 @@ namespace de4dot.code.AssemblyClient {
this.serverVersion = serverVersion; this.serverVersion = serverVersion;
} }
public IAssemblyClient create(ModuleDef module) { public IAssemblyClient Create(ModuleDef module) {
return new AssemblyClient(new NewProcessAssemblyServerLoader(getServerClrVersion(module))); return new AssemblyClient(new NewProcessAssemblyServerLoader(GetServerClrVersion(module)));
} }
public IAssemblyClient create() { public IAssemblyClient Create() {
return new AssemblyClient(new NewProcessAssemblyServerLoader(serverVersion)); return new AssemblyClient(new NewProcessAssemblyServerLoader(serverVersion));
} }
internal static ServerClrVersion getServerClrVersion(ModuleDef module) { internal static ServerClrVersion GetServerClrVersion(ModuleDef module) {
switch (module.GetPointerSize()) { switch (module.GetPointerSize()) {
default: default:
case 4: case 4:

View File

@ -23,7 +23,7 @@ using AssemblyData;
namespace de4dot.code.AssemblyClient { namespace de4dot.code.AssemblyClient {
public interface IAssemblyClient : IDisposable { public interface IAssemblyClient : IDisposable {
IAssemblyService Service { get; } IAssemblyService Service { get; }
void connect(); void Connect();
void waitConnected(); void WaitConnected();
} }
} }

View File

@ -22,7 +22,7 @@ using AssemblyData;
namespace de4dot.code.AssemblyClient { namespace de4dot.code.AssemblyClient {
interface IAssemblyServerLoader : IDisposable { interface IAssemblyServerLoader : IDisposable {
void loadServer(); void LoadServer();
IAssemblyService createService(); IAssemblyService CreateService();
} }
} }

View File

@ -42,13 +42,13 @@ namespace de4dot.code.AssemblyClient {
} }
protected IpcAssemblyServerLoader(ServerClrVersion serverVersion) { protected IpcAssemblyServerLoader(ServerClrVersion serverVersion) {
assemblyServerFilename = getServerName(serverVersion); assemblyServerFilename = GetServerName(serverVersion);
ipcName = Utils.randomName(15, 20); ipcName = Utils.RandomName(15, 20);
ipcUri = Utils.randomName(15, 20); ipcUri = Utils.RandomName(15, 20);
url = string.Format("ipc://{0}/{1}", ipcName, ipcUri); url = string.Format("ipc://{0}/{1}", ipcName, ipcUri);
} }
static string getServerName(ServerClrVersion serverVersion) { static string GetServerName(ServerClrVersion serverVersion) {
if (serverVersion == ServerClrVersion.CLR_ANY_ANYCPU) if (serverVersion == ServerClrVersion.CLR_ANY_ANYCPU)
serverVersion = IntPtr.Size == 4 ? ServerClrVersion.CLR_ANY_x86 : ServerClrVersion.CLR_ANY_x64; serverVersion = IntPtr.Size == 4 ? ServerClrVersion.CLR_ANY_x86 : ServerClrVersion.CLR_ANY_x64;
switch (serverVersion) { switch (serverVersion) {
@ -62,13 +62,13 @@ namespace de4dot.code.AssemblyClient {
} }
} }
public void loadServer() { public void LoadServer() {
loadServer(Utils.getPathOfOurFile(assemblyServerFilename)); LoadServer(Utils.GetPathOfOurFile(assemblyServerFilename));
} }
public abstract void loadServer(string filename); public abstract void LoadServer(string filename);
public IAssemblyService createService() { public IAssemblyService CreateService() {
return (IAssemblyService)Activator.GetObject(typeof(AssemblyService), url); return (IAssemblyService)Activator.GetObject(typeof(AssemblyService), url);
} }

View File

@ -26,11 +26,11 @@ namespace de4dot.code.AssemblyClient {
AppDomain appDomain; AppDomain appDomain;
Thread thread; Thread thread;
public override void loadServer(string filename) { public override void LoadServer(string filename) {
if (appDomain != null) if (appDomain != null)
throw new ApplicationException("Server is already loaded"); throw new ApplicationException("Server is already loaded");
appDomain = AppDomain.CreateDomain(Utils.randomName(15, 20)); appDomain = AppDomain.CreateDomain(Utils.RandomName(15, 20));
thread = new Thread(new ThreadStart(() => { thread = new Thread(new ThreadStart(() => {
try { try {
appDomain.ExecuteAssembly(filename, null, new string[] { ipcName, ipcUri }); appDomain.ExecuteAssembly(filename, null, new string[] { ipcName, ipcUri });
@ -41,14 +41,14 @@ namespace de4dot.code.AssemblyClient {
catch (AppDomainUnloadedException) { catch (AppDomainUnloadedException) {
// Here if it was unloaded by Dispose() // Here if it was unloaded by Dispose()
} }
unloadAppDomain(appDomain); UnloadAppDomain(appDomain);
appDomain = null; appDomain = null;
})); }));
thread.Start(); thread.Start();
} }
public override void Dispose() { public override void Dispose() {
unloadAppDomain(appDomain); UnloadAppDomain(appDomain);
if (thread != null) { if (thread != null) {
try { try {
if (!thread.Join(100)) if (!thread.Join(100))
@ -60,11 +60,11 @@ namespace de4dot.code.AssemblyClient {
thread = null; thread = null;
} }
// It could still be loaded if the thread was aborted so do it again // It could still be loaded if the thread was aborted so do it again
unloadAppDomain(appDomain); UnloadAppDomain(appDomain);
appDomain = null; appDomain = null;
} }
static void unloadAppDomain(AppDomain appDomain) { static void UnloadAppDomain(AppDomain appDomain) {
if (appDomain != null) { if (appDomain != null) {
try { try {
AppDomain.Unload(appDomain); AppDomain.Unload(appDomain);

View File

@ -32,18 +32,18 @@ namespace de4dot.code.AssemblyClient {
: base(version) { : base(version) {
} }
public override void loadServer(string filename) { public override void LoadServer(string filename) {
if (process != null) if (process != null)
throw new ApplicationException("Server is already loaded"); throw new ApplicationException("Server is already loaded");
var psi = new ProcessStartInfo { var psi = new ProcessStartInfo {
Arguments = string.Format("{0} {1}", Utils.shellEscape(ipcName), Utils.shellEscape(ipcUri)), Arguments = string.Format("{0} {1}", Utils.ShellEscape(ipcName), Utils.ShellEscape(ipcUri)),
CreateNoWindow = true, CreateNoWindow = true,
ErrorDialog = false, ErrorDialog = false,
FileName = filename, FileName = filename,
LoadUserProfile = false, LoadUserProfile = false,
UseShellExecute = false, UseShellExecute = false,
WorkingDirectory = Utils.getOurBaseDir(), WorkingDirectory = Utils.GetOurBaseDir(),
}; };
process = Process.Start(psi); process = Process.Start(psi);
if (process == null) if (process == null)

View File

@ -25,13 +25,13 @@ namespace de4dot.code.AssemblyClient {
class SameAppDomainAssemblyServerLoader : IAssemblyServerLoader { class SameAppDomainAssemblyServerLoader : IAssemblyServerLoader {
IAssemblyService service; IAssemblyService service;
public void loadServer() { public void LoadServer() {
if (service != null) if (service != null)
throw new ApplicationException("Server already loaded"); throw new ApplicationException("Server already loaded");
service = new AssemblyService(); service = new AssemblyService();
} }
public IAssemblyService createService() { public IAssemblyService CreateService() {
return service; return service;
} }

View File

@ -31,27 +31,27 @@ namespace de4dot.code {
ModuleContext moduleContext; ModuleContext moduleContext;
public AssemblyModule(string filename, ModuleContext moduleContext) { public AssemblyModule(string filename, ModuleContext moduleContext) {
this.filename = Utils.getFullPath(filename); this.filename = Utils.GetFullPath(filename);
this.moduleContext = moduleContext; this.moduleContext = moduleContext;
} }
public ModuleDefMD load() { public ModuleDefMD Load() {
return setModule(ModuleDefMD.Load(filename, moduleContext)); return SetModule(ModuleDefMD.Load(filename, moduleContext));
} }
public ModuleDefMD load(byte[] fileData) { public ModuleDefMD Load(byte[] fileData) {
return setModule(ModuleDefMD.Load(fileData, moduleContext)); return SetModule(ModuleDefMD.Load(fileData, moduleContext));
} }
ModuleDefMD setModule(ModuleDefMD newModule) { ModuleDefMD SetModule(ModuleDefMD newModule) {
module = newModule; module = newModule;
TheAssemblyResolver.Instance.addModule(module); TheAssemblyResolver.Instance.AddModule(module);
module.EnableTypeDefFindCache = true; module.EnableTypeDefFindCache = true;
module.Location = filename; module.Location = filename;
return module; return module;
} }
public void save(string newFilename, MetaDataFlags mdFlags, IModuleWriterListener writerListener) { public void Save(string newFilename, MetaDataFlags mdFlags, IModuleWriterListener writerListener) {
if (module.IsILOnly) { if (module.IsILOnly) {
var writerOptions = new ModuleWriterOptions(module, writerListener); var writerOptions = new ModuleWriterOptions(module, writerListener);
writerOptions.MetaDataOptions.Flags |= mdFlags; writerOptions.MetaDataOptions.Flags |= mdFlags;
@ -68,7 +68,7 @@ namespace de4dot.code {
} }
} }
public ModuleDefMD reload(byte[] newModuleData, DumpedMethodsRestorer dumpedMethodsRestorer, IStringDecrypter stringDecrypter) { public ModuleDefMD Reload(byte[] newModuleData, DumpedMethodsRestorer dumpedMethodsRestorer, IStringDecrypter stringDecrypter) {
TheAssemblyResolver.Instance.Remove(module); TheAssemblyResolver.Instance.Remove(module);
var mod = ModuleDefMD.Load(newModuleData, moduleContext); var mod = ModuleDefMD.Load(newModuleData, moduleContext);
if (dumpedMethodsRestorer != null) if (dumpedMethodsRestorer != null)
@ -77,7 +77,7 @@ namespace de4dot.code {
mod.MethodDecrypter = dumpedMethodsRestorer; mod.MethodDecrypter = dumpedMethodsRestorer;
mod.TablesStream.ColumnReader = dumpedMethodsRestorer; mod.TablesStream.ColumnReader = dumpedMethodsRestorer;
mod.TablesStream.MethodRowReader = dumpedMethodsRestorer; mod.TablesStream.MethodRowReader = dumpedMethodsRestorer;
return setModule(mod); return SetModule(mod);
} }
public override string ToString() { public override string ToString() {

View File

@ -27,16 +27,16 @@ namespace de4dot.code {
EnableTypeDefCache = true; EnableTypeDefCache = true;
} }
public void addSearchDirectory(string dir) { public void AddSearchDirectory(string dir) {
if (!PostSearchPaths.Contains(dir)) if (!PostSearchPaths.Contains(dir))
PostSearchPaths.Add(dir); PostSearchPaths.Add(dir);
} }
public void addModule(ModuleDef module) { public void AddModule(ModuleDef module) {
AddToCache(module.Assembly); AddToCache(module.Assembly);
} }
public void removeModule(ModuleDef module) { public void RemoveModule(ModuleDef module) {
var assembly = module.Assembly; var assembly = module.Assembly;
if (assembly == null) if (assembly == null)
return; return;
@ -44,7 +44,7 @@ namespace de4dot.code {
Remove(module.Assembly); Remove(module.Assembly);
} }
public void clearAll() { public void ClearAll() {
//TODO: cache.Clear(); //TODO: cache.Clear();
//TODO: resetSearchPaths(); //TODO: resetSearchPaths();
} }

View File

@ -28,25 +28,25 @@ namespace de4dot.code {
public class DeobfuscatorContext : IDeobfuscatorContext { public class DeobfuscatorContext : IDeobfuscatorContext {
Dictionary<string, object> dataDict = new Dictionary<string, object>(StringComparer.Ordinal); Dictionary<string, object> dataDict = new Dictionary<string, object>(StringComparer.Ordinal);
public void clear() { public void Clear() {
dataDict.Clear(); dataDict.Clear();
} }
public void setData(string name, object data) { public void SetData(string name, object data) {
dataDict[name] = data; dataDict[name] = data;
} }
public object getData(string name) { public object GetData(string name) {
object value; object value;
dataDict.TryGetValue(name, out value); dataDict.TryGetValue(name, out value);
return value; return value;
} }
public void clearData(string name) { public void ClearData(string name) {
dataDict.Remove(name); dataDict.Remove(name);
} }
static ITypeDefOrRef getNonGenericTypeRef(ITypeDefOrRef typeRef) { static ITypeDefOrRef GetNonGenericTypeRef(ITypeDefOrRef typeRef) {
var ts = typeRef as TypeSpec; var ts = typeRef as TypeSpec;
if (ts == null) if (ts == null)
return typeRef; return typeRef;
@ -56,10 +56,10 @@ namespace de4dot.code {
return gis.GenericType.TypeDefOrRef; return gis.GenericType.TypeDefOrRef;
} }
public TypeDef resolveType(ITypeDefOrRef type) { public TypeDef ResolveType(ITypeDefOrRef type) {
if (type == null) if (type == null)
return null; return null;
type = getNonGenericTypeRef(type); type = GetNonGenericTypeRef(type);
var typeDef = type as TypeDef; var typeDef = type as TypeDef;
if (typeDef != null) if (typeDef != null)
@ -72,7 +72,7 @@ namespace de4dot.code {
return null; return null;
} }
public MethodDef resolveMethod(IMethod method) { public MethodDef ResolveMethod(IMethod method) {
if (method == null) if (method == null)
return null; return null;
@ -84,14 +84,14 @@ namespace de4dot.code {
if (mr == null || !mr.IsMethodRef) if (mr == null || !mr.IsMethodRef)
return null; return null;
var type = resolveType(mr.DeclaringType); var type = ResolveType(mr.DeclaringType);
if (type == null) if (type == null)
return null; return null;
return type.Resolve(mr) as MethodDef; return type.Resolve(mr) as MethodDef;
} }
public FieldDef resolveField(IField field) { public FieldDef ResolveField(IField field) {
if (field == null) if (field == null)
return null; return null;
@ -103,7 +103,7 @@ namespace de4dot.code {
if (mr == null || !mr.IsFieldRef) if (mr == null || !mr.IsFieldRef)
return null; return null;
var type = resolveType(mr.DeclaringType); var type = ResolveType(mr.DeclaringType);
if (type == null) if (type == null)
return null; return null;

View File

@ -37,12 +37,12 @@ namespace de4dot.code {
this.dumpedMethods = dumpedMethods; this.dumpedMethods = dumpedMethods;
} }
DumpedMethod getDumpedMethod(uint rid) { DumpedMethod GetDumpedMethod(uint rid) {
return dumpedMethods.get(0x06000000 | rid); return dumpedMethods.Get(0x06000000 | rid);
} }
public RawMethodRow ReadRow(uint rid) { public RawMethodRow ReadRow(uint rid) {
var dm = getDumpedMethod(rid); var dm = GetDumpedMethod(rid);
if (dm == null) if (dm == null)
return null; return null;
return new RawMethodRow(dm.mdRVA, dm.mdImplFlags, dm.mdFlags, dm.mdName, dm.mdSignature, dm.mdParamList); return new RawMethodRow(dm.mdRVA, dm.mdImplFlags, dm.mdFlags, dm.mdName, dm.mdSignature, dm.mdParamList);
@ -62,11 +62,11 @@ namespace de4dot.code {
} }
public bool HasMethodBody(uint rid) { public bool HasMethodBody(uint rid) {
return getDumpedMethod(rid) != null; return GetDumpedMethod(rid) != null;
} }
public MethodBody GetMethodBody(uint rid, RVA rva, IList<Parameter> parameters) { public MethodBody GetMethodBody(uint rid, RVA rva, IList<Parameter> parameters) {
var dm = getDumpedMethod(rid); var dm = GetDumpedMethod(rid);
if (dm == null) if (dm == null)
return null; return null;
return MethodBodyReader.Create(module, dm.code, dm.extraSections, parameters, dm.mhFlags, dm.mhMaxStack, dm.mhCodeSize, dm.mhLocalVarSigTok); return MethodBodyReader.Create(module, dm.code, dm.extraSections, parameters, dm.mhFlags, dm.mhMaxStack, dm.mhCodeSize, dm.mhLocalVarSigTok);

View File

@ -21,12 +21,12 @@ using dnlib.DotNet;
namespace de4dot.code { namespace de4dot.code {
public interface IDeobfuscatorContext { public interface IDeobfuscatorContext {
void clear(); void Clear();
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);
TypeDef resolveType(ITypeDefOrRef type); TypeDef ResolveType(ITypeDefOrRef type);
MethodDef resolveMethod(IMethod method); MethodDef ResolveMethod(IMethod method);
FieldDef resolveField(IField field); FieldDef ResolveField(IField field);
} }
} }

View File

@ -35,12 +35,12 @@ namespace de4dot.code {
bool RemoveNamespaceWithOneType { get; } bool RemoveNamespaceWithOneType { get; }
bool RenameResourceKeys { get; } bool RenameResourceKeys { get; }
void deobfuscateBegin(); void DeobfuscateBegin();
void deobfuscate(); void Deobfuscate();
void deobfuscateEnd(); void DeobfuscateEnd();
void deobfuscateCleanUp(); void DeobfuscateCleanUp();
void load(IList<IDeobfuscator> deobfuscators); void Load(IList<IDeobfuscator> deobfuscators);
void save(); void Save();
} }
} }

View File

@ -39,7 +39,7 @@ namespace de4dot.code {
if (indentLevel == value) if (indentLevel == value)
return; return;
indentLevel = value; indentLevel = value;
initIndentString(); InitIndentString();
} }
} }
@ -66,20 +66,20 @@ namespace de4dot.code {
this.canIgnoreMessages = canIgnoreMessages; this.canIgnoreMessages = canIgnoreMessages;
} }
void initIndentString() { void InitIndentString() {
if (indentLevel < 0) if (indentLevel < 0)
indentLevel = 0; indentLevel = 0;
indentString = new string(' ', indentLevel * indentSize); indentString = new string(' ', indentLevel * indentSize);
} }
public void indent() { public void Indent() {
indentLevel++; indentLevel++;
initIndentString(); InitIndentString();
} }
public void deIndent() { public void DeIndent() {
indentLevel--; indentLevel--;
initIndentString(); InitIndentString();
} }
public void Log(object sender, LoggerEvent loggerEvent, string format, params object[] args) { public void Log(object sender, LoggerEvent loggerEvent, string format, params object[] args) {
@ -93,7 +93,7 @@ namespace de4dot.code {
public void Log(bool canIgnore, object sender, LoggerEvent loggerEvent, string format, params object[] args) { public void Log(bool canIgnore, object sender, LoggerEvent loggerEvent, string format, params object[] args) {
if (IgnoresEvent(loggerEvent)) if (IgnoresEvent(loggerEvent))
return; return;
if (canIgnore && ignoreMessage(loggerEvent, format, args)) if (canIgnore && IgnoreMessage(loggerEvent, format, args))
return; return;
switch (loggerEvent) { switch (loggerEvent) {
@ -114,7 +114,7 @@ namespace de4dot.code {
} }
} }
bool ignoreMessage(LoggerEvent loggerEvent, string format, object[] args) { bool IgnoreMessage(LoggerEvent loggerEvent, string format, object[] args) {
if (loggerEvent != LoggerEvent.Error && loggerEvent != LoggerEvent.Warning) if (loggerEvent != LoggerEvent.Error && loggerEvent != LoggerEvent.Warning)
return false; return false;
if (!canIgnoreMessages) if (!canIgnoreMessages)
@ -138,7 +138,7 @@ namespace de4dot.code {
return loggerEvent > maxLoggerEvent; return loggerEvent > maxLoggerEvent;
} }
public static void log(LoggerEvent loggerEvent, string format, params object[] args) { public static void Log(LoggerEvent loggerEvent, string format, params object[] args) {
Instance.Log(null, loggerEvent, format, args); Instance.Log(null, loggerEvent, format, args);
} }

View File

@ -41,13 +41,13 @@ namespace de4dot.code {
Dictionary<Instruction, ExInfo> exInfos = new Dictionary<Instruction, ExInfo>(); Dictionary<Instruction, ExInfo> exInfos = new Dictionary<Instruction, ExInfo>();
ExInfo lastExInfo; ExInfo lastExInfo;
public void print(LoggerEvent loggerEvent, IList<Instruction> allInstructions, IList<ExceptionHandler> allExceptionHandlers) { public void Print(LoggerEvent loggerEvent, IList<Instruction> allInstructions, IList<ExceptionHandler> allExceptionHandlers) {
try { try {
this.loggerEvent = loggerEvent; this.loggerEvent = loggerEvent;
this.allInstructions = allInstructions; this.allInstructions = allInstructions;
this.allExceptionHandlers = allExceptionHandlers; this.allExceptionHandlers = allExceptionHandlers;
lastExInfo = new ExInfo(); lastExInfo = new ExInfo();
print(); Print();
} }
finally { finally {
this.allInstructions = null; this.allInstructions = null;
@ -59,27 +59,27 @@ namespace de4dot.code {
} }
} }
void initTargets() { void InitTargets() {
foreach (var instr in allInstructions) { foreach (var instr in allInstructions) {
switch (instr.OpCode.OperandType) { switch (instr.OpCode.OperandType) {
case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineBrTarget:
case OperandType.InlineBrTarget: case OperandType.InlineBrTarget:
setTarget(instr.Operand as Instruction); SetTarget(instr.Operand as Instruction);
break; break;
case OperandType.InlineSwitch: case OperandType.InlineSwitch:
foreach (var targetInstr in (Instruction[])instr.Operand) foreach (var targetInstr in (Instruction[])instr.Operand)
setTarget(targetInstr); SetTarget(targetInstr);
break; break;
} }
} }
foreach (var ex in allExceptionHandlers) { foreach (var ex in allExceptionHandlers) {
setTarget(ex.TryStart); SetTarget(ex.TryStart);
setTarget(ex.TryEnd); SetTarget(ex.TryEnd);
setTarget(ex.FilterStart); SetTarget(ex.FilterStart);
setTarget(ex.HandlerStart); SetTarget(ex.HandlerStart);
setTarget(ex.HandlerEnd); SetTarget(ex.HandlerEnd);
} }
var sortedTargets = new List<Instruction>(targets.Keys); var sortedTargets = new List<Instruction>(targets.Keys);
@ -88,27 +88,27 @@ namespace de4dot.code {
labels[sortedTargets[i]] = string.Format("label_{0}", i); labels[sortedTargets[i]] = string.Format("label_{0}", i);
} }
void setTarget(Instruction instr) { void SetTarget(Instruction instr) {
if (instr != null) if (instr != null)
targets[instr] = true; targets[instr] = true;
} }
void initExHandlers() { void InitExHandlers() {
foreach (var ex in allExceptionHandlers) { foreach (var ex in allExceptionHandlers) {
if (ex.TryStart != null) { if (ex.TryStart != null) {
getExInfo(ex.TryStart).tryStarts.Add(ex); GetExInfo(ex.TryStart).tryStarts.Add(ex);
getExInfo(ex.TryEnd).tryEnds.Add(ex); GetExInfo(ex.TryEnd).tryEnds.Add(ex);
} }
if (ex.FilterStart != null) if (ex.FilterStart != null)
getExInfo(ex.FilterStart).filterStarts.Add(ex); GetExInfo(ex.FilterStart).filterStarts.Add(ex);
if (ex.HandlerStart != null) { if (ex.HandlerStart != null) {
getExInfo(ex.HandlerStart).handlerStarts.Add(ex); GetExInfo(ex.HandlerStart).handlerStarts.Add(ex);
getExInfo(ex.HandlerEnd).handlerEnds.Add(ex); GetExInfo(ex.HandlerEnd).handlerEnds.Add(ex);
} }
} }
} }
ExInfo getExInfo(Instruction instruction) { ExInfo GetExInfo(Instruction instruction) {
if (instruction == null) if (instruction == null)
return lastExInfo; return lastExInfo;
ExInfo exInfo; ExInfo exInfo;
@ -117,49 +117,49 @@ namespace de4dot.code {
return exInfo; return exInfo;
} }
void print() { void Print() {
initTargets(); InitTargets();
initExHandlers(); InitExHandlers();
Logger.Instance.indent(); Logger.Instance.Indent();
foreach (var instr in allInstructions) { foreach (var instr in allInstructions) {
if (targets.ContainsKey(instr)) { if (targets.ContainsKey(instr)) {
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
Logger.log(loggerEvent, "{0}:", getLabel(instr)); Logger.Log(loggerEvent, "{0}:", GetLabel(instr));
Logger.Instance.indent(); Logger.Instance.Indent();
} }
ExInfo exInfo; ExInfo exInfo;
if (exInfos.TryGetValue(instr, out exInfo)) if (exInfos.TryGetValue(instr, out exInfo))
printExInfo(exInfo); PrintExInfo(exInfo);
var instrString = instr.OpCode.Name; var instrString = instr.OpCode.Name;
var operandString = getOperandString(instr); var operandString = GetOperandString(instr);
var memberRef = instr.Operand as ITokenOperand; var memberRef = instr.Operand as ITokenOperand;
if (operandString == "") if (operandString == "")
Logger.log(loggerEvent, "{0}", instrString); Logger.Log(loggerEvent, "{0}", instrString);
else if (memberRef != null) else if (memberRef != null)
Logger.log(loggerEvent, "{0,-9} {1} // {2:X8}", instrString, Utils.removeNewlines(operandString), memberRef.MDToken.ToUInt32()); Logger.Log(loggerEvent, "{0,-9} {1} // {2:X8}", instrString, Utils.RemoveNewlines(operandString), memberRef.MDToken.ToUInt32());
else else
Logger.log(loggerEvent, "{0,-9} {1}", instrString, Utils.removeNewlines(operandString)); Logger.Log(loggerEvent, "{0,-9} {1}", instrString, Utils.RemoveNewlines(operandString));
} }
printExInfo(lastExInfo); PrintExInfo(lastExInfo);
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
} }
string getOperandString(Instruction instr) { string GetOperandString(Instruction instr) {
if (instr.Operand is Instruction) if (instr.Operand is Instruction)
return getLabel((Instruction)instr.Operand); return GetLabel((Instruction)instr.Operand);
else if (instr.Operand is Instruction[]) { else if (instr.Operand is Instruction[]) {
var sb = new StringBuilder(); var sb = new StringBuilder();
var targets = (Instruction[])instr.Operand; var targets = (Instruction[])instr.Operand;
for (int i = 0; i < targets.Length; i++) { for (int i = 0; i < targets.Length; i++) {
if (i > 0) if (i > 0)
sb.Append(','); sb.Append(',');
sb.Append(getLabel(targets[i])); sb.Append(GetLabel(targets[i]));
} }
return sb.ToString(); return sb.ToString();
} }
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 Parameter) { else if (instr.Operand is Parameter) {
var arg = (Parameter)instr.Operand; var arg = (Parameter)instr.Operand;
var s = InstructionPrinter.GetOperandString(instr); var s = InstructionPrinter.GetOperandString(instr);
@ -171,36 +171,36 @@ namespace de4dot.code {
return InstructionPrinter.GetOperandString(instr); return InstructionPrinter.GetOperandString(instr);
} }
void printExInfo(ExInfo exInfo) { void PrintExInfo(ExInfo exInfo) {
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
foreach (var ex in exInfo.tryStarts) foreach (var ex in exInfo.tryStarts)
Logger.log(loggerEvent, "// try start: {0}", getExceptionString(ex)); Logger.Log(loggerEvent, "// try start: {0}", GetExceptionString(ex));
foreach (var ex in exInfo.tryEnds) foreach (var ex in exInfo.tryEnds)
Logger.log(loggerEvent, "// try end: {0}", getExceptionString(ex)); Logger.Log(loggerEvent, "// try end: {0}", GetExceptionString(ex));
foreach (var ex in exInfo.filterStarts) foreach (var ex in exInfo.filterStarts)
Logger.log(loggerEvent, "// filter start: {0}", getExceptionString(ex)); Logger.Log(loggerEvent, "// filter start: {0}", GetExceptionString(ex));
foreach (var ex in exInfo.handlerStarts) foreach (var ex in exInfo.handlerStarts)
Logger.log(loggerEvent, "// handler start: {0}", getExceptionString(ex)); Logger.Log(loggerEvent, "// handler start: {0}", GetExceptionString(ex));
foreach (var ex in exInfo.handlerEnds) foreach (var ex in exInfo.handlerEnds)
Logger.log(loggerEvent, "// handler end: {0}", getExceptionString(ex)); Logger.Log(loggerEvent, "// handler end: {0}", GetExceptionString(ex));
Logger.Instance.indent(); Logger.Instance.Indent();
} }
string getExceptionString(ExceptionHandler ex) { string GetExceptionString(ExceptionHandler ex) {
var sb = new StringBuilder(); var sb = new StringBuilder();
if (ex.TryStart != null) if (ex.TryStart != null)
sb.Append(string.Format("TRY: {0}-{1}", getLabel(ex.TryStart), getLabel(ex.TryEnd))); sb.Append(string.Format("TRY: {0}-{1}", GetLabel(ex.TryStart), GetLabel(ex.TryEnd)));
if (ex.FilterStart != null) if (ex.FilterStart != null)
sb.Append(string.Format(", FILTER: {0}", getLabel(ex.FilterStart))); sb.Append(string.Format(", FILTER: {0}", GetLabel(ex.FilterStart)));
if (ex.HandlerStart != null) if (ex.HandlerStart != null)
sb.Append(string.Format(", HANDLER: {0}-{1}", getLabel(ex.HandlerStart), getLabel(ex.HandlerEnd))); sb.Append(string.Format(", HANDLER: {0}-{1}", GetLabel(ex.HandlerStart), GetLabel(ex.HandlerEnd)));
sb.Append(string.Format(", TYPE: {0}", ex.HandlerType)); sb.Append(string.Format(", TYPE: {0}", ex.HandlerType));
if (ex.CatchType != null) if (ex.CatchType != null)
sb.Append(string.Format(", CATCH: {0}", ex.CatchType)); sb.Append(string.Format(", CATCH: {0}", ex.CatchType));
return sb.ToString(); return sb.ToString();
} }
string getLabel(Instruction instr) { string GetLabel(Instruction instr) {
if (instr == null) if (instr == null)
return "<end>"; return "<end>";
return labels[instr]; return labels[instr];

View File

@ -35,24 +35,24 @@ namespace de4dot.code {
object value; object value;
bool unknownValue = false; bool unknownValue = false;
public bool isValid() { public bool IsValid() {
return !unknownValue && writes == 1; return !unknownValue && writes == 1;
} }
public object Value { public object Value {
get { get {
if (!isValid()) if (!IsValid())
throw new ApplicationException("Unknown variable value"); throw new ApplicationException("Unknown variable value");
return value; return value;
} }
set { this.value = value; } set { this.value = value; }
} }
public void addWrite() { public void AddWrite() {
writes++; writes++;
} }
public void setUnknown() { public void SetUnknown() {
unknownValue = true; unknownValue = true;
} }
} }
@ -60,10 +60,10 @@ namespace de4dot.code {
public VariableValues(IList<Local> 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(); Initialize();
} }
void init() { void Initialize() {
foreach (var variable in locals) foreach (var variable in locals)
variableToValue[variable] = new Variable(); variableToValue[variable] = new Variable();
@ -78,12 +78,12 @@ namespace de4dot.code {
case Code.Stloc_1: case Code.Stloc_1:
case Code.Stloc_2: case Code.Stloc_2:
case Code.Stloc_3: case Code.Stloc_3:
var variable = Instr.getLocalVar(locals, instr); var variable = Instr.GetLocalVar(locals, instr);
var val = variableToValue[variable]; var val = variableToValue[variable];
val.addWrite(); val.AddWrite();
object obj; object obj;
if (!getValue(block, i, out obj)) if (!GetValue(block, i, out obj))
val.setUnknown(); val.SetUnknown();
val.Value = obj; val.Value = obj;
break; break;
@ -94,7 +94,7 @@ namespace de4dot.code {
} }
} }
bool getValue(Block block, int index, out object obj) { bool GetValue(Block block, int index, out object obj) {
while (true) { while (true) {
if (index <= 0) { if (index <= 0) {
obj = null; obj = null;
@ -135,7 +135,7 @@ namespace de4dot.code {
} }
} }
public Variable getValue(Local variable) { public Variable GetValue(Local variable) {
return variableToValue[variable]; return variableToValue[variable];
} }
} }
@ -165,7 +165,7 @@ namespace de4dot.code {
this.callEndIndex = callEndIndex; this.callEndIndex = callEndIndex;
} }
public IMethod getMethodRef() { public IMethod GetMethodRef() {
return (IMethod)block.Instructions[callEndIndex].Operand; return (IMethod)block.Instructions[callEndIndex].Operand;
} }
} }
@ -180,18 +180,18 @@ namespace de4dot.code {
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(IMethod method, MethodSpec 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)
return 0; return 0;
return decrypt(blocks.Method, blocks.MethodBlocks.getAllBlocks()); return Decrypt(blocks.Method, blocks.MethodBlocks.GetAllBlocks());
} }
public int decrypt(MethodDef method, List<Block> allBlocks) { public int Decrypt(MethodDef method, List<Block> allBlocks) {
if (!HasHandlers) if (!HasHandlers)
return 0; return 0;
try { try {
@ -199,9 +199,9 @@ namespace de4dot.code {
callResults = new List<CallResult>(); callResults = new List<CallResult>();
this.allBlocks = allBlocks; this.allBlocks = allBlocks;
findAllCallResults(); FindAllCallResults();
inlineAllCalls(); InlineAllCalls();
inlineReturnValues(); InlineReturnValues();
return callResults.Count; return callResults.Count;
} }
catch { catch {
@ -216,11 +216,11 @@ namespace de4dot.code {
} }
} }
bool getLocalVariableValue(Local 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.Body.Variables, allBlocks);
var val = variableValues.getValue(variable); var val = variableValues.GetValue(variable);
if (!val.isValid()) { if (!val.IsValid()) {
value = null; value = null;
return false; return false;
} }
@ -228,12 +228,12 @@ namespace de4dot.code {
return true; return true;
} }
void findAllCallResults() { void FindAllCallResults() {
foreach (var block in allBlocks) foreach (var block in allBlocks)
findCallResults(block); FindCallResults(block);
} }
void findCallResults(Block block) { void FindCallResults(Block block) {
for (int i = 0; i < block.Instructions.Count; i++) { for (int i = 0; i < block.Instructions.Count; i++) {
var instr = block.Instructions[i]; var instr = block.Instructions[i];
if (instr.OpCode != OpCodes.Call) if (instr.OpCode != OpCodes.Call)
@ -246,31 +246,31 @@ namespace de4dot.code {
var gim = method as MethodSpec; var gim = method as MethodSpec;
if (gim != null) if (gim != null)
elementMethod = gim.Method; 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;
if (findArgs(callResult)) if (FindArgs(callResult))
callResults.Add(callResult); callResults.Add(callResult);
} }
} }
bool findArgs(CallResult callResult) { bool FindArgs(CallResult callResult) {
var block = callResult.block; var block = callResult.block;
var method = callResult.getMethodRef(); var method = callResult.GetMethodRef();
var methodArgs = DotNetUtils.getArgs(method); var methodArgs = DotNetUtils.GetArgs(method);
int numArgs = methodArgs.Count; int numArgs = methodArgs.Count;
var args = new object[numArgs]; var args = new object[numArgs];
int instrIndex = callResult.callEndIndex - 1; int instrIndex = callResult.callEndIndex - 1;
for (int i = numArgs - 1; i >= 0; i--) { for (int i = numArgs - 1; i >= 0; i--) {
object arg = null; object arg = null;
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], (int)arg); arg = FixIntArg(methodArgs[i], (int)arg);
else if (arg is long) else if (arg is long)
arg = fixIntArg(methodArgs[i], (long)arg); arg = FixIntArg(methodArgs[i], (long)arg);
args[i] = arg; args[i] = arg;
} }
@ -279,7 +279,7 @@ namespace de4dot.code {
return true; return true;
} }
object fixIntArg(TypeSig type, long value) { object FixIntArg(TypeSig type, long value) {
switch (type.ElementType) { 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;
@ -295,14 +295,14 @@ namespace de4dot.code {
throw new ApplicationException(string.Format("Wrong type {0}", type)); throw new ApplicationException(string.Format("Wrong type {0}", type));
} }
bool getArg(IMethod 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
// more blocks branching to the decrypter method, or the two blocks can't be // more blocks branching to the decrypter method, or the two blocks can't be
// merged because one is outside the exception handler (eg. buggy obfuscator). // merged because one is outside the exception handler (eg. buggy obfuscator).
Logger.w("Could not find all arguments to method {0} ({1:X8})", Logger.w("Could not find all arguments to method {0} ({1:X8})",
Utils.removeNewlines(method), Utils.RemoveNewlines(method),
method.MDToken.ToInt32()); method.MDToken.ToInt32());
errors++; errors++;
return false; return false;
@ -342,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.Instruction.GetLocal(theMethod.Body.Variables), out arg); GetLocalVariableValue(instr.Instruction.GetLocal(theMethod.Body.Variables), out arg);
break; break;
case Code.Ldfld: case Code.Ldfld:
@ -355,7 +355,7 @@ namespace de4dot.code {
instr.Instruction.CalculateStackUsage(false, out pushes, out pops); instr.Instruction.CalculateStackUsage(false, out pushes, out pops);
if (!useUnknownArgs || pushes != 1) { if (!useUnknownArgs || pushes != 1) {
Logger.w("Could not find all arguments to method {0} ({1:X8}), instr: {2}", Logger.w("Could not find all arguments to method {0} ({1:X8}), instr: {2}",
Utils.removeNewlines(method), Utils.RemoveNewlines(method),
method.MDToken.ToInt32(), method.MDToken.ToInt32(),
instr); instr);
errors++; errors++;
@ -363,7 +363,7 @@ namespace de4dot.code {
} }
for (int i = 0; i < pops; i++) { for (int i = 0; i < pops; i++) {
if (!getArg(method, block, ref arg, ref instrIndex)) if (!GetArg(method, block, ref arg, ref instrIndex))
return false; return false;
} }
arg = null; arg = null;
@ -375,8 +375,8 @@ namespace de4dot.code {
return true; return true;
} }
void inlineReturnValues() { void InlineReturnValues() {
callResults = removeNulls(callResults); callResults = RemoveNulls(callResults);
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);
@ -386,10 +386,10 @@ namespace de4dot.code {
return a.callStartIndex.CompareTo(b.callStartIndex); return a.callStartIndex.CompareTo(b.callStartIndex);
}); });
callResults.Reverse(); callResults.Reverse();
inlineReturnValues(callResults); InlineReturnValues(callResults);
} }
static List<CallResult> removeNulls(List<CallResult> inList) { static List<CallResult> RemoveNulls(List<CallResult> inList) {
var outList = new List<CallResult>(inList.Count); var outList = new List<CallResult>(inList.Count);
foreach (var callResult in inList) { foreach (var callResult in inList) {
if (callResult.returnValue != null) if (callResult.returnValue != null)
@ -398,6 +398,6 @@ namespace de4dot.code {
return outList; return outList;
} }
protected abstract void inlineReturnValues(IList<CallResult> callResults); protected abstract void InlineReturnValues(IList<CallResult> callResults);
} }
} }

View File

@ -39,7 +39,7 @@ namespace de4dot.code {
} }
// Returns true if the regex matches. Use MatchValue to get result. // Returns true if the regex matches. Use MatchValue to get result.
public bool isMatch(string s) { public bool IsMatch(string s) {
return regex.IsMatch(s); return regex.IsMatch(s);
} }
@ -60,10 +60,10 @@ namespace de4dot.code {
} }
public NameRegexes(string regex) { public NameRegexes(string regex) {
set(regex); Set(regex);
} }
public void set(string regexesString) { public void Set(string regexesString) {
regexes = new List<NameRegex>(); regexes = new List<NameRegex>();
if (regexesString != "") { if (regexesString != "") {
foreach (var regex in regexesString.Split(new char[] { regexSeparatorChar })) foreach (var regex in regexesString.Split(new char[] { regexSeparatorChar }))
@ -71,9 +71,9 @@ namespace de4dot.code {
} }
} }
public bool isMatch(string s) { public bool IsMatch(string s) {
foreach (var regex in regexes) { foreach (var regex in regexes) {
if (regex.isMatch(s)) if (regex.IsMatch(s))
return regex.MatchValue; return regex.MatchValue;
} }

View File

@ -55,27 +55,27 @@ namespace de4dot.code {
public SavedMethodBody(MethodDef method) { public SavedMethodBody(MethodDef method) {
this.method = method; this.method = method;
DotNetUtils.copyBody(method, out instructions, out exceptionHandlers); DotNetUtils.CopyBody(method, out instructions, out exceptionHandlers);
} }
public void restore() { public void Restore() {
DotNetUtils.restoreBody(method, instructions, exceptionHandlers); DotNetUtils.RestoreBody(method, instructions, exceptionHandlers);
} }
} }
public void save(MethodDef method) { public void Save(MethodDef method) {
if (isSaved(method)) if (IsSaved(method))
return; return;
savedMethodBodies[method] = new SavedMethodBody(method); savedMethodBodies[method] = new SavedMethodBody(method);
} }
public void restoreAll() { public void RestoreAll() {
foreach (var smb in savedMethodBodies.Values) foreach (var smb in savedMethodBodies.Values)
smb.restore(); smb.Restore();
savedMethodBodies.Clear(); savedMethodBodies.Clear();
} }
public bool isSaved(MethodDef method) { public bool IsSaved(MethodDef method) {
return savedMethodBodies.ContainsKey(method); return savedMethodBodies.ContainsKey(method);
} }
} }
@ -139,17 +139,17 @@ namespace de4dot.code {
this.assemblyClientFactory = assemblyClientFactory; this.assemblyClientFactory = assemblyClientFactory;
this.options = options; this.options = options;
userStringDecrypterMethods = options.StringDecrypterMethods.Count > 0; userStringDecrypterMethods = options.StringDecrypterMethods.Count > 0;
options.Filename = Utils.getFullPath(options.Filename); options.Filename = Utils.GetFullPath(options.Filename);
assemblyModule = new AssemblyModule(options.Filename, moduleContext); assemblyModule = new AssemblyModule(options.Filename, moduleContext);
if (options.NewFilename == null) if (options.NewFilename == null)
options.NewFilename = getDefaultNewFilename(); options.NewFilename = GetDefaultNewFilename();
if (string.Equals(options.Filename, options.NewFilename, StringComparison.OrdinalIgnoreCase)) if (string.Equals(options.Filename, options.NewFilename, StringComparison.OrdinalIgnoreCase))
throw new UserException(string.Format("filename is same as new filename! ({0})", options.Filename)); throw new UserException(string.Format("filename is same as new filename! ({0})", options.Filename));
} }
string getDefaultNewFilename() { string GetDefaultNewFilename() {
int dotIndex = options.Filename.LastIndexOf('.'); int dotIndex = options.Filename.LastIndexOf('.');
string noExt, ext; string noExt, ext;
if (dotIndex != -1) { if (dotIndex != -1) {
@ -163,15 +163,15 @@ namespace de4dot.code {
return noExt + "-cleaned" + ext; return noExt + "-cleaned" + ext;
} }
public void load(IList<IDeobfuscator> deobfuscators) { public void Load(IList<IDeobfuscator> deobfuscators) {
try { try {
loadModule(deobfuscators); LoadModule(deobfuscators);
TheAssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(Filename)); TheAssemblyResolver.Instance.AddSearchDirectory(Utils.GetDirName(Filename));
TheAssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(NewFilename)); TheAssemblyResolver.Instance.AddSearchDirectory(Utils.GetDirName(NewFilename));
detectObfuscator(deobfuscators); DetectObfuscator(deobfuscators);
if (deob == null) if (deob == null)
throw new ApplicationException("Could not detect obfuscator!"); throw new ApplicationException("Could not detect obfuscator!");
initializeDeobfuscator(); InitializeDeobfuscator();
} }
finally { finally {
foreach (var d in deobfuscators) { foreach (var d in deobfuscators) {
@ -181,13 +181,13 @@ namespace de4dot.code {
} }
} }
void loadModule(IEnumerable<IDeobfuscator> deobfuscators) { void LoadModule(IEnumerable<IDeobfuscator> deobfuscators) {
ModuleDefMD oldModule = module; ModuleDefMD oldModule = module;
try { try {
module = assemblyModule.load(); module = assemblyModule.Load();
} }
catch (BadImageFormatException) { catch (BadImageFormatException) {
if (!unpackNativeImage(deobfuscators)) if (!UnpackNativeImage(deobfuscators))
throw new BadImageFormatException(); throw new BadImageFormatException();
Logger.v("Unpacked native file"); Logger.v("Unpacked native file");
} }
@ -197,12 +197,12 @@ namespace de4dot.code {
} }
} }
bool unpackNativeImage(IEnumerable<IDeobfuscator> deobfuscators) { bool UnpackNativeImage(IEnumerable<IDeobfuscator> deobfuscators) {
using (var peImage = new PEImage(Filename)) { using (var peImage = new PEImage(Filename)) {
foreach (var deob in deobfuscators) { foreach (var deob in deobfuscators) {
byte[] unpackedData = null; byte[] unpackedData = null;
try { try {
unpackedData = deob.unpackNativeFile(peImage); unpackedData = deob.UnpackNativeFile(peImage);
} }
catch { catch {
} }
@ -211,7 +211,7 @@ namespace de4dot.code {
var oldModule = module; var oldModule = module;
try { try {
module = assemblyModule.load(unpackedData); module = assemblyModule.Load(unpackedData);
} }
catch { catch {
Logger.w("Could not load unpacked data. File: {0}, deobfuscator: {0}", peImage.FileName ?? "(unknown filename)", deob.TypeLong); Logger.w("Could not load unpacked data. File: {0}, deobfuscator: {0}", peImage.FileName ?? "(unknown filename)", deob.TypeLong);
@ -229,16 +229,16 @@ namespace de4dot.code {
return false; return false;
} }
void initializeDeobfuscator() { void InitializeDeobfuscator() {
if (options.StringDecrypterType == DecrypterType.Default) if (options.StringDecrypterType == DecrypterType.Default)
options.StringDecrypterType = deob.DefaultDecrypterType; options.StringDecrypterType = deob.DefaultDecrypterType;
if (options.StringDecrypterType == DecrypterType.Default) if (options.StringDecrypterType == DecrypterType.Default)
options.StringDecrypterType = DecrypterType.Static; options.StringDecrypterType = DecrypterType.Static;
deob.Operations = createOperations(); deob.Operations = CreateOperations();
} }
IOperations createOperations() { IOperations CreateOperations() {
var op = new Operations(); var op = new Operations();
switch (options.StringDecrypterType) { switch (options.StringDecrypterType) {
@ -260,7 +260,7 @@ namespace de4dot.code {
return op; return op;
} }
void detectObfuscator(IEnumerable<IDeobfuscator> deobfuscators) { void DetectObfuscator(IEnumerable<IDeobfuscator> deobfuscators) {
// The deobfuscators may call methods to deobfuscate control flow and decrypt // The deobfuscators may call methods to deobfuscate control flow and decrypt
// strings (statically) in order to detect the obfuscator. // strings (statically) in order to detect the obfuscator.
@ -269,14 +269,14 @@ namespace de4dot.code {
// It's not null if it unpacked a native file // It's not null if it unpacked a native file
if (this.deob != null) { if (this.deob != null) {
deob.init(module); deob.Initialize(module);
deob.DeobfuscatedFile = this; deob.DeobfuscatedFile = this;
deob.detect(); deob.Detect();
return; return;
} }
foreach (var deob in deobfuscators) { foreach (var deob in deobfuscators) {
deob.init(module); deob.Initialize(module);
deob.DeobfuscatedFile = this; deob.DeobfuscatedFile = this;
} }
@ -284,16 +284,16 @@ namespace de4dot.code {
foreach (var deob in deobfuscators) { foreach (var deob in deobfuscators) {
if (string.Equals(options.ForcedObfuscatorType, deob.Type, StringComparison.OrdinalIgnoreCase)) { if (string.Equals(options.ForcedObfuscatorType, deob.Type, StringComparison.OrdinalIgnoreCase)) {
this.deob = deob; this.deob = deob;
deob.detect(); deob.Detect();
return; return;
} }
} }
} }
else else
this.deob = detectObfuscator2(deobfuscators); this.deob = DetectObfuscator2(deobfuscators);
} }
IDeobfuscator detectObfuscator2(IEnumerable<IDeobfuscator> deobfuscators) { IDeobfuscator DetectObfuscator2(IEnumerable<IDeobfuscator> deobfuscators) {
var allDetected = new List<IDeobfuscator>(); var allDetected = new List<IDeobfuscator>();
IDeobfuscator detected = null; IDeobfuscator detected = null;
int detectVal = 0; int detectVal = 0;
@ -301,7 +301,7 @@ namespace de4dot.code {
this.deob = deob; // So we can call deob.CanInlineMethods in deobfuscate() this.deob = deob; // So we can call deob.CanInlineMethods in deobfuscate()
int val; int val;
try { try {
val = deob.detect(); val = deob.Detect();
} }
catch { catch {
val = deob.Type == "un" ? 1 : 0; val = deob.Type == "un" ? 1 : 0;
@ -318,16 +318,16 @@ namespace de4dot.code {
if (allDetected.Count > 1) { if (allDetected.Count > 1) {
Logger.n("More than one obfuscator detected:"); Logger.n("More than one obfuscator detected:");
Logger.Instance.indent(); Logger.Instance.Indent();
foreach (var deob in allDetected) foreach (var deob in allDetected)
Logger.n("{0} (use: -p {1})", deob.Name, deob.Type); Logger.n("{0} (use: -p {1})", deob.Name, deob.Type);
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
} }
return detected; return detected;
} }
MetaDataFlags getMetaDataFlags() { MetaDataFlags GetMetaDataFlags() {
var mdFlags = options.MetaDataFlags | deob.MetaDataFlags; var mdFlags = options.MetaDataFlags | deob.MetaDataFlags;
// Always preserve tokens if it's an unknown obfuscator // Always preserve tokens if it's an unknown obfuscator
@ -341,15 +341,15 @@ namespace de4dot.code {
return mdFlags; return mdFlags;
} }
public void save() { public void Save() {
Logger.n("Saving {0}", options.NewFilename); Logger.n("Saving {0}", options.NewFilename);
var mdFlags = getMetaDataFlags(); var mdFlags = GetMetaDataFlags();
if (!options.ControlFlowDeobfuscation) if (!options.ControlFlowDeobfuscation)
mdFlags |= MetaDataFlags.KeepOldMaxStack; mdFlags |= MetaDataFlags.KeepOldMaxStack;
assemblyModule.save(options.NewFilename, mdFlags, deob as IModuleWriterListener); assemblyModule.Save(options.NewFilename, mdFlags, deob as IModuleWriterListener);
} }
IList<MethodDef> getAllMethods() { IList<MethodDef> GetAllMethods() {
var list = new List<MethodDef>(); var list = new List<MethodDef>();
foreach (var type in module.GetTypes()) { foreach (var type in module.GetTypes()) {
@ -360,25 +360,25 @@ namespace de4dot.code {
return list; return list;
} }
public void deobfuscateBegin() { public void DeobfuscateBegin() {
switch (options.StringDecrypterType) { switch (options.StringDecrypterType) {
case DecrypterType.None: case DecrypterType.None:
checkSupportedStringDecrypter(StringFeatures.AllowNoDecryption); CheckSupportedStringDecrypter(StringFeatures.AllowNoDecryption);
break; break;
case DecrypterType.Static: case DecrypterType.Static:
checkSupportedStringDecrypter(StringFeatures.AllowStaticDecryption); CheckSupportedStringDecrypter(StringFeatures.AllowStaticDecryption);
break; break;
case DecrypterType.Delegate: case DecrypterType.Delegate:
case DecrypterType.Emulate: case DecrypterType.Emulate:
checkSupportedStringDecrypter(StringFeatures.AllowDynamicDecryption); CheckSupportedStringDecrypter(StringFeatures.AllowDynamicDecryption);
var newProcFactory = assemblyClientFactory as NewProcessAssemblyClientFactory; var newProcFactory = assemblyClientFactory as NewProcessAssemblyClientFactory;
if (newProcFactory != null) if (newProcFactory != null)
assemblyClient = newProcFactory.create(module); assemblyClient = newProcFactory.Create(module);
else else
assemblyClient = assemblyClientFactory.create(); assemblyClient = assemblyClientFactory.Create();
assemblyClient.connect(); assemblyClient.Connect();
break; break;
default: default:
@ -386,73 +386,73 @@ namespace de4dot.code {
} }
} }
public void checkSupportedStringDecrypter(StringFeatures feature) { public void CheckSupportedStringDecrypter(StringFeatures feature) {
if ((deob.StringFeatures & feature) == feature) if ((deob.StringFeatures & feature) == feature)
return; return;
throw new UserException(string.Format("Deobfuscator {0} does not support this string decryption type", deob.TypeLong)); throw new UserException(string.Format("Deobfuscator {0} does not support this string decryption type", deob.TypeLong));
} }
public void deobfuscate() { public void Deobfuscate() {
Logger.n("Cleaning {0}", options.Filename); Logger.n("Cleaning {0}", options.Filename);
initAssemblyClient(); InitAssemblyClient();
for (int i = 0; ; i++) { for (int i = 0; ; i++) {
byte[] fileData = null; byte[] fileData = null;
DumpedMethods dumpedMethods = null; DumpedMethods dumpedMethods = null;
if (!deob.getDecryptedModule(i, ref fileData, ref dumpedMethods)) if (!deob.GetDecryptedModule(i, ref fileData, ref dumpedMethods))
break; break;
reloadModule(fileData, dumpedMethods); ReloadModule(fileData, dumpedMethods);
} }
deob.deobfuscateBegin(); deob.DeobfuscateBegin();
deobfuscateMethods(); DeobfuscateMethods();
deob.deobfuscateEnd(); deob.DeobfuscateEnd();
} }
void reloadModule(byte[] newModuleData, DumpedMethods dumpedMethods) { void ReloadModule(byte[] newModuleData, DumpedMethods dumpedMethods) {
Logger.v("Reloading decrypted assembly (original filename: {0})", Filename); Logger.v("Reloading decrypted assembly (original filename: {0})", Filename);
simpleDeobfuscatorFlags.Clear(); simpleDeobfuscatorFlags.Clear();
using (var oldModule = module) { using (var oldModule = module) {
module = assemblyModule.reload(newModuleData, createDumpedMethodsRestorer(dumpedMethods), deob as IStringDecrypter); module = assemblyModule.Reload(newModuleData, CreateDumpedMethodsRestorer(dumpedMethods), deob as IStringDecrypter);
deob = deob.moduleReloaded(module); deob = deob.ModuleReloaded(module);
} }
initializeDeobfuscator(); InitializeDeobfuscator();
deob.DeobfuscatedFile = this; deob.DeobfuscatedFile = this;
updateDynamicStringInliner(); UpdateDynamicStringInliner();
} }
DumpedMethodsRestorer createDumpedMethodsRestorer(DumpedMethods dumpedMethods) { DumpedMethodsRestorer CreateDumpedMethodsRestorer(DumpedMethods dumpedMethods) {
if (dumpedMethods == null || dumpedMethods.Count == 0) if (dumpedMethods == null || dumpedMethods.Count == 0)
return null; return null;
return new DumpedMethodsRestorer(dumpedMethods); return new DumpedMethodsRestorer(dumpedMethods);
} }
void initAssemblyClient() { void InitAssemblyClient() {
if (assemblyClient == null) if (assemblyClient == null)
return; return;
assemblyClient.waitConnected(); assemblyClient.WaitConnected();
assemblyClient.Service.loadAssembly(options.Filename); assemblyClient.Service.LoadAssembly(options.Filename);
if (options.StringDecrypterType == DecrypterType.Delegate) if (options.StringDecrypterType == DecrypterType.Delegate)
assemblyClient.Service.setStringDecrypterType(AssemblyData.StringDecrypterType.Delegate); assemblyClient.Service.SetStringDecrypterType(AssemblyData.StringDecrypterType.Delegate);
else if (options.StringDecrypterType == DecrypterType.Emulate) else if (options.StringDecrypterType == DecrypterType.Emulate)
assemblyClient.Service.setStringDecrypterType(AssemblyData.StringDecrypterType.Emulate); assemblyClient.Service.SetStringDecrypterType(AssemblyData.StringDecrypterType.Emulate);
else else
throw new ApplicationException(string.Format("Invalid string decrypter type '{0}'", options.StringDecrypterType)); throw new ApplicationException(string.Format("Invalid string decrypter type '{0}'", options.StringDecrypterType));
dynamicStringInliner = new DynamicStringInliner(assemblyClient); dynamicStringInliner = new DynamicStringInliner(assemblyClient);
updateDynamicStringInliner(); UpdateDynamicStringInliner();
} }
void updateDynamicStringInliner() { void UpdateDynamicStringInliner() {
if (dynamicStringInliner != null) if (dynamicStringInliner != null)
dynamicStringInliner.init(getMethodTokens()); dynamicStringInliner.Initialize(GetMethodTokens());
} }
IEnumerable<int> getMethodTokens() { IEnumerable<int> GetMethodTokens() {
if (!userStringDecrypterMethods) if (!userStringDecrypterMethods)
return deob.getStringDecrypterMethods(); return deob.GetStringDecrypterMethods();
var tokens = new List<int>(); var tokens = new List<int>();
@ -464,18 +464,18 @@ namespace de4dot.code {
if (int.TryParse(tokenStr, NumberStyles.HexNumber, null, out methodToken)) if (int.TryParse(tokenStr, NumberStyles.HexNumber, null, out methodToken))
tokens.Add(methodToken); tokens.Add(methodToken);
else else
tokens.AddRange(findMethodTokens(val)); tokens.AddRange(FindMethodTokens(val));
} }
return tokens; return tokens;
} }
IEnumerable<int> findMethodTokens(string methodDesc) { IEnumerable<int> FindMethodTokens(string methodDesc) {
var tokens = new List<int>(); var tokens = new List<int>();
string typeString, methodName; string typeString, methodName;
string[] argsStrings; string[] argsStrings;
splitMethodDesc(methodDesc, out typeString, out methodName, out argsStrings); SplitMethodDesc(methodDesc, out typeString, out methodName, out argsStrings);
foreach (var type in module.GetTypes()) { foreach (var type in module.GetTypes()) {
if (typeString != null && typeString != type.FullName) if (typeString != null && typeString != type.FullName)
@ -502,7 +502,7 @@ namespace de4dot.code {
} }
} }
Logger.v("Adding string decrypter; token: {0:X8}, method: {1}", method.MDToken.ToInt32(), Utils.removeNewlines(method.FullName)); Logger.v("Adding string decrypter; token: {0:X8}, method: {1}", method.MDToken.ToInt32(), Utils.RemoveNewlines(method.FullName));
tokens.Add(method.MDToken.ToInt32()); tokens.Add(method.MDToken.ToInt32());
} }
} }
@ -510,7 +510,7 @@ namespace de4dot.code {
return tokens; return tokens;
} }
static void splitMethodDesc(string methodDesc, out string type, out string name, out string[] args) { static void SplitMethodDesc(string methodDesc, out string type, out string name, out string[] args) {
string stringArgs = null; string stringArgs = null;
args = null; args = null;
type = null; type = null;
@ -555,20 +555,20 @@ namespace de4dot.code {
name = null; name = null;
} }
public void deobfuscateEnd() { public void DeobfuscateEnd() {
deobfuscateCleanUp(); DeobfuscateCleanUp();
} }
public void deobfuscateCleanUp() { public void DeobfuscateCleanUp() {
if (assemblyClient != null) { if (assemblyClient != null) {
assemblyClient.Dispose(); assemblyClient.Dispose();
assemblyClient = null; assemblyClient = null;
} }
} }
void deobfuscateMethods() { void DeobfuscateMethods() {
if (savedMethodBodies != null) { if (savedMethodBodies != null) {
savedMethodBodies.restoreAll(); savedMethodBodies.RestoreAll();
savedMethodBodies = null; savedMethodBodies = null;
} }
deob.DeobfuscatedFile = null; deob.DeobfuscatedFile = null;
@ -584,21 +584,21 @@ namespace de4dot.code {
Logger.v("Deobfuscating methods"); Logger.v("Deobfuscating methods");
var methodPrinter = new MethodPrinter(); var methodPrinter = new MethodPrinter();
var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators); var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators);
foreach (var method in getAllMethods()) { foreach (var method in GetAllMethods()) {
if (isVerbose) { if (isVerbose) {
Logger.v("Deobfuscating {0} ({1:X8})", Utils.removeNewlines(method), method.MDToken.ToUInt32()); Logger.v("Deobfuscating {0} ({1:X8})", Utils.RemoveNewlines(method), method.MDToken.ToUInt32());
Logger.Instance.indent(); Logger.Instance.Indent();
} }
int oldIndentLevel = Logger.Instance.IndentLevel; int oldIndentLevel = Logger.Instance.IndentLevel;
try { try {
deobfuscate(method, cflowDeobfuscator, methodPrinter, isVerbose, isVV); Deobfuscate(method, cflowDeobfuscator, methodPrinter, isVerbose, isVV);
} }
catch (ApplicationException) { catch (ApplicationException) {
throw; throw;
} }
catch (Exception ex) { catch (Exception ex) {
if (!canLoadMethodBody(method)) { if (!CanLoadMethodBody(method)) {
if (isVerbose) if (isVerbose)
Logger.v("Invalid method body. {0:X8}", method.MDToken.ToInt32()); Logger.v("Invalid method body. {0:X8}", method.MDToken.ToInt32());
method.Body = new CilBody(); method.Body = new CilBody();
@ -612,14 +612,14 @@ namespace de4dot.code {
finally { finally {
Logger.Instance.IndentLevel = oldIndentLevel; Logger.Instance.IndentLevel = oldIndentLevel;
} }
removeNoInliningAttribute(method); RemoveNoInliningAttribute(method);
if (isVerbose) if (isVerbose)
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
} }
} }
static bool canLoadMethodBody(MethodDef method) { static bool CanLoadMethodBody(MethodDef method) {
try { try {
var body = method.Body; var body = method.Body;
return true; return true;
@ -631,39 +631,39 @@ namespace de4dot.code {
bool CanOptimizeLocals() { bool CanOptimizeLocals() {
// Don't remove any locals if we must preserve StandAloneSig table // Don't remove any locals if we must preserve StandAloneSig table
return (getMetaDataFlags() & MetaDataFlags.PreserveStandAloneSigRids) == 0; return (GetMetaDataFlags() & MetaDataFlags.PreserveStandAloneSigRids) == 0;
} }
void deobfuscate(MethodDef method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter, bool isVerbose, bool isVV) { void Deobfuscate(MethodDef method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter, bool isVerbose, bool isVV) {
if (!hasNonEmptyBody(method)) if (!HasNonEmptyBody(method))
return; return;
var blocks = new Blocks(method); var blocks = new Blocks(method);
int numRemovedLocals = 0; int numRemovedLocals = 0;
int oldNumInstructions = method.Body.Instructions.Count; int oldNumInstructions = method.Body.Instructions.Count;
deob.deobfuscateMethodBegin(blocks); deob.DeobfuscateMethodBegin(blocks);
if (options.ControlFlowDeobfuscation) { if (options.ControlFlowDeobfuscation) {
cflowDeobfuscator.init(blocks); cflowDeobfuscator.Initialize(blocks);
cflowDeobfuscator.deobfuscate(); cflowDeobfuscator.Deobfuscate();
} }
if (deob.deobfuscateOther(blocks) && options.ControlFlowDeobfuscation) if (deob.DeobfuscateOther(blocks) && options.ControlFlowDeobfuscation)
cflowDeobfuscator.deobfuscate(); cflowDeobfuscator.Deobfuscate();
if (options.ControlFlowDeobfuscation) { if (options.ControlFlowDeobfuscation) {
if (CanOptimizeLocals()) if (CanOptimizeLocals())
numRemovedLocals = blocks.optimizeLocals(); numRemovedLocals = blocks.OptimizeLocals();
blocks.repartitionBlocks(); blocks.RepartitionBlocks();
} }
deobfuscateStrings(blocks); DeobfuscateStrings(blocks);
deob.deobfuscateMethodEnd(blocks); deob.DeobfuscateMethodEnd(blocks);
IList<Instruction> allInstructions; IList<Instruction> allInstructions;
IList<ExceptionHandler> allExceptionHandlers; IList<ExceptionHandler> allExceptionHandlers;
blocks.getCode(out allInstructions, out allExceptionHandlers); blocks.GetCode(out allInstructions, out allExceptionHandlers);
DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers); DotNetUtils.RestoreBody(method, allInstructions, allExceptionHandlers);
if (isVerbose && numRemovedLocals > 0) if (isVerbose && numRemovedLocals > 0)
Logger.v("Removed {0} unused local(s)", numRemovedLocals); Logger.v("Removed {0} unused local(s)", numRemovedLocals);
@ -672,29 +672,29 @@ namespace de4dot.code {
Logger.v("Removed {0} dead instruction(s)", numRemovedInstructions); Logger.v("Removed {0} dead instruction(s)", numRemovedInstructions);
if (isVV) { if (isVV) {
Logger.log(LoggerEvent.VeryVerbose, "Deobfuscated code:"); Logger.Log(LoggerEvent.VeryVerbose, "Deobfuscated code:");
Logger.Instance.indent(); Logger.Instance.Indent();
methodPrinter.print(LoggerEvent.VeryVerbose, allInstructions, allExceptionHandlers); methodPrinter.Print(LoggerEvent.VeryVerbose, allInstructions, allExceptionHandlers);
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
} }
} }
bool hasNonEmptyBody(MethodDef method) { bool HasNonEmptyBody(MethodDef method) {
return method.HasBody && method.Body.Instructions.Count > 0; return method.HasBody && method.Body.Instructions.Count > 0;
} }
void deobfuscateStrings(Blocks blocks) { void DeobfuscateStrings(Blocks blocks) {
switch (options.StringDecrypterType) { switch (options.StringDecrypterType) {
case DecrypterType.None: case DecrypterType.None:
break; break;
case DecrypterType.Static: case DecrypterType.Static:
deob.deobfuscateStrings(blocks); deob.DeobfuscateStrings(blocks);
break; break;
case DecrypterType.Delegate: case DecrypterType.Delegate:
case DecrypterType.Emulate: case DecrypterType.Emulate:
dynamicStringInliner.decrypt(blocks); dynamicStringInliner.Decrypt(blocks);
break; break;
default: default:
@ -702,14 +702,14 @@ namespace de4dot.code {
} }
} }
void removeNoInliningAttribute(MethodDef method) { void RemoveNoInliningAttribute(MethodDef method) {
method.IsNoInlining = false; 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.TypeFullName != "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))
continue; continue;
if (options != 0 && options != (int)MethodImplAttributes.NoInlining) if (options != 0 && options != (int)MethodImplAttributes.NoInlining)
continue; continue;
@ -718,7 +718,7 @@ namespace de4dot.code {
} }
} }
static bool getMethodImplOptions(CustomAttribute cattr, ref int value) { static bool GetMethodImplOptions(CustomAttribute cattr, ref int value) {
if (cattr.IsRawBlob) if (cattr.IsRawBlob)
return false; return false;
if (cattr.ConstructorArguments.Count != 1) if (cattr.ConstructorArguments.Count != 1)
@ -751,21 +751,21 @@ namespace de4dot.code {
HasDeobfuscated = 0x1, HasDeobfuscated = 0x1,
} }
Dictionary<MethodDef, SimpleDeobFlags> simpleDeobfuscatorFlags = new Dictionary<MethodDef, SimpleDeobFlags>(); Dictionary<MethodDef, SimpleDeobFlags> simpleDeobfuscatorFlags = new Dictionary<MethodDef, SimpleDeobFlags>();
bool check(MethodDef method, SimpleDeobFlags flag) { bool Check(MethodDef method, SimpleDeobFlags flag) {
SimpleDeobFlags oldFlags; SimpleDeobFlags oldFlags;
simpleDeobfuscatorFlags.TryGetValue(method, out oldFlags); simpleDeobfuscatorFlags.TryGetValue(method, out oldFlags);
simpleDeobfuscatorFlags[method] = oldFlags | flag; simpleDeobfuscatorFlags[method] = oldFlags | flag;
return (oldFlags & flag) == flag; return (oldFlags & flag) == flag;
} }
void deobfuscate(MethodDef method, string msg, Action<Blocks> handler) { void Deobfuscate(MethodDef method, string msg, Action<Blocks> handler) {
if (savedMethodBodies != null) if (savedMethodBodies != null)
savedMethodBodies.save(method); savedMethodBodies.Save(method);
Logger.v("{0}: {1} ({2:X8})", msg, Utils.removeNewlines(method), method.MDToken.ToUInt32()); Logger.v("{0}: {1} ({2:X8})", msg, Utils.RemoveNewlines(method), method.MDToken.ToUInt32());
Logger.Instance.indent(); Logger.Instance.Indent();
if (hasNonEmptyBody(method)) { if (HasNonEmptyBody(method)) {
try { try {
var blocks = new Blocks(method); var blocks = new Blocks(method);
@ -773,55 +773,55 @@ namespace de4dot.code {
IList<Instruction> allInstructions; IList<Instruction> allInstructions;
IList<ExceptionHandler> allExceptionHandlers; IList<ExceptionHandler> allExceptionHandlers;
blocks.getCode(out allInstructions, out allExceptionHandlers); blocks.GetCode(out allInstructions, out allExceptionHandlers);
DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers); DotNetUtils.RestoreBody(method, allInstructions, allExceptionHandlers);
} }
catch { catch {
Logger.v("Could not deobfuscate {0:X8}", method.MDToken.ToInt32()); Logger.v("Could not deobfuscate {0:X8}", method.MDToken.ToInt32());
} }
} }
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
} }
void ISimpleDeobfuscator.deobfuscate(MethodDef method) { void ISimpleDeobfuscator.Deobfuscate(MethodDef method) {
((ISimpleDeobfuscator)this).deobfuscate(method, false); ((ISimpleDeobfuscator)this).Deobfuscate(method, false);
} }
void ISimpleDeobfuscator.deobfuscate(MethodDef method, bool force) { void ISimpleDeobfuscator.Deobfuscate(MethodDef method, bool force) {
if (!force && check(method, SimpleDeobFlags.HasDeobfuscated)) if (!force && Check(method, SimpleDeobFlags.HasDeobfuscated))
return; return;
deobfuscate(method, "Deobfuscating control flow", (blocks) => { Deobfuscate(method, "Deobfuscating control flow", (blocks) => {
var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators); var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators);
cflowDeobfuscator.init(blocks); cflowDeobfuscator.Initialize(blocks);
cflowDeobfuscator.deobfuscate(); cflowDeobfuscator.Deobfuscate();
}); });
} }
void ISimpleDeobfuscator.decryptStrings(MethodDef method, IDeobfuscator theDeob) { void ISimpleDeobfuscator.DecryptStrings(MethodDef method, IDeobfuscator theDeob) {
deobfuscate(method, "Static string decryption", (blocks) => theDeob.deobfuscateStrings(blocks)); Deobfuscate(method, "Static string decryption", (blocks) => theDeob.DeobfuscateStrings(blocks));
} }
void IDeobfuscatedFile.createAssemblyFile(byte[] data, string assemblyName, string extension) { void IDeobfuscatedFile.CreateAssemblyFile(byte[] data, string assemblyName, string extension) {
if (extension == null) if (extension == null)
extension = ".dll"; extension = ".dll";
var baseDir = Utils.getDirName(options.NewFilename); var baseDir = Utils.GetDirName(options.NewFilename);
var newName = Path.Combine(baseDir, assemblyName + extension); var newName = Path.Combine(baseDir, assemblyName + extension);
Logger.n("Creating file {0}", newName); Logger.n("Creating file {0}", newName);
File.WriteAllBytes(newName, data); File.WriteAllBytes(newName, data);
} }
void IDeobfuscatedFile.stringDecryptersAdded() { void IDeobfuscatedFile.StringDecryptersAdded() {
updateDynamicStringInliner(); UpdateDynamicStringInliner();
} }
void IDeobfuscatedFile.setDeobfuscator(IDeobfuscator deob) { void IDeobfuscatedFile.SetDeobfuscator(IDeobfuscator deob) {
this.deob = deob; this.deob = deob;
} }
public void Dispose() { public void Dispose() {
deobfuscateCleanUp(); DeobfuscateCleanUp();
if (module != null) if (module != null)
module.Dispose(); module.Dispose();
if (deob != null) if (deob != null)

View File

@ -57,7 +57,7 @@ namespace de4dot.code {
} }
// Returns true if the new value is set, or false on error. error string is also updated. // Returns true if the new value is set, or false on error. error string is also updated.
public abstract bool set(string val, out string error); public abstract bool Set(string val, out string error);
public Option(string shortName, string longName, string description) { public Option(string shortName, string longName, string description) {
if (shortName != null) if (shortName != null)
@ -79,7 +79,7 @@ namespace de4dot.code {
get { return "bool"; } get { return "bool"; }
} }
public override bool set(string newVal, out string error) { public override bool Set(string newVal, out string error) {
if (string.Equals(newVal, "false", StringComparison.OrdinalIgnoreCase) || if (string.Equals(newVal, "false", StringComparison.OrdinalIgnoreCase) ||
string.Equals(newVal, "off", StringComparison.OrdinalIgnoreCase) || string.Equals(newVal, "off", StringComparison.OrdinalIgnoreCase) ||
string.Equals(newVal, "0", StringComparison.OrdinalIgnoreCase)) { string.Equals(newVal, "0", StringComparison.OrdinalIgnoreCase)) {
@ -107,7 +107,7 @@ namespace de4dot.code {
get { return "int"; } get { return "int"; }
} }
public override bool set(string newVal, out string error) { public override bool Set(string newVal, out string error) {
int newInt; int newInt;
if (!int.TryParse(newVal, out newInt)) { if (!int.TryParse(newVal, out newInt)) {
error = string.Format("Not an integer: '{0}'", newVal); error = string.Format("Not an integer: '{0}'", newVal);
@ -135,7 +135,7 @@ namespace de4dot.code {
Default = this.val = val; Default = this.val = val;
} }
public override bool set(string newVal, out string error) { public override bool Set(string newVal, out string error) {
val = newVal; val = newVal;
error = ""; error = "";
return true; return true;
@ -158,10 +158,10 @@ namespace de4dot.code {
Default = this.val = new NameRegexes(val); Default = this.val = new NameRegexes(val);
} }
public override bool set(string newVal, out string error) { public override bool Set(string newVal, out string error) {
try { try {
var regexes = new NameRegexes(); var regexes = new NameRegexes();
regexes.set(newVal); regexes.Set(newVal);
val = regexes; val = regexes;
} }
catch (ArgumentException) { catch (ArgumentException) {
@ -189,7 +189,7 @@ namespace de4dot.code {
Default = this.val = new Regex(val); Default = this.val = new Regex(val);
} }
public override bool set(string newVal, out string error) { public override bool Set(string newVal, out string error) {
try { try {
val = new Regex(newVal); val = new Regex(newVal);
} }
@ -223,7 +223,7 @@ namespace de4dot.code {
this.action = action; this.action = action;
} }
public override bool set(string val, out string error) { public override bool Set(string val, out string error) {
triggered = true; triggered = true;
if (action != null) if (action != null)
action(); action();
@ -251,7 +251,7 @@ namespace de4dot.code {
Default = null; Default = null;
} }
public override bool set(string val, out string error) { public override bool Set(string val, out string error) {
action(val); action(val);
error = ""; error = "";
return true; return true;

View File

@ -26,7 +26,7 @@ using de4dot.blocks;
namespace de4dot.code { namespace de4dot.code {
abstract class StringInlinerBase : MethodReturnValueInliner { abstract class StringInlinerBase : MethodReturnValueInliner {
protected override void inlineReturnValues(IList<CallResult> callResults) { protected override void InlineReturnValues(IList<CallResult> callResults) {
foreach (var callResult in callResults) { foreach (var callResult in callResults) {
var block = callResult.block; var block = callResult.block;
int num = callResult.callEndIndex - callResult.callStartIndex + 1; int num = callResult.callEndIndex - callResult.callStartIndex + 1;
@ -36,13 +36,13 @@ namespace de4dot.code {
continue; continue;
int ldstrIndex = callResult.callStartIndex; int ldstrIndex = callResult.callStartIndex;
block.replace(ldstrIndex, num, OpCodes.Ldstr.ToInstruction(decryptedString)); block.Replace(ldstrIndex, num, OpCodes.Ldstr.ToInstruction(decryptedString));
// If it's followed by castclass string, remove it // If it's followed by castclass string, remove it
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.Castclass && instr.Operand.ToString() == "System.String") if (instr.OpCode.Code == Code.Castclass && instr.Operand.ToString() == "System.String")
block.remove(ldstrIndex + 1, 1); block.Remove(ldstrIndex + 1, 1);
} }
// If it's followed by String.Intern(), then nop out that call // If it's followed by String.Intern(), then nop out that call
@ -52,12 +52,12 @@ namespace de4dot.code {
var calledMethod = instr.Operand as IMethod; 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);
} }
} }
} }
Logger.v("Decrypted string: {0}", Utils.toCsharpString(decryptedString)); Logger.v("Decrypted string: {0}", Utils.ToCsharpString(decryptedString));
} }
} }
} }
@ -84,23 +84,23 @@ namespace de4dot.code {
this.assemblyClient = assemblyClient; this.assemblyClient = assemblyClient;
} }
public void init(IEnumerable<int> methodTokens) { public void Initialize(IEnumerable<int> methodTokens) {
methodTokenToId.Clear(); methodTokenToId.Clear();
foreach (var methodToken in methodTokens) { foreach (var methodToken in methodTokens) {
if (methodTokenToId.ContainsKey(methodToken)) if (methodTokenToId.ContainsKey(methodToken))
continue; continue;
methodTokenToId[methodToken] = assemblyClient.Service.defineStringDecrypter(methodToken); methodTokenToId[methodToken] = assemblyClient.Service.DefineStringDecrypter(methodToken);
} }
} }
protected override CallResult createCallResult(IMethod method, MethodSpec 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.MDToken.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);
} }
protected override void inlineAllCalls() { protected override void InlineAllCalls() {
var sortedCalls = new Dictionary<int, List<MyCallResult>>(); var sortedCalls = new Dictionary<int, List<MyCallResult>>();
foreach (var tmp in callResults) { foreach (var tmp in callResults) {
var callResult = (MyCallResult)tmp; var callResult = (MyCallResult)tmp;
@ -114,13 +114,13 @@ namespace de4dot.code {
var list = sortedCalls[methodId]; var list = sortedCalls[methodId];
var args = new object[list.Count]; var args = new object[list.Count];
for (int i = 0; i < list.Count; i++) { for (int i = 0; i < list.Count; i++) {
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.MDToken.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);
for (int i = 0; i < list.Count; i++) for (int i = 0; i < list.Count; i++)
list[i].returnValue = (string)decryptedStrings[i]; list[i].returnValue = (string)decryptedStrings[i];
} }
@ -135,7 +135,7 @@ namespace de4dot.code {
} }
public IEnumerable<MethodDef> Methods { public IEnumerable<MethodDef> Methods {
get { return stringDecrypters.getKeys(); } get { return stringDecrypters.GetKeys(); }
} }
class MyCallResult : CallResult { class MyCallResult : CallResult {
@ -148,21 +148,21 @@ namespace de4dot.code {
} }
} }
public void add(MethodDef method, Func<MethodDef, MethodSpec, 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);
} }
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.IMethod); var handler = stringDecrypters.Find(callResult.IMethod);
callResult.returnValue = handler((MethodDef)callResult.IMethod, callResult.gim, callResult.args); callResult.returnValue = handler((MethodDef)callResult.IMethod, callResult.gim, callResult.args);
} }
} }
protected override CallResult createCallResult(IMethod method, MethodSpec 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);
} }

View File

@ -55,7 +55,7 @@ namespace de4dot.code {
public static class Utils { public static class Utils {
static Random random = new Random(); static Random random = new Random();
public static IEnumerable<T> unique<T>(IEnumerable<T> values) { public static IEnumerable<T> Unique<T>(IEnumerable<T> values) {
// HashSet is only available in .NET 3.5 and later. // HashSet is only available in .NET 3.5 and later.
var dict = new Dictionary<T, bool>(); var dict = new Dictionary<T, bool>();
foreach (var val in values) foreach (var val in values)
@ -63,30 +63,30 @@ namespace de4dot.code {
return dict.Keys; return dict.Keys;
} }
public static string toCsharpString(UTF8String s) { public static string ToCsharpString(UTF8String s) {
return toCsharpString(UTF8String.ToSystemStringOrEmpty(s)); return ToCsharpString(UTF8String.ToSystemStringOrEmpty(s));
} }
public static string toCsharpString(string s) { public static string ToCsharpString(string s) {
var sb = new StringBuilder(s.Length + 2); var sb = new StringBuilder(s.Length + 2);
sb.Append('"'); sb.Append('"');
foreach (var c in s) { foreach (var c in s) {
if ((int)c < 0x20) { if ((int)c < 0x20) {
switch (c) { switch (c) {
case '\a': appendEscape(sb, 'a'); break; case '\a': AppendEscape(sb, 'a'); break;
case '\b': appendEscape(sb, 'b'); break; case '\b': AppendEscape(sb, 'b'); break;
case '\f': appendEscape(sb, 'f'); break; case '\f': AppendEscape(sb, 'f'); break;
case '\n': appendEscape(sb, 'n'); break; case '\n': AppendEscape(sb, 'n'); break;
case '\r': appendEscape(sb, 'r'); break; case '\r': AppendEscape(sb, 'r'); break;
case '\t': appendEscape(sb, 't'); break; case '\t': AppendEscape(sb, 't'); break;
case '\v': appendEscape(sb, 'v'); break; case '\v': AppendEscape(sb, 'v'); break;
default: default:
sb.Append(string.Format(@"\u{0:X4}", (int)c)); sb.Append(string.Format(@"\u{0:X4}", (int)c));
break; break;
} }
} }
else if (c == '\\' || c == '"') { else if (c == '\\' || c == '"') {
appendEscape(sb, c); AppendEscape(sb, c);
} }
else else
sb.Append(c); sb.Append(c);
@ -95,12 +95,12 @@ namespace de4dot.code {
return sb.ToString(); return sb.ToString();
} }
public static string shellEscape(string s) { public static string ShellEscape(string s) {
var sb = new StringBuilder(s.Length + 2); var sb = new StringBuilder(s.Length + 2);
sb.Append('"'); sb.Append('"');
foreach (var c in s) { foreach (var c in s) {
if (c == '"') if (c == '"')
appendEscape(sb, c); AppendEscape(sb, c);
else else
sb.Append(c); sb.Append(c);
} }
@ -108,20 +108,20 @@ namespace de4dot.code {
return sb.ToString(); return sb.ToString();
} }
static void appendEscape(StringBuilder sb, char c) { static void AppendEscape(StringBuilder sb, char c) {
sb.Append('\\'); sb.Append('\\');
sb.Append(c); sb.Append(c);
} }
public static string removeNewlines(object o) { public static string RemoveNewlines(object o) {
return removeNewlines(o.ToString()); return RemoveNewlines(o.ToString());
} }
public static string removeNewlines(string s) { public static string RemoveNewlines(string s) {
return s.Replace('\n', ' ').Replace('\r', ' '); return s.Replace('\n', ' ').Replace('\r', ' ');
} }
public static string getFullPath(string path) { public static string GetFullPath(string path) {
try { try {
return Path.GetFullPath(path); return Path.GetFullPath(path);
} }
@ -130,7 +130,7 @@ namespace de4dot.code {
} }
} }
public static string randomName(int min, int max) { public static string RandomName(int min, int max) {
int numChars = random.Next(min, max + 1); int numChars = random.Next(min, max + 1);
var sb = new StringBuilder(numChars); var sb = new StringBuilder(numChars);
int numLower = 0; int numLower = 0;
@ -150,26 +150,26 @@ namespace de4dot.code {
return sb.ToString(); return sb.ToString();
} }
public static string getBaseName(string name) { public static string GetBaseName(string name) {
int index = name.LastIndexOf(Path.DirectorySeparatorChar); int index = name.LastIndexOf(Path.DirectorySeparatorChar);
if (index < 0) if (index < 0)
return name; return name;
return name.Substring(index + 1); return name.Substring(index + 1);
} }
public static string getDirName(string name) { public static string GetDirName(string name) {
return Path.GetDirectoryName(name); return Path.GetDirectoryName(name);
} }
static string ourBaseDir = null; static string ourBaseDir = null;
public static string getOurBaseDir() { public static string GetOurBaseDir() {
if (ourBaseDir != null) if (ourBaseDir != null)
return ourBaseDir; return ourBaseDir;
return ourBaseDir = getDirName(typeof(Utils).Assembly.Location); return ourBaseDir = GetDirName(typeof(Utils).Assembly.Location);
} }
public static string getPathOfOurFile(string filename) { public static string GetPathOfOurFile(string filename) {
return Path.Combine(getOurBaseDir(), filename); return Path.Combine(GetOurBaseDir(), filename);
} }
// This fixes a mono (tested 2.10.5) String.StartsWith() bug. NB: stringComparison must be // This fixes a mono (tested 2.10.5) String.StartsWith() bug. NB: stringComparison must be
@ -180,14 +180,14 @@ namespace de4dot.code {
return left.Substring(0, right.Length).Equals(right, stringComparison); return left.Substring(0, right.Length).Equals(right, stringComparison);
} }
public static string getAssemblySimpleName(string name) { public static string GetAssemblySimpleName(string name) {
int i = name.IndexOf(','); int i = name.IndexOf(',');
if (i < 0) if (i < 0)
return name; return name;
return name.Substring(0, i); return name.Substring(0, i);
} }
public static bool pathExists(string path) { public static bool PathExists(string path) {
try { try {
return new DirectoryInfo(path).Exists; return new DirectoryInfo(path).Exists;
} }
@ -196,7 +196,7 @@ namespace de4dot.code {
} }
} }
public static bool fileExists(string path) { public static bool FileExists(string path) {
try { try {
return new FileInfo(path).Exists; return new FileInfo(path).Exists;
} }
@ -205,7 +205,7 @@ namespace de4dot.code {
} }
} }
public static bool compare(byte[] a, byte[] b) { public static bool Compare(byte[] a, byte[] b) {
if (a.Length != b.Length) if (a.Length != b.Length)
return false; return false;
for (int i = 0; i < a.Length; i++) { for (int i = 0; i < a.Length; i++) {
@ -215,7 +215,7 @@ namespace de4dot.code {
return true; return true;
} }
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.
const int MAX_BYTES_READ = 0x200000; const int MAX_BYTES_READ = 0x200000;

View File

@ -63,26 +63,26 @@ namespace de4dot.code.deobfuscators.Agile_NET {
public CliSecureRtType(ModuleDefMD module, CliSecureRtType oldOne) { public CliSecureRtType(ModuleDefMD module, CliSecureRtType oldOne) {
this.module = module; this.module = module;
cliSecureRtType = lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type"); cliSecureRtType = Lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type");
postInitializeMethod = lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method"); postInitializeMethod = Lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method");
initializeMethod = lookup(oldOne.initializeMethod, "Could not find initializeMethod method"); initializeMethod = Lookup(oldOne.initializeMethod, "Could not find initializeMethod method");
stringDecrypterMethod = lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod method"); stringDecrypterMethod = Lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod method");
loadMethod = lookup(oldOne.loadMethod, "Could not find loadMethod method"); loadMethod = Lookup(oldOne.loadMethod, "Could not find loadMethod method");
foundSig = oldOne.foundSig; foundSig = oldOne.foundSig;
} }
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken { T Lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
return DeobUtils.lookup(module, def, errorMessage); return DeobUtils.Lookup(module, def, errorMessage);
} }
public void find(byte[] moduleBytes) { public void Find(byte[] moduleBytes) {
if (cliSecureRtType != null) if (cliSecureRtType != null)
return; return;
if (find2()) if (Find2())
return; return;
if (find3()) if (Find3())
return; return;
findNativeCode(moduleBytes); FindNativeCode(moduleBytes);
} }
static readonly string[] requiredFields1 = new string[] { static readonly string[] requiredFields1 = new string[] {
@ -101,23 +101,23 @@ namespace de4dot.code.deobfuscators.Agile_NET {
"System.Reflection.Assembly", "System.Reflection.Assembly",
"System.Byte[]", "System.Byte[]",
}; };
bool find2() { bool Find2() {
foreach (var cctor in DeobUtils.getInitCctors(module, 3)) { foreach (var cctor in DeobUtils.GetInitCctors(module, 3)) {
foreach (var calledMethod in DotNetUtils.getCalledMethods(module, cctor)) { foreach (var calledMethod in DotNetUtils.GetCalledMethods(module, cctor)) {
var type = calledMethod.DeclaringType; var type = calledMethod.DeclaringType;
if (type.IsPublic) if (type.IsPublic)
continue; continue;
var fieldTypes = new FieldTypes(type); var fieldTypes = new FieldTypes(type);
if (!fieldTypes.exactly(requiredFields1) && !fieldTypes.exactly(requiredFields2) && if (!fieldTypes.Exactly(requiredFields1) && !fieldTypes.Exactly(requiredFields2) &&
!fieldTypes.exactly(requiredFields3) && !fieldTypes.exactly(requiredFields4)) !fieldTypes.Exactly(requiredFields3) && !fieldTypes.Exactly(requiredFields4))
continue; continue;
if (!hasInitializeMethod(type, "_Initialize") && !hasInitializeMethod(type, "_Initialize64")) if (!HasInitializeMethod(type, "_Initialize") && !HasInitializeMethod(type, "_Initialize64"))
continue; continue;
stringDecrypterMethod = findStringDecrypterMethod(type); stringDecrypterMethod = FindStringDecrypterMethod(type);
initializeMethod = calledMethod; initializeMethod = calledMethod;
postInitializeMethod = findMethod(type, "System.Void", "PostInitialize", "()"); postInitializeMethod = FindMethod(type, "System.Void", "PostInitialize", "()");
loadMethod = findMethod(type, "System.IntPtr", "Load", "()"); loadMethod = FindMethod(type, "System.IntPtr", "Load", "()");
cliSecureRtType = type; cliSecureRtType = type;
return true; return true;
} }
@ -126,7 +126,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return false; return false;
} }
bool find3() { bool Find3() {
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (type.Fields.Count != 1) if (type.Fields.Count != 1)
continue; continue;
@ -148,11 +148,11 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return false; return false;
} }
static MethodDef findStringDecrypterMethod(TypeDef type) { static MethodDef FindStringDecrypterMethod(TypeDef type) {
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (method.Body == null || !method.IsStatic) if (method.Body == null || !method.IsStatic)
continue; continue;
if (!DotNetUtils.isMethod(method, "System.String", "(System.String)")) if (!DotNetUtils.IsMethod(method, "System.String", "(System.String)"))
continue; continue;
return method; return method;
@ -161,7 +161,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return null; return null;
} }
static MethodDef findMethod(TypeDef type, string returnType, string name, string parameters) { static MethodDef FindMethod(TypeDef type, string returnType, string name, string parameters) {
var methodName = returnType + " " + type.FullName + "::" + name + parameters; var methodName = returnType + " " + type.FullName + "::" + name + parameters;
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (method.Body == null || !method.IsStatic) if (method.Body == null || !method.IsStatic)
@ -175,8 +175,8 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return null; return null;
} }
static bool hasInitializeMethod(TypeDef type, string name) { static bool HasInitializeMethod(TypeDef type, string name) {
var method = DotNetUtils.getPInvokeMethod(type, name); var method = DotNetUtils.GetPInvokeMethod(type, name);
if (method == null) if (method == null)
return false; return false;
var sig = method.MethodSig; var sig = method.MethodSig;
@ -190,17 +190,17 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return true; return true;
} }
bool findNativeCode(byte[] moduleBytes) { bool FindNativeCode(byte[] moduleBytes) {
var bytes = moduleBytes != null ? moduleBytes : DeobUtils.readModule(module); var bytes = moduleBytes != null ? moduleBytes : DeobUtils.ReadModule(module);
using (var peImage = new MyPEImage(bytes)) using (var peImage = new MyPEImage(bytes))
return foundSig = MethodsDecrypter.detect(peImage); return foundSig = MethodsDecrypter.Detect(peImage);
} }
public bool isAtLeastVersion50() { public bool IsAtLeastVersion50() {
return DotNetUtils.hasPinvokeMethod(cliSecureRtType, "LoadLibraryA"); return DotNetUtils.HasPinvokeMethod(cliSecureRtType, "LoadLibraryA");
} }
public void findStringDecrypterMethod() { public void FindStringDecrypterMethod() {
if (cliSecureRtType != null) if (cliSecureRtType != null)
return; return;
@ -210,7 +210,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
if (type.Methods.Count != 1) if (type.Methods.Count != 1)
continue; continue;
var cs = type.Methods[0]; var cs = type.Methods[0];
if (!isOldStringDecrypterMethod(cs)) if (!IsOldStringDecrypterMethod(cs))
continue; continue;
cliSecureRtType = type; cliSecureRtType = type;
@ -219,12 +219,12 @@ namespace de4dot.code.deobfuscators.Agile_NET {
} }
} }
static bool isOldStringDecrypterMethod(MethodDef method) { static bool IsOldStringDecrypterMethod(MethodDef method) {
if (method == null || method.Body == null || !method.IsStatic) if (method == null || method.Body == null || !method.IsStatic)
return false; return false;
if (!DotNetUtils.isMethod(method, "System.String", "(System.String)")) if (!DotNetUtils.IsMethod(method, "System.String", "(System.String)"))
return false; return false;
if (!DeobUtils.hasInteger(method, 0xFF)) if (!DeobUtils.HasInteger(method, 0xFF))
return false; return false;
return true; return true;

View File

@ -26,7 +26,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
: base(key) { : base(key) {
} }
protected override void encrypt(ref uint rxl, ref uint rxr) { protected override void Encrypt(ref uint rxl, ref uint rxr) {
uint xl = rxl, xr = rxr; uint xl = rxl, xr = rxr;
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
xl ^= P[i]; xl ^= P[i];
@ -38,7 +38,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
rxl = xr ^ P[17]; rxl = xr ^ P[17];
} }
protected override void decrypt(ref uint rxl, ref uint rxr) { protected override void Decrypt(ref uint rxl, ref uint rxr) {
uint xl = rxl, xr = rxr; uint xl = rxl, xr = rxr;
for (int i = 17; i >= 2; i--) { for (int i = 17; i >= 2; i--) {
xl ^= P[i]; xl ^= P[i];

View File

@ -37,11 +37,11 @@ namespace de4dot.code.deobfuscators.Agile_NET {
public DeobfuscatorInfo() public DeobfuscatorInfo()
: base(DEFAULT_REGEX) { : base(DEFAULT_REGEX) {
decryptMethods = new BoolOption(null, makeArgName("methods"), "Decrypt methods", true); decryptMethods = new BoolOption(null, MakeArgName("methods"), "Decrypt methods", true);
decryptResources = new BoolOption(null, makeArgName("rsrc"), "Decrypt resources", true); decryptResources = new BoolOption(null, MakeArgName("rsrc"), "Decrypt resources", true);
removeStackFrameHelper = new BoolOption(null, makeArgName("stack"), "Remove all StackFrameHelper code", true); removeStackFrameHelper = new BoolOption(null, MakeArgName("stack"), "Remove all StackFrameHelper code", true);
restoreVmCode = new BoolOption(null, makeArgName("vm"), "Restore VM code", true); restoreVmCode = new BoolOption(null, MakeArgName("vm"), "Restore VM code", true);
setInitLocals = new BoolOption(null, makeArgName("initlocals"), "Set initlocals in method header", true); setInitLocals = new BoolOption(null, MakeArgName("initlocals"), "Set initlocals in method header", true);
} }
public override string Name { public override string Name {
@ -52,7 +52,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
get { return THE_TYPE; } get { return THE_TYPE; }
} }
public override IDeobfuscator createDeobfuscator() { public override IDeobfuscator CreateDeobfuscator() {
return new Deobfuscator(new Deobfuscator.Options { return new Deobfuscator(new Deobfuscator.Options {
ValidNameRegex = validNameRegex.get(), ValidNameRegex = validNameRegex.get(),
DecryptMethods = decryptMethods.get(), DecryptMethods = decryptMethods.get(),
@ -63,7 +63,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
}); });
} }
protected override IEnumerable<Option> getOptionsInternal() { protected override IEnumerable<Option> GetOptionsInternal() {
return new List<Option>() { return new List<Option>() {
decryptMethods, decryptMethods,
decryptResources, decryptResources,
@ -112,16 +112,16 @@ namespace de4dot.code.deobfuscators.Agile_NET {
this.options = options; this.options = options;
} }
public override void init(ModuleDefMD module) { public override void Initialize(ModuleDefMD module) {
base.init(module); base.Initialize(module);
} }
public override byte[] unpackNativeFile(IPEImage peImage) { public override byte[] UnpackNativeFile(IPEImage peImage) {
return unpackNativeFile1(peImage) ?? unpackNativeFile2(peImage); return UnpackNativeFile1(peImage) ?? UnpackNativeFile2(peImage);
} }
// Old CS versions // Old CS versions
byte[] unpackNativeFile1(IPEImage peImage) { byte[] UnpackNativeFile1(IPEImage peImage) {
const int dataDirNum = 6; // debug dir const int dataDirNum = 6; // debug dir
const int dotNetDirNum = 14; const int dotNetDirNum = 14;
@ -135,16 +135,16 @@ namespace de4dot.code.deobfuscators.Agile_NET {
long dataDirBaseOffset = (long)optHeader.DataDirectories[0].StartOffset; long dataDirBaseOffset = (long)optHeader.DataDirectories[0].StartOffset;
int dataDir = (int)dataDirBaseOffset + dataDirNum * 8; int dataDir = (int)dataDirBaseOffset + dataDirNum * 8;
int dotNetDir = (int)dataDirBaseOffset + dotNetDirNum * 8; int dotNetDir = (int)dataDirBaseOffset + dotNetDirNum * 8;
writeUInt32(fileData, dotNetDir, BitConverter.ToUInt32(fileData, dataDir)); WriteUInt32(fileData, dotNetDir, BitConverter.ToUInt32(fileData, dataDir));
writeUInt32(fileData, dotNetDir + 4, BitConverter.ToUInt32(fileData, dataDir + 4)); WriteUInt32(fileData, dotNetDir + 4, BitConverter.ToUInt32(fileData, dataDir + 4));
writeUInt32(fileData, dataDir, 0); WriteUInt32(fileData, dataDir, 0);
writeUInt32(fileData, dataDir + 4, 0); WriteUInt32(fileData, dataDir + 4, 0);
ModuleBytes = fileData; ModuleBytes = fileData;
return fileData; return fileData;
} }
// CS 1.x // CS 1.x
byte[] unpackNativeFile2(IPEImage peImage) { byte[] UnpackNativeFile2(IPEImage peImage) {
var data = peImage.FindWin32ResourceData("ASSEMBLY", 101, 0); var data = peImage.FindWin32ResourceData("ASSEMBLY", 101, 0);
if (data == null) if (data == null)
return null; return null;
@ -152,21 +152,21 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return ModuleBytes = data.Data.ReadAllBytes(); return ModuleBytes = data.Data.ReadAllBytes();
} }
static void writeUInt32(byte[] data, int offset, uint value) { static void WriteUInt32(byte[] data, int offset, uint value) {
data[offset] = (byte)value; data[offset] = (byte)value;
data[offset + 1] = (byte)(value >> 8); data[offset + 1] = (byte)(value >> 8);
data[offset + 2] = (byte)(value >> 16); data[offset + 2] = (byte)(value >> 16);
data[offset + 3] = (byte)(value >> 24); data[offset + 3] = (byte)(value >> 24);
} }
protected override int detectInternal() { protected override int DetectInternal() {
int val = 0; int val = 0;
int sum = toInt32(cliSecureRtType.Detected) + int sum = ToInt32(cliSecureRtType.Detected) +
toInt32(stringDecrypter.Detected) + ToInt32(stringDecrypter.Detected) +
toInt32(proxyCallFixer.Detected) + ToInt32(proxyCallFixer.Detected) +
toInt32(resourceDecrypter.Detected) + ToInt32(resourceDecrypter.Detected) +
toInt32(csvm.Detected); ToInt32(csvm.Detected);
if (sum > 0) if (sum > 0)
val += 100 + 10 * (sum - 1); val += 100 + 10 * (sum - 1);
if (cliSecureAttributes.Count != 0) if (cliSecureAttributes.Count != 0)
@ -175,21 +175,21 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return val; return val;
} }
protected override void scanForObfuscator() { protected override void ScanForObfuscator() {
findCliSecureAttribute(); FindCliSecureAttribute();
cliSecureRtType = new CliSecureRtType(module); cliSecureRtType = new CliSecureRtType(module);
cliSecureRtType.find(ModuleBytes); cliSecureRtType.Find(ModuleBytes);
stringDecrypter = new StringDecrypter(module, cliSecureRtType.StringDecrypterMethod); stringDecrypter = new StringDecrypter(module, cliSecureRtType.StringDecrypterMethod);
stringDecrypter.find(); stringDecrypter.Find();
resourceDecrypter = new ResourceDecrypter(module); resourceDecrypter = new ResourceDecrypter(module);
resourceDecrypter.find(); resourceDecrypter.Find();
proxyCallFixer = new ProxyCallFixer(module); proxyCallFixer = new ProxyCallFixer(module);
proxyCallFixer.findDelegateCreator(); proxyCallFixer.FindDelegateCreator();
csvm = new vm.Csvm(DeobfuscatedFile.DeobfuscatorContext, module); csvm = new vm.Csvm(DeobfuscatedFile.DeobfuscatorContext, module);
csvm.find(); csvm.Find();
} }
void findCliSecureAttribute() { void FindCliSecureAttribute() {
obfuscatorName = "CliSecure"; obfuscatorName = "CliSecure";
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (Utils.StartsWith(type.FullName, "SecureTeam.Attributes.ObfuscatedByCliSecureAttribute", StringComparison.Ordinal)) { if (Utils.StartsWith(type.FullName, "SecureTeam.Attributes.ObfuscatedByCliSecureAttribute", StringComparison.Ordinal)) {
@ -203,13 +203,13 @@ namespace de4dot.code.deobfuscators.Agile_NET {
} }
} }
public override bool getDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) { public override bool GetDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) {
if (count != 0 || !options.DecryptMethods) if (count != 0 || !options.DecryptMethods)
return false; return false;
byte[] fileData = ModuleBytes ?? DeobUtils.readModule(module); byte[] fileData = ModuleBytes ?? DeobUtils.ReadModule(module);
using (var peImage = new MyPEImage(fileData)) { using (var peImage = new MyPEImage(fileData)) {
if (!new MethodsDecrypter().decrypt(peImage, module, cliSecureRtType, ref dumpedMethods)) { if (!new MethodsDecrypter().Decrypt(peImage, module, cliSecureRtType, ref dumpedMethods)) {
Logger.v("Methods aren't encrypted or invalid signature"); Logger.v("Methods aren't encrypted or invalid signature");
return false; return false;
} }
@ -219,10 +219,10 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return true; return true;
} }
public override IDeobfuscator moduleReloaded(ModuleDefMD module) { public override IDeobfuscator ModuleReloaded(ModuleDefMD module) {
var newOne = new Deobfuscator(options); var newOne = new Deobfuscator(options);
newOne.setModule(module); newOne.SetModule(module);
newOne.cliSecureAttributes = lookup(module, cliSecureAttributes, "Could not find CliSecure attribute"); newOne.cliSecureAttributes = Lookup(module, cliSecureAttributes, "Could not find CliSecure attribute");
newOne.cliSecureRtType = new CliSecureRtType(module, cliSecureRtType); newOne.cliSecureRtType = new CliSecureRtType(module, cliSecureRtType);
newOne.stringDecrypter = new StringDecrypter(module, stringDecrypter); newOne.stringDecrypter = new StringDecrypter(module, stringDecrypter);
newOne.resourceDecrypter = new ResourceDecrypter(module, resourceDecrypter); newOne.resourceDecrypter = new ResourceDecrypter(module, resourceDecrypter);
@ -231,105 +231,105 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return newOne; return newOne;
} }
static List<TypeDef> lookup(ModuleDefMD module, List<TypeDef> types, string errorMsg) { static List<TypeDef> Lookup(ModuleDefMD module, List<TypeDef> types, string errorMsg) {
var list = new List<TypeDef>(types.Count); var list = new List<TypeDef>(types.Count);
foreach (var type in types) foreach (var type in types)
list.Add(DeobUtils.lookup(module, type, errorMsg)); list.Add(DeobUtils.Lookup(module, type, errorMsg));
return list; return list;
} }
public override void deobfuscateBegin() { public override void DeobfuscateBegin() {
base.deobfuscateBegin(); base.DeobfuscateBegin();
cliSecureRtType.findStringDecrypterMethod(); cliSecureRtType.FindStringDecrypterMethod();
stringDecrypter.Method = cliSecureRtType.StringDecrypterMethod; stringDecrypter.Method = cliSecureRtType.StringDecrypterMethod;
addAttributesToBeRemoved(cliSecureAttributes, "Obfuscator attribute"); AddAttributesToBeRemoved(cliSecureAttributes, "Obfuscator attribute");
if (options.DecryptResources) { if (options.DecryptResources) {
decryptResources(resourceDecrypter); DecryptResources(resourceDecrypter);
addCctorInitCallToBeRemoved(resourceDecrypter.RsrcRrrMethod); AddCctorInitCallToBeRemoved(resourceDecrypter.RsrcRrrMethod);
} }
stackFrameHelper = new StackFrameHelper(module); stackFrameHelper = new StackFrameHelper(module);
stackFrameHelper.find(); stackFrameHelper.Find();
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (type.FullName == "InitializeDelegate" && DotNetUtils.derivesFromDelegate(type)) if (type.FullName == "InitializeDelegate" && DotNetUtils.DerivesFromDelegate(type))
this.addTypeToBeRemoved(type, "Obfuscator type"); this.AddTypeToBeRemoved(type, "Obfuscator type");
} }
proxyCallFixer.find(); proxyCallFixer.Find();
staticStringInliner.add(stringDecrypter.Method, (method, gim, args) => stringDecrypter.decrypt((string)args[0])); staticStringInliner.Add(stringDecrypter.Method, (method, gim, args) => stringDecrypter.Decrypt((string)args[0]));
DeobfuscatedFile.stringDecryptersAdded(); DeobfuscatedFile.StringDecryptersAdded();
if (options.DecryptMethods) { if (options.DecryptMethods) {
addCctorInitCallToBeRemoved(cliSecureRtType.InitializeMethod); AddCctorInitCallToBeRemoved(cliSecureRtType.InitializeMethod);
addCctorInitCallToBeRemoved(cliSecureRtType.PostInitializeMethod); AddCctorInitCallToBeRemoved(cliSecureRtType.PostInitializeMethod);
findPossibleNamesToRemove(cliSecureRtType.LoadMethod); FindPossibleNamesToRemove(cliSecureRtType.LoadMethod);
} }
if (options.RestoreVmCode) { if (options.RestoreVmCode) {
if (csvm.restore()) if (csvm.Restore())
addResourceToBeRemoved(csvm.Resource, "CSVM data resource"); AddResourceToBeRemoved(csvm.Resource, "CSVM data resource");
else { else {
Logger.e("Couldn't restore VM methods. Use --dont-rename or it will not run"); Logger.e("Couldn't restore VM methods. Use --dont-rename or it will not run");
preserveTokensAndTypes(); PreserveTokensAndTypes();
} }
} }
} }
void decryptResources(ResourceDecrypter resourceDecrypter) { void DecryptResources(ResourceDecrypter resourceDecrypter) {
var rsrc = resourceDecrypter.mergeResources(); var rsrc = resourceDecrypter.MergeResources();
if (rsrc == null) if (rsrc == null)
return; return;
addResourceToBeRemoved(rsrc, "Encrypted resources"); AddResourceToBeRemoved(rsrc, "Encrypted resources");
addTypeToBeRemoved(resourceDecrypter.Type, "Resource decrypter type"); AddTypeToBeRemoved(resourceDecrypter.Type, "Resource decrypter type");
} }
public override void deobfuscateMethodEnd(Blocks blocks) { public override void DeobfuscateMethodEnd(Blocks blocks) {
proxyCallFixer.deobfuscate(blocks); proxyCallFixer.Deobfuscate(blocks);
removeStackFrameHelperCode(blocks); RemoveStackFrameHelperCode(blocks);
base.deobfuscateMethodEnd(blocks); base.DeobfuscateMethodEnd(blocks);
} }
public override void deobfuscateEnd() { public override void DeobfuscateEnd() {
if (options.SetInitLocals) if (options.SetInitLocals)
setInitLocals(); SetInitLocals();
removeProxyDelegates(proxyCallFixer); RemoveProxyDelegates(proxyCallFixer);
if (options.RemoveStackFrameHelper) { if (options.RemoveStackFrameHelper) {
if (stackFrameHelper.ExceptionLoggerRemover.NumRemovedExceptionLoggers > 0) if (stackFrameHelper.ExceptionLoggerRemover.NumRemovedExceptionLoggers > 0)
addTypeToBeRemoved(stackFrameHelper.Type, "StackFrameHelper type"); AddTypeToBeRemoved(stackFrameHelper.Type, "StackFrameHelper type");
} }
if (CanRemoveStringDecrypterType) { if (CanRemoveStringDecrypterType) {
addTypeToBeRemoved(stringDecrypter.Type, "String decrypter type"); AddTypeToBeRemoved(stringDecrypter.Type, "String decrypter type");
if (options.DecryptMethods) if (options.DecryptMethods)
addTypeToBeRemoved(cliSecureRtType.Type, "Obfuscator type"); AddTypeToBeRemoved(cliSecureRtType.Type, "Obfuscator type");
} }
if (options.DecryptMethods) { if (options.DecryptMethods) {
addResources("Obfuscator protection files"); AddResources("Obfuscator protection files");
} }
base.deobfuscateEnd(); base.DeobfuscateEnd();
// Call hasNativeMethods() after all types/methods/etc have been removed since // Call hasNativeMethods() after all types/methods/etc have been removed since
// some of the removed methods could be native methods // some of the removed methods could be native methods
if (!module.IsILOnly && !hasNativeMethods()) if (!module.IsILOnly && !HasNativeMethods())
module.IsILOnly = true; module.IsILOnly = true;
} }
public override IEnumerable<int> getStringDecrypterMethods() { public override IEnumerable<int> GetStringDecrypterMethods() {
var list = new List<int>(); var list = new List<int>();
if (stringDecrypter.Method != null) if (stringDecrypter.Method != null)
list.Add(stringDecrypter.Method.MDToken.ToInt32()); list.Add(stringDecrypter.Method.MDToken.ToInt32());
return list; return list;
} }
void removeStackFrameHelperCode(Blocks blocks) { void RemoveStackFrameHelperCode(Blocks blocks) {
if (!options.RemoveStackFrameHelper) if (!options.RemoveStackFrameHelper)
return; return;
if (stackFrameHelper.ExceptionLoggerRemover.remove(blocks)) if (stackFrameHelper.ExceptionLoggerRemover.Remove(blocks))
Logger.v("Removed StackFrameHelper code"); Logger.v("Removed StackFrameHelper code");
} }
} }

View File

@ -72,7 +72,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
SigType sigType; SigType sigType;
interface IDecrypter { interface IDecrypter {
MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections); MethodBodyHeader Decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections);
} }
abstract class DecrypterBase : IDecrypter { abstract class DecrypterBase : IDecrypter {
@ -84,13 +84,13 @@ namespace de4dot.code.deobfuscators.Agile_NET {
this.peImage = peImage; this.peImage = peImage;
this.codeHeader = codeHeader; this.codeHeader = codeHeader;
var mdDir = peImage.Cor20Header.MetaData; var mdDir = peImage.Cor20Header.MetaData;
endOfMetadata = peImage.rvaToOffset((uint)mdDir.VirtualAddress + mdDir.Size); endOfMetadata = peImage.RvaToOffset((uint)mdDir.VirtualAddress + mdDir.Size);
} }
public abstract MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections); public abstract MethodBodyHeader Decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections);
protected MethodBodyHeader getCodeBytes(byte[] methodBody, out byte[] code, out byte[] extraSections) { protected MethodBodyHeader GetCodeBytes(byte[] methodBody, out byte[] code, out byte[] extraSections) {
return MethodBodyParser.parseMethodBody(MemoryImageStream.Create(methodBody), out code, out extraSections); return MethodBodyParser.ParseMethodBody(MemoryImageStream.Create(methodBody), out code, out extraSections);
} }
} }
@ -104,10 +104,10 @@ namespace de4dot.code.deobfuscators.Agile_NET {
this.blowfish = new CsBlowfish(key); this.blowfish = new CsBlowfish(key);
} }
public MethodBodyHeader decrypt(uint bodyOffset, out byte[] code, out byte[] extraSections) { public MethodBodyHeader Decrypt(uint bodyOffset, out byte[] code, out byte[] extraSections) {
peImage.Reader.Position = bodyOffset; peImage.Reader.Position = bodyOffset;
var mbHeader = MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections); var mbHeader = MethodBodyParser.ParseMethodBody(peImage.Reader, out code, out extraSections);
blowfish.decrypt(code); blowfish.Decrypt(code);
return mbHeader; return mbHeader;
} }
} }
@ -118,9 +118,9 @@ namespace de4dot.code.deobfuscators.Agile_NET {
: base(peImage, codeHeader) { : base(peImage, codeHeader) {
} }
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) { public override MethodBodyHeader Decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
peImage.Reader.Position = peImage.rvaToOffset(methodInfo.codeOffs); peImage.Reader.Position = peImage.RvaToOffset(methodInfo.codeOffs);
return MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections); return MethodBodyParser.ParseMethodBody(peImage.Reader, out code, out extraSections);
} }
} }
@ -130,9 +130,9 @@ namespace de4dot.code.deobfuscators.Agile_NET {
: base(peImage, codeHeader) { : base(peImage, codeHeader) {
} }
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) { public override MethodBodyHeader Decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
peImage.Reader.Position = endOfMetadata + methodInfo.codeOffs; peImage.Reader.Position = endOfMetadata + methodInfo.codeOffs;
return MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections); return MethodBodyParser.ParseMethodBody(peImage.Reader, out code, out extraSections);
} }
} }
@ -142,14 +142,14 @@ namespace de4dot.code.deobfuscators.Agile_NET {
: base(peImage, codeHeader) { : base(peImage, codeHeader) {
} }
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) { public override MethodBodyHeader Decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
var data = peImage.offsetReadBytes(endOfMetadata + methodInfo.codeOffs, (int)methodInfo.codeSize); var data = peImage.OffsetReadBytes(endOfMetadata + methodInfo.codeOffs, (int)methodInfo.codeSize);
for (int i = 0; i < data.Length; i++) { for (int i = 0; i < data.Length; i++) {
byte b = data[i]; byte b = data[i];
b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - 0x28 + i) % 16]; b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - 0x28 + i) % 16];
data[i] = b; data[i] = b;
} }
return getCodeBytes(data, out code, out extraSections); return GetCodeBytes(data, out code, out extraSections);
} }
} }
@ -162,15 +162,15 @@ namespace de4dot.code.deobfuscators.Agile_NET {
this.codeHeaderSize = codeHeaderSize; this.codeHeaderSize = codeHeaderSize;
} }
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) { public override MethodBodyHeader Decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
byte[] data = peImage.offsetReadBytes(endOfMetadata + methodInfo.codeOffs, (int)methodInfo.codeSize); byte[] data = peImage.OffsetReadBytes(endOfMetadata + methodInfo.codeOffs, (int)methodInfo.codeSize);
for (int i = 0; i < data.Length; i++) { for (int i = 0; i < data.Length; i++) {
byte b = data[i]; byte b = data[i];
b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - codeHeaderSize + i) % 16]; b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - codeHeaderSize + i) % 16];
b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - codeHeaderSize + i + 7) % 16]; b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - codeHeaderSize + i + 7) % 16];
data[i] = b; data[i] = b;
} }
return getCodeBytes(data, out code, out extraSections); return GetCodeBytes(data, out code, out extraSections);
} }
} }
@ -181,17 +181,17 @@ namespace de4dot.code.deobfuscators.Agile_NET {
public ProDecrypter(MyPEImage peImage, CodeHeader codeHeader) public ProDecrypter(MyPEImage peImage, CodeHeader codeHeader)
: base(peImage, codeHeader) { : base(peImage, codeHeader) {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
key[i] = be_readUInt32(codeHeader.decryptionKey, i * 4); key[i] = ReadUInt32_be(codeHeader.decryptionKey, i * 4);
} }
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) { public override MethodBodyHeader Decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
byte[] data = peImage.offsetReadBytes(endOfMetadata + methodInfo.codeOffs, (int)methodInfo.codeSize); byte[] data = peImage.OffsetReadBytes(endOfMetadata + methodInfo.codeOffs, (int)methodInfo.codeSize);
int numQwords = (int)(methodInfo.codeSize / 8); int numQwords = (int)(methodInfo.codeSize / 8);
for (int i = 0; i < numQwords; i++) { for (int i = 0; i < numQwords; i++) {
int offset = i * 8; int offset = i * 8;
uint q0 = be_readUInt32(data, offset); uint q0 = ReadUInt32_be(data, offset);
uint q1 = be_readUInt32(data, offset + 4); uint q1 = ReadUInt32_be(data, offset + 4);
const uint magic = 0x9E3779B8; const uint magic = 0x9E3779B8;
uint val = 0xC6EF3700; // magic * 0x20 uint val = 0xC6EF3700; // magic * 0x20
@ -201,21 +201,21 @@ namespace de4dot.code.deobfuscators.Agile_NET {
val -= magic; val -= magic;
} }
be_writeUInt32(data, offset, q0); WriteUInt32_be(data, offset, q0);
be_writeUInt32(data, offset + 4, q1); WriteUInt32_be(data, offset + 4, q1);
} }
return getCodeBytes(data, out code, out extraSections); return GetCodeBytes(data, out code, out extraSections);
} }
static uint be_readUInt32(byte[] data, int offset) { static uint ReadUInt32_be(byte[] data, int offset) {
return (uint)((data[offset] << 24) + return (uint)((data[offset] << 24) +
(data[offset + 1] << 16) + (data[offset + 1] << 16) +
(data[offset + 2] << 8) + (data[offset + 2] << 8) +
data[offset + 3]); data[offset + 3]);
} }
static void be_writeUInt32(byte[] data, int offset, uint value) { static void WriteUInt32_be(byte[] data, int offset, uint value) {
data[offset] = (byte)(value >> 24); data[offset] = (byte)(value >> 24);
data[offset + 1] = (byte)(value >> 16); data[offset + 1] = (byte)(value >> 16);
data[offset + 2] = (byte)(value >> 8); data[offset + 2] = (byte)(value >> 8);
@ -224,9 +224,9 @@ namespace de4dot.code.deobfuscators.Agile_NET {
} }
interface ICsHeader { interface ICsHeader {
IDecrypter createDecrypter(); IDecrypter CreateDecrypter();
List<MethodInfo> getMethodInfos(uint codeHeaderOffset); List<MethodInfo> GetMethodInfos(uint codeHeaderOffset);
void patchMethodTable(MDTable methodDefTable, IList<MethodInfo> methodInfos); void PatchMethodTable(MDTable methodDefTable, IList<MethodInfo> methodInfos);
} }
abstract class CsHeaderBase : ICsHeader { abstract class CsHeaderBase : ICsHeader {
@ -238,42 +238,42 @@ namespace de4dot.code.deobfuscators.Agile_NET {
this.codeHeaderSize = codeHeaderSize; this.codeHeaderSize = codeHeaderSize;
} }
public abstract IDecrypter createDecrypter(); public abstract IDecrypter CreateDecrypter();
public virtual void patchMethodTable(MDTable methodDefTable, IList<MethodInfo> methodInfos) { public virtual void PatchMethodTable(MDTable methodDefTable, IList<MethodInfo> methodInfos) {
} }
public abstract List<MethodInfo> getMethodInfos(uint codeHeaderOffset); public abstract List<MethodInfo> GetMethodInfos(uint codeHeaderOffset);
protected List<MethodInfo> getMethodInfos1(uint codeHeaderOffset) { protected List<MethodInfo> GetMethodInfos1(uint codeHeaderOffset) {
uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + codeHeaderSize; uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + codeHeaderSize;
var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods); var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods);
for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 4) { for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 4) {
uint codeOffs = methodsDecrypter.peImage.offsetReadUInt32(offset); uint codeOffs = methodsDecrypter.peImage.OffsetReadUInt32(offset);
methodInfos.Add(new MethodInfo(codeOffs, 0, 0, 0)); methodInfos.Add(new MethodInfo(codeOffs, 0, 0, 0));
} }
return methodInfos; return methodInfos;
} }
protected List<MethodInfo> getMethodInfos2(uint codeHeaderOffset) { protected List<MethodInfo> GetMethodInfos2(uint codeHeaderOffset) {
uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + codeHeaderSize; uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + codeHeaderSize;
var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods); var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods);
for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 8) { for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 8) {
uint codeOffs = methodsDecrypter.peImage.offsetReadUInt32(offset); uint codeOffs = methodsDecrypter.peImage.OffsetReadUInt32(offset);
uint codeSize = methodsDecrypter.peImage.offsetReadUInt32(offset + 4); uint codeSize = methodsDecrypter.peImage.OffsetReadUInt32(offset + 4);
methodInfos.Add(new MethodInfo(codeOffs, codeSize, 0, 0)); methodInfos.Add(new MethodInfo(codeOffs, codeSize, 0, 0));
} }
return methodInfos; return methodInfos;
} }
protected List<MethodInfo> getMethodInfos4(uint codeHeaderOffset) { protected List<MethodInfo> GetMethodInfos4(uint codeHeaderOffset) {
uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + codeHeaderSize; uint offset = codeHeaderOffset + methodsDecrypter.codeHeader.totalCodeSize + codeHeaderSize;
var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods); var methodInfos = new List<MethodInfo>((int)methodsDecrypter.codeHeader.numMethods);
for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 16) { for (int i = 0; i < (int)methodsDecrypter.codeHeader.numMethods; i++, offset += 16) {
uint codeOffs = methodsDecrypter.peImage.offsetReadUInt32(offset); uint codeOffs = methodsDecrypter.peImage.OffsetReadUInt32(offset);
uint codeSize = methodsDecrypter.peImage.offsetReadUInt32(offset + 4); uint codeSize = methodsDecrypter.peImage.OffsetReadUInt32(offset + 4);
uint flags = methodsDecrypter.peImage.offsetReadUInt32(offset + 8); uint flags = methodsDecrypter.peImage.OffsetReadUInt32(offset + 8);
uint localVarSigTok = methodsDecrypter.peImage.offsetReadUInt32(offset + 12); uint localVarSigTok = methodsDecrypter.peImage.OffsetReadUInt32(offset + 12);
methodInfos.Add(new MethodInfo(codeOffs, codeSize, flags, localVarSigTok)); methodInfos.Add(new MethodInfo(codeOffs, codeSize, flags, localVarSigTok));
} }
return methodInfos; return methodInfos;
@ -286,12 +286,12 @@ namespace de4dot.code.deobfuscators.Agile_NET {
: base(methodsDecrypter, 0x28) { : base(methodsDecrypter, 0x28) {
} }
public override IDecrypter createDecrypter() { public override IDecrypter CreateDecrypter() {
return new Decrypter30(methodsDecrypter.peImage, methodsDecrypter.codeHeader); return new Decrypter30(methodsDecrypter.peImage, methodsDecrypter.codeHeader);
} }
public override List<MethodInfo> getMethodInfos(uint codeHeaderOffset) { public override List<MethodInfo> GetMethodInfos(uint codeHeaderOffset) {
return getMethodInfos1(codeHeaderOffset); return GetMethodInfos1(codeHeaderOffset);
} }
} }
@ -301,12 +301,12 @@ namespace de4dot.code.deobfuscators.Agile_NET {
: base(methodsDecrypter, 0x28) { : base(methodsDecrypter, 0x28) {
} }
public override IDecrypter createDecrypter() { public override IDecrypter CreateDecrypter() {
return new Decrypter40(methodsDecrypter.peImage, methodsDecrypter.codeHeader); return new Decrypter40(methodsDecrypter.peImage, methodsDecrypter.codeHeader);
} }
public override List<MethodInfo> getMethodInfos(uint codeHeaderOffset) { public override List<MethodInfo> GetMethodInfos(uint codeHeaderOffset) {
return getMethodInfos1(codeHeaderOffset); return GetMethodInfos1(codeHeaderOffset);
} }
} }
@ -316,12 +316,12 @@ namespace de4dot.code.deobfuscators.Agile_NET {
: base(methodsDecrypter, 0x28) { : base(methodsDecrypter, 0x28) {
} }
public override IDecrypter createDecrypter() { public override IDecrypter CreateDecrypter() {
return new Decrypter45(methodsDecrypter.peImage, methodsDecrypter.codeHeader); return new Decrypter45(methodsDecrypter.peImage, methodsDecrypter.codeHeader);
} }
public override List<MethodInfo> getMethodInfos(uint codeHeaderOffset) { public override List<MethodInfo> GetMethodInfos(uint codeHeaderOffset) {
return getMethodInfos2(codeHeaderOffset); return GetMethodInfos2(codeHeaderOffset);
} }
} }
@ -331,8 +331,8 @@ namespace de4dot.code.deobfuscators.Agile_NET {
: base(methodsDecrypter, codeHeaderSize) { : base(methodsDecrypter, codeHeaderSize) {
} }
public override IDecrypter createDecrypter() { public override IDecrypter CreateDecrypter() {
switch (getSigType(methodsDecrypter.codeHeader.signature)) { switch (GetSigType(methodsDecrypter.codeHeader.signature)) {
case SigType.Normal: case SigType.Normal:
return new Decrypter5(methodsDecrypter.peImage, methodsDecrypter.codeHeader, codeHeaderSize); return new Decrypter5(methodsDecrypter.peImage, methodsDecrypter.codeHeader, codeHeaderSize);
@ -345,21 +345,21 @@ namespace de4dot.code.deobfuscators.Agile_NET {
} }
} }
public override List<MethodInfo> getMethodInfos(uint codeHeaderOffset) { public override List<MethodInfo> GetMethodInfos(uint codeHeaderOffset) {
if (codeHeaderSize == 0x28) if (codeHeaderSize == 0x28)
return getMethodInfos2(codeHeaderOffset); return GetMethodInfos2(codeHeaderOffset);
return getMethodInfos4(codeHeaderOffset); return GetMethodInfos4(codeHeaderOffset);
} }
public override void patchMethodTable(MDTable methodDefTable, IList<MethodInfo> methodInfos) { public override void PatchMethodTable(MDTable methodDefTable, IList<MethodInfo> methodInfos) {
uint offset = (uint)methodDefTable.StartOffset - methodDefTable.RowSize; uint offset = (uint)methodDefTable.StartOffset - methodDefTable.RowSize;
foreach (var methodInfo in methodInfos) { foreach (var methodInfo in methodInfos) {
offset += methodDefTable.RowSize; offset += methodDefTable.RowSize;
if (methodInfo.flags == 0 || methodInfo.codeOffs == 0) if (methodInfo.flags == 0 || methodInfo.codeOffs == 0)
continue; continue;
uint rva = methodsDecrypter.peImage.offsetReadUInt32(offset); uint rva = methodsDecrypter.peImage.OffsetReadUInt32(offset);
methodsDecrypter.peImage.writeUInt16(rva, (ushort)methodInfo.flags); methodsDecrypter.peImage.WriteUInt16(rva, (ushort)methodInfo.flags);
methodsDecrypter.peImage.writeUInt32(rva + 8, methodInfo.localVarSigTok); methodsDecrypter.peImage.WriteUInt32(rva + 8, methodInfo.localVarSigTok);
} }
} }
} }
@ -374,14 +374,14 @@ namespace de4dot.code.deobfuscators.Agile_NET {
V52, // 5.2+ (or maybe 5.1+) V52, // 5.2+ (or maybe 5.1+)
} }
List<CsHeaderVersion> getCsHeaderVersions(uint codeHeaderOffset, MDTable methodDefTable) { List<CsHeaderVersion> GetCsHeaderVersions(uint codeHeaderOffset, MDTable methodDefTable) {
if (sigType == SigType.Old) if (sigType == SigType.Old)
return new List<CsHeaderVersion> { CsHeaderVersion.V10 }; return new List<CsHeaderVersion> { CsHeaderVersion.V10 };
if (!isOldHeader(methodDefTable)) if (!IsOldHeader(methodDefTable))
return new List<CsHeaderVersion> { CsHeaderVersion.V52 }; return new List<CsHeaderVersion> { CsHeaderVersion.V52 };
if (csRtType.isAtLeastVersion50()) if (csRtType.IsAtLeastVersion50())
return new List<CsHeaderVersion> { CsHeaderVersion.V50 }; return new List<CsHeaderVersion> { CsHeaderVersion.V50 };
if (isCsHeader40(codeHeaderOffset)) { if (IsCsHeader40(codeHeaderOffset)) {
return new List<CsHeaderVersion> { return new List<CsHeaderVersion> {
CsHeaderVersion.V40, CsHeaderVersion.V40,
CsHeaderVersion.V30, CsHeaderVersion.V30,
@ -393,12 +393,12 @@ namespace de4dot.code.deobfuscators.Agile_NET {
}; };
} }
bool isCsHeader40(uint codeHeaderOffset) { bool IsCsHeader40(uint codeHeaderOffset) {
try { try {
uint offset = codeHeaderOffset + codeHeader.totalCodeSize + 0x28; uint offset = codeHeaderOffset + codeHeader.totalCodeSize + 0x28;
uint prevCodeOffs = 0; uint prevCodeOffs = 0;
for (int i = 0; i < (int)codeHeader.numMethods; i++, offset += 4) { for (int i = 0; i < (int)codeHeader.numMethods; i++, offset += 4) {
uint codeOffs = peImage.offsetReadUInt32(offset); uint codeOffs = peImage.OffsetReadUInt32(offset);
if (prevCodeOffs != 0 && codeOffs != 0 && codeOffs < prevCodeOffs) if (prevCodeOffs != 0 && codeOffs != 0 && codeOffs < prevCodeOffs)
return false; return false;
if (codeOffs != 0) if (codeOffs != 0)
@ -412,16 +412,16 @@ namespace de4dot.code.deobfuscators.Agile_NET {
} }
} }
bool isOldHeader(MDTable methodDefTable) { bool IsOldHeader(MDTable methodDefTable) {
if (methodDefTable.RowSize != codeHeader.methodDefElemSize) if (methodDefTable.RowSize != codeHeader.methodDefElemSize)
return true; return true;
if ((uint)methodDefTable.StartOffset - peImage.rvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress) != codeHeader.methodDefTableOffset) if ((uint)methodDefTable.StartOffset - peImage.RvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress) != codeHeader.methodDefTableOffset)
return true; return true;
return false; return false;
} }
ICsHeader createCsHeader(CsHeaderVersion version) { ICsHeader CreateCsHeader(CsHeaderVersion version) {
switch (version) { switch (version) {
case CsHeaderVersion.V30: return new CsHeader30(this); case CsHeaderVersion.V30: return new CsHeader30(this);
case CsHeaderVersion.V40: return new CsHeader40(this); case CsHeaderVersion.V40: return new CsHeader40(this);
@ -438,19 +438,19 @@ namespace de4dot.code.deobfuscators.Agile_NET {
Error, Error,
} }
public bool decrypt(MyPEImage peImage, ModuleDefMD module, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) { public bool Decrypt(MyPEImage peImage, ModuleDefMD module, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) {
this.peImage = peImage; this.peImage = peImage;
this.csRtType = csRtType; this.csRtType = csRtType;
this.module = module; this.module = module;
switch (decrypt2(ref dumpedMethods)) { switch (Decrypt2(ref dumpedMethods)) {
case DecryptResult.Decrypted: return true; case DecryptResult.Decrypted: return true;
case DecryptResult.NotEncrypted: return false; case DecryptResult.NotEncrypted: return false;
case DecryptResult.Error: case DecryptResult.Error:
Logger.n("Using dynamic method decryption"); Logger.n("Using dynamic method decryption");
byte[] moduleCctorBytes = getModuleCctorBytes(csRtType); byte[] moduleCctorBytes = GetModuleCctorBytes(csRtType);
dumpedMethods = de4dot.code.deobfuscators.MethodsDecrypter.decrypt(module, moduleCctorBytes); dumpedMethods = de4dot.code.deobfuscators.MethodsDecrypter.Decrypt(module, moduleCctorBytes);
return true; return true;
default: default:
@ -458,7 +458,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
} }
} }
static byte[] getModuleCctorBytes(CliSecureRtType csRtType) { static byte[] GetModuleCctorBytes(CliSecureRtType csRtType) {
var initMethod = csRtType.InitializeMethod; var initMethod = csRtType.InitializeMethod;
if (initMethod == null) if (initMethod == null)
return null; return null;
@ -473,24 +473,24 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return moduleCctorBytes; return moduleCctorBytes;
} }
static uint getCodeHeaderOffset(MyPEImage peImage) { static uint GetCodeHeaderOffset(MyPEImage peImage) {
return peImage.rvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress + peImage.Cor20Header.MetaData.Size); return peImage.RvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress + peImage.Cor20Header.MetaData.Size);
} }
static string[] sections = new string[] { static string[] sections = new string[] {
".text", ".rsrc", ".data", ".rdata", ".text", ".rsrc", ".data", ".rdata",
}; };
static uint getOldCodeHeaderOffset(MyPEImage peImage) { static uint GetOldCodeHeaderOffset(MyPEImage peImage) {
var sect = getLastOf(peImage, sections); var sect = GetLastOf(peImage, sections);
if (sect == null || sect.VirtualSize < 0x100) if (sect == null || sect.VirtualSize < 0x100)
return 0; return 0;
return peImage.rvaToOffset((uint)sect.VirtualAddress + sect.VirtualSize - 0x100); return peImage.RvaToOffset((uint)sect.VirtualAddress + sect.VirtualSize - 0x100);
} }
static ImageSectionHeader getLastOf(MyPEImage peImage, string[] sections) { static ImageSectionHeader GetLastOf(MyPEImage peImage, string[] sections) {
ImageSectionHeader sect = null; ImageSectionHeader sect = null;
foreach (var name in sections) { foreach (var name in sections) {
var sect2 = peImage.findSection(name); var sect2 = peImage.FindSection(name);
if (sect2 == null) if (sect2 == null)
continue; continue;
if (sect == null || sect2.VirtualAddress > sect.VirtualAddress) if (sect == null || sect2.VirtualAddress > sect.VirtualAddress)
@ -499,19 +499,19 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return sect; return sect;
} }
DecryptResult decrypt2(ref DumpedMethods dumpedMethods) { DecryptResult Decrypt2(ref DumpedMethods dumpedMethods) {
uint codeHeaderOffset = initializeCodeHeader(); uint codeHeaderOffset = InitializeCodeHeader();
if (sigType == SigType.Unknown) if (sigType == SigType.Unknown)
return DecryptResult.NotEncrypted; return DecryptResult.NotEncrypted;
var methodDefTable = peImage.DotNetFile.MetaData.TablesStream.MethodTable; var methodDefTable = peImage.DotNetFile.MetaData.TablesStream.MethodTable;
foreach (var version in getCsHeaderVersions(codeHeaderOffset, methodDefTable)) { foreach (var version in GetCsHeaderVersions(codeHeaderOffset, methodDefTable)) {
try { try {
if (version == CsHeaderVersion.V10) if (version == CsHeaderVersion.V10)
decryptMethodsOld(methodDefTable, ref dumpedMethods); DecryptMethodsOld(methodDefTable, ref dumpedMethods);
else else
decryptMethods(codeHeaderOffset, methodDefTable, createCsHeader(version), ref dumpedMethods); DecryptMethods(codeHeaderOffset, methodDefTable, CreateCsHeader(version), ref dumpedMethods);
return DecryptResult.Decrypted; return DecryptResult.Decrypted;
} }
catch { catch {
@ -521,23 +521,23 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return DecryptResult.Error; return DecryptResult.Error;
} }
uint initializeCodeHeader() { uint InitializeCodeHeader() {
uint codeHeaderOffset = getCodeHeaderOffset(peImage); uint codeHeaderOffset = GetCodeHeaderOffset(peImage);
readCodeHeader(codeHeaderOffset); ReadCodeHeader(codeHeaderOffset);
sigType = getSigType(codeHeader.signature); sigType = GetSigType(codeHeader.signature);
if (sigType == SigType.Unknown) { if (sigType == SigType.Unknown) {
codeHeaderOffset = getOldCodeHeaderOffset(peImage); codeHeaderOffset = GetOldCodeHeaderOffset(peImage);
if (codeHeaderOffset != 0) { if (codeHeaderOffset != 0) {
readCodeHeader(codeHeaderOffset); ReadCodeHeader(codeHeaderOffset);
sigType = getSigType(codeHeader.signature); sigType = GetSigType(codeHeader.signature);
} }
} }
return codeHeaderOffset; return codeHeaderOffset;
} }
void decryptMethodsOld(MDTable methodDefTable, ref DumpedMethods dumpedMethods) { void DecryptMethodsOld(MDTable methodDefTable, ref DumpedMethods dumpedMethods) {
dumpedMethods = new DumpedMethods(); dumpedMethods = new DumpedMethods();
var decrypter = new Decrypter10(peImage, codeHeader.decryptionKey); var decrypter = new Decrypter10(peImage, codeHeader.decryptionKey);
for (uint rid = 1; rid <= methodDefTable.Rows; rid++) { for (uint rid = 1; rid <= methodDefTable.Rows; rid++) {
@ -547,74 +547,74 @@ namespace de4dot.code.deobfuscators.Agile_NET {
if (method == null || method.DeclaringType == module.GlobalType) if (method == null || method.DeclaringType == module.GlobalType)
continue; continue;
peImage.readMethodTableRowTo(dm, rid); peImage.ReadMethodTableRowTo(dm, rid);
if (dm.mdRVA == 0) if (dm.mdRVA == 0)
continue; continue;
uint bodyOffset = peImage.rvaToOffset(dm.mdRVA); uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);
var mbHeader = decrypter.decrypt(bodyOffset, out dm.code, out dm.extraSections); var mbHeader = decrypter.Decrypt(bodyOffset, out dm.code, out dm.extraSections);
peImage.updateMethodHeaderInfo(dm, mbHeader); peImage.UpdateMethodHeaderInfo(dm, mbHeader);
dumpedMethods.add(dm); dumpedMethods.Add(dm);
} }
} }
void decryptMethods(uint codeHeaderOffset, MDTable methodDefTable, ICsHeader csHeader, ref DumpedMethods dumpedMethods) { void DecryptMethods(uint codeHeaderOffset, MDTable methodDefTable, ICsHeader csHeader, ref DumpedMethods dumpedMethods) {
var methodInfos = csHeader.getMethodInfos(codeHeaderOffset); var methodInfos = csHeader.GetMethodInfos(codeHeaderOffset);
csHeader.patchMethodTable(methodDefTable, methodInfos); csHeader.PatchMethodTable(methodDefTable, methodInfos);
dumpedMethods = new DumpedMethods(); dumpedMethods = new DumpedMethods();
decrypter = csHeader.createDecrypter(); decrypter = csHeader.CreateDecrypter();
for (uint rid = 1; rid <= (uint)methodInfos.Count; rid++) { for (uint rid = 1; rid <= (uint)methodInfos.Count; rid++) {
var methodInfo = methodInfos[(int)rid - 1]; var methodInfo = methodInfos[(int)rid - 1];
if (methodInfo.codeOffs == 0) if (methodInfo.codeOffs == 0)
continue; continue;
var dm = new DumpedMethod(); var dm = new DumpedMethod();
peImage.readMethodTableRowTo(dm, rid); peImage.ReadMethodTableRowTo(dm, rid);
var mbHeader = decrypter.decrypt(methodInfo, out dm.code, out dm.extraSections); var mbHeader = decrypter.Decrypt(methodInfo, out dm.code, out dm.extraSections);
peImage.updateMethodHeaderInfo(dm, mbHeader); peImage.UpdateMethodHeaderInfo(dm, mbHeader);
dumpedMethods.add(dm); dumpedMethods.Add(dm);
} }
} }
void readCodeHeader(uint offset) { void ReadCodeHeader(uint offset) {
codeHeader.signature = peImage.offsetReadBytes(offset, 16); codeHeader.signature = peImage.OffsetReadBytes(offset, 16);
codeHeader.decryptionKey = peImage.offsetReadBytes(offset + 0x10, 16); codeHeader.decryptionKey = peImage.OffsetReadBytes(offset + 0x10, 16);
codeHeader.totalCodeSize = peImage.offsetReadUInt32(offset + 0x20); codeHeader.totalCodeSize = peImage.OffsetReadUInt32(offset + 0x20);
codeHeader.numMethods = peImage.offsetReadUInt32(offset + 0x24); codeHeader.numMethods = peImage.OffsetReadUInt32(offset + 0x24);
codeHeader.methodDefTableOffset = peImage.offsetReadUInt32(offset + 0x28); codeHeader.methodDefTableOffset = peImage.OffsetReadUInt32(offset + 0x28);
codeHeader.methodDefElemSize = peImage.offsetReadUInt32(offset + 0x2C); codeHeader.methodDefElemSize = peImage.OffsetReadUInt32(offset + 0x2C);
} }
static SigType getSigType(byte[] sig) { static SigType GetSigType(byte[] sig) {
if (Utils.compare(sig, normalSignature)) if (Utils.Compare(sig, normalSignature))
return SigType.Normal; return SigType.Normal;
else if (Utils.compare(sig, proSignature)) else if (Utils.Compare(sig, proSignature))
return SigType.Pro; return SigType.Pro;
else if (Utils.compare(sig, oldSignature)) else if (Utils.Compare(sig, oldSignature))
return SigType.Old; return SigType.Old;
return SigType.Unknown; return SigType.Unknown;
} }
static bool isValidSignature(byte[] signature) { static bool IsValidSignature(byte[] signature) {
return getSigType(signature) != SigType.Unknown; return GetSigType(signature) != SigType.Unknown;
} }
public static bool detect(MyPEImage peImage) { public static bool Detect(MyPEImage peImage) {
try { try {
uint codeHeaderOffset = getCodeHeaderOffset(peImage); uint codeHeaderOffset = GetCodeHeaderOffset(peImage);
if (isValidSignature(peImage.offsetReadBytes(codeHeaderOffset, 16))) if (IsValidSignature(peImage.OffsetReadBytes(codeHeaderOffset, 16)))
return true; return true;
} }
catch { catch {
} }
try { try {
uint codeHeaderOffset = getOldCodeHeaderOffset(peImage); uint codeHeaderOffset = GetOldCodeHeaderOffset(peImage);
if (codeHeaderOffset != 0 && isValidSignature(peImage.offsetReadBytes(codeHeaderOffset, 16))) if (codeHeaderOffset != 0 && IsValidSignature(peImage.OffsetReadBytes(codeHeaderOffset, 16)))
return true; return true;
} }
catch { catch {

View File

@ -32,28 +32,28 @@ namespace de4dot.code.deobfuscators.Agile_NET {
public ProxyCallFixer(ModuleDefMD module, ProxyCallFixer oldOne) public ProxyCallFixer(ModuleDefMD module, ProxyCallFixer oldOne)
: base(module) { : base(module) {
foreach (var method in oldOne.delegateCreatorMethods) foreach (var method in oldOne.delegateCreatorMethods)
setDelegateCreatorMethod(lookup(method, "Could not find delegate creator method")); SetDelegateCreatorMethod(Lookup(method, "Could not find delegate creator method"));
} }
public void findDelegateCreator() { public void FindDelegateCreator() {
foreach (var type in module.Types) { foreach (var type in module.Types) {
var methodName = "System.Void " + type.FullName + "::icgd(System.Int32)"; var methodName = "System.Void " + type.FullName + "::icgd(System.Int32)";
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (method.FullName == methodName) { if (method.FullName == methodName) {
setDelegateCreatorMethod(method); SetDelegateCreatorMethod(method);
return; return;
} }
} }
} }
} }
protected override object checkCctor(ref TypeDef type, MethodDef cctor) { protected override object CheckCctor(ref TypeDef type, MethodDef cctor) {
var instrs = cctor.Body.Instructions; var instrs = cctor.Body.Instructions;
if (instrs.Count != 3) if (instrs.Count != 3)
return null; return null;
if (!instrs[0].IsLdcI4()) if (!instrs[0].IsLdcI4())
return null; return null;
if (instrs[1].OpCode != OpCodes.Call || !isDelegateCreatorMethod(instrs[1].Operand as MethodDef)) if (instrs[1].OpCode != OpCodes.Call || !IsDelegateCreatorMethod(instrs[1].Operand as MethodDef))
return null; return null;
if (instrs[2].OpCode != OpCodes.Ret) if (instrs[2].OpCode != OpCodes.Ret)
return null; return null;
@ -67,7 +67,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
return new object(); return new object();
} }
protected override void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) { protected override void GetCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) {
var name = field.Name.String; var name = field.Name.String;
callOpcode = OpCodes.Call; callOpcode = OpCodes.Call;
if (name.EndsWith("%", StringComparison.Ordinal)) { if (name.EndsWith("%", StringComparison.Ordinal)) {

View File

@ -49,39 +49,39 @@ namespace de4dot.code.deobfuscators.Agile_NET {
public ResourceDecrypter(ModuleDefMD module, ResourceDecrypter oldOne) { public ResourceDecrypter(ModuleDefMD module, ResourceDecrypter oldOne) {
this.module = module; this.module = module;
rsrcType = lookup(oldOne.rsrcType, "Could not find rsrcType"); rsrcType = Lookup(oldOne.rsrcType, "Could not find rsrcType");
rsrcRrrMethod = lookup(oldOne.rsrcRrrMethod, "Could not find rsrcRrrMethod"); rsrcRrrMethod = Lookup(oldOne.rsrcRrrMethod, "Could not find rsrcRrrMethod");
rsrcResolveMethod = lookup(oldOne.rsrcResolveMethod, "Could not find rsrcResolveMethod"); rsrcResolveMethod = Lookup(oldOne.rsrcResolveMethod, "Could not find rsrcResolveMethod");
} }
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken { T Lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
return DeobUtils.lookup(module, def, errorMessage); return DeobUtils.Lookup(module, def, errorMessage);
} }
public void find() { public void Find() {
findResourceType(); FindResourceType();
} }
static readonly string[] requiredFields = new string[] { static readonly string[] requiredFields = new string[] {
"System.Reflection.Assembly", "System.Reflection.Assembly",
"System.String[]", "System.String[]",
}; };
void findResourceType() { void FindResourceType() {
var cctor = DotNetUtils.getModuleTypeCctor(module); var cctor = DotNetUtils.GetModuleTypeCctor(module);
if (cctor == null) if (cctor == null)
return; return;
foreach (var calledMethod in DotNetUtils.getCalledMethods(module, cctor)) { foreach (var calledMethod in DotNetUtils.GetCalledMethods(module, cctor)) {
if (!calledMethod.IsStatic || calledMethod.Body == null) if (!calledMethod.IsStatic || calledMethod.Body == null)
continue; continue;
if (!DotNetUtils.isMethod(calledMethod, "System.Void", "()")) if (!DotNetUtils.IsMethod(calledMethod, "System.Void", "()"))
continue; continue;
var type = calledMethod.DeclaringType; var type = calledMethod.DeclaringType;
if (!new FieldTypes(type).exactly(requiredFields)) if (!new FieldTypes(type).Exactly(requiredFields))
continue; continue;
var resolveHandler = DotNetUtils.getMethod(type, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)"); var resolveHandler = DotNetUtils.GetMethod(type, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)");
var decryptMethod = DotNetUtils.getMethod(type, "System.Byte[]", "(System.IO.Stream)"); var decryptMethod = DotNetUtils.GetMethod(type, "System.Byte[]", "(System.IO.Stream)");
if (resolveHandler == null || !resolveHandler.IsStatic) if (resolveHandler == null || !resolveHandler.IsStatic)
continue; continue;
if (decryptMethod == null || !decryptMethod.IsStatic) if (decryptMethod == null || !decryptMethod.IsStatic)
@ -94,17 +94,17 @@ namespace de4dot.code.deobfuscators.Agile_NET {
} }
} }
public EmbeddedResource mergeResources() { public EmbeddedResource MergeResources() {
if (rsrcResolveMethod == null) if (rsrcResolveMethod == null)
return null; return null;
var resource = DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(rsrcResolveMethod)) as EmbeddedResource; var resource = DotNetUtils.GetResource(module, DotNetUtils.GetCodeStrings(rsrcResolveMethod)) as EmbeddedResource;
if (resource == null) if (resource == null)
return null; return null;
DeobUtils.decryptAndAddResources(module, resource.Name.String, () => decryptResource(resource)); DeobUtils.DecryptAndAddResources(module, resource.Name.String, () => DecryptResource(resource));
return resource; return resource;
} }
byte[] decryptResource(EmbeddedResource resource) { byte[] DecryptResource(EmbeddedResource resource) {
var reader = resource.Data; var reader = resource.Data;
reader.Position = 0; reader.Position = 0;
var key = reader.ReadString(); var key = reader.ReadString();

View File

@ -39,7 +39,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
this.module = module; this.module = module;
} }
public void find() { public void Find() {
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (!type.HasMethods) if (!type.HasMethods)
continue; continue;
@ -55,7 +55,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
var sig = method.MethodSig; var sig = method.MethodSig;
if (sig != null && method.IsStatic && method.HasBody && if (sig != null && method.IsStatic && method.HasBody &&
sig.Params.Count == 2 && !method.HasGenericParameters && sig.Params.Count == 2 && !method.HasGenericParameters &&
!DotNetUtils.hasReturnValue(method) && !DotNetUtils.HasReturnValue(method) &&
sig.Params[0].GetFullName() == "System.Exception" && sig.Params[0].GetFullName() == "System.Exception" &&
sig.Params[1].GetFullName() == "System.Object[]") { sig.Params[1].GetFullName() == "System.Object[]") {
errorMethod = method; errorMethod = method;
@ -65,7 +65,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
} }
if (errorMethod != null) { if (errorMethod != null) {
stackFrameHelperType = type; stackFrameHelperType = type;
exceptionLoggerRemover.add(errorMethod); exceptionLoggerRemover.Add(errorMethod);
return; return;
} }
} }

View File

@ -48,16 +48,16 @@ namespace de4dot.code.deobfuscators.Agile_NET {
public StringDecrypter(ModuleDefMD module, StringDecrypter oldOne) { public StringDecrypter(ModuleDefMD module, StringDecrypter oldOne) {
this.module = module; this.module = module;
stringDecrypterType = lookup(oldOne.stringDecrypterType, "Could not find stringDecrypterType"); stringDecrypterType = Lookup(oldOne.stringDecrypterType, "Could not find stringDecrypterType");
stringDecrypterMethod = lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod"); stringDecrypterMethod = Lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod");
stringDecrypterKey = oldOne.stringDecrypterKey; stringDecrypterKey = oldOne.stringDecrypterKey;
} }
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken { T Lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
return DeobUtils.lookup(module, def, errorMessage); return DeobUtils.Lookup(module, def, errorMessage);
} }
public void find() { public void Find() {
stringDecrypterKey = new byte[1] { 0xFF }; stringDecrypterKey = new byte[1] { 0xFF };
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (type.FullName == "<D234>" || type.FullName == "<ClassD234>") { if (type.FullName == "<D234>" || type.FullName == "<ClassD234>") {
@ -73,7 +73,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
} }
} }
public string decrypt(string es) { public string Decrypt(string es) {
if (stringDecrypterKey == null) if (stringDecrypterKey == null)
throw new ApplicationException("Trying to decrypt strings when stringDecrypterKey is null (could not find it!)"); throw new ApplicationException("Trying to decrypt strings when stringDecrypterKey is null (could not find it!)");
char[] buf = new char[es.Length]; char[] buf = new char[es.Length];

View File

@ -29,7 +29,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
class CilOperandInstructionRestorer { class CilOperandInstructionRestorer {
MethodDef method; MethodDef method;
public bool restore(MethodDef method) { public bool Restore(MethodDef method) {
this.method = method; this.method = method;
bool atLeastOneFailed = false; bool atLeastOneFailed = false;
@ -45,26 +45,26 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
TypeSig operandType = null; TypeSig operandType = null;
switch (instr.OpCode.Code) { switch (instr.OpCode.Code) {
case Code.Ldelema: case Code.Ldelema:
var arrayType = MethodStack.getLoadedType(method, instrs, i, 1) as SZArraySig; var arrayType = MethodStack.GetLoadedType(method, instrs, i, 1) as SZArraySig;
if (arrayType == null) if (arrayType == null)
break; break;
operandType = arrayType.Next; operandType = arrayType.Next;
break; break;
case Code.Ldobj: case Code.Ldobj:
operandType = getPtrElementType(MethodStack.getLoadedType(method, instrs, i, 0)); operandType = GetPtrElementType(MethodStack.GetLoadedType(method, instrs, i, 0));
break; break;
case Code.Stobj: case Code.Stobj:
operandType = MethodStack.getLoadedType(method, instrs, i, 0); operandType = MethodStack.GetLoadedType(method, instrs, i, 0);
if (!isValidType(operandType)) if (!IsValidType(operandType))
operandType = getPtrElementType(MethodStack.getLoadedType(method, instrs, i, 1)); operandType = GetPtrElementType(MethodStack.GetLoadedType(method, instrs, i, 1));
break; break;
default: default:
continue; continue;
} }
if (!isValidType(operandType)) { if (!IsValidType(operandType)) {
atLeastOneFailed = true; atLeastOneFailed = true;
continue; continue;
} }
@ -75,7 +75,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
return !atLeastOneFailed; return !atLeastOneFailed;
} }
static TypeSig getPtrElementType(TypeSig type) { static TypeSig GetPtrElementType(TypeSig type) {
if (type == null) if (type == null)
return null; return null;
if (type.IsPointer || type.IsByRef) if (type.IsPointer || type.IsByRef)
@ -83,7 +83,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
return null; return null;
} }
bool isValidType(TypeSig type) { bool IsValidType(TypeSig type) {
type = type.RemovePinnedAndModifiers(); type = type.RemovePinnedAndModifiers();
if (type == null) if (type == null)
return false; return false;

View File

@ -52,12 +52,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
this.vmAssemblyRef = module.ResolveAssemblyRef(oldOne.vmAssemblyRef.Rid); this.vmAssemblyRef = module.ResolveAssemblyRef(oldOne.vmAssemblyRef.Rid);
} }
public void find() { public void Find() {
resource = findCsvmResource(); resource = FindCsvmResource();
vmAssemblyRef = findVmAssemblyRef(); vmAssemblyRef = FindVmAssemblyRef();
} }
AssemblyRef findVmAssemblyRef() { AssemblyRef FindVmAssemblyRef() {
foreach (var memberRef in module.GetMemberRefs()) { foreach (var memberRef in module.GetMemberRefs()) {
var sig = memberRef.MethodSig; var sig = memberRef.MethodSig;
if (sig == null) if (sig == null)
@ -74,17 +74,17 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
return null; return null;
} }
EmbeddedResource findCsvmResource() { EmbeddedResource FindCsvmResource() {
return DotNetUtils.getResource(module, "_CSVM") as EmbeddedResource; return DotNetUtils.GetResource(module, "_CSVM") as EmbeddedResource;
} }
public bool restore() { public bool Restore() {
if (!Detected) if (!Detected)
return true; return true;
int oldIndent = Logger.Instance.IndentLevel; int oldIndent = Logger.Instance.IndentLevel;
try { try {
restore2(); Restore2();
return true; return true;
} }
catch { catch {
@ -95,66 +95,66 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
} }
} }
void restore2() { void Restore2() {
Logger.v("Restoring CSVM methods"); Logger.v("Restoring CSVM methods");
Logger.Instance.indent(); Logger.Instance.Indent();
var opcodeDetector = getVmOpCodeHandlerDetector(); var opcodeDetector = GetVmOpCodeHandlerDetector();
var csvmMethods = new CsvmDataReader(resource.Data).read(); var csvmMethods = new CsvmDataReader(resource.Data).Read();
var converter = new CsvmToCilMethodConverter(deobfuscatorContext, module, opcodeDetector); var converter = new CsvmToCilMethodConverter(deobfuscatorContext, module, opcodeDetector);
var methodPrinter = new MethodPrinter(); var methodPrinter = new MethodPrinter();
foreach (var csvmMethod in csvmMethods) { foreach (var csvmMethod in csvmMethods) {
var cilMethod = module.ResolveToken(csvmMethod.Token) as MethodDef; var cilMethod = module.ResolveToken(csvmMethod.Token) as MethodDef;
if (cilMethod == null) if (cilMethod == null)
throw new ApplicationException(string.Format("Could not find method {0:X8}", csvmMethod.Token)); throw new ApplicationException(string.Format("Could not find method {0:X8}", csvmMethod.Token));
converter.convert(cilMethod, csvmMethod); converter.Convert(cilMethod, csvmMethod);
Logger.v("Restored method {0:X8}", cilMethod.MDToken.ToInt32()); Logger.v("Restored method {0:X8}", cilMethod.MDToken.ToInt32());
printMethod(methodPrinter, cilMethod); PrintMethod(methodPrinter, cilMethod);
} }
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
} }
static void printMethod(MethodPrinter methodPrinter, MethodDef method) { static void PrintMethod(MethodPrinter methodPrinter, MethodDef method) {
const LoggerEvent dumpLogLevel = LoggerEvent.Verbose; const LoggerEvent dumpLogLevel = LoggerEvent.Verbose;
if (Logger.Instance.IgnoresEvent(dumpLogLevel)) if (Logger.Instance.IgnoresEvent(dumpLogLevel))
return; return;
Logger.Instance.indent(); Logger.Instance.Indent();
Logger.v("Locals:"); Logger.v("Locals:");
Logger.Instance.indent(); Logger.Instance.Indent();
for (int i = 0; i < method.Body.Variables.Count; i++) for (int i = 0; i < method.Body.Variables.Count; i++)
Logger.v("#{0}: {1}", i, method.Body.Variables[i].Type); Logger.v("#{0}: {1}", i, method.Body.Variables[i].Type);
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
Logger.v("Code:"); Logger.v("Code:");
Logger.Instance.indent(); Logger.Instance.Indent();
methodPrinter.print(dumpLogLevel, method.Body.Instructions, method.Body.ExceptionHandlers); methodPrinter.Print(dumpLogLevel, method.Body.Instructions, method.Body.ExceptionHandlers);
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
} }
VmOpCodeHandlerDetector getVmOpCodeHandlerDetector() { VmOpCodeHandlerDetector GetVmOpCodeHandlerDetector() {
var vmFilename = vmAssemblyRef.Name + ".dll"; var vmFilename = vmAssemblyRef.Name + ".dll";
var vmModulePath = Path.Combine(Path.GetDirectoryName(module.Location), vmFilename); var vmModulePath = Path.Combine(Path.GetDirectoryName(module.Location), vmFilename);
Logger.v("CSVM filename: {0}", vmFilename); Logger.v("CSVM filename: {0}", vmFilename);
var dataKey = "cs cached VmOpCodeHandlerDetector"; var dataKey = "cs cached VmOpCodeHandlerDetector";
var dict = (Dictionary<string, VmOpCodeHandlerDetector>)deobfuscatorContext.getData(dataKey); var dict = (Dictionary<string, VmOpCodeHandlerDetector>)deobfuscatorContext.GetData(dataKey);
if (dict == null) if (dict == null)
deobfuscatorContext.setData(dataKey, dict = new Dictionary<string, VmOpCodeHandlerDetector>(StringComparer.OrdinalIgnoreCase)); deobfuscatorContext.SetData(dataKey, dict = new Dictionary<string, VmOpCodeHandlerDetector>(StringComparer.OrdinalIgnoreCase));
VmOpCodeHandlerDetector detector; VmOpCodeHandlerDetector detector;
if (dict.TryGetValue(vmModulePath, out detector)) if (dict.TryGetValue(vmModulePath, out detector))
return detector; return detector;
dict[vmModulePath] = detector = new VmOpCodeHandlerDetector(ModuleDefMD.Load(vmModulePath)); dict[vmModulePath] = detector = new VmOpCodeHandlerDetector(ModuleDefMD.Load(vmModulePath));
detector.findHandlers(); detector.FindHandlers();
Logger.v("CSVM opcodes:"); Logger.v("CSVM opcodes:");
Logger.Instance.indent(); Logger.Instance.Indent();
for (int i = 0; i < detector.Handlers.Count; i++) for (int i = 0; i < detector.Handlers.Count; i++)
Logger.v("{0:X4}: {1}", i, detector.Handlers[i].Name); Logger.v("{0:X4}: {1}", i, detector.Handlers[i].Name);
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
return detector; return detector;
} }

View File

@ -33,7 +33,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
this.reader = reader; this.reader = reader;
} }
public List<CsvmMethodData> read() { public List<CsvmMethodData> Read() {
int numMethods = reader.ReadInt32(); int numMethods = reader.ReadInt32();
if (numMethods < 0) if (numMethods < 0)
throw new ApplicationException("Invalid number of methods"); throw new ApplicationException("Invalid number of methods");

View File

@ -37,33 +37,33 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
this.opCodeDetector = opCodeDetector; this.opCodeDetector = opCodeDetector;
} }
public void convert(MethodDef cilMethod, CsvmMethodData csvmMethod) { public void Convert(MethodDef cilMethod, CsvmMethodData csvmMethod) {
var newInstructions = readInstructions(cilMethod, csvmMethod); var newInstructions = ReadInstructions(cilMethod, csvmMethod);
var newLocals = readLocals(cilMethod, csvmMethod); var newLocals = ReadLocals(cilMethod, csvmMethod);
var newExceptions = readExceptions(cilMethod, csvmMethod, newInstructions); var newExceptions = ReadExceptions(cilMethod, csvmMethod, newInstructions);
fixInstructionOperands(newInstructions); FixInstructionOperands(newInstructions);
fixLocals(newInstructions, cilMethod.Body.Variables); FixLocals(newInstructions, cilMethod.Body.Variables);
fixArgs(newInstructions, cilMethod); FixArgs(newInstructions, cilMethod);
DotNetUtils.restoreBody(cilMethod, newInstructions, newExceptions); DotNetUtils.RestoreBody(cilMethod, newInstructions, newExceptions);
if (!operandRestorer.restore(cilMethod)) if (!operandRestorer.Restore(cilMethod))
Logger.w("Failed to restore one or more instruction operands in CSVM method {0:X8}", cilMethod.MDToken.ToInt32()); Logger.w("Failed to restore one or more instruction operands in CSVM method {0:X8}", cilMethod.MDToken.ToInt32());
restoreConstrainedPrefix(cilMethod); RestoreConstrainedPrefix(cilMethod);
} }
void fixLocals(IList<Instruction> instrs, IList<Local> locals) { void FixLocals(IList<Instruction> instrs, IList<Local> locals) {
foreach (var instr in instrs) { foreach (var instr in instrs) {
var op = instr.Operand as LocalOperand; var op = instr.Operand as LocalOperand;
if (op == null) if (op == null)
continue; continue;
updateLocalInstruction(instr, locals[op.local], op.local); UpdateLocalInstruction(instr, locals[op.local], op.local);
} }
} }
static void updateLocalInstruction(Instruction instr, Local local, int index) { static void UpdateLocalInstruction(Instruction instr, Local local, int index) {
object operand = null; object operand = null;
OpCode opcode; OpCode opcode;
@ -128,17 +128,17 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
instr.Operand = operand; instr.Operand = operand;
} }
void fixArgs(IList<Instruction> instrs, MethodDef method) { void FixArgs(IList<Instruction> instrs, MethodDef method) {
foreach (var instr in instrs) { foreach (var instr in instrs) {
var op = instr.Operand as ArgOperand; var op = instr.Operand as ArgOperand;
if (op == null) if (op == null)
continue; continue;
updateArgInstruction(instr, method.Parameters[op.arg], op.arg); UpdateArgInstruction(instr, method.Parameters[op.arg], op.arg);
} }
} }
static void updateArgInstruction(Instruction instr, Parameter arg, int index) { static void UpdateArgInstruction(Instruction instr, Parameter arg, int index) {
switch (instr.OpCode.Code) { switch (instr.OpCode.Code) {
case Code.Ldarg: case Code.Ldarg:
case Code.Ldarg_S: case Code.Ldarg_S:
@ -197,7 +197,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
} }
} }
List<Instruction> readInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) { List<Instruction> ReadInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) {
var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions)); var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions));
var instrs = new List<Instruction>(); var instrs = new List<Instruction>();
uint offset = 0; uint offset = 0;
@ -205,13 +205,13 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
int vmOpCode = reader.ReadUInt16(); int vmOpCode = reader.ReadUInt16();
var instr = opCodeDetector.Handlers[vmOpCode].Read(reader); var instr = opCodeDetector.Handlers[vmOpCode].Read(reader);
instr.Offset = offset; instr.Offset = offset;
offset += (uint)getInstructionSize(instr); offset += (uint)GetInstructionSize(instr);
instrs.Add(instr); instrs.Add(instr);
} }
return instrs; return instrs;
} }
static int getInstructionSize(Instruction instr) { static int GetInstructionSize(Instruction instr) {
var opcode = instr.OpCode; var opcode = instr.OpCode;
if (opcode == null) if (opcode == null)
return 5; // Load store/field return 5; // Load store/field
@ -221,7 +221,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
return instr.OpCode.Size + (op.targetDisplacements.Length + 1) * 4; return instr.OpCode.Size + (op.targetDisplacements.Length + 1) * 4;
} }
List<Local> readLocals(MethodDef cilMethod, CsvmMethodData csvmMethod) { List<Local> ReadLocals(MethodDef cilMethod, CsvmMethodData csvmMethod) {
var locals = new List<Local>(); var locals = new List<Local>();
var reader = new BinaryReader(new MemoryStream(csvmMethod.Locals)); var reader = new BinaryReader(new MemoryStream(csvmMethod.Locals));
@ -234,12 +234,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
throw new ApplicationException("Invalid number of locals"); throw new ApplicationException("Invalid number of locals");
for (int i = 0; i < numLocals; i++) for (int i = 0; i < numLocals; i++)
locals.Add(new Local(readTypeRef(reader))); locals.Add(new Local(ReadTypeRef(reader)));
return locals; return locals;
} }
TypeSig readTypeRef(BinaryReader reader) { TypeSig ReadTypeRef(BinaryReader reader) {
var etype = (ElementType)reader.ReadInt32(); var etype = (ElementType)reader.ReadInt32();
switch (etype) { switch (etype) {
case ElementType.Void: return module.CorLibTypes.Void; case ElementType.Void: return module.CorLibTypes.Void;
@ -289,7 +289,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
} }
} }
List<ExceptionHandler> readExceptions(MethodDef cilMethod, CsvmMethodData csvmMethod, List<Instruction> cilInstructions) { List<ExceptionHandler> ReadExceptions(MethodDef cilMethod, CsvmMethodData csvmMethod, List<Instruction> cilInstructions) {
var reader = new BinaryReader(new MemoryStream(csvmMethod.Exceptions)); var reader = new BinaryReader(new MemoryStream(csvmMethod.Exceptions));
var ehs = new List<ExceptionHandler>(); var ehs = new List<ExceptionHandler>();
@ -302,14 +302,14 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
for (int i = 0; i < numExceptions; i++) { for (int i = 0; i < numExceptions; i++) {
var eh = new ExceptionHandler((ExceptionHandlerType)reader.ReadInt32()); var eh = new ExceptionHandler((ExceptionHandlerType)reader.ReadInt32());
eh.TryStart = getInstruction(cilInstructions, reader.ReadInt32()); eh.TryStart = GetInstruction(cilInstructions, reader.ReadInt32());
eh.TryEnd = getInstructionEnd(cilInstructions, reader.ReadInt32()); eh.TryEnd = GetInstructionEnd(cilInstructions, reader.ReadInt32());
eh.HandlerStart = getInstruction(cilInstructions, reader.ReadInt32()); eh.HandlerStart = GetInstruction(cilInstructions, reader.ReadInt32());
eh.HandlerEnd = getInstructionEnd(cilInstructions, reader.ReadInt32()); eh.HandlerEnd = GetInstructionEnd(cilInstructions, reader.ReadInt32());
if (eh.HandlerType == ExceptionHandlerType.Catch) if (eh.HandlerType == ExceptionHandlerType.Catch)
eh.CatchType = module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; eh.CatchType = module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
else if (eh.HandlerType == ExceptionHandlerType.Filter) else if (eh.HandlerType == ExceptionHandlerType.Filter)
eh.FilterStart = getInstruction(cilInstructions, reader.ReadInt32()); eh.FilterStart = GetInstruction(cilInstructions, reader.ReadInt32());
ehs.Add(eh); ehs.Add(eh);
} }
@ -317,44 +317,44 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
return ehs; return ehs;
} }
static Instruction getInstruction(IList<Instruction> instrs, int index) { static Instruction GetInstruction(IList<Instruction> instrs, int index) {
return instrs[index]; return instrs[index];
} }
static Instruction getInstructionEnd(IList<Instruction> instrs, int index) { static Instruction GetInstructionEnd(IList<Instruction> instrs, int index) {
index++; index++;
if (index == instrs.Count) if (index == instrs.Count)
return null; return null;
return instrs[index]; return instrs[index];
} }
static Instruction getInstruction(IList<Instruction> instrs, Instruction source, int displ) { static Instruction GetInstruction(IList<Instruction> instrs, Instruction source, int displ) {
int sourceIndex = instrs.IndexOf(source); int sourceIndex = instrs.IndexOf(source);
if (sourceIndex < 0) if (sourceIndex < 0)
throw new ApplicationException("Could not find source instruction"); throw new ApplicationException("Could not find source instruction");
return instrs[sourceIndex + displ]; return instrs[sourceIndex + displ];
} }
void fixInstructionOperands(IList<Instruction> instrs) { void FixInstructionOperands(IList<Instruction> instrs) {
foreach (var instr in instrs) { foreach (var instr in instrs) {
var op = instr.Operand as IVmOperand; var op = instr.Operand as IVmOperand;
if (op != null) if (op != null)
instr.Operand = fixOperand(instrs, instr, op); instr.Operand = FixOperand(instrs, instr, op);
} }
} }
object fixOperand(IList<Instruction> instrs, Instruction instr, IVmOperand vmOperand) { object FixOperand(IList<Instruction> instrs, Instruction instr, IVmOperand vmOperand) {
if (vmOperand is TokenOperand) if (vmOperand is TokenOperand)
return getMemberRef(((TokenOperand)vmOperand).token); return GetMemberRef(((TokenOperand)vmOperand).token);
if (vmOperand is TargetDisplOperand) if (vmOperand is TargetDisplOperand)
return getInstruction(instrs, instr, ((TargetDisplOperand)vmOperand).displacement); return GetInstruction(instrs, instr, ((TargetDisplOperand)vmOperand).displacement);
if (vmOperand is SwitchTargetDisplOperand) { if (vmOperand is SwitchTargetDisplOperand) {
var targetDispls = ((SwitchTargetDisplOperand)vmOperand).targetDisplacements; var targetDispls = ((SwitchTargetDisplOperand)vmOperand).targetDisplacements;
Instruction[] targets = new Instruction[targetDispls.Length]; Instruction[] targets = new Instruction[targetDispls.Length];
for (int i = 0; i < targets.Length; i++) for (int i = 0; i < targets.Length; i++)
targets[i] = getInstruction(instrs, instr, targetDispls[i]); targets[i] = GetInstruction(instrs, instr, targetDispls[i]);
return targets; return targets;
} }
@ -362,20 +362,20 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
return vmOperand; return vmOperand;
if (vmOperand is LoadFieldOperand) if (vmOperand is LoadFieldOperand)
return fixLoadStoreFieldInstruction(instr, ((LoadFieldOperand)vmOperand).token, OpCodes.Ldsfld, OpCodes.Ldfld); return FixLoadStoreFieldInstruction(instr, ((LoadFieldOperand)vmOperand).token, OpCodes.Ldsfld, OpCodes.Ldfld);
if (vmOperand is LoadFieldAddressOperand) if (vmOperand is LoadFieldAddressOperand)
return fixLoadStoreFieldInstruction(instr, ((LoadFieldAddressOperand)vmOperand).token, OpCodes.Ldsflda, OpCodes.Ldflda); return FixLoadStoreFieldInstruction(instr, ((LoadFieldAddressOperand)vmOperand).token, OpCodes.Ldsflda, OpCodes.Ldflda);
if (vmOperand is StoreFieldOperand) if (vmOperand is StoreFieldOperand)
return fixLoadStoreFieldInstruction(instr, ((StoreFieldOperand)vmOperand).token, OpCodes.Stsfld, OpCodes.Stfld); return FixLoadStoreFieldInstruction(instr, ((StoreFieldOperand)vmOperand).token, OpCodes.Stsfld, OpCodes.Stfld);
throw new ApplicationException(string.Format("Unknown operand type: {0}", vmOperand.GetType())); throw new ApplicationException(string.Format("Unknown operand type: {0}", vmOperand.GetType()));
} }
IField fixLoadStoreFieldInstruction(Instruction instr, int token, OpCode staticInstr, OpCode instanceInstr) { IField FixLoadStoreFieldInstruction(Instruction instr, int token, OpCode staticInstr, OpCode instanceInstr) {
var fieldRef = module.ResolveToken(token) as IField; var fieldRef = module.ResolveToken(token) as IField;
var field = deobfuscatorContext.resolveField(fieldRef); var field = deobfuscatorContext.ResolveField(fieldRef);
bool isStatic; bool isStatic;
if (field == null) { if (field == null) {
Logger.w("Could not resolve field {0:X8}. Assuming it's not static.", token); Logger.w("Could not resolve field {0:X8}. Assuming it's not static.", token);
@ -387,14 +387,14 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
return fieldRef; return fieldRef;
} }
ITokenOperand getMemberRef(int token) { ITokenOperand GetMemberRef(int token) {
var memberRef = module.ResolveToken(token) as ITokenOperand; var memberRef = module.ResolveToken(token) as ITokenOperand;
if (memberRef == null) if (memberRef == null)
throw new ApplicationException(string.Format("Could not find member ref: {0:X8}", token)); throw new ApplicationException(string.Format("Could not find member ref: {0:X8}", token));
return memberRef; return memberRef;
} }
static void restoreConstrainedPrefix(MethodDef method) { static void RestoreConstrainedPrefix(MethodDef method) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return; return;
@ -410,17 +410,17 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
var sig = calledMethod.MethodSig; var sig = calledMethod.MethodSig;
if (sig == null || !sig.HasThis) if (sig == null || !sig.HasThis)
continue; continue;
var thisType = MethodStack.getLoadedType(method, instrs, i, sig.Params.Count) as ByRefSig; var thisType = MethodStack.GetLoadedType(method, instrs, i, sig.Params.Count) as ByRefSig;
if (thisType == null) if (thisType == null)
continue; continue;
if (hasPrefix(instrs, i, Code.Constrained)) if (HasPrefix(instrs, i, Code.Constrained))
continue; continue;
instrs.Insert(i, OpCodes.Constrained.ToInstruction(thisType.Next.ToTypeDefOrRef())); instrs.Insert(i, OpCodes.Constrained.ToInstruction(thisType.Next.ToTypeDefOrRef()));
i++; i++;
} }
} }
static bool hasPrefix(IList<Instruction> instrs, int index, Code prefix) { static bool HasPrefix(IList<Instruction> instrs, int index, Code prefix) {
index--; index--;
for (; index >= 0; index--) { for (; index >= 0; index--) {
var instr = instrs[index]; var instr = instrs[index];

View File

@ -35,36 +35,36 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
foreach (var field in fields) { foreach (var field in fields) {
var fieldTypeDef = field.FieldSig.GetFieldType().TryGetTypeDef(); var fieldTypeDef = field.FieldSig.GetFieldType().TryGetTypeDef();
if (fieldTypeDef != null && fieldTypeDef.IsEnum) if (fieldTypeDef != null && fieldTypeDef.IsEnum)
addEnum(); AddEnum();
else else
add(field.FieldSig.GetFieldType()); Add(field.FieldSig.GetFieldType());
} }
} }
public FieldsInfo(object[] fieldTypes) { public FieldsInfo(object[] fieldTypes) {
foreach (var o in fieldTypes) { foreach (var o in fieldTypes) {
if (o == EnumType) if (o == EnumType)
addEnum(); AddEnum();
else else
add((string)o); Add((string)o);
} }
} }
void add(TypeSig type) { void Add(TypeSig type) {
add(type.GetFullName()); Add(type.GetFullName());
} }
void add(string typeFullName) { void Add(string typeFullName) {
int count; int count;
fieldTypes.TryGetValue(typeFullName, out count); fieldTypes.TryGetValue(typeFullName, out count);
fieldTypes[typeFullName] = count + 1; fieldTypes[typeFullName] = count + 1;
} }
void addEnum() { void AddEnum() {
numEnums++; numEnums++;
} }
public bool isSame(FieldsInfo other) { public bool IsSame(FieldsInfo other) {
if (numEnums != other.numEnums) if (numEnums != other.numEnums)
return false; return false;
if (fieldTypes.Count != other.fieldTypes.Count) if (fieldTypes.Count != other.fieldTypes.Count)

View File

@ -31,24 +31,24 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
public Predicate<UnknownHandlerInfo> Check { get; set; } public Predicate<UnknownHandlerInfo> Check { get; set; }
public Func<BinaryReader, Instruction> Read { get; set; } public Func<BinaryReader, Instruction> Read { get; set; }
public bool detect(UnknownHandlerInfo info) { public bool Detect(UnknownHandlerInfo info) {
var sigInfo = OpCodeHandlerSigInfo; var sigInfo = OpCodeHandlerSigInfo;
if (!compare(sigInfo.NumStaticMethods, info.NumStaticMethods)) if (!Compare(sigInfo.NumStaticMethods, info.NumStaticMethods))
return false; return false;
if (!compare(sigInfo.NumInstanceMethods, info.NumInstanceMethods)) if (!Compare(sigInfo.NumInstanceMethods, info.NumInstanceMethods))
return false; return false;
if (!compare(sigInfo.NumVirtualMethods, info.NumVirtualMethods)) if (!Compare(sigInfo.NumVirtualMethods, info.NumVirtualMethods))
return false; return false;
if (!compare(sigInfo.NumCtors, info.NumCtors)) if (!Compare(sigInfo.NumCtors, info.NumCtors))
return false; return false;
if (!compare(sigInfo.ExecuteMethodThrows, info.ExecuteMethodThrows)) if (!Compare(sigInfo.ExecuteMethodThrows, info.ExecuteMethodThrows))
return false; return false;
if (!compare(sigInfo.ExecuteMethodPops, info.ExecuteMethodPops)) if (!Compare(sigInfo.ExecuteMethodPops, info.ExecuteMethodPops))
return false; return false;
if (!info.hasSameFieldTypes(sigInfo.RequiredFieldTypes)) if (!info.HasSameFieldTypes(sigInfo.RequiredFieldTypes))
return false; return false;
if (sigInfo.ExecuteMethodLocals != null && !new LocalTypes(info.ExecuteMethod).all(sigInfo.ExecuteMethodLocals)) if (sigInfo.ExecuteMethodLocals != null && !new LocalTypes(info.ExecuteMethod).All(sigInfo.ExecuteMethodLocals))
return false; return false;
if (Check != null) if (Check != null)
@ -56,7 +56,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
return true; return true;
} }
static bool compare(int? val1, int val2) { static bool Compare(int? val1, int val2) {
if (!val1.HasValue) if (!val1.HasValue)
return true; return true;
return val1.Value == val2; return val1.Value == val2;
@ -88,7 +88,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
} }
static bool newarr_check(UnknownHandlerInfo info) { static bool newarr_check(UnknownHandlerInfo info) {
return DotNetUtils.callsMethod(info.ExecuteMethod, "System.Type System.Reflection.Module::ResolveType(System.Int32)"); return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Type System.Reflection.Module::ResolveType(System.Int32)");
} }
static Instruction newarr_read(BinaryReader reader) { static Instruction newarr_read(BinaryReader reader) {
@ -286,7 +286,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
} }
static bool endfinally_check(UnknownHandlerInfo info) { static bool endfinally_check(UnknownHandlerInfo info) {
return DotNetUtils.callsMethod(info.ExecuteMethod, "System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags)"); return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags)");
} }
static Instruction endfinally_read(BinaryReader reader) { static Instruction endfinally_read(BinaryReader reader) {
@ -365,7 +365,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
} }
static bool ldtoken_check(UnknownHandlerInfo info) { static bool ldtoken_check(UnknownHandlerInfo info) {
return DotNetUtils.callsMethod(info.ExecuteMethod, "System.Reflection.MemberInfo System.Reflection.Module::ResolveMember(System.Int32)"); return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MemberInfo System.Reflection.Module::ResolveMember(System.Int32)");
} }
static Instruction ldtoken_read(BinaryReader reader) { static Instruction ldtoken_read(BinaryReader reader) {
@ -376,9 +376,9 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
} }
static bool leave_check(UnknownHandlerInfo info) { static bool leave_check(UnknownHandlerInfo info) {
return !DotNetUtils.callsMethod(info.ExecuteMethod, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)") && return !DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)") &&
!DotNetUtils.callsMethod(info.ExecuteMethod, "System.Type System.Reflection.Module::ResolveType(System.Int32)") && !DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Type System.Reflection.Module::ResolveType(System.Int32)") &&
!DotNetUtils.callsMethod(info.ExecuteMethod, "System.Reflection.MemberInfo System.Reflection.Module::ResolveMember(System.Int32)"); !DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MemberInfo System.Reflection.Module::ResolveMember(System.Int32)");
} }
static Instruction leave_read(BinaryReader reader) { static Instruction leave_read(BinaryReader reader) {
@ -435,10 +435,10 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
} }
static bool nop_check(UnknownHandlerInfo info) { static bool nop_check(UnknownHandlerInfo info) {
return isEmptyMethod(info.ReadMethod) && isEmptyMethod(info.ExecuteMethod); return IsEmptyMethod(info.ReadMethod) && IsEmptyMethod(info.ExecuteMethod);
} }
static bool isEmptyMethod(MethodDef method) { static bool IsEmptyMethod(MethodDef method) {
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code == Code.Ret) if (instr.OpCode.Code == Code.Ret)
return true; return true;
@ -453,7 +453,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
} }
static bool ret_check(UnknownHandlerInfo info) { static bool ret_check(UnknownHandlerInfo info) {
return DotNetUtils.callsMethod(info.ExecuteMethod, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)"); return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)");
} }
static Instruction ret_read(BinaryReader reader) { static Instruction ret_read(BinaryReader reader) {
@ -506,7 +506,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
} }
static bool throw_check(UnknownHandlerInfo info) { static bool throw_check(UnknownHandlerInfo info) {
return !DotNetUtils.callsMethod(info.ExecuteMethod, "System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags)"); return !DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags)");
} }
static Instruction throw_read(BinaryReader reader) { static Instruction throw_read(BinaryReader reader) {

Some files were not shown because too many files have changed in this diff Show More