Merge branch 'master' into confuser
This commit is contained in:
commit
08ca871406
|
@ -30,17 +30,17 @@ namespace AssemblyData {
|
|||
List<string> assemblySearchPaths = new List<string>();
|
||||
|
||||
public AssemblyResolver() {
|
||||
AppDomain.CurrentDomain.AssemblyResolve += assemblyResolve;
|
||||
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;
|
||||
}
|
||||
|
||||
void addAssemblySearchPath(string path) {
|
||||
void AddAssemblySearchPath(string path) {
|
||||
if (assemblySearchPathsDict.ContainsKey(path))
|
||||
return;
|
||||
assemblySearchPathsDict[path] = true;
|
||||
assemblySearchPaths.Add(path);
|
||||
}
|
||||
|
||||
Assembly get(string assemblyFullName) {
|
||||
Assembly Get(string assemblyFullName) {
|
||||
var asmName = new AssemblyName(assemblyFullName);
|
||||
|
||||
Assembly assembly;
|
||||
|
@ -53,8 +53,8 @@ namespace AssemblyData {
|
|||
}
|
||||
|
||||
static string[] assemblyExtensions = new string[] { ".dll", ".exe" };
|
||||
Assembly assemblyResolve(object sender, ResolveEventArgs args) {
|
||||
var assembly = get(args.Name);
|
||||
Assembly AssemblyResolve(object sender, ResolveEventArgs args) {
|
||||
var assembly = Get(args.Name);
|
||||
if (assembly != null)
|
||||
return assembly;
|
||||
|
||||
|
@ -65,8 +65,8 @@ namespace AssemblyData {
|
|||
var filename = Path.Combine(path, asmName.Name + ext);
|
||||
if (!new FileInfo(filename).Exists)
|
||||
continue;
|
||||
addConfigFile(filename + ".config");
|
||||
return addAssembly(Assembly.LoadFile(filename));
|
||||
AddConfigFile(filename + ".config");
|
||||
return AddAssembly(Assembly.LoadFile(filename));
|
||||
}
|
||||
catch (IOException) {
|
||||
}
|
||||
|
@ -86,12 +86,12 @@ namespace AssemblyData {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Assembly load(string filename) {
|
||||
addConfigFile(filename + ".config");
|
||||
return addAssembly(loadFile(filename));
|
||||
public Assembly Load(string filename) {
|
||||
AddConfigFile(filename + ".config");
|
||||
return AddAssembly(LoadFile(filename));
|
||||
}
|
||||
|
||||
Assembly loadFile(string filename) {
|
||||
Assembly LoadFile(string filename) {
|
||||
try {
|
||||
return Assembly.LoadFrom(filename);
|
||||
}
|
||||
|
@ -101,16 +101,16 @@ namespace AssemblyData {
|
|||
}
|
||||
}
|
||||
|
||||
Assembly addAssembly(Assembly assembly) {
|
||||
Assembly AddAssembly(Assembly assembly) {
|
||||
var asmName = assembly.GetName();
|
||||
assemblies[asmName.FullName] = assembly;
|
||||
assemblies[asmName.Name] = assembly;
|
||||
return assembly;
|
||||
}
|
||||
|
||||
void addConfigFile(string configFilename) {
|
||||
var dirName = Utils.getDirName(Utils.getFullPath(configFilename));
|
||||
addAssemblySearchPath(dirName);
|
||||
void AddConfigFile(string configFilename) {
|
||||
var dirName = Utils.GetDirName(Utils.GetFullPath(configFilename));
|
||||
AddAssemblySearchPath(dirName);
|
||||
|
||||
try {
|
||||
using (var xmlStream = new FileStream(configFilename, FileMode.Open, FileAccess.Read, FileShare.Read)) {
|
||||
|
@ -124,7 +124,7 @@ namespace AssemblyData {
|
|||
if (string.IsNullOrEmpty(privatePath))
|
||||
continue;
|
||||
foreach (var path in privatePath.Split(';'))
|
||||
addAssemblySearchPath(Path.Combine(dirName, path));
|
||||
AddAssemblySearchPath(Path.Combine(dirName, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,19 +26,19 @@ using AssemblyData;
|
|||
|
||||
namespace AssemblyServer {
|
||||
public static class Start {
|
||||
public static int main(string[] args) {
|
||||
public static int Main2(string[] args) {
|
||||
if (args.Length != 2)
|
||||
Environment.Exit(1);
|
||||
var channelName = args[0];
|
||||
var uri = args[1];
|
||||
|
||||
var service = new AssemblyService();
|
||||
startServer(service, channelName, uri);
|
||||
service.waitExit();
|
||||
StartServer(service, channelName, uri);
|
||||
service.WaitExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void startServer(AssemblyService service, string name, string uri) {
|
||||
static void StartServer(AssemblyService service, string name, string uri) {
|
||||
var props = new Hashtable();
|
||||
props["portName"] = name;
|
||||
var provider = new BinaryServerFormatterSinkProvider();
|
||||
|
|
|
@ -33,14 +33,14 @@ namespace AssemblyData {
|
|||
AssemblyResolver assemblyResolver = new AssemblyResolver();
|
||||
bool installCompileMethodCalled = false;
|
||||
|
||||
public void doNothing() {
|
||||
public void DoNothing() {
|
||||
}
|
||||
|
||||
public void exit() {
|
||||
public void Exit() {
|
||||
exitEvent.Set();
|
||||
}
|
||||
|
||||
public void waitExit() {
|
||||
public void WaitExit() {
|
||||
exitEvent.WaitOne();
|
||||
}
|
||||
|
||||
|
@ -48,28 +48,28 @@ namespace AssemblyData {
|
|||
return null;
|
||||
}
|
||||
|
||||
void checkStringDecrypter() {
|
||||
void CheckStringDecrypter() {
|
||||
if (stringDecrypter == null)
|
||||
throw new ApplicationException("setStringDecrypterType() hasn't been called yet.");
|
||||
}
|
||||
|
||||
void checkAssembly() {
|
||||
void CheckAssembly() {
|
||||
if (assembly == null)
|
||||
throw new ApplicationException("loadAssembly() hasn't been called yet.");
|
||||
}
|
||||
|
||||
public void loadAssembly(string filename) {
|
||||
public void LoadAssembly(string filename) {
|
||||
if (assembly != null)
|
||||
throw new ApplicationException("Only one assembly can be explicitly loaded");
|
||||
try {
|
||||
assembly = assemblyResolver.load(filename);
|
||||
assembly = assemblyResolver.Load(filename);
|
||||
}
|
||||
catch (BadImageFormatException) {
|
||||
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)
|
||||
throw new ApplicationException("StringDecrypterType already set");
|
||||
|
||||
|
@ -87,25 +87,25 @@ namespace AssemblyData {
|
|||
}
|
||||
}
|
||||
|
||||
public int defineStringDecrypter(int methodToken) {
|
||||
checkStringDecrypter();
|
||||
var methodInfo = findMethod(methodToken);
|
||||
public int DefineStringDecrypter(int methodToken) {
|
||||
CheckStringDecrypter();
|
||||
var methodInfo = FindMethod(methodToken);
|
||||
if (methodInfo == null)
|
||||
throw new ApplicationException(string.Format("Could not find method {0:X8}", methodToken));
|
||||
if (methodInfo.ReturnType != typeof(string) && methodInfo.ReturnType != typeof(object))
|
||||
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) {
|
||||
checkStringDecrypter();
|
||||
var caller = getCaller(callerToken);
|
||||
public object[] DecryptStrings(int stringDecrypterMethod, object[] args, int callerToken) {
|
||||
CheckStringDecrypter();
|
||||
var caller = GetCaller(callerToken);
|
||||
foreach (var arg in args)
|
||||
SimpleData.unpack((object[])arg);
|
||||
return SimpleData.pack(stringDecrypter.decryptStrings(stringDecrypterMethod, args, caller));
|
||||
SimpleData.Unpack((object[])arg);
|
||||
return SimpleData.Pack(stringDecrypter.DecryptStrings(stringDecrypterMethod, args, caller));
|
||||
}
|
||||
|
||||
MethodBase getCaller(int callerToken) {
|
||||
MethodBase GetCaller(int callerToken) {
|
||||
try {
|
||||
return assembly.GetModules()[0].ResolveMethod(callerToken);
|
||||
}
|
||||
|
@ -114,8 +114,8 @@ namespace AssemblyData {
|
|||
}
|
||||
}
|
||||
|
||||
MethodInfo findMethod(int methodToken) {
|
||||
checkAssembly();
|
||||
MethodInfo FindMethod(int methodToken) {
|
||||
CheckAssembly();
|
||||
|
||||
foreach (var module in assembly.GetModules()) {
|
||||
var method = module.ResolveMethod(methodToken) as MethodInfo;
|
||||
|
@ -126,28 +126,28 @@ namespace AssemblyData {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void installCompileMethod(DecryptMethodsInfo decryptMethodsInfo) {
|
||||
public void InstallCompileMethod(DecryptMethodsInfo decryptMethodsInfo) {
|
||||
if (installCompileMethodCalled)
|
||||
throw new ApplicationException("installCompileMethod() has already been called");
|
||||
installCompileMethodCalled = true;
|
||||
DynamicMethodsDecrypter.Instance.DecryptMethodsInfo = decryptMethodsInfo;
|
||||
DynamicMethodsDecrypter.Instance.installCompileMethod();
|
||||
DynamicMethodsDecrypter.Instance.InstallCompileMethod();
|
||||
}
|
||||
|
||||
public void loadObfuscator(string filename) {
|
||||
loadAssembly(filename);
|
||||
public void LoadObfuscator(string filename) {
|
||||
LoadAssembly(filename);
|
||||
DynamicMethodsDecrypter.Instance.Module = assembly.ManifestModule;
|
||||
DynamicMethodsDecrypter.Instance.loadObfuscator();
|
||||
DynamicMethodsDecrypter.Instance.LoadObfuscator();
|
||||
}
|
||||
|
||||
public bool canDecryptMethods() {
|
||||
checkAssembly();
|
||||
return DynamicMethodsDecrypter.Instance.canDecryptMethods();
|
||||
public bool CanDecryptMethods() {
|
||||
CheckAssembly();
|
||||
return DynamicMethodsDecrypter.Instance.CanDecryptMethods();
|
||||
}
|
||||
|
||||
public DumpedMethods decryptMethods() {
|
||||
checkAssembly();
|
||||
return DynamicMethodsDecrypter.Instance.decryptMethods();
|
||||
public DumpedMethods DecryptMethods() {
|
||||
CheckAssembly();
|
||||
return DynamicMethodsDecrypter.Instance.DecryptMethods();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,12 +27,12 @@ namespace AssemblyData {
|
|||
delegate string DecryptString(object[] args);
|
||||
List<DecryptString> stringDecryptMethods = new List<DecryptString>();
|
||||
|
||||
public int defineStringDecrypter(MethodInfo method) {
|
||||
stringDecryptMethods.Add(buildDynamicMethod(method));
|
||||
public int DefineStringDecrypter(MethodInfo method) {
|
||||
stringDecryptMethods.Add(BuildDynamicMethod(method));
|
||||
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)
|
||||
throw new ApplicationException("Invalid string decrypter method");
|
||||
|
||||
|
@ -43,9 +43,9 @@ namespace AssemblyData {
|
|||
return rv;
|
||||
}
|
||||
|
||||
DecryptString buildDynamicMethod(MethodInfo method) {
|
||||
DecryptString BuildDynamicMethod(MethodInfo method) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,26 +36,26 @@ namespace AssemblyData {
|
|||
}
|
||||
}
|
||||
|
||||
public int defineStringDecrypter(MethodInfo method) {
|
||||
public int DefineStringDecrypter(MethodInfo method) {
|
||||
decryptInfos.Add(new DecryptInfo(method));
|
||||
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];
|
||||
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];
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
result[i] = decryptInfo.decryptString((object[])args[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
RewrittenMethod createDecryptString(MethodInfo method) {
|
||||
methodsRewriter.createMethod(method);
|
||||
return methodsRewriter.createDelegate(method);
|
||||
RewrittenMethod CreateDecryptString(MethodInfo method) {
|
||||
methodsRewriter.CreateMethod(method);
|
||||
return methodsRewriter.CreateDelegate(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,18 +28,18 @@ namespace AssemblyData {
|
|||
}
|
||||
|
||||
public interface IAssemblyService {
|
||||
void doNothing();
|
||||
void exit();
|
||||
void DoNothing();
|
||||
void Exit();
|
||||
|
||||
void loadAssembly(string filename);
|
||||
void LoadAssembly(string filename);
|
||||
|
||||
void setStringDecrypterType(StringDecrypterType type);
|
||||
int defineStringDecrypter(int methodToken);
|
||||
object[] decryptStrings(int stringDecrypterMethod, object[] args, int callerToken);
|
||||
void SetStringDecrypterType(StringDecrypterType type);
|
||||
int DefineStringDecrypter(int methodToken);
|
||||
object[] DecryptStrings(int stringDecrypterMethod, object[] args, int callerToken);
|
||||
|
||||
void installCompileMethod(DecryptMethodsInfo decryptMethodsInfo);
|
||||
void loadObfuscator(string filename);
|
||||
bool canDecryptMethods();
|
||||
DumpedMethods decryptMethods();
|
||||
void InstallCompileMethod(DecryptMethodsInfo decryptMethodsInfo);
|
||||
void LoadObfuscator(string filename);
|
||||
bool CanDecryptMethods();
|
||||
DumpedMethods DecryptMethods();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ using System.Reflection;
|
|||
|
||||
namespace AssemblyData {
|
||||
interface IStringDecrypter {
|
||||
int defineStringDecrypter(MethodInfo method);
|
||||
object[] decryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller);
|
||||
int DefineStringDecrypter(MethodInfo method);
|
||||
object[] DecryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace AssemblyData {
|
|||
}
|
||||
|
||||
public static class SimpleData {
|
||||
public static object[] pack(object[] args) {
|
||||
public static object[] Pack(object[] args) {
|
||||
for (int i = 0; i < args.Length; i++) {
|
||||
var s = args[i] as string;
|
||||
if (s != null)
|
||||
|
@ -60,7 +60,7 @@ namespace AssemblyData {
|
|||
return args;
|
||||
}
|
||||
|
||||
public static object[] unpack(object[] args) {
|
||||
public static object[] Unpack(object[] args) {
|
||||
for (int i = 0; i < args.Length; i++) {
|
||||
var s = args[i] as MyString;
|
||||
if (s != null)
|
||||
|
|
|
@ -68,11 +68,11 @@ namespace AssemblyData {
|
|||
static class Utils {
|
||||
static Random random = new Random();
|
||||
|
||||
public static uint getRandomUint() {
|
||||
public static uint GetRandomUint() {
|
||||
return (uint)(random.NextDouble() * uint.MaxValue);
|
||||
}
|
||||
|
||||
public static Type getDelegateType(Type returnType, Type[] args) {
|
||||
public static Type GetDelegateType(Type returnType, Type[] args) {
|
||||
Type[] types;
|
||||
if (returnType == typeof(void)) {
|
||||
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);
|
||||
var sb = new StringBuilder(numChars);
|
||||
int numLower = 0;
|
||||
|
@ -153,7 +153,7 @@ namespace AssemblyData {
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static void addCallStringDecrypterMethodInstructions(MethodInfo method, ILGenerator ilg) {
|
||||
public static void AddCallStringDecrypterMethodInstructions(MethodInfo method, ILGenerator ilg) {
|
||||
var args = method.GetParameters();
|
||||
for (int i = 0; i < args.Length; i++) {
|
||||
var arg = args[i].ParameterType;
|
||||
|
@ -171,7 +171,7 @@ namespace AssemblyData {
|
|||
ilg.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
public static string getFullPath(string path) {
|
||||
public static string GetFullPath(string path) {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,10 +35,10 @@ namespace AssemblyData.methodsrewriter {
|
|||
|
||||
public AssemblyResolver(string asmName) {
|
||||
assembly = Assembly.Load(new AssemblyName(asmName));
|
||||
initTypes();
|
||||
InitTypes();
|
||||
}
|
||||
|
||||
void initTypes() {
|
||||
void InitTypes() {
|
||||
foreach (var type in assembly.GetTypes()) {
|
||||
string key = (type.Namespace ?? "") + "." + type.Name;
|
||||
List<TypeResolver> list;
|
||||
|
@ -48,7 +48,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
}
|
||||
|
||||
TypeResolver getTypeResolver(ITypeDefOrRef typeRef) {
|
||||
TypeResolver GetTypeResolver(ITypeDefOrRef typeRef) {
|
||||
if (typeRef == null)
|
||||
return null;
|
||||
var scopeType = typeRef.ScopeType;
|
||||
|
@ -65,30 +65,30 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
|
||||
foreach (var resolver in list) {
|
||||
if (ResolverUtils.compareTypes(resolver.type, scopeType))
|
||||
if (ResolverUtils.CompareTypes(resolver.type, scopeType))
|
||||
return resolver;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public FieldInfo resolve(IField fieldRef) {
|
||||
var resolver = getTypeResolver(fieldRef.DeclaringType);
|
||||
public FieldInfo Resolve(IField fieldRef) {
|
||||
var resolver = GetTypeResolver(fieldRef.DeclaringType);
|
||||
if (resolver != null)
|
||||
return resolver.resolve(fieldRef);
|
||||
return resolveGlobalField(fieldRef);
|
||||
return resolver.Resolve(fieldRef);
|
||||
return ResolveGlobalField(fieldRef);
|
||||
}
|
||||
|
||||
FieldInfo resolveGlobalField(IField fieldRef) {
|
||||
initGlobalFields();
|
||||
FieldInfo ResolveGlobalField(IField fieldRef) {
|
||||
InitGlobalFields();
|
||||
foreach (var globalField in globalFields) {
|
||||
if (ResolverUtils.compareFields(globalField, fieldRef))
|
||||
if (ResolverUtils.CompareFields(globalField, fieldRef))
|
||||
return globalField;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void initGlobalFields() {
|
||||
void InitGlobalFields() {
|
||||
if (globalFields != null)
|
||||
return;
|
||||
globalFields = new List<FieldInfo>();
|
||||
|
@ -100,23 +100,23 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
}
|
||||
|
||||
public MethodBase resolve(IMethod methodRef) {
|
||||
var resolver = getTypeResolver(methodRef.DeclaringType);
|
||||
public MethodBase Resolve(IMethod methodRef) {
|
||||
var resolver = GetTypeResolver(methodRef.DeclaringType);
|
||||
if (resolver != null)
|
||||
return resolver.resolve(methodRef);
|
||||
return resolveGlobalMethod(methodRef);
|
||||
return resolver.Resolve(methodRef);
|
||||
return ResolveGlobalMethod(methodRef);
|
||||
}
|
||||
|
||||
MethodBase resolveGlobalMethod(IMethod methodRef) {
|
||||
initGlobalMethods();
|
||||
MethodBase ResolveGlobalMethod(IMethod methodRef) {
|
||||
InitGlobalMethods();
|
||||
foreach (var globalMethod in globalMethods) {
|
||||
if (ResolverUtils.compareMethods(globalMethod, methodRef))
|
||||
if (ResolverUtils.CompareMethods(globalMethod, methodRef))
|
||||
return globalMethod;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void initGlobalMethods() {
|
||||
void InitGlobalMethods() {
|
||||
if (globalMethods != null)
|
||||
return;
|
||||
globalMethods = new List<MethodBase>();
|
||||
|
@ -128,8 +128,8 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
}
|
||||
|
||||
public Type resolve(ITypeDefOrRef typeRef) {
|
||||
var resolver = getTypeResolver(typeRef);
|
||||
public Type Resolve(ITypeDefOrRef typeRef) {
|
||||
var resolver = GetTypeResolver(typeRef);
|
||||
if (resolver != null)
|
||||
return resolver.type;
|
||||
|
||||
|
|
|
@ -81,14 +81,14 @@ namespace AssemblyData.methodsrewriter {
|
|||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
public void setMethodInfo(MMethod methodInfo) {
|
||||
public void SetMethodInfo(MMethod methodInfo) {
|
||||
this.methodInfo = methodInfo;
|
||||
methodReturnType = ResolverUtils.getReturnType(methodInfo.methodBase);
|
||||
methodParameters = getMethodParameterTypes(methodInfo.methodBase);
|
||||
delegateType = Utils.getDelegateType(methodReturnType, methodParameters);
|
||||
methodReturnType = ResolverUtils.GetReturnType(methodInfo.methodBase);
|
||||
methodParameters = GetMethodParameterTypes(methodInfo.methodBase);
|
||||
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.allExceptionHandlers = allExceptionHandlers;
|
||||
|
||||
|
@ -96,37 +96,37 @@ namespace AssemblyData.methodsrewriter {
|
|||
var lastInstr = allInstructions[allInstructions.Count - 1];
|
||||
ilg = dm.GetILGenerator((int)lastInstr.Offset + lastInstr.GetSize());
|
||||
|
||||
initInstrToIndex();
|
||||
initLocals();
|
||||
initLabels();
|
||||
InitInstrToIndex();
|
||||
InitLocals();
|
||||
InitLabels();
|
||||
|
||||
exceptionHandlersStack = new Stack<ExceptionHandler>();
|
||||
for (int i = 0; i < allInstructions.Count; i++) {
|
||||
updateExceptionHandlers(i);
|
||||
UpdateExceptionHandlers(i);
|
||||
var instr = allInstructions[i];
|
||||
ilg.MarkLabel(labels[i]);
|
||||
if (instr.Operand is Operand)
|
||||
writeSpecialInstr(instr, (Operand)instr.Operand);
|
||||
WriteSpecialInstr(instr, (Operand)instr.Operand);
|
||||
else
|
||||
writeInstr(instr);
|
||||
WriteInstr(instr);
|
||||
}
|
||||
updateExceptionHandlers(-1);
|
||||
UpdateExceptionHandlers(-1);
|
||||
|
||||
return dm.CreateDelegate(delegateType);
|
||||
}
|
||||
|
||||
Instruction getExceptionInstruction(int instructionIndex) {
|
||||
Instruction GetExceptionInstruction(int instructionIndex) {
|
||||
return instructionIndex < 0 ? null : allInstructions[instructionIndex];
|
||||
}
|
||||
|
||||
void updateExceptionHandlers(int instructionIndex) {
|
||||
var instr = getExceptionInstruction(instructionIndex);
|
||||
updateExceptionHandlers(instr);
|
||||
if (addTryStart(instr))
|
||||
updateExceptionHandlers(instr);
|
||||
void UpdateExceptionHandlers(int instructionIndex) {
|
||||
var instr = GetExceptionInstruction(instructionIndex);
|
||||
UpdateExceptionHandlers(instr);
|
||||
if (AddTryStart(instr))
|
||||
UpdateExceptionHandlers(instr);
|
||||
}
|
||||
|
||||
void updateExceptionHandlers(Instruction instr) {
|
||||
void UpdateExceptionHandlers(Instruction instr) {
|
||||
while (exceptionHandlersStack.Count > 0) {
|
||||
var ex = exceptionHandlersStack.Peek();
|
||||
if (ex.TryEnd == instr) {
|
||||
|
@ -137,11 +137,11 @@ namespace AssemblyData.methodsrewriter {
|
|||
if (ex.HandlerType == ExceptionHandlerType.Finally)
|
||||
ilg.BeginFinallyBlock();
|
||||
else
|
||||
ilg.BeginCatchBlock(Resolver.getRtType(ex.CatchType));
|
||||
ilg.BeginCatchBlock(Resolver.GetRtType(ex.CatchType));
|
||||
}
|
||||
if (ex.HandlerEnd == instr) {
|
||||
exceptionHandlersStack.Pop();
|
||||
if (exceptionHandlersStack.Count == 0 || !isSameTryBlock(ex, exceptionHandlersStack.Peek()))
|
||||
if (exceptionHandlersStack.Count == 0 || !IsSameTryBlock(ex, exceptionHandlersStack.Peek()))
|
||||
ilg.EndExceptionBlock();
|
||||
}
|
||||
else
|
||||
|
@ -149,7 +149,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
}
|
||||
|
||||
bool addTryStart(Instruction instr) {
|
||||
bool AddTryStart(Instruction instr) {
|
||||
var list = new List<ExceptionHandler>();
|
||||
foreach (var ex in allExceptionHandlers) {
|
||||
if (ex.TryStart == instr)
|
||||
|
@ -158,7 +158,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
list.Reverse();
|
||||
|
||||
foreach (var ex in list) {
|
||||
if (exceptionHandlersStack.Count == 0 || !isSameTryBlock(ex, exceptionHandlersStack.Peek()))
|
||||
if (exceptionHandlersStack.Count == 0 || !IsSameTryBlock(ex, exceptionHandlersStack.Peek()))
|
||||
ilg.BeginExceptionBlock();
|
||||
exceptionHandlersStack.Push(ex);
|
||||
}
|
||||
|
@ -166,33 +166,33 @@ namespace AssemblyData.methodsrewriter {
|
|||
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;
|
||||
}
|
||||
|
||||
void initInstrToIndex() {
|
||||
void InitInstrToIndex() {
|
||||
instrToIndex = new Dictionary<Instruction, int>(allInstructions.Count);
|
||||
for (int i = 0; i < allInstructions.Count; i++)
|
||||
instrToIndex[allInstructions[i]] = i;
|
||||
}
|
||||
|
||||
void initLocals() {
|
||||
void InitLocals() {
|
||||
locals = new List<LocalBuilder>();
|
||||
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));
|
||||
tempObjArrayLocal = ilg.DeclareLocal(typeof(object[]));
|
||||
}
|
||||
|
||||
void initLabels() {
|
||||
void InitLabels() {
|
||||
labels = new List<Label>(allInstructions.Count);
|
||||
for (int i = 0; i < allInstructions.Count; i++)
|
||||
labels.Add(ilg.DefineLabel());
|
||||
}
|
||||
|
||||
Type[] getMethodParameterTypes(MethodBase method) {
|
||||
Type[] GetMethodParameterTypes(MethodBase method) {
|
||||
var list = new List<Type>();
|
||||
if (ResolverUtils.hasThis(method))
|
||||
if (ResolverUtils.HasThis(method))
|
||||
list.Add(method.DeclaringType);
|
||||
|
||||
foreach (var param in method.GetParameters())
|
||||
|
@ -204,19 +204,19 @@ namespace AssemblyData.methodsrewriter {
|
|||
return list.ToArray();
|
||||
}
|
||||
|
||||
void writeSpecialInstr(Instruction instr, Operand operand) {
|
||||
void WriteSpecialInstr(Instruction instr, Operand operand) {
|
||||
BindingFlags flags;
|
||||
switch (operand.type) {
|
||||
case Operand.Type.ThisArg:
|
||||
ilg.Emit(convertOpCode(instr.OpCode), (short)thisArgIndex);
|
||||
ilg.Emit(ConvertOpCode(instr.OpCode), (short)thisArgIndex);
|
||||
break;
|
||||
|
||||
case Operand.Type.TempObj:
|
||||
ilg.Emit(convertOpCode(instr.OpCode), tempObjLocal);
|
||||
ilg.Emit(ConvertOpCode(instr.OpCode), tempObjLocal);
|
||||
break;
|
||||
|
||||
case Operand.Type.TempObjArray:
|
||||
ilg.Emit(convertOpCode(instr.OpCode), tempObjArrayLocal);
|
||||
ilg.Emit(ConvertOpCode(instr.OpCode), tempObjArrayLocal);
|
||||
break;
|
||||
|
||||
case Operand.Type.OurMethod:
|
||||
|
@ -225,19 +225,19 @@ namespace AssemblyData.methodsrewriter {
|
|||
var ourMethod = methodsRewriter.GetType().GetMethod(methodName, flags);
|
||||
if (ourMethod == null)
|
||||
throw new ApplicationException(string.Format("Could not find method {0}", methodName));
|
||||
ilg.Emit(convertOpCode(instr.OpCode), ourMethod);
|
||||
ilg.Emit(ConvertOpCode(instr.OpCode), ourMethod);
|
||||
break;
|
||||
|
||||
case Operand.Type.NewMethod:
|
||||
var methodBase = (MethodBase)operand.data;
|
||||
var delegateType = methodsRewriter.getDelegateType(methodBase);
|
||||
var delegateType = methodsRewriter.GetDelegateType(methodBase);
|
||||
flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance;
|
||||
var invokeMethod = delegateType.GetMethod("Invoke", flags);
|
||||
ilg.Emit(convertOpCode(instr.OpCode), invokeMethod);
|
||||
ilg.Emit(ConvertOpCode(instr.OpCode), invokeMethod);
|
||||
break;
|
||||
|
||||
case Operand.Type.ReflectionType:
|
||||
ilg.Emit(convertOpCode(instr.OpCode), (Type)operand.data);
|
||||
ilg.Emit(ConvertOpCode(instr.OpCode), (Type)operand.data);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -245,19 +245,19 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
}
|
||||
|
||||
Label getLabel(Instruction target) {
|
||||
Label GetLabel(Instruction target) {
|
||||
return labels[instrToIndex[target]];
|
||||
}
|
||||
|
||||
Label[] getLabels(Instruction[] targets) {
|
||||
Label[] GetLabels(Instruction[] targets) {
|
||||
var labels = new Label[targets.Length];
|
||||
for (int i = 0; i < labels.Length; i++)
|
||||
labels[i] = getLabel(targets[i]);
|
||||
labels[i] = GetLabel(targets[i]);
|
||||
return labels;
|
||||
}
|
||||
|
||||
void writeInstr(Instruction instr) {
|
||||
var opcode = convertOpCode(instr.OpCode);
|
||||
void WriteInstr(Instruction instr) {
|
||||
var opcode = ConvertOpCode(instr.OpCode);
|
||||
switch (instr.OpCode.OperandType) {
|
||||
case OperandType.InlineNone:
|
||||
ilg.Emit(opcode);
|
||||
|
@ -265,11 +265,11 @@ namespace AssemblyData.methodsrewriter {
|
|||
|
||||
case OperandType.InlineBrTarget:
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
ilg.Emit(opcode, getLabel((Instruction)instr.Operand));
|
||||
ilg.Emit(opcode, GetLabel((Instruction)instr.Operand));
|
||||
break;
|
||||
|
||||
case OperandType.InlineSwitch:
|
||||
ilg.Emit(opcode, getLabels((Instruction[])instr.Operand));
|
||||
ilg.Emit(opcode, GetLabels((Instruction[])instr.Operand));
|
||||
break;
|
||||
|
||||
case OperandType.ShortInlineI:
|
||||
|
@ -303,7 +303,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
case OperandType.InlineType:
|
||||
case OperandType.InlineMethod:
|
||||
case OperandType.InlineField:
|
||||
var obj = Resolver.getRtObject((ITokenOperand)instr.Operand);
|
||||
var obj = Resolver.GetRtObject((ITokenOperand)instr.Operand);
|
||||
if (obj is ConstructorInfo)
|
||||
ilg.Emit(opcode, (ConstructorInfo)obj);
|
||||
else if (obj is MethodInfo)
|
||||
|
@ -330,7 +330,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
}
|
||||
|
||||
ROpCode convertOpCode(OpCode opcode) {
|
||||
ROpCode ConvertOpCode(OpCode opcode) {
|
||||
ROpCode ropcode;
|
||||
if (dnlibToReflection.TryGetValue(opcode, out ropcode))
|
||||
return ropcode;
|
||||
|
|
|
@ -22,6 +22,6 @@ using System.Reflection;
|
|||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
interface IMethodsRewriter {
|
||||
Type getDelegateType(MethodBase methodBase);
|
||||
Type GetDelegateType(MethodBase methodBase);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
this.methodDef = methodDef;
|
||||
}
|
||||
|
||||
public bool hasInstructions() {
|
||||
public bool HasInstructions() {
|
||||
return methodDef.Body != null && methodDef.Body.Instructions.Count != 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,10 +36,10 @@ namespace AssemblyData.methodsrewriter {
|
|||
public MModule(Module module, ModuleDefMD moduleDef) {
|
||||
this.module = module;
|
||||
this.moduleDef = moduleDef;
|
||||
initTokenToType();
|
||||
InitTokenToType();
|
||||
}
|
||||
|
||||
void initTokenToType() {
|
||||
void InitTokenToType() {
|
||||
moduleType = moduleDef.Types[0];
|
||||
foreach (var typeDef in moduleDef.GetTypes()) {
|
||||
int token = (int)typeDef.MDToken.Raw;
|
||||
|
@ -49,27 +49,27 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
catch {
|
||||
tokenToType[token] = null;
|
||||
typeRefToType.add(typeDef, null);
|
||||
typeRefToType.Add(typeDef, null);
|
||||
continue;
|
||||
}
|
||||
var mtype = new MType(type, typeDef);
|
||||
tokenToType[token] = mtype;
|
||||
typeRefToType.add(typeDef, mtype);
|
||||
typeRefToType.Add(typeDef, mtype);
|
||||
}
|
||||
}
|
||||
|
||||
public MType getType(IType typeRef) {
|
||||
return typeRefToType.find(typeRef);
|
||||
public MType GetType(IType typeRef) {
|
||||
return typeRefToType.Find(typeRef);
|
||||
}
|
||||
|
||||
public MMethod getMethod(IMethod methodRef) {
|
||||
var type = getType(methodRef.DeclaringType);
|
||||
public MMethod GetMethod(IMethod methodRef) {
|
||||
var type = GetType(methodRef.DeclaringType);
|
||||
if (type != null)
|
||||
return type.getMethod(methodRef);
|
||||
return type.GetMethod(methodRef);
|
||||
if (!new SigComparer().Equals(moduleType, methodRef.DeclaringType))
|
||||
return null;
|
||||
|
||||
initGlobalMethods();
|
||||
InitGlobalMethods();
|
||||
foreach (var method in tokenToGlobalMethod.Values) {
|
||||
if (new SigComparer().Equals(methodRef, method.methodDef))
|
||||
return method;
|
||||
|
@ -78,14 +78,14 @@ namespace AssemblyData.methodsrewriter {
|
|||
return null;
|
||||
}
|
||||
|
||||
public MField getField(IField fieldRef) {
|
||||
var type = getType(fieldRef.DeclaringType);
|
||||
public MField GetField(IField fieldRef) {
|
||||
var type = GetType(fieldRef.DeclaringType);
|
||||
if (type != null)
|
||||
return type.getField(fieldRef);
|
||||
return type.GetField(fieldRef);
|
||||
if (!new SigComparer().Equals(moduleType, fieldRef.DeclaringType))
|
||||
return null;
|
||||
|
||||
initGlobalFields();
|
||||
InitGlobalFields();
|
||||
foreach (var field in tokenToGlobalField.Values) {
|
||||
if (new SigComparer().Equals(fieldRef, field.fieldDef))
|
||||
return field;
|
||||
|
@ -94,21 +94,21 @@ namespace AssemblyData.methodsrewriter {
|
|||
return null;
|
||||
}
|
||||
|
||||
public MMethod getMethod(MethodBase method) {
|
||||
public MMethod GetMethod(MethodBase method) {
|
||||
if (method.Module != module)
|
||||
throw new ApplicationException("Not our module");
|
||||
if (method.DeclaringType == null)
|
||||
return getGlobalMethod(method);
|
||||
return GetGlobalMethod(method);
|
||||
var type = tokenToType[method.DeclaringType.MetadataToken];
|
||||
return type.getMethod(method.MetadataToken);
|
||||
return type.GetMethod(method.MetadataToken);
|
||||
}
|
||||
|
||||
public MMethod getGlobalMethod(MethodBase method) {
|
||||
initGlobalMethods();
|
||||
public MMethod GetGlobalMethod(MethodBase method) {
|
||||
InitGlobalMethods();
|
||||
return tokenToGlobalMethod[method.MetadataToken];
|
||||
}
|
||||
|
||||
void initGlobalMethods() {
|
||||
void InitGlobalMethods() {
|
||||
if (tokenToGlobalMethod != null)
|
||||
return;
|
||||
tokenToGlobalMethod = new Dictionary<int, MMethod>();
|
||||
|
@ -125,7 +125,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
}
|
||||
|
||||
void initGlobalFields() {
|
||||
void InitGlobalFields() {
|
||||
if (tokenToGlobalField != null)
|
||||
return;
|
||||
tokenToGlobalField = new Dictionary<int, MField>();
|
||||
|
|
|
@ -37,27 +37,27 @@ namespace AssemblyData.methodsrewriter {
|
|||
this.typeDef = typeDef;
|
||||
}
|
||||
|
||||
public MMethod getMethod(IMethod methodRef) {
|
||||
initMethods();
|
||||
return methodRefToMethod.find(methodRef);
|
||||
public MMethod GetMethod(IMethod methodRef) {
|
||||
InitMethods();
|
||||
return methodRefToMethod.Find(methodRef);
|
||||
}
|
||||
|
||||
public MField getField(IField fieldRef) {
|
||||
initFields();
|
||||
return fieldRefToField.find(fieldRef);
|
||||
public MField GetField(IField fieldRef) {
|
||||
InitFields();
|
||||
return fieldRefToField.Find(fieldRef);
|
||||
}
|
||||
|
||||
public MMethod getMethod(int token) {
|
||||
initMethods();
|
||||
public MMethod GetMethod(int token) {
|
||||
InitMethods();
|
||||
return tokenToMethod[token];
|
||||
}
|
||||
|
||||
public MField getField(int token) {
|
||||
initFields();
|
||||
public MField GetField(int token) {
|
||||
InitFields();
|
||||
return tokenToField[token];
|
||||
}
|
||||
|
||||
void initMethods() {
|
||||
void InitMethods() {
|
||||
if (tokenToMethod != null)
|
||||
return;
|
||||
tokenToMethod = new Dictionary<int, MMethod>(typeDef.Methods.Count);
|
||||
|
@ -65,17 +65,17 @@ namespace AssemblyData.methodsrewriter {
|
|||
|
||||
var tmpTokenToMethod = new Dictionary<int, MethodBase>();
|
||||
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;
|
||||
foreach (var m in typeDef.Methods) {
|
||||
var token = (int)m.MDToken.Raw;
|
||||
var method = new MMethod(tmpTokenToMethod[token], m);
|
||||
tokenToMethod[token] = method;
|
||||
methodRefToMethod.add(method.methodDef, method);
|
||||
methodRefToMethod.Add(method.methodDef, method);
|
||||
}
|
||||
}
|
||||
|
||||
void initFields() {
|
||||
void InitFields() {
|
||||
if (tokenToField != null)
|
||||
return;
|
||||
tokenToField = new Dictionary<int, MField>(typeDef.Fields.Count);
|
||||
|
@ -89,7 +89,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
var token = (int)f.MDToken.Raw;
|
||||
var field = new MField(tmpTokenToField[token], f);
|
||||
tokenToField[token] = field;
|
||||
fieldRefToField.add(field.fieldDef, field);
|
||||
fieldRefToField.Add(field.fieldDef, field);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,16 +62,16 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
}
|
||||
|
||||
public MethodBase getNext() {
|
||||
public MethodBase GetNext() {
|
||||
return methods[next++ % methods.Count];
|
||||
}
|
||||
}
|
||||
|
||||
public MethodBase getMethod(Module module) {
|
||||
public MethodBase GetMethod(Module module) {
|
||||
MethodsModule methodsModule;
|
||||
if (!moduleToMethods.TryGetValue(module, out methodsModule))
|
||||
moduleToMethods[module] = methodsModule = new MethodsModule(module);
|
||||
return methodsModule.getNext();
|
||||
return methodsModule.GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,20 +112,20 @@ namespace AssemblyData.methodsrewriter {
|
|||
this.rewrittenMethodName = rewrittenMethodName;
|
||||
}
|
||||
|
||||
public bool isRewrittenMethod(string name) {
|
||||
public bool IsRewrittenMethod(string name) {
|
||||
return name == rewrittenMethodName;
|
||||
}
|
||||
|
||||
public bool isDelegateMethod(string name) {
|
||||
public bool IsDelegateMethod(string name) {
|
||||
return name == delegateMethodName;
|
||||
}
|
||||
}
|
||||
|
||||
public Type getDelegateType(MethodBase methodBase) {
|
||||
public Type GetDelegateType(MethodBase methodBase) {
|
||||
return realMethodToNewMethod[methodBase].delegateType;
|
||||
}
|
||||
|
||||
public RewrittenMethod createDelegate(MethodBase realMethod) {
|
||||
public RewrittenMethod CreateDelegate(MethodBase realMethod) {
|
||||
var newMethodInfo = realMethodToNewMethod[realMethod];
|
||||
if (newMethodInfo.rewrittenMethod != null)
|
||||
return newMethodInfo.rewrittenMethod;
|
||||
|
@ -135,7 +135,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
|
||||
ilg.Emit(ROpCodes.Ldarg_0);
|
||||
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);
|
||||
|
||||
var args = newMethodInfo.oldMethod.GetParameters();
|
||||
|
@ -156,7 +156,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
var flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance;
|
||||
var invokeMethod = newMethodInfo.delegateType.GetMethod("Invoke", flags);
|
||||
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.Ret);
|
||||
|
||||
|
@ -164,50 +164,50 @@ namespace AssemblyData.methodsrewriter {
|
|||
return newMethodInfo.rewrittenMethod;
|
||||
}
|
||||
|
||||
public void setCaller(RewrittenMethod rewrittenMethod, MethodBase caller) {
|
||||
public void SetCaller(RewrittenMethod rewrittenMethod, MethodBase caller) {
|
||||
if (caller == null)
|
||||
return;
|
||||
var newMethodInfo = getNewMethodInfo(rewrittenMethod.Method.Name);
|
||||
var newMethodInfo = GetNewMethodInfo(rewrittenMethod.Method.Name);
|
||||
newStackMethodDict[newMethodInfo] = caller;
|
||||
}
|
||||
|
||||
string getDelegateMethodName(MethodBase method) {
|
||||
string GetDelegateMethodName(MethodBase method) {
|
||||
string name = null;
|
||||
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));
|
||||
return name;
|
||||
}
|
||||
|
||||
public void createMethod(MethodBase realMethod) {
|
||||
public void CreateMethod(MethodBase realMethod) {
|
||||
if (realMethodToNewMethod.ContainsKey(realMethod))
|
||||
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);
|
||||
delegateNameToNewMethodInfo[newMethodInfo.delegateMethodName] = newMethodInfo;
|
||||
delegateNameToNewMethodInfo[newMethodInfo.rewrittenMethodName] = newMethodInfo;
|
||||
realMethodToNewMethod[realMethod] = newMethodInfo;
|
||||
|
||||
var moduleInfo = Resolver.loadAssembly(realMethod.Module);
|
||||
var methodInfo = moduleInfo.getMethod(realMethod);
|
||||
if (!methodInfo.hasInstructions())
|
||||
var moduleInfo = Resolver.LoadAssembly(realMethod.Module);
|
||||
var methodInfo = moduleInfo.GetMethod(realMethod);
|
||||
if (!methodInfo.HasInstructions())
|
||||
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);
|
||||
codeGenerator.setMethodInfo(methodInfo);
|
||||
codeGenerator.SetMethodInfo(methodInfo);
|
||||
newMethodInfo.delegateType = codeGenerator.DelegateType;
|
||||
|
||||
var blocks = new Blocks(methodInfo.methodDef);
|
||||
foreach (var block in blocks.MethodBlocks.getAllBlocks())
|
||||
update(block, newMethodInfo);
|
||||
foreach (var block in blocks.MethodBlocks.GetAllBlocks())
|
||||
Update(block, newMethodInfo);
|
||||
|
||||
IList<Instruction> allInstructions;
|
||||
IList<ExceptionHandler> allExceptionHandlers;
|
||||
blocks.getCode(out allInstructions, out allExceptionHandlers);
|
||||
newMethodInfo.delegateInstance = codeGenerator.generate(allInstructions, allExceptionHandlers);
|
||||
blocks.GetCode(out allInstructions, out allExceptionHandlers);
|
||||
newMethodInfo.delegateInstance = codeGenerator.Generate(allInstructions, allExceptionHandlers);
|
||||
}
|
||||
|
||||
static Instruction create(OpCode opcode, object operand) {
|
||||
static Instruction Create(OpCode opcode, object operand) {
|
||||
return new Instruction {
|
||||
OpCode = opcode,
|
||||
Operand = operand,
|
||||
|
@ -215,17 +215,17 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
|
||||
// Inserts ldarg THIS, and returns number of instructions inserted at 'i'
|
||||
int insertLoadThis(Block block, int i) {
|
||||
block.insert(i, create(OpCodes.Ldarg, new Operand(Operand.Type.ThisArg)));
|
||||
int InsertLoadThis(Block block, int i) {
|
||||
block.Insert(i, Create(OpCodes.Ldarg, new Operand(Operand.Type.ThisArg)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int insertCallOurMethod(Block block, int i, string methodName) {
|
||||
block.insert(i, create(OpCodes.Call, new Operand(Operand.Type.OurMethod, methodName)));
|
||||
int InsertCallOurMethod(Block block, int i, string methodName) {
|
||||
block.Insert(i, Create(OpCodes.Call, new Operand(Operand.Type.OurMethod, methodName)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void update(Block block, NewMethodInfo currentMethodInfo) {
|
||||
void Update(Block block, NewMethodInfo currentMethodInfo) {
|
||||
var instrs = block.Instructions;
|
||||
for (int i = 0; i < instrs.Count; i++) {
|
||||
var instr = instrs[i];
|
||||
|
@ -233,14 +233,14 @@ namespace AssemblyData.methodsrewriter {
|
|||
var ctor = (IMethod)instr.Operand;
|
||||
var ctorTypeFullName = ctor.DeclaringType.FullName;
|
||||
if (ctorTypeFullName == "System.Diagnostics.StackTrace") {
|
||||
insertLoadThis(block, i + 1);
|
||||
insertCallOurMethod(block, i + 2, "static_rtFixStackTrace");
|
||||
InsertLoadThis(block, i + 1);
|
||||
InsertCallOurMethod(block, i + 2, "static_RtFixStackTrace");
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
else if (ctorTypeFullName == "System.Diagnostics.StackFrame") {
|
||||
insertLoadThis(block, i + 1);
|
||||
insertCallOurMethod(block, i + 2, "static_rtFixStackFrame");
|
||||
InsertLoadThis(block, i + 1);
|
||||
InsertCallOurMethod(block, i + 2, "static_RtFixStackFrame");
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
|
@ -251,67 +251,67 @@ namespace AssemblyData.methodsrewriter {
|
|||
if (calledMethod.DeclaringType.DefinitionAssembly.IsCorLib()) {
|
||||
var calledMethodFullName = calledMethod.FullName;
|
||||
if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetAssembly(System.Type)") {
|
||||
block.replace(i, 1, OpCodes.Nop.ToInstruction());
|
||||
insertLoadThis(block, i + 1);
|
||||
insertCallOurMethod(block, i + 2, "static_rtGetAssembly_TypeArg");
|
||||
block.Replace(i, 1, OpCodes.Nop.ToInstruction());
|
||||
InsertLoadThis(block, i + 1);
|
||||
InsertCallOurMethod(block, i + 2, "static_RtGetAssembly_TypeArg");
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
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::GetExecutingAssembly()") {
|
||||
block.replace(i, 1, OpCodes.Nop.ToInstruction());
|
||||
insertLoadThis(block, i + 1);
|
||||
block.insert(i + 2, OpCodes.Ldc_I4.ToInstruction(currentMethodInfo.delegateIndex));
|
||||
insertCallOurMethod(block, i + 3, "rtGetAssembly");
|
||||
block.Replace(i, 1, OpCodes.Nop.ToInstruction());
|
||||
InsertLoadThis(block, i + 1);
|
||||
block.Insert(i + 2, OpCodes.Ldc_I4.ToInstruction(currentMethodInfo.delegateIndex));
|
||||
InsertCallOurMethod(block, i + 3, "RtGetAssembly");
|
||||
i += 3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var method = Resolver.getMethod((IMethod)instr.Operand);
|
||||
var method = Resolver.GetMethod((IMethod)instr.Operand);
|
||||
if (method != null) {
|
||||
createMethod(method.methodBase);
|
||||
CreateMethod(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;
|
||||
|
||||
// Pop all pushed args to a temp array
|
||||
var mparams = getParameters(method.methodDef);
|
||||
var mparams = GetParameters(method.methodDef);
|
||||
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;
|
||||
block.insert(n++, OpCodes.Newarr.ToInstruction(objectType));
|
||||
block.insert(n++, create(OpCodes.Stloc, new Operand(Operand.Type.TempObjArray)));
|
||||
block.Insert(n++, OpCodes.Newarr.ToInstruction(objectType));
|
||||
block.Insert(n++, Create(OpCodes.Stloc, new Operand(Operand.Type.TempObjArray)));
|
||||
|
||||
for (int j = mparams.Count - 1; j >= 0; j--) {
|
||||
var argType = mparams[j];
|
||||
if (argType.RemovePinnedAndModifiers().IsValueType)
|
||||
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.Ldloc, new Operand(Operand.Type.TempObjArray)));
|
||||
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(j));
|
||||
block.insert(n++, create(OpCodes.Ldloc, new Operand(Operand.Type.TempObj)));
|
||||
block.insert(n++, OpCodes.Stelem_Ref.ToInstruction());
|
||||
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.Ldloc, new Operand(Operand.Type.TempObjArray)));
|
||||
block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(j));
|
||||
block.Insert(n++, Create(OpCodes.Ldloc, new Operand(Operand.Type.TempObj)));
|
||||
block.Insert(n++, OpCodes.Stelem_Ref.ToInstruction());
|
||||
}
|
||||
}
|
||||
|
||||
// Push delegate instance
|
||||
insertLoadThis(block, n++);
|
||||
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(newMethodInfo.delegateIndex));
|
||||
insertCallOurMethod(block, n++, "rtGetDelegateInstance");
|
||||
block.insert(n++, create(OpCodes.Castclass, new Operand(Operand.Type.ReflectionType, newMethodInfo.delegateType)));
|
||||
InsertLoadThis(block, n++);
|
||||
block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(newMethodInfo.delegateIndex));
|
||||
InsertCallOurMethod(block, n++, "RtGetDelegateInstance");
|
||||
block.Insert(n++, Create(OpCodes.Castclass, new Operand(Operand.Type.ReflectionType, newMethodInfo.delegateType)));
|
||||
|
||||
// Push all popped args
|
||||
if (mparams.Count > 0) {
|
||||
for (int j = 0; j < mparams.Count; j++) {
|
||||
block.insert(n++, create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray)));
|
||||
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(j));
|
||||
block.insert(n++, OpCodes.Ldelem_Ref.ToInstruction());
|
||||
block.Insert(n++, Create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray)));
|
||||
block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(j));
|
||||
block.Insert(n++, OpCodes.Ldelem_Ref.ToInstruction());
|
||||
var argType = mparams[j];
|
||||
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 {
|
||||
// Don't cast it to its correct type. This will sometimes cause
|
||||
// an exception in some EF obfuscated assembly since we'll be
|
||||
|
@ -322,8 +322,8 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
}
|
||||
|
||||
insertLoadThis(block, n++);
|
||||
block.insert(n++, create(OpCodes.Call, new Operand(Operand.Type.NewMethod, method.methodBase)));
|
||||
InsertLoadThis(block, n++);
|
||||
block.Insert(n++, Create(OpCodes.Call, new Operand(Operand.Type.NewMethod, method.methodBase)));
|
||||
i = n - 1;
|
||||
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);
|
||||
for (int i = 0; i < method.Parameters.Count; i++)
|
||||
list.Add(method.Parameters[i].Type);
|
||||
return list;
|
||||
}
|
||||
|
||||
static FieldInfo getStackTraceStackFramesField() {
|
||||
static FieldInfo GgetStackTraceStackFramesField() {
|
||||
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;
|
||||
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) {
|
||||
var methodField = getStackFrameMethodField();
|
||||
static void WriteMethodBase(StackFrame frame, MethodBase method) {
|
||||
var methodField = GetStackFrameMethodField();
|
||||
methodField.SetValue(frame, method);
|
||||
if (frame.GetMethod() != method)
|
||||
throw new ApplicationException(string.Format("Could not set new method: {0}", method));
|
||||
}
|
||||
|
||||
NewMethodInfo getNewMethodInfo(string name) {
|
||||
NewMethodInfo GetNewMethodInfo(string name) {
|
||||
NewMethodInfo info;
|
||||
delegateNameToNewMethodInfo.TryGetValue(name, out info);
|
||||
return info;
|
||||
}
|
||||
|
||||
// Called after the StackTrace ctor has been called.
|
||||
static StackTrace static_rtFixStackTrace(StackTrace stackTrace, MethodsRewriter self) {
|
||||
return self.rtFixStackTrace(stackTrace);
|
||||
static StackTrace static_RtFixStackTrace(StackTrace stackTrace, MethodsRewriter self) {
|
||||
return self.RtFixStackTrace(stackTrace);
|
||||
}
|
||||
|
||||
StackTrace rtFixStackTrace(StackTrace stackTrace) {
|
||||
var framesField = getStackTraceStackFramesField();
|
||||
StackTrace RtFixStackTrace(StackTrace stackTrace) {
|
||||
var framesField = GgetStackTraceStackFramesField();
|
||||
var frames = (StackFrame[])framesField.GetValue(stackTrace);
|
||||
|
||||
var newFrames = new List<StackFrame>(frames.Length);
|
||||
foreach (var frame in frames) {
|
||||
fixStackFrame(frame);
|
||||
FixStackFrame(frame);
|
||||
newFrames.Add(frame);
|
||||
}
|
||||
|
||||
|
@ -380,52 +380,52 @@ namespace AssemblyData.methodsrewriter {
|
|||
return stackTrace;
|
||||
}
|
||||
|
||||
static StackFrame static_rtFixStackFrame(StackFrame stackFrame, MethodsRewriter self) {
|
||||
return self.rtFixStackFrame(stackFrame);
|
||||
static StackFrame static_RtFixStackFrame(StackFrame stackFrame, MethodsRewriter self) {
|
||||
return self.RtFixStackFrame(stackFrame);
|
||||
}
|
||||
|
||||
StackFrame rtFixStackFrame(StackFrame frame) {
|
||||
fixStackFrame(frame);
|
||||
StackFrame RtFixStackFrame(StackFrame frame) {
|
||||
FixStackFrame(frame);
|
||||
return frame;
|
||||
}
|
||||
|
||||
void fixStackFrame(StackFrame frame) {
|
||||
void FixStackFrame(StackFrame frame) {
|
||||
var method = frame.GetMethod();
|
||||
var info = getNewMethodInfo(method.Name);
|
||||
var info = GetNewMethodInfo(method.Name);
|
||||
if (info == null)
|
||||
return;
|
||||
|
||||
MethodBase 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
|
||||
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
|
||||
writeMethodBase(frame, info.oldMethod);
|
||||
WriteMethodBase(frame, info.oldMethod);
|
||||
}
|
||||
else
|
||||
throw new ApplicationException("BUG: Shouldn't be here");
|
||||
}
|
||||
|
||||
// Called when the code calls GetCallingAssembly(), GetEntryAssembly(), or GetExecutingAssembly()
|
||||
Assembly rtGetAssembly(int delegateIndex) {
|
||||
Assembly RtGetAssembly(int delegateIndex) {
|
||||
return newMethodInfos[delegateIndex].oldMethod.Module.Assembly;
|
||||
}
|
||||
|
||||
// Called when the code calls GetAssembly(Type)
|
||||
static Assembly static_rtGetAssembly_TypeArg(Type type, MethodsRewriter self) {
|
||||
return self.rtGetAssembly_TypeArg(type);
|
||||
static Assembly static_RtGetAssembly_TypeArg(Type type, MethodsRewriter self) {
|
||||
return self.RtGetAssembly_TypeArg(type);
|
||||
}
|
||||
|
||||
Assembly rtGetAssembly_TypeArg(Type type) {
|
||||
Assembly RtGetAssembly_TypeArg(Type type) {
|
||||
return Assembly.GetAssembly(type);
|
||||
}
|
||||
|
||||
Delegate rtGetDelegateInstance(int delegateIndex) {
|
||||
Delegate RtGetDelegateInstance(int delegateIndex) {
|
||||
return newMethodInfos[delegateIndex].delegateInstance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
static Dictionary<string, AssemblyResolver> assemblyResolvers = new Dictionary<string, AssemblyResolver>(StringComparer.Ordinal);
|
||||
static Dictionary<Module, MModule> modules = new Dictionary<Module, MModule>();
|
||||
|
||||
public static MModule loadAssembly(Module module) {
|
||||
public static MModule LoadAssembly(Module module) {
|
||||
MModule info;
|
||||
if (modules.TryGetValue(module, out info))
|
||||
return info;
|
||||
|
@ -38,7 +38,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
return info;
|
||||
}
|
||||
|
||||
static MModule getModule(ModuleDef moduleDef) {
|
||||
static MModule GetModule(ModuleDef moduleDef) {
|
||||
foreach (var mm in modules.Values) {
|
||||
if (mm.moduleDef == moduleDef)
|
||||
return mm;
|
||||
|
@ -46,7 +46,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
return null;
|
||||
}
|
||||
|
||||
static MModule getModule(AssemblyRef asmRef) {
|
||||
static MModule GetModule(AssemblyRef asmRef) {
|
||||
foreach (var mm in modules.Values) {
|
||||
var asm = mm.moduleDef.Assembly;
|
||||
if (asm != null && asm.FullName == asmRef.FullName)
|
||||
|
@ -55,83 +55,83 @@ namespace AssemblyData.methodsrewriter {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static MModule getModule(IScope scope) {
|
||||
public static MModule GetModule(IScope scope) {
|
||||
if (scope.ScopeType == ScopeType.ModuleDef)
|
||||
return getModule((ModuleDef)scope);
|
||||
return GetModule((ModuleDef)scope);
|
||||
else if (scope.ScopeType == ScopeType.AssemblyRef)
|
||||
return getModule((AssemblyRef)scope);
|
||||
return GetModule((AssemblyRef)scope);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MType getType(IType typeRef) {
|
||||
public static MType GetType(IType typeRef) {
|
||||
if (typeRef == null)
|
||||
return null;
|
||||
var module = getModule(typeRef.Scope);
|
||||
var module = GetModule(typeRef.Scope);
|
||||
if (module != null)
|
||||
return module.getType(typeRef);
|
||||
return module.GetType(typeRef);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MMethod getMethod(IMethod methodRef) {
|
||||
public static MMethod GetMethod(IMethod methodRef) {
|
||||
if (methodRef == null)
|
||||
return null;
|
||||
var module = getModule(methodRef.DeclaringType.Scope);
|
||||
var module = GetModule(methodRef.DeclaringType.Scope);
|
||||
if (module != null)
|
||||
return module.getMethod(methodRef);
|
||||
return module.GetMethod(methodRef);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MField getField(IField fieldRef) {
|
||||
public static MField GetField(IField fieldRef) {
|
||||
if (fieldRef == null)
|
||||
return null;
|
||||
var module = getModule(fieldRef.DeclaringType.Scope);
|
||||
var module = GetModule(fieldRef.DeclaringType.Scope);
|
||||
if (module != null)
|
||||
return module.getField(fieldRef);
|
||||
return module.GetField(fieldRef);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static object getRtObject(ITokenOperand memberRef) {
|
||||
public static object GetRtObject(ITokenOperand memberRef) {
|
||||
if (memberRef == null)
|
||||
return null;
|
||||
var tdr = memberRef as ITypeDefOrRef;
|
||||
if (tdr != null)
|
||||
return getRtType(tdr);
|
||||
return GetRtType(tdr);
|
||||
var field = memberRef as IField;
|
||||
if (field != null && field.FieldSig != null)
|
||||
return getRtField(field);
|
||||
return GetRtField(field);
|
||||
var method = memberRef as IMethod;
|
||||
if (method != null && method.MethodSig != null)
|
||||
return getRtMethod(method);
|
||||
return GetRtMethod(method);
|
||||
|
||||
throw new ApplicationException(string.Format("Unknown MemberRef: {0}", memberRef));
|
||||
}
|
||||
|
||||
public static Type getRtType(IType typeRef) {
|
||||
var mtype = getType(typeRef);
|
||||
public static Type GetRtType(IType typeRef) {
|
||||
var mtype = GetType(typeRef);
|
||||
if (mtype != null)
|
||||
return mtype.type;
|
||||
|
||||
return Resolver.resolve(typeRef);
|
||||
return Resolver.Resolve(typeRef);
|
||||
}
|
||||
|
||||
public static FieldInfo getRtField(IField fieldRef) {
|
||||
var mfield = getField(fieldRef);
|
||||
public static FieldInfo GetRtField(IField fieldRef) {
|
||||
var mfield = GetField(fieldRef);
|
||||
if (mfield != null)
|
||||
return mfield.fieldInfo;
|
||||
|
||||
return Resolver.resolve(fieldRef);
|
||||
return Resolver.Resolve(fieldRef);
|
||||
}
|
||||
|
||||
public static MethodBase getRtMethod(IMethod methodRef) {
|
||||
var mmethod = getMethod(methodRef);
|
||||
public static MethodBase GetRtMethod(IMethod methodRef) {
|
||||
var mmethod = GetMethod(methodRef);
|
||||
if (mmethod != null)
|
||||
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;
|
||||
AssemblyResolver resolver;
|
||||
if (!assemblyResolvers.TryGetValue(asmName, out resolver))
|
||||
|
@ -139,38 +139,38 @@ namespace AssemblyData.methodsrewriter {
|
|||
return resolver;
|
||||
}
|
||||
|
||||
static Type resolve(IType typeRef) {
|
||||
static Type Resolve(IType typeRef) {
|
||||
if (typeRef == null)
|
||||
return null;
|
||||
var scopeType = typeRef.ScopeType;
|
||||
var resolver = getAssemblyResolver(scopeType);
|
||||
var resolvedType = resolver.resolve(scopeType);
|
||||
var resolver = GetAssemblyResolver(scopeType);
|
||||
var resolvedType = resolver.Resolve(scopeType);
|
||||
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));
|
||||
}
|
||||
|
||||
static FieldInfo resolve(IField fieldRef) {
|
||||
static FieldInfo Resolve(IField fieldRef) {
|
||||
if (fieldRef == null)
|
||||
return null;
|
||||
var resolver = getAssemblyResolver(fieldRef.DeclaringType);
|
||||
var fieldInfo = resolver.resolve(fieldRef);
|
||||
var resolver = GetAssemblyResolver(fieldRef.DeclaringType);
|
||||
var fieldInfo = resolver.Resolve(fieldRef);
|
||||
if (fieldInfo != null)
|
||||
return fieldInfo;
|
||||
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)
|
||||
return null;
|
||||
var resolver = getAssemblyResolver(methodRef.DeclaringType);
|
||||
var methodBase = resolver.resolve(methodRef);
|
||||
var resolver = GetAssemblyResolver(methodRef.DeclaringType);
|
||||
var methodBase = resolver.Resolve(methodRef);
|
||||
if (methodBase != null)
|
||||
return methodBase;
|
||||
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;
|
||||
if (sig == null) {
|
||||
var ts = typeRef as TypeSpec;
|
||||
|
@ -203,7 +203,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
var arg = git.GenericArguments[i];
|
||||
if (!(arg is GenericSig))
|
||||
isGenericTypeDef = false;
|
||||
args[i] = Resolver.resolve(arg);
|
||||
args[i] = Resolver.Resolve(arg);
|
||||
}
|
||||
if (!isGenericTypeDef)
|
||||
type = type.MakeGenericType(args);
|
||||
|
|
|
@ -25,27 +25,27 @@ using de4dot.blocks;
|
|||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
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);
|
||||
}
|
||||
|
||||
public static bool compareFields(FieldInfo a, IField b) {
|
||||
public static bool CompareFields(FieldInfo a, IField 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;
|
||||
}
|
||||
|
||||
public static bool explicitThis(MethodBase method) {
|
||||
public static bool ExplicitThis(MethodBase method) {
|
||||
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);
|
||||
}
|
||||
|
||||
public static Type getReturnType(MethodBase methodBase) {
|
||||
public static Type GetReturnType(MethodBase methodBase) {
|
||||
var methodInfo = methodBase as MethodInfo;
|
||||
if (methodInfo != null)
|
||||
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));
|
||||
}
|
||||
|
||||
public static Type[] getGenericArguments(MethodBase methodBase) {
|
||||
public static Type[] GetGenericArguments(MethodBase methodBase) {
|
||||
try {
|
||||
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)
|
||||
yield return type.TypeInitializer;
|
||||
foreach (var ctor in type.GetConstructors(flags))
|
||||
|
@ -96,7 +96,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
|
||||
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);
|
||||
FieldInfo fieldInfo;
|
||||
if (cachedFieldInfos.TryGetValue(key, out fieldInfo))
|
||||
|
@ -111,14 +111,14 @@ namespace AssemblyData.methodsrewriter {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static FieldInfo getFieldThrow(Type type, Type fieldType, BindingFlags flags, string msg) {
|
||||
var info = getField(type, fieldType, flags);
|
||||
public static FieldInfo GetFieldThrow(Type type, Type fieldType, BindingFlags flags, string msg) {
|
||||
var info = GetField(type, fieldType, flags);
|
||||
if (info != null)
|
||||
return info;
|
||||
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>();
|
||||
foreach (var field in type.GetFields(flags)) {
|
||||
if (field.FieldType == fieldType)
|
||||
|
@ -127,7 +127,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
return list;
|
||||
}
|
||||
|
||||
public static Type makeInstanceType(Type type, ITypeDefOrRef typeRef) {
|
||||
public static Type MakeInstanceType(Type type, ITypeDefOrRef typeRef) {
|
||||
var ts = typeRef as TypeSpec;
|
||||
if (ts == null)
|
||||
return type;
|
||||
|
@ -140,7 +140,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
var arg = git.GenericArguments[i];
|
||||
if (!(arg is GenericSig))
|
||||
isTypeDef = false;
|
||||
types[i] = Resolver.getRtType(arg);
|
||||
types[i] = Resolver.GetRtType(arg);
|
||||
}
|
||||
if (isTypeDef)
|
||||
return type;
|
||||
|
|
|
@ -30,27 +30,27 @@ namespace AssemblyData.methodsrewriter {
|
|||
Dictionary<string, List<FieldInfo>> fields;
|
||||
|
||||
public TypeInstanceResolver(Type type, ITypeDefOrRef typeRef) {
|
||||
this.type = ResolverUtils.makeInstanceType(type, typeRef);
|
||||
this.type = ResolverUtils.MakeInstanceType(type, typeRef);
|
||||
}
|
||||
|
||||
public FieldInfo resolve(IField fieldRef) {
|
||||
initFields();
|
||||
public FieldInfo Resolve(IField fieldRef) {
|
||||
InitFields();
|
||||
|
||||
List<FieldInfo> list;
|
||||
if (!fields.TryGetValue(fieldRef.Name.String, out list))
|
||||
return null;
|
||||
|
||||
fieldRef = GenericArgsSubstitutor.create(fieldRef, fieldRef.DeclaringType.TryGetGenericInstSig());
|
||||
fieldRef = GenericArgsSubstitutor.Create(fieldRef, fieldRef.DeclaringType.TryGetGenericInstSig());
|
||||
|
||||
foreach (var field in list) {
|
||||
if (ResolverUtils.compareFields(field, fieldRef))
|
||||
if (ResolverUtils.CompareFields(field, fieldRef))
|
||||
return field;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void initFields() {
|
||||
void InitFields() {
|
||||
if (fields != null)
|
||||
return;
|
||||
fields = new Dictionary<string, List<FieldInfo>>(StringComparer.Ordinal);
|
||||
|
@ -64,30 +64,30 @@ namespace AssemblyData.methodsrewriter {
|
|||
}
|
||||
}
|
||||
|
||||
public MethodBase resolve(IMethod methodRef) {
|
||||
initMethods();
|
||||
public MethodBase Resolve(IMethod methodRef) {
|
||||
InitMethods();
|
||||
|
||||
List<MethodBase> list;
|
||||
if (!methods.TryGetValue(methodRef.Name.String, out list))
|
||||
return null;
|
||||
|
||||
methodRef = GenericArgsSubstitutor.create(methodRef, methodRef.DeclaringType.TryGetGenericInstSig());
|
||||
methodRef = GenericArgsSubstitutor.Create(methodRef, methodRef.DeclaringType.TryGetGenericInstSig());
|
||||
|
||||
foreach (var method in list) {
|
||||
if (ResolverUtils.compareMethods(method, methodRef))
|
||||
if (ResolverUtils.CompareMethods(method, methodRef))
|
||||
return method;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void initMethods() {
|
||||
void InitMethods() {
|
||||
if (methods != null)
|
||||
return;
|
||||
methods = new Dictionary<string, List<MethodBase>>(StringComparer.Ordinal);
|
||||
|
||||
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;
|
||||
if (!methods.TryGetValue(method.Name, out list))
|
||||
methods[method.Name] = list = new List<MethodBase>();
|
||||
|
|
|
@ -32,19 +32,19 @@ namespace AssemblyData.methodsrewriter {
|
|||
this.type = type;
|
||||
}
|
||||
|
||||
TypeInstanceResolver getTypeInstance(ITypeDefOrRef typeRef) {
|
||||
TypeInstanceResolver GetTypeInstance(ITypeDefOrRef typeRef) {
|
||||
TypeInstanceResolver instance;
|
||||
if (!typeRefToInstance.TryGetValue(typeRef, out instance))
|
||||
typeRefToInstance[typeRef] = instance = new TypeInstanceResolver(type, typeRef);
|
||||
return instance;
|
||||
}
|
||||
|
||||
public FieldInfo resolve(IField fieldRef) {
|
||||
return getTypeInstance(fieldRef.DeclaringType).resolve(fieldRef);
|
||||
public FieldInfo Resolve(IField fieldRef) {
|
||||
return GetTypeInstance(fieldRef.DeclaringType).Resolve(fieldRef);
|
||||
}
|
||||
|
||||
public MethodBase resolve(IMethod methodRef) {
|
||||
return getTypeInstance(methodRef.DeclaringType).resolve(methodRef);
|
||||
public MethodBase Resolve(IMethod methodRef) {
|
||||
return GetTypeInstance(methodRef.DeclaringType).Resolve(methodRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
namespace AssemblyServer_CLR20_x64 {
|
||||
class Program {
|
||||
static int Main(string[] args) {
|
||||
return AssemblyServer.Start.main(args);
|
||||
return AssemblyServer.Start.Main2(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
namespace AssemblyServer_CLR20 {
|
||||
class Program {
|
||||
static int Main(string[] args) {
|
||||
return AssemblyServer.Start.main(args);
|
||||
return AssemblyServer.Start.Main2(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
namespace AssemblyServer_CLR40_x64 {
|
||||
class Program {
|
||||
static int Main(string[] args) {
|
||||
return AssemblyServer.Start.main(args);
|
||||
return AssemblyServer.Start.Main2(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
namespace AssemblyServer_CLR40 {
|
||||
class Program {
|
||||
static int Main(string[] args) {
|
||||
return AssemblyServer.Start.main(args);
|
||||
return AssemblyServer.Start.Main2(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
namespace AssemblyServer_x64 {
|
||||
class Program {
|
||||
static int Main(string[] args) {
|
||||
return AssemblyServer.Start.main(args);
|
||||
return AssemblyServer.Start.Main2(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
namespace AssemblyServer_x86 {
|
||||
class Program {
|
||||
static int Main(string[] args) {
|
||||
return AssemblyServer.Start.main(args);
|
||||
return AssemblyServer.Start.Main2(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
142
blocks/Block.cs
142
blocks/Block.cs
|
@ -52,7 +52,7 @@ namespace de4dot.blocks {
|
|||
public Instr FirstInstr {
|
||||
get {
|
||||
if (instructions.Count == 0)
|
||||
add(new Instr(OpCodes.Nop.ToInstruction()));
|
||||
Add(new Instr(OpCodes.Nop.ToInstruction()));
|
||||
return instructions[0];
|
||||
}
|
||||
}
|
||||
|
@ -60,16 +60,16 @@ namespace de4dot.blocks {
|
|||
public Instr LastInstr {
|
||||
get {
|
||||
if (instructions.Count == 0)
|
||||
add(new Instr(OpCodes.Nop.ToInstruction()));
|
||||
Add(new Instr(OpCodes.Nop.ToInstruction()));
|
||||
return instructions[instructions.Count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public void add(Instr instr) {
|
||||
public void Add(Instr instr) {
|
||||
instructions.Add(instr);
|
||||
}
|
||||
|
||||
public void insert(int index, Instruction instr) {
|
||||
public void Insert(int index, Instruction 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
|
||||
public void removeLastBr() {
|
||||
if (!LastInstr.isBr())
|
||||
public void RemoveLastBr() {
|
||||
if (!LastInstr.IsBr())
|
||||
return;
|
||||
|
||||
if (fallThrough != null || (LastInstr.Operand != null && (targets == null || targets.Count != 1)))
|
||||
|
@ -89,111 +89,111 @@ namespace de4dot.blocks {
|
|||
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)
|
||||
throw new ArgumentOutOfRangeException("num");
|
||||
remove(index, num);
|
||||
Remove(index, num);
|
||||
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)
|
||||
throw new ApplicationException("Overflow");
|
||||
if (num > 0 && index + num == instructions.Count && LastInstr.isConditionalBranch())
|
||||
disconnectFromFallThroughAndTargets();
|
||||
if (num > 0 && index + num == instructions.Count && LastInstr.IsConditionalBranch())
|
||||
DisconnectFromFallThroughAndTargets();
|
||||
instructions.RemoveRange(index, num);
|
||||
}
|
||||
|
||||
public void remove(IEnumerable<int> indexes) {
|
||||
var instrsToDelete = new List<int>(Utils.unique(indexes));
|
||||
public void Remove(IEnumerable<int> indexes) {
|
||||
var instrsToDelete = new List<int>(Utils.Unique(indexes));
|
||||
instrsToDelete.Sort();
|
||||
instrsToDelete.Reverse();
|
||||
foreach (var index in instrsToDelete)
|
||||
remove(index, 1);
|
||||
Remove(index, 1);
|
||||
}
|
||||
|
||||
// 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)
|
||||
throw new ApplicationException("Invalid numInstrs to replace with branch");
|
||||
if (target == null)
|
||||
throw new ApplicationException("Invalid new target, it's null");
|
||||
|
||||
disconnectFromFallThroughAndTargets();
|
||||
DisconnectFromFallThroughAndTargets();
|
||||
if (numInstrs > 0)
|
||||
instructions.RemoveRange(instructions.Count - numInstrs, numInstrs);
|
||||
fallThrough = target;
|
||||
target.sources.Add(this);
|
||||
}
|
||||
|
||||
public void replaceLastNonBranchWithBranch(int numInstrs, Block target) {
|
||||
if (LastInstr.isBr())
|
||||
public void ReplaceLastNonBranchWithBranch(int numInstrs, Block target) {
|
||||
if (LastInstr.IsBr())
|
||||
numInstrs++;
|
||||
replaceLastInstrsWithBranch(numInstrs, target);
|
||||
ReplaceLastInstrsWithBranch(numInstrs, target);
|
||||
}
|
||||
|
||||
public void replaceBccWithBranch(bool isTaken) {
|
||||
public void ReplaceBccWithBranch(bool isTaken) {
|
||||
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)
|
||||
throw new ApplicationException("Last instruction is not a switch");
|
||||
replaceLastInstrsWithBranch(1, target);
|
||||
ReplaceLastInstrsWithBranch(1, target);
|
||||
}
|
||||
|
||||
public void setNewFallThrough(Block newFallThrough) {
|
||||
disconnectFromFallThrough();
|
||||
public void SetNewFallThrough(Block newFallThrough) {
|
||||
DisconnectFromFallThrough();
|
||||
fallThrough = newFallThrough;
|
||||
newFallThrough.sources.Add(this);
|
||||
}
|
||||
|
||||
public void setNewTarget(int index, Block newTarget) {
|
||||
disconnectFromBlock(targets[index]);
|
||||
public void SetNewTarget(int index, Block newTarget) {
|
||||
DisconnectFromBlock(targets[index]);
|
||||
targets[index] = newTarget;
|
||||
newTarget.sources.Add(this);
|
||||
}
|
||||
|
||||
public void removeDeadBlock() {
|
||||
public void RemoveDeadBlock() {
|
||||
if (sources.Count != 0)
|
||||
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
|
||||
// that it really is dead.
|
||||
public void removeGuaranteedDeadBlock() {
|
||||
disconnectFromFallThroughAndTargets();
|
||||
public void RemoveGuaranteedDeadBlock() {
|
||||
DisconnectFromFallThroughAndTargets();
|
||||
Parent = null;
|
||||
}
|
||||
|
||||
void disconnectFromFallThroughAndTargets() {
|
||||
disconnectFromFallThrough();
|
||||
disconnectFromTargets();
|
||||
void DisconnectFromFallThroughAndTargets() {
|
||||
DisconnectFromFallThrough();
|
||||
DisconnectFromTargets();
|
||||
}
|
||||
|
||||
void disconnectFromFallThrough() {
|
||||
void DisconnectFromFallThrough() {
|
||||
if (fallThrough != null) {
|
||||
disconnectFromBlock(fallThrough);
|
||||
DisconnectFromBlock(fallThrough);
|
||||
fallThrough = null;
|
||||
}
|
||||
}
|
||||
|
||||
void disconnectFromTargets() {
|
||||
void DisconnectFromTargets() {
|
||||
if (targets != null) {
|
||||
foreach (var target in targets)
|
||||
disconnectFromBlock(target);
|
||||
DisconnectFromBlock(target);
|
||||
targets = null;
|
||||
}
|
||||
}
|
||||
|
||||
void disconnectFromBlock(Block target) {
|
||||
void DisconnectFromBlock(Block target) {
|
||||
if (!target.sources.Remove(this))
|
||||
throw new ApplicationException("Could not remove the block from its target block");
|
||||
}
|
||||
|
||||
public int countTargets() {
|
||||
public int CountTargets() {
|
||||
int count = fallThrough != null ? 1 : 0;
|
||||
if (targets != null)
|
||||
count += targets.Count;
|
||||
|
@ -201,8 +201,8 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
// Returns the target iff it has only ONE target. Else it returns null.
|
||||
public Block getOnlyTarget() {
|
||||
if (countTargets() != 1)
|
||||
public Block GetOnlyTarget() {
|
||||
if (CountTargets() != 1)
|
||||
return null;
|
||||
if (fallThrough != null)
|
||||
return fallThrough;
|
||||
|
@ -210,7 +210,7 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
// Returns all targets. FallThrough (if not null) is always returned first!
|
||||
public IEnumerable<Block> getTargets() {
|
||||
public IEnumerable<Block> GetTargets() {
|
||||
if (fallThrough != null)
|
||||
yield return fallThrough;
|
||||
if (targets != null) {
|
||||
|
@ -220,52 +220,52 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Returns true if we can merge other with this
|
||||
public bool canMerge(Block other) {
|
||||
return canAppend(other) && other.isOnlySource(this);
|
||||
public bool CanMerge(Block other) {
|
||||
return CanAppend(other) && other.IsOnlySource(this);
|
||||
}
|
||||
|
||||
// Merge two blocks into one
|
||||
public void merge(Block other) {
|
||||
if (!canMerge(other))
|
||||
public void Merge(Block other) {
|
||||
if (!CanMerge(other))
|
||||
throw new ApplicationException("Can't merge the two blocks!");
|
||||
append(other);
|
||||
other.disconnectFromFallThroughAndTargets();
|
||||
Append(other);
|
||||
other.DisconnectFromFallThroughAndTargets();
|
||||
other.Parent = null;
|
||||
}
|
||||
|
||||
public bool canAppend(Block other) {
|
||||
if (other == null || other == this || getOnlyTarget() != other)
|
||||
public bool CanAppend(Block other) {
|
||||
if (other == null || other == this || GetOnlyTarget() != other)
|
||||
return false;
|
||||
// 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) {
|
||||
if (!canAppend(other))
|
||||
public void Append(Block other) {
|
||||
if (!CanAppend(other))
|
||||
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);
|
||||
addInstructions(newInstructions, instructions, false);
|
||||
addInstructions(newInstructions, other.instructions, true);
|
||||
AddInstructions(newInstructions, instructions, false);
|
||||
AddInstructions(newInstructions, other.instructions, true);
|
||||
instructions = newInstructions;
|
||||
|
||||
disconnectFromFallThroughAndTargets();
|
||||
DisconnectFromFallThroughAndTargets();
|
||||
if (other.targets != null)
|
||||
targets = new List<Block>(other.targets);
|
||||
else
|
||||
targets = null;
|
||||
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++) {
|
||||
var instr = instrs[i];
|
||||
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
|
||||
// Sources list!
|
||||
public void updateSources() {
|
||||
public void UpdateSources() {
|
||||
if (fallThrough != null)
|
||||
fallThrough.sources.Add(this);
|
||||
if (targets != null) {
|
||||
|
@ -285,30 +285,30 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
// Returns true if it falls through
|
||||
public bool isFallThrough() {
|
||||
public bool IsFallThrough() {
|
||||
return targets == null && fallThrough != null;
|
||||
}
|
||||
|
||||
public bool canFlipConditionalBranch() {
|
||||
return LastInstr.canFlipConditionalBranch();
|
||||
public bool CanFlipConditionalBranch() {
|
||||
return LastInstr.CanFlipConditionalBranch();
|
||||
}
|
||||
|
||||
public void flipConditionalBranch() {
|
||||
public void FlipConditionalBranch() {
|
||||
if (fallThrough == null || targets == null || targets.Count != 1)
|
||||
throw new ApplicationException("Invalid bcc block state");
|
||||
LastInstr.flipConditonalBranch();
|
||||
LastInstr.FlipConditonalBranch();
|
||||
var oldFallThrough = fallThrough;
|
||||
fallThrough = targets[0];
|
||||
targets[0] = oldFallThrough;
|
||||
}
|
||||
|
||||
// Returns true if it's a conditional branch
|
||||
public bool isConditionalBranch() {
|
||||
return LastInstr.isConditionalBranch();
|
||||
public bool IsConditionalBranch() {
|
||||
return LastInstr.IsConditionalBranch();
|
||||
}
|
||||
|
||||
public bool isNopBlock() {
|
||||
if (!isFallThrough())
|
||||
public bool IsNopBlock() {
|
||||
if (!IsFallThrough())
|
||||
return false;
|
||||
foreach (var instr in instructions) {
|
||||
if (instr.OpCode.Code != Code.Nop)
|
||||
|
|
|
@ -42,28 +42,28 @@ namespace de4dot.blocks {
|
|||
|
||||
public Blocks(MethodDef method) {
|
||||
this.method = method;
|
||||
updateBlocks();
|
||||
UpdateBlocks();
|
||||
}
|
||||
|
||||
public void updateBlocks() {
|
||||
public void UpdateBlocks() {
|
||||
var body = method.Body;
|
||||
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>();
|
||||
list.Add(scopeBlock);
|
||||
list.AddRange(scopeBlock.getAllScopeBlocks());
|
||||
list.AddRange(scopeBlock.GetAllScopeBlocks());
|
||||
return list;
|
||||
}
|
||||
|
||||
public int removeDeadBlocks() {
|
||||
return new DeadBlocksRemover(methodBlocks).remove();
|
||||
public int RemoveDeadBlocks() {
|
||||
return new DeadBlocksRemover(methodBlocks).Remove();
|
||||
}
|
||||
|
||||
public void getCode(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers) {
|
||||
new CodeGenerator(methodBlocks).getCode(out allInstructions, out allExceptionHandlers);
|
||||
public void GetCode(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers) {
|
||||
new CodeGenerator(methodBlocks).GetCode(out allInstructions, out allExceptionHandlers);
|
||||
}
|
||||
|
||||
struct LocalVariableInfo {
|
||||
|
@ -75,12 +75,12 @@ namespace de4dot.blocks {
|
|||
}
|
||||
}
|
||||
|
||||
public int optimizeLocals() {
|
||||
public int OptimizeLocals() {
|
||||
if (locals.Count == 0)
|
||||
return 0;
|
||||
|
||||
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++) {
|
||||
var instr = block.Instructions[i];
|
||||
Local local;
|
||||
|
@ -97,7 +97,7 @@ namespace de4dot.blocks {
|
|||
case Code.Stloc_1:
|
||||
case Code.Stloc_2:
|
||||
case Code.Stloc_3:
|
||||
local = Instr.getLocalVar(locals, instr);
|
||||
local = Instr.GetLocalVar(locals, instr);
|
||||
break;
|
||||
|
||||
case Code.Ldloca_S:
|
||||
|
@ -129,7 +129,7 @@ namespace de4dot.blocks {
|
|||
newLocals.Add(local);
|
||||
newLocalsDict[local] = true;
|
||||
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
|
||||
|
@ -162,7 +162,7 @@ namespace de4dot.blocks {
|
|||
return numRemoved;
|
||||
}
|
||||
|
||||
static Instruction optimizeLocalInstr(Instr instr, Local local, uint newIndex) {
|
||||
static Instruction OptimizeLocalInstr(Instr instr, Local local, uint newIndex) {
|
||||
switch (instr.OpCode.Code) {
|
||||
case Code.Ldloc:
|
||||
case Code.Ldloc_S:
|
||||
|
@ -211,11 +211,11 @@ namespace de4dot.blocks {
|
|||
}
|
||||
}
|
||||
|
||||
public void repartitionBlocks() {
|
||||
mergeNopBlocks();
|
||||
foreach (var scopeBlock in getAllScopeBlocks(methodBlocks)) {
|
||||
public void RepartitionBlocks() {
|
||||
MergeNopBlocks();
|
||||
foreach (var scopeBlock in GetAllScopeBlocks(methodBlocks)) {
|
||||
try {
|
||||
scopeBlock.repartitionBlocks();
|
||||
scopeBlock.RepartitionBlocks();
|
||||
}
|
||||
catch (NullReferenceException) {
|
||||
//TODO: Send this message to the log
|
||||
|
@ -225,12 +225,12 @@ namespace de4dot.blocks {
|
|||
}
|
||||
}
|
||||
|
||||
void mergeNopBlocks() {
|
||||
var allBlocks = methodBlocks.getAllBlocks();
|
||||
void MergeNopBlocks() {
|
||||
var allBlocks = methodBlocks.GetAllBlocks();
|
||||
|
||||
var nopBlocks = new Dictionary<Block, bool>();
|
||||
foreach (var nopBlock in allBlocks) {
|
||||
if (nopBlock.isNopBlock())
|
||||
if (nopBlock.IsNopBlock())
|
||||
nopBlocks[nopBlock] = true;
|
||||
}
|
||||
|
||||
|
@ -243,18 +243,18 @@ namespace de4dot.blocks {
|
|||
foreach (var block in allBlocks) {
|
||||
Block nopBlockTarget;
|
||||
|
||||
nopBlockTarget = getNopBlockTarget(nopBlocks, block, block.FallThrough);
|
||||
nopBlockTarget = GetNopBlockTarget(nopBlocks, block, block.FallThrough);
|
||||
if (nopBlockTarget != null) {
|
||||
block.setNewFallThrough(nopBlockTarget);
|
||||
block.SetNewFallThrough(nopBlockTarget);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (block.Targets != null) {
|
||||
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)
|
||||
continue;
|
||||
block.setNewTarget(targetIndex, nopBlockTarget);
|
||||
block.SetNewTarget(targetIndex, nopBlockTarget);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
@ -265,10 +265,10 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
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)
|
||||
return null;
|
||||
if (nopBlock.Parent.BaseBlocks[0] == nopBlock)
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace de4dot.blocks {
|
|||
this.baseBlock = baseBlock;
|
||||
}
|
||||
|
||||
public bool visited() {
|
||||
public bool Visited() {
|
||||
return dfsNumber >= 0;
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ namespace de4dot.blocks {
|
|||
this.skipFirstBlock = skipFirstBlock;
|
||||
}
|
||||
|
||||
public List<BaseBlock> sort() {
|
||||
public List<BaseBlock> Sort() {
|
||||
if (validBlocks.Count == 0)
|
||||
return new List<BaseBlock>();
|
||||
if (skipFirstBlock)
|
||||
|
@ -77,14 +77,14 @@ namespace de4dot.blocks {
|
|||
var finalList = new List<BaseBlock>(validBlocks.Count);
|
||||
|
||||
if (firstBlock is Block) {
|
||||
foreach (var target in getTargets(firstBlock)) {
|
||||
visit(target);
|
||||
foreach (var target in GetTargets(firstBlock)) {
|
||||
Visit(target);
|
||||
finalList.AddRange(sorted);
|
||||
sorted.Clear();
|
||||
}
|
||||
}
|
||||
foreach (var bb in validBlocks) {
|
||||
visit(bb);
|
||||
Visit(bb);
|
||||
finalList.AddRange(sorted);
|
||||
sorted.Clear();
|
||||
}
|
||||
|
@ -103,19 +103,19 @@ namespace de4dot.blocks {
|
|||
return finalList;
|
||||
}
|
||||
|
||||
void visit(BaseBlock bb) {
|
||||
var info = getInfo(bb);
|
||||
void Visit(BaseBlock bb) {
|
||||
var info = GetInfo(bb);
|
||||
if (info == null)
|
||||
return;
|
||||
if (info.baseBlock == firstBlock)
|
||||
return;
|
||||
if (info.visited())
|
||||
if (info.Visited())
|
||||
return;
|
||||
visit(info);
|
||||
Visit(info);
|
||||
}
|
||||
|
||||
BlockInfo getInfo(BaseBlock baseBlock) {
|
||||
baseBlock = scopeBlock.toChild(baseBlock);
|
||||
BlockInfo GetInfo(BaseBlock baseBlock) {
|
||||
baseBlock = scopeBlock.ToChild(baseBlock);
|
||||
if (baseBlock == null)
|
||||
return null;
|
||||
BlockInfo info;
|
||||
|
@ -123,54 +123,54 @@ namespace de4dot.blocks {
|
|||
return info;
|
||||
}
|
||||
|
||||
List<BaseBlock> getTargets(BaseBlock baseBlock) {
|
||||
List<BaseBlock> GetTargets(BaseBlock baseBlock) {
|
||||
var list = new List<BaseBlock>();
|
||||
|
||||
if (baseBlock is Block) {
|
||||
var block = (Block)baseBlock;
|
||||
addTargets(list, block.getTargets());
|
||||
AddTargets(list, block.GetTargets());
|
||||
}
|
||||
else if (baseBlock is TryBlock)
|
||||
addTargets(list, (TryBlock)baseBlock);
|
||||
AddTargets(list, (TryBlock)baseBlock);
|
||||
else if (baseBlock is TryHandlerBlock)
|
||||
addTargets(list, (TryHandlerBlock)baseBlock);
|
||||
AddTargets(list, (TryHandlerBlock)baseBlock);
|
||||
else
|
||||
addTargets(list, (ScopeBlock)baseBlock);
|
||||
AddTargets(list, (ScopeBlock)baseBlock);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void addTargets(List<BaseBlock> dest, TryBlock tryBlock) {
|
||||
addTargets(dest, (ScopeBlock)tryBlock);
|
||||
void AddTargets(List<BaseBlock> dest, TryBlock tryBlock) {
|
||||
AddTargets(dest, (ScopeBlock)tryBlock);
|
||||
foreach (var tryHandlerBlock in tryBlock.TryHandlerBlocks) {
|
||||
dest.Add(tryHandlerBlock);
|
||||
addTargets(dest, tryHandlerBlock);
|
||||
AddTargets(dest, tryHandlerBlock);
|
||||
}
|
||||
}
|
||||
|
||||
void addTargets(List<BaseBlock> dest, TryHandlerBlock tryHandlerBlock) {
|
||||
addTargets(dest, (ScopeBlock)tryHandlerBlock);
|
||||
void AddTargets(List<BaseBlock> dest, TryHandlerBlock tryHandlerBlock) {
|
||||
AddTargets(dest, (ScopeBlock)tryHandlerBlock);
|
||||
|
||||
dest.Add(tryHandlerBlock.FilterHandlerBlock);
|
||||
addTargets(dest, tryHandlerBlock.FilterHandlerBlock);
|
||||
AddTargets(dest, tryHandlerBlock.FilterHandlerBlock);
|
||||
|
||||
dest.Add(tryHandlerBlock.HandlerBlock);
|
||||
addTargets(dest, tryHandlerBlock.HandlerBlock);
|
||||
AddTargets(dest, tryHandlerBlock.HandlerBlock);
|
||||
}
|
||||
|
||||
void addTargets(List<BaseBlock> dest, ScopeBlock scopeBlock) {
|
||||
foreach (var block in scopeBlock.getAllBlocks())
|
||||
addTargets(dest, block.getTargets());
|
||||
void AddTargets(List<BaseBlock> dest, ScopeBlock scopeBlock) {
|
||||
foreach (var block in scopeBlock.GetAllBlocks())
|
||||
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);
|
||||
list.Reverse();
|
||||
foreach (var block in list)
|
||||
dest.Add(block);
|
||||
}
|
||||
|
||||
void visit(BlockInfo info) {
|
||||
void Visit(BlockInfo info) {
|
||||
if (info.baseBlock == firstBlock)
|
||||
throw new ApplicationException("Can't visit firstBlock");
|
||||
stack.Push(info);
|
||||
|
@ -179,15 +179,15 @@ namespace de4dot.blocks {
|
|||
info.low = dfsNumber;
|
||||
dfsNumber++;
|
||||
|
||||
foreach (var tmp in getTargets(info.baseBlock)) {
|
||||
var targetInfo = getInfo(tmp);
|
||||
foreach (var tmp in GetTargets(info.baseBlock)) {
|
||||
var targetInfo = GetInfo(tmp);
|
||||
if (targetInfo == null)
|
||||
continue;
|
||||
if (targetInfo.baseBlock == firstBlock)
|
||||
continue;
|
||||
|
||||
if (!targetInfo.visited()) {
|
||||
visit(targetInfo);
|
||||
if (!targetInfo.Visited()) {
|
||||
Visit(targetInfo);
|
||||
info.low = Math.Min(info.low, targetInfo.low);
|
||||
}
|
||||
else if (targetInfo.onStack)
|
||||
|
@ -206,8 +206,8 @@ namespace de4dot.blocks {
|
|||
}
|
||||
if (sccBlocks.Count > 1) {
|
||||
sccBlocks.Reverse();
|
||||
var result = new Sorter(scopeBlock, sccBlocks, true).sort();
|
||||
sortLoopBlock(result);
|
||||
var result = new Sorter(scopeBlock, sccBlocks, true).Sort();
|
||||
SortLoopBlock(result);
|
||||
sorted.InsertRange(0, result);
|
||||
}
|
||||
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
|
||||
// checker block is at the end of the loop. Eg., they may use a while loop when
|
||||
// it's really a for/foreach loop.
|
||||
|
||||
var loopStart = getLoopStartBlock(list);
|
||||
var loopStart = GetLoopStartBlock(list);
|
||||
if (loopStart == null)
|
||||
return;
|
||||
|
||||
|
@ -229,7 +229,7 @@ namespace de4dot.blocks {
|
|||
list.Add(loopStart);
|
||||
}
|
||||
|
||||
Block getLoopStartBlock(List<BaseBlock> list) {
|
||||
Block GetLoopStartBlock(List<BaseBlock> list) {
|
||||
var loopBlocks = new Dictionary<Block, bool>(list.Count);
|
||||
foreach (var bb in list) {
|
||||
var block = bb as Block;
|
||||
|
@ -268,9 +268,9 @@ namespace de4dot.blocks {
|
|||
this.scopeBlock = scopeBlock;
|
||||
}
|
||||
|
||||
public List<BaseBlock> sort() {
|
||||
var sorted = new Sorter(scopeBlock, scopeBlock.BaseBlocks, false).sort();
|
||||
return new ForwardScanOrder(scopeBlock, sorted).fix();
|
||||
public List<BaseBlock> Sort() {
|
||||
var sorted = new Sorter(scopeBlock, scopeBlock.BaseBlocks, false).Sort();
|
||||
return new ForwardScanOrder(scopeBlock, sorted).Fix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,11 +67,11 @@ namespace de4dot.blocks {
|
|||
this.methodBlocks = methodBlocks;
|
||||
}
|
||||
|
||||
public void getCode(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers) {
|
||||
fixEmptyBlocks();
|
||||
layOutBlocks();
|
||||
sortExceptions();
|
||||
layOutInstructions(out allInstructions, out allExceptionHandlers);
|
||||
public void GetCode(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers) {
|
||||
FixEmptyBlocks();
|
||||
LayOutBlocks();
|
||||
SortExceptions();
|
||||
LayOutInstructions(out allInstructions, out allExceptionHandlers);
|
||||
|
||||
allInstructions.SimplifyBranches();
|
||||
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>();
|
||||
allExceptionHandlers = new List<ExceptionHandler>();
|
||||
|
||||
|
@ -103,20 +103,20 @@ namespace de4dot.blocks {
|
|||
var targets = new List<Instr>();
|
||||
foreach (var target in block.Targets)
|
||||
targets.Add(target.FirstInstr);
|
||||
block.LastInstr.updateTargets(targets);
|
||||
block.LastInstr.UpdateTargets(targets);
|
||||
}
|
||||
allInstructions.Add(block.LastInstr.Instruction);
|
||||
|
||||
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 (block.Targets != null && block.canFlipConditionalBranch() && block.Targets[0] == next) {
|
||||
block.flipConditionalBranch();
|
||||
block.LastInstr.updateTargets(new List<Instr> { block.Targets[0].FirstInstr });
|
||||
if (block.Targets != null && block.CanFlipConditionalBranch() && block.Targets[0] == next) {
|
||||
block.FlipConditionalBranch();
|
||||
block.LastInstr.UpdateTargets(new List<Instr> { block.Targets[0].FirstInstr });
|
||||
}
|
||||
else if (block.FallThrough != null && block.FallThrough != next) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -126,25 +126,25 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
foreach (var ex in exceptions) {
|
||||
var tryStart = getBlockInfo(blockInfos, ex.tryStart).start;
|
||||
var tryEnd = getBlockInfo(blockInfos, ex.tryEnd).end;
|
||||
var filterStart = ex.filterStart == -1 ? -1 : getBlockInfo(blockInfos, ex.filterStart).start;
|
||||
var handlerStart = getBlockInfo(blockInfos, ex.handlerStart).start;
|
||||
var handlerEnd = getBlockInfo(blockInfos, ex.handlerEnd).end;
|
||||
var tryStart = GetBlockInfo(blockInfos, ex.tryStart).start;
|
||||
var tryEnd = GetBlockInfo(blockInfos, ex.tryEnd).end;
|
||||
var filterStart = ex.filterStart == -1 ? -1 : GetBlockInfo(blockInfos, ex.filterStart).start;
|
||||
var handlerStart = GetBlockInfo(blockInfos, ex.handlerStart).start;
|
||||
var handlerEnd = GetBlockInfo(blockInfos, ex.handlerEnd).end;
|
||||
|
||||
var eh = new ExceptionHandler(ex.handlerType);
|
||||
eh.CatchType = ex.catchType;
|
||||
eh.TryStart = getInstruction(allInstructions, tryStart);
|
||||
eh.TryEnd = getInstruction(allInstructions, tryEnd + 1);
|
||||
eh.FilterStart = filterStart == -1 ? null : getInstruction(allInstructions, filterStart);
|
||||
eh.HandlerStart = getInstruction(allInstructions, handlerStart);
|
||||
eh.HandlerEnd = getInstruction(allInstructions, handlerEnd + 1);
|
||||
eh.TryStart = GetInstruction(allInstructions, tryStart);
|
||||
eh.TryEnd = GetInstruction(allInstructions, tryEnd + 1);
|
||||
eh.FilterStart = filterStart == -1 ? null : GetInstruction(allInstructions, filterStart);
|
||||
eh.HandlerStart = GetInstruction(allInstructions, handlerStart);
|
||||
eh.HandlerEnd = GetInstruction(allInstructions, handlerEnd + 1);
|
||||
|
||||
allExceptionHandlers.Add(eh);
|
||||
}
|
||||
}
|
||||
|
||||
static BlockInfo getBlockInfo(List<BlockInfo> blockInfos, int index) {
|
||||
static BlockInfo GetBlockInfo(List<BlockInfo> blockInfos, int index) {
|
||||
if (index >= blockInfos.Count)
|
||||
index = blockInfos.Count - 1;
|
||||
if (index < 0)
|
||||
|
@ -152,13 +152,13 @@ namespace de4dot.blocks {
|
|||
return blockInfos[index];
|
||||
}
|
||||
|
||||
static Instruction getInstruction(IList<Instruction> allInstructions, int i) {
|
||||
static Instruction GetInstruction(IList<Instruction> allInstructions, int i) {
|
||||
if (i < allInstructions.Count)
|
||||
return allInstructions[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
void sortExceptions() {
|
||||
void SortExceptions() {
|
||||
exceptions.Sort((a, b) => {
|
||||
// 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
|
||||
|
@ -184,8 +184,8 @@ namespace de4dot.blocks {
|
|||
});
|
||||
}
|
||||
|
||||
void fixEmptyBlocks() {
|
||||
foreach (var block in methodBlocks.getAllBlocks()) {
|
||||
void FixEmptyBlocks() {
|
||||
foreach (var block in methodBlocks.GetAllBlocks()) {
|
||||
if (block.Instructions.Count == 0) {
|
||||
block.Instructions.Add(new Instr(OpCodes.Nop.ToInstruction()));
|
||||
}
|
||||
|
@ -193,12 +193,12 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
// Write all blocks to the blocks list
|
||||
void layOutBlocks() {
|
||||
void LayOutBlocks() {
|
||||
if (methodBlocks.BaseBlocks.Count == 0)
|
||||
return;
|
||||
|
||||
stateStack.Push(new BlockState(methodBlocks));
|
||||
processBaseBlocks(methodBlocks.BaseBlocks, (block) => {
|
||||
ProcessBaseBlocks(methodBlocks.BaseBlocks, (block) => {
|
||||
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>();
|
||||
int lastIndex = -1;
|
||||
for (int i = 0; i < lb.Count; i++) {
|
||||
|
@ -228,22 +228,22 @@ namespace de4dot.blocks {
|
|||
bbs.Add(block);
|
||||
}
|
||||
foreach (var bb in bbs)
|
||||
doBaseBlock(bb);
|
||||
DoBaseBlock(bb);
|
||||
}
|
||||
|
||||
// Returns the BaseBlock's ScopeBlock. The return value is either current ScopeBlock,
|
||||
// the ScopeBlock one step below current (current one's child), or null.
|
||||
ScopeBlock getScopeBlock(BaseBlock bb) {
|
||||
ScopeBlock GetScopeBlock(BaseBlock bb) {
|
||||
BlockState current = stateStack.Peek();
|
||||
|
||||
if (current.scopeBlock.isOurBaseBlock(bb))
|
||||
if (current.scopeBlock.IsOurBaseBlock(bb))
|
||||
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();
|
||||
ScopeBlock newOne = getScopeBlock(bb);
|
||||
ScopeBlock newOne = GetScopeBlock(bb);
|
||||
if (newOne == null)
|
||||
return; // Not a BaseBlock somewhere inside this ScopeBlock
|
||||
if (newOne != current.scopeBlock)
|
||||
|
@ -257,13 +257,13 @@ namespace de4dot.blocks {
|
|||
visited[bb] = true;
|
||||
|
||||
if (bb is Block)
|
||||
doBlock(bb as Block);
|
||||
DoBlock(bb as Block);
|
||||
else if (bb is TryBlock)
|
||||
doTryBlock(bb as TryBlock);
|
||||
DoTryBlock(bb as TryBlock);
|
||||
else if (bb is FilterHandlerBlock)
|
||||
doFilterHandlerBlock(bb as FilterHandlerBlock);
|
||||
DoFilterHandlerBlock(bb as FilterHandlerBlock);
|
||||
else if (bb is HandlerBlock)
|
||||
doHandlerBlock(bb as HandlerBlock);
|
||||
DoHandlerBlock(bb as HandlerBlock);
|
||||
else if (bb is TryHandlerBlock) {
|
||||
// The try handler block is usually after the try block, but sometimes it isn't...
|
||||
// Handle that case here.
|
||||
|
@ -274,14 +274,14 @@ namespace de4dot.blocks {
|
|||
throw new ApplicationException("Invalid block found");
|
||||
}
|
||||
|
||||
void doBlock(Block block) {
|
||||
void DoBlock(Block block) {
|
||||
blocks.Add(block);
|
||||
}
|
||||
|
||||
void doTryBlock(TryBlock tryBlock) {
|
||||
void DoTryBlock(TryBlock tryBlock) {
|
||||
var tryStart = blocks.Count;
|
||||
stateStack.Push(new BlockState(tryBlock));
|
||||
processBaseBlocks(tryBlock.BaseBlocks, (block) => {
|
||||
ProcessBaseBlocks(tryBlock.BaseBlocks, (block) => {
|
||||
return block.LastInstr.OpCode == OpCodes.Leave ||
|
||||
block.LastInstr.OpCode == OpCodes.Leave_S;
|
||||
});
|
||||
|
@ -298,10 +298,10 @@ namespace de4dot.blocks {
|
|||
|
||||
var filterStart = blocks.Count;
|
||||
if (handlerBlock.FilterHandlerBlock.BaseBlocks != null)
|
||||
doBaseBlock(handlerBlock.FilterHandlerBlock);
|
||||
DoBaseBlock(handlerBlock.FilterHandlerBlock);
|
||||
|
||||
var handlerStart = blocks.Count;
|
||||
doBaseBlock(handlerBlock.HandlerBlock);
|
||||
DoBaseBlock(handlerBlock.HandlerBlock);
|
||||
var handlerEnd = blocks.Count - 1;
|
||||
|
||||
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));
|
||||
processBaseBlocks(filterHandlerBlock.BaseBlocks, (block) => {
|
||||
ProcessBaseBlocks(filterHandlerBlock.BaseBlocks, (block) => {
|
||||
return block.LastInstr.OpCode == OpCodes.Endfilter; // MUST end with endfilter!
|
||||
});
|
||||
stateStack.Pop();
|
||||
}
|
||||
|
||||
void doHandlerBlock(HandlerBlock handlerBlock) {
|
||||
void DoHandlerBlock(HandlerBlock handlerBlock) {
|
||||
stateStack.Push(new BlockState(handlerBlock));
|
||||
processBaseBlocks(handlerBlock.BaseBlocks, (block) => {
|
||||
ProcessBaseBlocks(handlerBlock.BaseBlocks, (block) => {
|
||||
return block.LastInstr.OpCode == OpCodes.Endfinally ||
|
||||
block.LastInstr.OpCode == OpCodes.Leave ||
|
||||
block.LastInstr.OpCode == OpCodes.Leave_S;
|
||||
|
|
|
@ -32,10 +32,10 @@ namespace de4dot.blocks {
|
|||
this.methodBlocks = methodBlocks;
|
||||
}
|
||||
|
||||
public int remove() {
|
||||
addScopeBlock(methodBlocks);
|
||||
processAll();
|
||||
return removeDeadBlocks();
|
||||
public int Remove() {
|
||||
AddScopeBlock(methodBlocks);
|
||||
ProcessAll();
|
||||
return RemoveDeadBlocks();
|
||||
}
|
||||
|
||||
class ScopeBlockInfo {
|
||||
|
@ -46,12 +46,12 @@ namespace de4dot.blocks {
|
|||
}
|
||||
}
|
||||
|
||||
int removeDeadBlocks() {
|
||||
int RemoveDeadBlocks() {
|
||||
int numDeadBlocks = 0;
|
||||
|
||||
var infos = new Dictionary<ScopeBlock, ScopeBlockInfo>();
|
||||
var deadBlocksDict = new Dictionary<BaseBlock, bool>();
|
||||
foreach (var baseBlock in findDeadBlocks()) {
|
||||
foreach (var baseBlock in FindDeadBlocks()) {
|
||||
deadBlocksDict[baseBlock] = true;
|
||||
ScopeBlock parent = baseBlock.Parent;
|
||||
ScopeBlockInfo info;
|
||||
|
@ -62,15 +62,15 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
foreach (var info in infos.Values)
|
||||
info.scopeBlock.removeAllDeadBlocks(info.deadBlocks, deadBlocksDict);
|
||||
info.scopeBlock.RemoveAllDeadBlocks(info.deadBlocks, deadBlocksDict);
|
||||
|
||||
return numDeadBlocks;
|
||||
}
|
||||
|
||||
IList<BaseBlock> findDeadBlocks() {
|
||||
IList<BaseBlock> FindDeadBlocks() {
|
||||
var deadBlocks = new List<BaseBlock>();
|
||||
|
||||
foreach (var bb in methodBlocks.getAllBaseBlocks()) {
|
||||
foreach (var bb in methodBlocks.GetAllBaseBlocks()) {
|
||||
if (!checkedBaseBlocks.ContainsKey(bb))
|
||||
deadBlocks.Add(bb);
|
||||
}
|
||||
|
@ -78,66 +78,66 @@ namespace de4dot.blocks {
|
|||
return deadBlocks;
|
||||
}
|
||||
|
||||
void addScopeBlock(ScopeBlock scopeBlock) {
|
||||
void AddScopeBlock(ScopeBlock scopeBlock) {
|
||||
scopeBlocksToCheck.Push(scopeBlock);
|
||||
}
|
||||
|
||||
void processAll() {
|
||||
void ProcessAll() {
|
||||
bool didSomething;
|
||||
do {
|
||||
didSomething = false;
|
||||
while (baseBlocksToCheck.Count > 0) {
|
||||
processBaseBlock(baseBlocksToCheck.Pop());
|
||||
ProcessBaseBlock(baseBlocksToCheck.Pop());
|
||||
didSomething = true;
|
||||
}
|
||||
while (scopeBlocksToCheck.Count > 0) {
|
||||
processScopeBlock(scopeBlocksToCheck.Pop());
|
||||
ProcessScopeBlock(scopeBlocksToCheck.Pop());
|
||||
didSomething = true;
|
||||
}
|
||||
} while (didSomething);
|
||||
}
|
||||
|
||||
void processBaseBlock(BaseBlock baseBlock) {
|
||||
void ProcessBaseBlock(BaseBlock baseBlock) {
|
||||
if (baseBlock == null || checkedBaseBlocks.ContainsKey(baseBlock))
|
||||
return;
|
||||
checkedBaseBlocks[baseBlock] = true;
|
||||
|
||||
if (baseBlock is Block) {
|
||||
var block = (Block)baseBlock;
|
||||
foreach (var block2 in block.getTargets())
|
||||
addBaseBlock(block2);
|
||||
foreach (var block2 in block.GetTargets())
|
||||
AddBaseBlock(block2);
|
||||
}
|
||||
else if (baseBlock is ScopeBlock) {
|
||||
var scopeBlock = (ScopeBlock)baseBlock;
|
||||
addScopeBlock(scopeBlock);
|
||||
AddScopeBlock(scopeBlock);
|
||||
if (scopeBlock.BaseBlocks != null && scopeBlock.BaseBlocks.Count > 0)
|
||||
addBaseBlock(scopeBlock.BaseBlocks[0]);
|
||||
AddBaseBlock(scopeBlock.BaseBlocks[0]);
|
||||
}
|
||||
else
|
||||
throw new ApplicationException(string.Format("Unknown BaseBlock type {0}", baseBlock.GetType()));
|
||||
}
|
||||
|
||||
// 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)
|
||||
baseBlocksToCheck.Push(bb);
|
||||
}
|
||||
|
||||
void processScopeBlock(ScopeBlock scopeBlock) {
|
||||
void ProcessScopeBlock(ScopeBlock scopeBlock) {
|
||||
if (scopeBlock == null || checkedScopeBlocks.ContainsKey(scopeBlock))
|
||||
return;
|
||||
checkedScopeBlocks[scopeBlock] = true;
|
||||
addBaseBlock(scopeBlock);
|
||||
AddBaseBlock(scopeBlock);
|
||||
|
||||
if (scopeBlock is TryBlock) {
|
||||
var tryBlock = (TryBlock)scopeBlock;
|
||||
foreach (var handler in tryBlock.TryHandlerBlocks)
|
||||
addScopeBlock(handler);
|
||||
AddScopeBlock(handler);
|
||||
}
|
||||
else if (scopeBlock is TryHandlerBlock) {
|
||||
var tryHandlerBlock = (TryHandlerBlock)scopeBlock;
|
||||
addScopeBlock(tryHandlerBlock.FilterHandlerBlock);
|
||||
addScopeBlock(tryHandlerBlock.HandlerBlock);
|
||||
AddScopeBlock(tryHandlerBlock.FilterHandlerBlock);
|
||||
AddScopeBlock(tryHandlerBlock.HandlerBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,18 +35,18 @@ namespace de4dot.blocks {
|
|||
public class CallCounter {
|
||||
Dictionary<IMethod, int> calls = new Dictionary<IMethod, int>(MethodEqualityComparer.CompareDeclaringTypes);
|
||||
|
||||
public void add(IMethod calledMethod) {
|
||||
public void Add(IMethod calledMethod) {
|
||||
int count;
|
||||
calls.TryGetValue(calledMethod, out count);
|
||||
calls[calledMethod] = count + 1;
|
||||
}
|
||||
|
||||
public IMethod most() {
|
||||
public IMethod Most() {
|
||||
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;
|
||||
int callCount = 0;
|
||||
foreach (var key in calls.Keys) {
|
||||
|
@ -61,15 +61,15 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
public static class DotNetUtils {
|
||||
public static TypeDef getModuleType(ModuleDef module) {
|
||||
public static TypeDef GetModuleType(ModuleDef module) {
|
||||
return module.GlobalType;
|
||||
}
|
||||
|
||||
public static MethodDef getModuleTypeCctor(ModuleDef module) {
|
||||
public static MethodDef GetModuleTypeCctor(ModuleDef module) {
|
||||
return module.GlobalType.FindStaticConstructor();
|
||||
}
|
||||
|
||||
public static bool isEmpty(MethodDef method) {
|
||||
public static bool IsEmpty(MethodDef method) {
|
||||
if (method.Body == null)
|
||||
return false;
|
||||
foreach (var instr in method.Body.Instructions) {
|
||||
|
@ -80,18 +80,18 @@ namespace de4dot.blocks {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static bool isEmptyObfuscated(MethodDef method) {
|
||||
public static bool IsEmptyObfuscated(MethodDef method) {
|
||||
if (method.Body == null)
|
||||
return false;
|
||||
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)
|
||||
return false;
|
||||
|
||||
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)
|
||||
return null;
|
||||
foreach (var field in typeDef.Fields) {
|
||||
|
@ -101,11 +101,11 @@ namespace de4dot.blocks {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static IEnumerable<MethodDef> findMethods(IEnumerable<MethodDef> methods, string returnType, string[] argsTypes) {
|
||||
return findMethods(methods, returnType, argsTypes, true);
|
||||
public static IEnumerable<MethodDef> FindMethods(IEnumerable<MethodDef> methods, string returnType, string[] argsTypes) {
|
||||
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) {
|
||||
var sig = method.MethodSig;
|
||||
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)
|
||||
return false;
|
||||
var fn = type.FullName;
|
||||
return fn == "System.Delegate" || fn == "System.MulticastDelegate";
|
||||
}
|
||||
|
||||
public static bool derivesFromDelegate(TypeDef type) {
|
||||
return type != null && isDelegate(type.BaseType);
|
||||
public static bool DerivesFromDelegate(TypeDef type) {
|
||||
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;
|
||||
}
|
||||
|
||||
public static string getDllName(string dll) {
|
||||
public static string GetDllName(string dll) {
|
||||
if (dll.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
|
||||
return dll.Substring(0, dll.Length - 4);
|
||||
return dll;
|
||||
}
|
||||
|
||||
public static bool hasPinvokeMethod(TypeDef type, string methodName) {
|
||||
return getPInvokeMethod(type, methodName) != null;
|
||||
public static bool HasPinvokeMethod(TypeDef type, string methodName) {
|
||||
return GetPInvokeMethod(type, methodName) != null;
|
||||
}
|
||||
|
||||
public static MethodDef getPInvokeMethod(TypeDef type, string methodName) {
|
||||
public static MethodDef GetPInvokeMethod(TypeDef type, string methodName) {
|
||||
if (type == null)
|
||||
return null;
|
||||
UTF8String mname = methodName;
|
||||
|
@ -163,69 +163,69 @@ namespace de4dot.blocks {
|
|||
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) {
|
||||
if (isPinvokeMethod(method, dll, funcName))
|
||||
if (IsPinvokeMethod(method, dll, funcName))
|
||||
return method;
|
||||
}
|
||||
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)
|
||||
return false;
|
||||
if (method.ImplMap == null || method.ImplMap.Name.String != funcName)
|
||||
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)
|
||||
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)
|
||||
return null;
|
||||
if (method is MethodDef)
|
||||
return (MethodDef)method;
|
||||
var git = method.DeclaringType.TryGetGenericInstSig();
|
||||
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)
|
||||
return null;
|
||||
if (method is MethodDef)
|
||||
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) {
|
||||
if (isMethod(method, returnType, parameters))
|
||||
if (IsMethod(method, returnType, parameters))
|
||||
return method;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MethodDef getMethod2(ModuleDef module, IMethod method) {
|
||||
public static MethodDef GetMethod2(ModuleDef module, IMethod method) {
|
||||
if (method == 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();
|
||||
var tdr = type as TypeDefOrRefSig;
|
||||
if (tdr == 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;
|
||||
if (td == null) {
|
||||
var tr = type as TypeRef;
|
||||
|
@ -239,15 +239,15 @@ namespace de4dot.blocks {
|
|||
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)
|
||||
return null;
|
||||
if (method is MethodDef)
|
||||
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)
|
||||
return null;
|
||||
if (methodRef is MethodDef)
|
||||
|
@ -255,7 +255,7 @@ namespace de4dot.blocks {
|
|||
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) {
|
||||
if (method.HasImplMap)
|
||||
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)
|
||||
return null;
|
||||
if (field is FieldDef)
|
||||
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)
|
||||
return null;
|
||||
if (fieldRef is FieldDef)
|
||||
|
@ -282,7 +282,7 @@ namespace de4dot.blocks {
|
|||
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)
|
||||
return null;
|
||||
foreach (var field in type.Fields) {
|
||||
|
@ -292,7 +292,7 @@ namespace de4dot.blocks {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static IEnumerable<IMethod> getMethodCalls(MethodDef method) {
|
||||
public static IEnumerable<IMethod> GetMethodCalls(MethodDef method) {
|
||||
var list = new List<IMethod>();
|
||||
if (method.HasBody) {
|
||||
foreach (var instr in method.Body.Instructions) {
|
||||
|
@ -304,7 +304,7 @@ namespace de4dot.blocks {
|
|||
return list;
|
||||
}
|
||||
|
||||
public static bool hasString(MethodDef method, string s) {
|
||||
public static bool HasString(MethodDef method, string s) {
|
||||
if (method == null || method.Body == null)
|
||||
return false;
|
||||
foreach (var instr in method.Body.Instructions) {
|
||||
|
@ -314,7 +314,7 @@ namespace de4dot.blocks {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static IList<string> getCodeStrings(MethodDef method) {
|
||||
public static IList<string> GetCodeStrings(MethodDef method) {
|
||||
var strings = new List<string>();
|
||||
if (method != null && method.Body != null) {
|
||||
foreach (var instr in method.Body.Instructions) {
|
||||
|
@ -325,17 +325,17 @@ namespace de4dot.blocks {
|
|||
return strings;
|
||||
}
|
||||
|
||||
public static Resource getResource(ModuleDef module, string name) {
|
||||
return getResource(module, new List<string> { name });
|
||||
public static Resource GetResource(ModuleDef module, 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)
|
||||
return null;
|
||||
|
||||
var resources = module.Resources;
|
||||
foreach (var tmp in strings) {
|
||||
var resourceName = removeFromNullChar(tmp);
|
||||
var resourceName = RemoveFromNullChar(tmp);
|
||||
if (resourceName == null)
|
||||
continue;
|
||||
UTF8String name = resourceName;
|
||||
|
@ -348,7 +348,7 @@ namespace de4dot.blocks {
|
|||
return null;
|
||||
}
|
||||
|
||||
static string removeFromNullChar(string s) {
|
||||
static string RemoveFromNullChar(string s) {
|
||||
int index = s.IndexOf((char)0);
|
||||
if (index < 0)
|
||||
return s;
|
||||
|
@ -356,7 +356,7 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
// 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);
|
||||
newMethod.Rid = method.Rid;
|
||||
newMethod.DeclaringType2 = method.DeclaringType;
|
||||
|
@ -369,11 +369,11 @@ namespace de4dot.blocks {
|
|||
newMethod.GenericParameters.Add(newGp);
|
||||
}
|
||||
newMethod.Body = new CilBody();
|
||||
copyBodyFromTo(method, newMethod);
|
||||
CopyBodyFromTo(method, 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) {
|
||||
instructions = new List<Instruction>();
|
||||
exceptionHandlers = new List<ExceptionHandler>();
|
||||
|
@ -384,7 +384,7 @@ namespace de4dot.blocks {
|
|||
var oldExHandlers = method.Body.ExceptionHandlers;
|
||||
instructions = new List<Instruction>(oldInstrs.Count);
|
||||
exceptionHandlers = new List<ExceptionHandler>(oldExHandlers.Count);
|
||||
var oldToIndex = Utils.createObjectToIndexDictionary(oldInstrs);
|
||||
var oldToIndex = Utils.CreateObjectToIndexDictionary(oldInstrs);
|
||||
|
||||
foreach (var oldInstr in oldInstrs)
|
||||
instructions.Add(oldInstr.Clone());
|
||||
|
@ -404,24 +404,24 @@ namespace de4dot.blocks {
|
|||
|
||||
foreach (var oldEx in oldExHandlers) {
|
||||
var newEx = new ExceptionHandler(oldEx.HandlerType) {
|
||||
TryStart = getInstruction(instructions, oldToIndex, oldEx.TryStart),
|
||||
TryEnd = getInstruction(instructions, oldToIndex, oldEx.TryEnd),
|
||||
FilterStart = getInstruction(instructions, oldToIndex, oldEx.FilterStart),
|
||||
HandlerStart = getInstruction(instructions, oldToIndex, oldEx.HandlerStart),
|
||||
HandlerEnd = getInstruction(instructions, oldToIndex, oldEx.HandlerEnd),
|
||||
TryStart = GetInstruction(instructions, oldToIndex, oldEx.TryStart),
|
||||
TryEnd = GetInstruction(instructions, oldToIndex, oldEx.TryEnd),
|
||||
FilterStart = GetInstruction(instructions, oldToIndex, oldEx.FilterStart),
|
||||
HandlerStart = GetInstruction(instructions, oldToIndex, oldEx.HandlerStart),
|
||||
HandlerEnd = GetInstruction(instructions, oldToIndex, oldEx.HandlerEnd),
|
||||
CatchType = oldEx.CatchType,
|
||||
};
|
||||
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)
|
||||
return null;
|
||||
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)
|
||||
return;
|
||||
|
||||
|
@ -436,19 +436,19 @@ namespace de4dot.blocks {
|
|||
bodyExceptionHandlers.Add(eh);
|
||||
}
|
||||
|
||||
public static void copyBodyFromTo(MethodDef fromMethod, MethodDef toMethod) {
|
||||
public static void CopyBodyFromTo(MethodDef fromMethod, MethodDef toMethod) {
|
||||
if (fromMethod == toMethod)
|
||||
return;
|
||||
|
||||
IList<Instruction> instructions;
|
||||
IList<ExceptionHandler> exceptionHandlers;
|
||||
copyBody(fromMethod, out instructions, out exceptionHandlers);
|
||||
restoreBody(toMethod, instructions, exceptionHandlers);
|
||||
copyLocalsFromTo(fromMethod, toMethod);
|
||||
updateInstructionOperands(fromMethod, toMethod);
|
||||
CopyBody(fromMethod, out instructions, out exceptionHandlers);
|
||||
RestoreBody(toMethod, instructions, exceptionHandlers);
|
||||
CopyLocalsFromTo(fromMethod, toMethod);
|
||||
UpdateInstructionOperands(fromMethod, toMethod);
|
||||
}
|
||||
|
||||
static void copyLocalsFromTo(MethodDef fromMethod, MethodDef toMethod) {
|
||||
static void CopyLocalsFromTo(MethodDef fromMethod, MethodDef toMethod) {
|
||||
var fromBody = fromMethod.Body;
|
||||
var toBody = toMethod.Body;
|
||||
|
||||
|
@ -457,7 +457,7 @@ namespace de4dot.blocks {
|
|||
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 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)
|
||||
return null;
|
||||
var carg = cattr.ConstructorArguments[arg];
|
||||
|
@ -490,7 +490,7 @@ namespace de4dot.blocks {
|
|||
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) {
|
||||
foreach (var call in method.Body.Instructions) {
|
||||
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
|
||||
|
@ -498,15 +498,15 @@ namespace de4dot.blocks {
|
|||
var methodRef = call.Operand as IMethod;
|
||||
if (methodRef == null)
|
||||
continue;
|
||||
var type = getType(module, methodRef.DeclaringType);
|
||||
var methodDef = getMethod(type, methodRef);
|
||||
var type = GetType(module, methodRef.DeclaringType);
|
||||
var methodDef = GetMethod(type, methodRef);
|
||||
if (methodDef != null)
|
||||
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)
|
||||
return null;
|
||||
if (opcodes.Length == 0)
|
||||
|
@ -524,25 +524,25 @@ namespace de4dot.blocks {
|
|||
return list;
|
||||
}
|
||||
|
||||
public static bool hasReturnValue(IMethod method) {
|
||||
public static bool HasReturnValue(IMethod method) {
|
||||
if (method == null || method.MethodSig == null || method.MethodSig.RetType == null)
|
||||
return false;
|
||||
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)
|
||||
return parameters[index];
|
||||
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)
|
||||
return args[index];
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<TypeSig> getArgs(IMethod method) {
|
||||
public static List<TypeSig> GetArgs(IMethod method) {
|
||||
var sig = method.MethodSig;
|
||||
var args = new List<TypeSig>(sig.Params.Count + 1);
|
||||
if (sig.ImplicitThis)
|
||||
|
@ -552,7 +552,7 @@ namespace de4dot.blocks {
|
|||
return args;
|
||||
}
|
||||
|
||||
public static int getArgsCount(IMethod method) {
|
||||
public static int GetArgsCount(IMethod method) {
|
||||
var sig = method.MethodSig;
|
||||
if (sig == null)
|
||||
return 0;
|
||||
|
@ -562,22 +562,22 @@ namespace de4dot.blocks {
|
|||
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)
|
||||
return types;
|
||||
for (int i = 0; i < types.Count; i++)
|
||||
types[i] = getGenericArgument(typeOwner, methodOwner, types[i]);
|
||||
types[i] = GetGenericArgument(typeOwner, methodOwner, types[i]);
|
||||
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 genMethodArgs = methodOwner == null || methodOwner.GenericInstMethodSig == null ?
|
||||
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++) {
|
||||
if (index < 0 || index >= instructions.Count)
|
||||
return null;
|
||||
|
@ -596,7 +596,7 @@ namespace de4dot.blocks {
|
|||
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));
|
||||
if (isValueType)
|
||||
return new ValueTypeSig(typeRef);
|
||||
|
@ -604,7 +604,7 @@ namespace de4dot.blocks {
|
|||
return new ClassSig(typeRef);
|
||||
}
|
||||
|
||||
public static FrameworkType getFrameworkType(ModuleDefMD module) {
|
||||
public static FrameworkType GetFrameworkType(ModuleDefMD module) {
|
||||
foreach (var modRef in module.GetAssemblyRefs()) {
|
||||
if (modRef.Name != "mscorlib")
|
||||
continue;
|
||||
|
@ -627,7 +627,7 @@ namespace de4dot.blocks {
|
|||
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)
|
||||
return 0;
|
||||
|
||||
|
@ -645,7 +645,7 @@ namespace de4dot.blocks {
|
|||
return count;
|
||||
}
|
||||
|
||||
public static bool callsMethod(MethodDef method, string methodFullName) {
|
||||
public static bool CallsMethod(MethodDef method, string methodFullName) {
|
||||
if (method == null || method.Body == null)
|
||||
return false;
|
||||
|
||||
|
@ -662,25 +662,25 @@ namespace de4dot.blocks {
|
|||
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)
|
||||
return false;
|
||||
|
||||
foreach (var instr in method.Body.Instructions) {
|
||||
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt && instr.OpCode.Code != Code.Newobj)
|
||||
continue;
|
||||
if (isMethod(instr.Operand as IMethod, returnType, parameters))
|
||||
if (IsMethod(instr.Operand as IMethod, returnType, parameters))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static IList<Instruction> getArgPushes(IList<Instruction> instrs, int index) {
|
||||
return getArgPushes(instrs, ref index);
|
||||
public static IList<Instruction> GetArgPushes(IList<Instruction> instrs, int 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)
|
||||
return null;
|
||||
var startInstr = instrs[index];
|
||||
|
@ -707,7 +707,7 @@ namespace de4dot.blocks {
|
|||
|
||||
if (pops != 0) {
|
||||
index++;
|
||||
if (getArgPushes(instrs, ref index) == null)
|
||||
if (GetArgPushes(instrs, ref index) == null)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,21 +31,21 @@ namespace de4dot.blocks {
|
|||
get { return methods.Count; }
|
||||
}
|
||||
|
||||
public void add(uint token, DumpedMethod info) {
|
||||
public void Add(uint token, DumpedMethod info) {
|
||||
methods[token] = info;
|
||||
}
|
||||
|
||||
public DumpedMethod get(MethodDef method) {
|
||||
return get(method.MDToken.ToUInt32());
|
||||
public DumpedMethod Get(MethodDef method) {
|
||||
return Get(method.MDToken.ToUInt32());
|
||||
}
|
||||
|
||||
public DumpedMethod get(uint token) {
|
||||
public DumpedMethod Get(uint token) {
|
||||
DumpedMethod dm;
|
||||
methods.TryGetValue(token, out 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)
|
||||
throw new ArgumentException("Invalid token");
|
||||
methods[dm.token] = dm;
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace de4dot.blocks {
|
|||
this.stackStart = stackStart;
|
||||
}
|
||||
|
||||
public void calculateStackUsage() {
|
||||
public void CalculateStackUsage() {
|
||||
Block block = baseBlock as Block;
|
||||
if (block == null) {
|
||||
stackEnd = stackStart;
|
||||
|
@ -60,17 +60,17 @@ namespace de4dot.blocks {
|
|||
this.sorted = sorted;
|
||||
}
|
||||
|
||||
public List<BaseBlock> fix() {
|
||||
createBlockInfos();
|
||||
createNewList();
|
||||
public List<BaseBlock> Fix() {
|
||||
CreateBlockInfos();
|
||||
CreateNewList();
|
||||
return newList;
|
||||
}
|
||||
|
||||
void createBlockInfos() {
|
||||
void CreateBlockInfos() {
|
||||
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;
|
||||
scanBaseBlock(bb, stackStart);
|
||||
ScanBaseBlock(bb, stackStart);
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
IEnumerable<BaseBlock> getStartBlocks() {
|
||||
IEnumerable<BaseBlock> GetStartBlocks() {
|
||||
if (sorted.Count > 0) {
|
||||
yield return sorted[0];
|
||||
foreach (var bb in sorted) {
|
||||
if (ReferenceEquals(bb, sorted[0]))
|
||||
continue;
|
||||
var block = bb as Block;
|
||||
if (block == null || block.Sources == null || isOneSourceInAnotherScopeBlock(block))
|
||||
if (block == null || block.Sources == null || IsOneSourceInAnotherScopeBlock(block))
|
||||
yield return bb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isOneSourceInAnotherScopeBlock(Block block) {
|
||||
bool IsOneSourceInAnotherScopeBlock(Block block) {
|
||||
foreach (var source in block.Sources) {
|
||||
if (!scopeBlock.isOurBaseBlock(source))
|
||||
if (!scopeBlock.IsOurBaseBlock(source))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void scanBaseBlock(BaseBlock bb, int stackStart) {
|
||||
if (blockInfos.ContainsKey(bb) || !scopeBlock.isOurBaseBlock(bb))
|
||||
void ScanBaseBlock(BaseBlock bb, int stackStart) {
|
||||
if (blockInfos.ContainsKey(bb) || !scopeBlock.IsOurBaseBlock(bb))
|
||||
return;
|
||||
|
||||
var blockInfo = new BlockInfo(bb, stackStart);
|
||||
|
@ -115,38 +115,38 @@ namespace de4dot.blocks {
|
|||
return;
|
||||
}
|
||||
|
||||
blockInfo.calculateStackUsage();
|
||||
blockInfo.CalculateStackUsage();
|
||||
|
||||
foreach (var target in block.getTargets())
|
||||
scanBaseBlock(target, blockInfo.stackEnd);
|
||||
foreach (var target in block.GetTargets())
|
||||
ScanBaseBlock(target, blockInfo.stackEnd);
|
||||
}
|
||||
|
||||
void createNewList() {
|
||||
void CreateNewList() {
|
||||
newList = new List<BaseBlock>(sorted.Count);
|
||||
foreach (var bb in sorted)
|
||||
addToNewList(bb);
|
||||
AddToNewList(bb);
|
||||
if (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]))
|
||||
throw new ApplicationException("Start block is not first block after sorting");
|
||||
}
|
||||
|
||||
void addToNewList(BaseBlock bb) {
|
||||
if (inNewList.ContainsKey(bb) || !scopeBlock.isOurBaseBlock(bb))
|
||||
void AddToNewList(BaseBlock bb) {
|
||||
if (inNewList.ContainsKey(bb) || !scopeBlock.IsOurBaseBlock(bb))
|
||||
return;
|
||||
inNewList[bb] = false;
|
||||
|
||||
var blockInfo = blockInfos[bb];
|
||||
var block = bb as Block;
|
||||
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 {
|
||||
foreach (var source in block.Sources) {
|
||||
if (!scopeBlock.isOurBaseBlock(source))
|
||||
if (!scopeBlock.IsOurBaseBlock(source))
|
||||
continue;
|
||||
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)
|
||||
break;
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ namespace de4dot.blocks {
|
|||
newList.Add(bb);
|
||||
}
|
||||
|
||||
bool isInNewList(IEnumerable<Block> blocks) {
|
||||
bool IsInNewList(IEnumerable<Block> blocks) {
|
||||
foreach (var block in blocks) {
|
||||
if (inNewList.ContainsKey(block) && inNewList[block])
|
||||
return true;
|
||||
|
|
|
@ -26,115 +26,115 @@ namespace de4dot.blocks {
|
|||
IList<TypeSig> genericMethodArgs;
|
||||
bool updated;
|
||||
|
||||
public static ITypeDefOrRef create(ITypeDefOrRef type, GenericInstSig git) {
|
||||
public static ITypeDefOrRef Create(ITypeDefOrRef type, GenericInstSig git) {
|
||||
if (git == null)
|
||||
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)
|
||||
return type;
|
||||
var ts = type as TypeSpec;
|
||||
if (ts == null)
|
||||
return type;
|
||||
var newSig = create(ts.TypeSig, genericArgs);
|
||||
var newSig = Create(ts.TypeSig, genericArgs);
|
||||
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)
|
||||
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) &&
|
||||
(genericMethodArgs == null || genericMethodArgs.Count == 0)))
|
||||
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)
|
||||
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)
|
||||
return field;
|
||||
var newSig = create(field.FieldSig, genericArgs);
|
||||
var newSig = Create(field.FieldSig, genericArgs);
|
||||
if (newSig == field.FieldSig)
|
||||
return field;
|
||||
var module = field.DeclaringType != null ? field.DeclaringType.Module : null;
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
return method;
|
||||
|
||||
var mdr = method as IMethodDefOrRef;
|
||||
if (mdr != null)
|
||||
return create(mdr, git);
|
||||
return Create(mdr, git);
|
||||
|
||||
var ms = method as MethodSpec;
|
||||
if (ms != null)
|
||||
return create(ms, git);
|
||||
return Create(ms, git);
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
public static MethodSpec create(MethodSpec method, GenericInstSig git) {
|
||||
public static MethodSpec Create(MethodSpec method, GenericInstSig git) {
|
||||
if (method == null || git == null)
|
||||
return method;
|
||||
var newMethod = create(method.Method, git);
|
||||
var newInst = create(method.GenericInstMethodSig, git);
|
||||
var newMethod = Create(method.Method, git);
|
||||
var newInst = Create(method.GenericInstMethodSig, git);
|
||||
bool updated = newMethod != method.Method || newInst != method.GenericInstMethodSig;
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
return method;
|
||||
return create(method, git.GenericArguments);
|
||||
return Create(method, git.GenericArguments);
|
||||
}
|
||||
|
||||
public static IMethodDefOrRef create(IMethodDefOrRef method, IList<TypeSig> genericArgs) {
|
||||
return create(method, genericArgs, null);
|
||||
public static IMethodDefOrRef Create(IMethodDefOrRef method, IList<TypeSig> genericArgs) {
|
||||
return Create(method, genericArgs, null);
|
||||
}
|
||||
|
||||
public static IMethodDefOrRef create(IMethodDefOrRef method, GenericInstSig git, IList<TypeSig> genericMethodArgs) {
|
||||
return create(method, git == null ? null : git.GenericArguments, genericMethodArgs);
|
||||
public static IMethodDefOrRef Create(IMethodDefOrRef method, GenericInstSig git, IList<TypeSig> genericMethodArgs) {
|
||||
return Create(method, git == null ? null : git.GenericArguments, genericMethodArgs);
|
||||
}
|
||||
|
||||
// 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)
|
||||
return method;
|
||||
if ((genericArgs == null || genericArgs.Count == 0) && (genericMethodArgs == null || genericMethodArgs.Count == 0))
|
||||
|
@ -144,7 +144,7 @@ namespace de4dot.blocks {
|
|||
if (sig == null)
|
||||
return method;
|
||||
|
||||
var newSig = new GenericArgsSubstitutor(genericArgs, genericMethodArgs).create(sig);
|
||||
var newSig = new GenericArgsSubstitutor(genericArgs, genericMethodArgs).Create(sig);
|
||||
if (newSig == sig)
|
||||
return method;
|
||||
|
||||
|
@ -163,12 +163,12 @@ namespace de4dot.blocks {
|
|||
this.updated = false;
|
||||
}
|
||||
|
||||
TypeSig create(TypeSig type) {
|
||||
var newType = create2(type);
|
||||
TypeSig Create(TypeSig type) {
|
||||
var newType = Create2(type);
|
||||
return updated ? newType : type;
|
||||
}
|
||||
|
||||
TypeSig create2(TypeSig type) {
|
||||
TypeSig Create2(TypeSig type) {
|
||||
if (type == null)
|
||||
return type;
|
||||
TypeSig result;
|
||||
|
@ -197,11 +197,11 @@ namespace de4dot.blocks {
|
|||
break;
|
||||
|
||||
case ElementType.Ptr:
|
||||
result = new PtrSig(create2(type.Next));
|
||||
result = new PtrSig(Create2(type.Next));
|
||||
break;
|
||||
|
||||
case ElementType.ByRef:
|
||||
result = new ByRefSig(create2(type.Next));
|
||||
result = new ByRefSig(Create2(type.Next));
|
||||
break;
|
||||
|
||||
case ElementType.Array:
|
||||
|
@ -210,11 +210,11 @@ namespace de4dot.blocks {
|
|||
break;
|
||||
|
||||
case ElementType.SZArray:
|
||||
result = new SZArraySig(create2(type.Next));
|
||||
result = new SZArraySig(Create2(type.Next));
|
||||
break;
|
||||
|
||||
case ElementType.Pinned:
|
||||
result = new PinnedSig(create2(type.Next));
|
||||
result = new PinnedSig(Create2(type.Next));
|
||||
break;
|
||||
|
||||
case ElementType.ValueType:
|
||||
|
@ -244,9 +244,9 @@ namespace de4dot.blocks {
|
|||
|
||||
case ElementType.GenericInst:
|
||||
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++)
|
||||
newGis.GenericArguments.Add(create2(gis.GenericArguments[i]));
|
||||
newGis.GenericArguments.Add(Create2(gis.GenericArguments[i]));
|
||||
result = newGis;
|
||||
break;
|
||||
|
||||
|
@ -267,7 +267,7 @@ namespace de4dot.blocks {
|
|||
break;
|
||||
|
||||
case ElementType.FnPtr:
|
||||
result = new FnPtrSig(create(((FnPtrSig)type).MethodSig));
|
||||
result = new FnPtrSig(Create(((FnPtrSig)type).MethodSig));
|
||||
break;
|
||||
|
||||
case ElementType.End:
|
||||
|
@ -282,31 +282,31 @@ namespace de4dot.blocks {
|
|||
return result;
|
||||
}
|
||||
|
||||
MethodSig create(MethodSig sig) {
|
||||
MethodSig Create(MethodSig sig) {
|
||||
if (sig == null)
|
||||
return sig;
|
||||
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++)
|
||||
newSig.Params.Add(create2(sig.Params[i]));
|
||||
newSig.Params.Add(Create2(sig.Params[i]));
|
||||
newSig.GenParamCount = sig.GenParamCount;
|
||||
if (sig.ParamsAfterSentinel != null) {
|
||||
newSig.ParamsAfterSentinel = new List<TypeSig>();
|
||||
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;
|
||||
}
|
||||
|
||||
GenericInstMethodSig create(GenericInstMethodSig sig) {
|
||||
GenericInstMethodSig Create(GenericInstMethodSig sig) {
|
||||
var newSig = new GenericInstMethodSig();
|
||||
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;
|
||||
}
|
||||
|
||||
FieldSig create(FieldSig sig) {
|
||||
var newSig = new FieldSig(create2(sig.Type));
|
||||
FieldSig Create(FieldSig sig) {
|
||||
var newSig = new FieldSig(Create2(sig.Type));
|
||||
return updated ? newSig : sig;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,11 +44,11 @@ namespace de4dot.blocks {
|
|||
|
||||
// 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.
|
||||
public static Local getLocalVar(IList<Local> locals, Instr instr) {
|
||||
public static Local GetLocalVar(IList<Local> locals, Instr instr) {
|
||||
return instr.Instruction.GetLocal(locals);
|
||||
}
|
||||
|
||||
static public bool isFallThrough(OpCode opCode) {
|
||||
static public bool IsFallThrough(OpCode opCode) {
|
||||
switch (opCode.FlowControl) {
|
||||
case FlowControl.Call:
|
||||
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
|
||||
public bool isSimpleLoad() {
|
||||
public bool IsSimpleLoad() {
|
||||
switch (OpCode.Code) {
|
||||
case Code.Ldarg:
|
||||
case Code.Ldarg_S:
|
||||
|
@ -103,55 +103,55 @@ namespace de4dot.blocks {
|
|||
}
|
||||
}
|
||||
|
||||
public bool isLdcI4() {
|
||||
public bool IsLdcI4() {
|
||||
return instruction.IsLdcI4();
|
||||
}
|
||||
|
||||
public int getLdcI4Value() {
|
||||
public int GetLdcI4Value() {
|
||||
return instruction.GetLdcI4Value();
|
||||
}
|
||||
|
||||
public bool isLdarg() {
|
||||
public bool IsLdarg() {
|
||||
return instruction.IsLdarg();
|
||||
}
|
||||
|
||||
public bool isStloc() {
|
||||
public bool IsStloc() {
|
||||
return instruction.IsStloc();
|
||||
}
|
||||
|
||||
public bool isLdloc() {
|
||||
public bool IsLdloc() {
|
||||
return instruction.IsLdloc();
|
||||
}
|
||||
|
||||
public bool isNop() {
|
||||
public bool IsNop() {
|
||||
return OpCode == OpCodes.Nop;
|
||||
}
|
||||
|
||||
public bool isPop() {
|
||||
public bool IsPop() {
|
||||
return OpCode == OpCodes.Pop;
|
||||
}
|
||||
|
||||
public bool isLeave() {
|
||||
public bool IsLeave() {
|
||||
return instruction.IsLeave();
|
||||
}
|
||||
|
||||
public bool isBr() {
|
||||
public bool IsBr() {
|
||||
return instruction.IsBr();
|
||||
}
|
||||
|
||||
public bool isBrfalse() {
|
||||
public bool IsBrfalse() {
|
||||
return instruction.IsBrfalse();
|
||||
}
|
||||
|
||||
public bool isBrtrue() {
|
||||
public bool IsBrtrue() {
|
||||
return instruction.IsBrtrue();
|
||||
}
|
||||
|
||||
public bool isConditionalBranch() {
|
||||
public bool IsConditionalBranch() {
|
||||
return instruction.IsConditionalBranch();
|
||||
}
|
||||
|
||||
public bool getFlippedBranchOpCode(out OpCode opcode) {
|
||||
public bool GetFlippedBranchOpCode(out OpCode opcode) {
|
||||
switch (OpCode.Code) {
|
||||
case Code.Bge: opcode = OpCodes.Blt; 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;
|
||||
if (!getFlippedBranchOpCode(out opcode))
|
||||
if (!GetFlippedBranchOpCode(out opcode))
|
||||
throw new ApplicationException("Can't flip conditional since it's not a supported conditional instruction");
|
||||
instruction.OpCode = opcode;
|
||||
}
|
||||
|
||||
// Returns true if we can flip a conditional branch
|
||||
public bool canFlipConditionalBranch() {
|
||||
public bool CanFlipConditionalBranch() {
|
||||
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) {
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
|
|
|
@ -33,44 +33,44 @@ namespace de4dot.blocks {
|
|||
this.exceptionHandlers = exceptionHandlers;
|
||||
this.branches = new Dictionary<int, List<int>>();
|
||||
|
||||
createInstrToIndex();
|
||||
createBranches();
|
||||
createExceptionBranches();
|
||||
CreateInstrToIndex();
|
||||
CreateBranches();
|
||||
CreateExceptionBranches();
|
||||
}
|
||||
|
||||
void createInstrToIndex() {
|
||||
void CreateInstrToIndex() {
|
||||
instrToIndex = new Dictionary<Instruction, int>();
|
||||
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
instrToIndex[instructions[i]] = i;
|
||||
}
|
||||
|
||||
List<int> getBranchTargetList(int index) {
|
||||
List<int> GetBranchTargetList(int index) {
|
||||
List<int> targetsList;
|
||||
if (!branches.TryGetValue(index, out targetsList))
|
||||
branches[index] = targetsList = new List<int>();
|
||||
return targetsList;
|
||||
}
|
||||
|
||||
void markAsBranchTarget(Instruction instr) {
|
||||
void MarkAsBranchTarget(Instruction instr) {
|
||||
if (instr == null)
|
||||
return;
|
||||
|
||||
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) {
|
||||
markAsBranchTarget(eh.TryStart);
|
||||
markAsBranchTarget(eh.TryEnd);
|
||||
markAsBranchTarget(eh.FilterStart);
|
||||
markAsBranchTarget(eh.HandlerStart);
|
||||
markAsBranchTarget(eh.HandlerEnd);
|
||||
MarkAsBranchTarget(eh.TryStart);
|
||||
MarkAsBranchTarget(eh.TryEnd);
|
||||
MarkAsBranchTarget(eh.FilterStart);
|
||||
MarkAsBranchTarget(eh.HandlerStart);
|
||||
MarkAsBranchTarget(eh.HandlerEnd);
|
||||
}
|
||||
}
|
||||
|
||||
void createBranches() {
|
||||
void CreateBranches() {
|
||||
for (int i = 0; i < instructions.Count; i++) {
|
||||
var instr = instructions[i];
|
||||
|
||||
|
@ -113,13 +113,13 @@ namespace de4dot.blocks {
|
|||
targets.Add(i + 1);
|
||||
for (int j = 0; j < targets.Count; 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;
|
||||
for (var i = 0; i < instructions.Count; i++) {
|
||||
List<int> branchSources;
|
||||
|
@ -128,7 +128,7 @@ namespace de4dot.blocks {
|
|||
allBlocks.Add(block);
|
||||
}
|
||||
|
||||
block.add(new Instr(this.instructions[i]));
|
||||
block.Add(new Instr(this.instructions[i]));
|
||||
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
|
||||
// block's Targets field is updated, not the Instruction's Operand field.
|
||||
// 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++) {
|
||||
var block = allBlocks[i];
|
||||
var lastInstr = block.LastInstr;
|
||||
|
@ -160,15 +160,15 @@ namespace de4dot.blocks {
|
|||
break;
|
||||
}
|
||||
|
||||
if (i + 1 < allBlocks.Count && Instr.isFallThrough(lastInstr.OpCode))
|
||||
if (i + 1 < allBlocks.Count && Instr.IsFallThrough(lastInstr.OpCode))
|
||||
block.FallThrough = allBlocks[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the sources field of each block
|
||||
void fixBlockSources(List<Block> allBlocks) {
|
||||
void FixBlockSources(List<Block> 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>>();
|
||||
foreach (var eh in exceptionHandlers) {
|
||||
List<ExceptionHandler> handlers;
|
||||
|
@ -220,8 +220,8 @@ namespace de4dot.blocks {
|
|||
|
||||
// Same start instruction. The nested one is the one that ends earliest,
|
||||
// so it should be sorted before the outer one.
|
||||
ai = getInstrIndex(a[0].TryEnd);
|
||||
bi = getInstrIndex(b[0].TryEnd);
|
||||
ai = GetInstrIndex(a[0].TryEnd);
|
||||
bi = GetInstrIndex(b[0].TryEnd);
|
||||
if (ai < bi) return -1;
|
||||
if (ai > bi) return 1;
|
||||
|
||||
|
@ -245,7 +245,7 @@ namespace de4dot.blocks {
|
|||
|
||||
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)
|
||||
throw new ApplicationException("Invalid start and/or end index");
|
||||
if (blocksLeft.Count != 0) {
|
||||
|
@ -256,7 +256,7 @@ namespace de4dot.blocks {
|
|||
blocksLeft.Add(new BaseBlockInfo(start, end, bb));
|
||||
}
|
||||
|
||||
int findStart(int instrIndex) {
|
||||
int FindStart(int instrIndex) {
|
||||
for (int i = 0; i < blocksLeft.Count; i++) {
|
||||
if (blocksLeft[i].startInstr == instrIndex)
|
||||
return i;
|
||||
|
@ -264,7 +264,7 @@ namespace de4dot.blocks {
|
|||
throw new ApplicationException("Could not find start BaseBlockInfo");
|
||||
}
|
||||
|
||||
int findEnd(int instrIndex) {
|
||||
int FindEnd(int instrIndex) {
|
||||
for (int i = 0; i < blocksLeft.Count; i++) {
|
||||
if (blocksLeft[i].endInstr == instrIndex)
|
||||
return i;
|
||||
|
@ -272,14 +272,14 @@ namespace de4dot.blocks {
|
|||
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)
|
||||
throw new ApplicationException("Invalid startInstr and/or endInstr");
|
||||
|
||||
var rv = new List<BaseBlock>();
|
||||
|
||||
startIndex = findStart(startInstr);
|
||||
endIndex = findEnd(endInstr);
|
||||
startIndex = FindStart(startInstr);
|
||||
endIndex = FindEnd(endInstr);
|
||||
|
||||
for (int i = startIndex; i <= endIndex; i++)
|
||||
rv.Add(blocksLeft[i].baseBlock);
|
||||
|
@ -288,13 +288,13 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
// 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)
|
||||
return new List<BaseBlock>();
|
||||
|
||||
int startIndex, endIndex;
|
||||
var rv = getBlocks(startInstr, endInstr, out startIndex, out endIndex);
|
||||
updateParent(rv, bb);
|
||||
var rv = GetBlocks(startInstr, endInstr, out startIndex, out endIndex);
|
||||
UpdateParent(rv, bb);
|
||||
|
||||
var bbi = new BaseBlockInfo(blocksLeft[startIndex].startInstr, blocksLeft[endIndex].endInstr, bb);
|
||||
blocksLeft.RemoveRange(startIndex, endIndex - startIndex + 1);
|
||||
|
@ -303,78 +303,78 @@ namespace de4dot.blocks {
|
|||
return rv;
|
||||
}
|
||||
|
||||
public List<BaseBlock> getBlocks(ScopeBlock parent) {
|
||||
public List<BaseBlock> GetBlocks(ScopeBlock parent) {
|
||||
if (blocksLeft.Count == 0)
|
||||
return new List<BaseBlock>();
|
||||
int startIndex, endIndex;
|
||||
var lb = getBlocks(0, blocksLeft[blocksLeft.Count - 1].endInstr, out startIndex, out endIndex);
|
||||
return updateParent(lb, parent);
|
||||
var lb = GetBlocks(0, blocksLeft[blocksLeft.Count - 1].endInstr, out startIndex, out endIndex);
|
||||
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)
|
||||
bb.Parent = parent;
|
||||
return lb;
|
||||
}
|
||||
}
|
||||
|
||||
BaseBlocksList createBaseBlockList(List<Block> allBlocks, List<List<ExceptionHandler>> exSorted) {
|
||||
BaseBlocksList CreateBaseBlockList(List<Block> allBlocks, List<List<ExceptionHandler>> exSorted) {
|
||||
var bbl = new BaseBlocksList();
|
||||
foreach (var block in allBlocks) {
|
||||
int start = instrToIndex[block.FirstInstr.Instruction];
|
||||
int end = instrToIndex[block.LastInstr.Instruction];
|
||||
bbl.add(block, start, end);
|
||||
bbl.Add(block, start, end);
|
||||
}
|
||||
|
||||
foreach (var exHandlers in exSorted) {
|
||||
var tryBlock = new TryBlock();
|
||||
var tryStart = instrToIndex[exHandlers[0].TryStart];
|
||||
var tryEnd = getInstrIndex(exHandlers[0].TryEnd) - 1;
|
||||
tryBlock.BaseBlocks = bbl.replace(tryStart, tryEnd, tryBlock);
|
||||
var tryEnd = GetInstrIndex(exHandlers[0].TryEnd) - 1;
|
||||
tryBlock.BaseBlocks = bbl.Replace(tryStart, tryEnd, tryBlock);
|
||||
|
||||
foreach (var exHandler in exHandlers) {
|
||||
var tryHandlerBlock = new TryHandlerBlock(exHandler);
|
||||
tryBlock.addTryHandler(tryHandlerBlock);
|
||||
tryBlock.AddTryHandler(tryHandlerBlock);
|
||||
|
||||
int filterStart = -1, handlerStart = -1, handlerEnd = -1;
|
||||
|
||||
if (exHandler.FilterStart != null) {
|
||||
filterStart = instrToIndex[exHandler.FilterStart];
|
||||
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];
|
||||
handlerEnd = getInstrIndex(exHandler.HandlerEnd) - 1;
|
||||
tryHandlerBlock.HandlerBlock.BaseBlocks = bbl.replace(handlerStart, handlerEnd, tryHandlerBlock.HandlerBlock);
|
||||
handlerEnd = GetInstrIndex(exHandler.HandlerEnd) - 1;
|
||||
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;
|
||||
}
|
||||
|
||||
int getInstrIndex(Instruction instruction) {
|
||||
int GetInstrIndex(Instruction instruction) {
|
||||
if (instruction == null)
|
||||
return instructions.Count;
|
||||
return instrToIndex[instruction];
|
||||
}
|
||||
|
||||
public MethodBlocks parse() {
|
||||
public MethodBlocks Parse() {
|
||||
var instrToBlock = new List<Block>(instructions.Count);
|
||||
var allBlocks = new List<Block>();
|
||||
findBlocks(instrToBlock, allBlocks);
|
||||
fixBranchTargets(instrToBlock, allBlocks);
|
||||
fixBlockSources(allBlocks);
|
||||
var exSorted = getSortedExceptionInfos();
|
||||
var bbl = createBaseBlockList(allBlocks, exSorted);
|
||||
FindBlocks(instrToBlock, allBlocks);
|
||||
FixBranchTargets(instrToBlock, allBlocks);
|
||||
FixBlockSources(allBlocks);
|
||||
var exSorted = GetSortedExceptionInfos();
|
||||
var bbl = CreateBaseBlockList(allBlocks, exSorted);
|
||||
|
||||
foreach (var block in allBlocks)
|
||||
block.removeLastBr();
|
||||
block.RemoveLastBr();
|
||||
|
||||
var mb = new MethodBlocks();
|
||||
mb.BaseBlocks = bbl.getBlocks(mb);
|
||||
mb.BaseBlocks = bbl.GetBlocks(mb);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,23 +32,23 @@ namespace de4dot.blocks {
|
|||
get { return tokenToValue.Count; }
|
||||
}
|
||||
|
||||
public IEnumerable<TypeDef> getKeys() {
|
||||
public IEnumerable<TypeDef> GetKeys() {
|
||||
return tokenToKey.Values;
|
||||
}
|
||||
|
||||
public IEnumerable<TValue> getValues() {
|
||||
public IEnumerable<TValue> GetValues() {
|
||||
return tokenToValue.Values;
|
||||
}
|
||||
|
||||
ScopeAndTokenKey getTokenKey(TypeDef typeDef) {
|
||||
ScopeAndTokenKey GetTokenKey(TypeDef typeDef) {
|
||||
return new ScopeAndTokenKey(typeDef);
|
||||
}
|
||||
|
||||
public TValue find(IType typeRef) {
|
||||
public TValue Find(IType typeRef) {
|
||||
TValue value;
|
||||
var typeDef = typeRef as TypeDef;
|
||||
if (typeDef != null)
|
||||
tokenToValue.TryGetValue(getTokenKey(typeDef), out value);
|
||||
tokenToValue.TryGetValue(GetTokenKey(typeDef), out value);
|
||||
else if (typeRef != null)
|
||||
refToValue.TryGetValue(typeRef, out value);
|
||||
else
|
||||
|
@ -56,23 +56,23 @@ namespace de4dot.blocks {
|
|||
return value;
|
||||
}
|
||||
|
||||
public TValue findAny(IType type) {
|
||||
public TValue FindAny(IType type) {
|
||||
TValue value;
|
||||
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;
|
||||
|
||||
refToValue.TryGetValue(type, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void add(TypeDef typeDef, TValue value) {
|
||||
var tokenKey = getTokenKey(typeDef);
|
||||
public void Add(TypeDef typeDef, TValue value) {
|
||||
var tokenKey = GetTokenKey(typeDef);
|
||||
tokenToValue[tokenKey] = value;
|
||||
tokenToKey[tokenKey] = typeDef;
|
||||
|
||||
if (!refToValue.ContainsKey(typeDef) ||
|
||||
getAccessibilityOrder(typeDef) < getAccessibilityOrder(refToKey[typeDef])) {
|
||||
GetAccessibilityOrder(typeDef) < GetAccessibilityOrder(refToKey[typeDef])) {
|
||||
refToKey[typeDef] = typeDef;
|
||||
refToValue[typeDef] = value;
|
||||
}
|
||||
|
@ -89,11 +89,11 @@ namespace de4dot.blocks {
|
|||
60, // NestedFamANDAssem
|
||||
30, // NestedFamORAssem
|
||||
};
|
||||
static int getAccessibilityOrder(TypeDef typeDef) {
|
||||
static int GetAccessibilityOrder(TypeDef typeDef) {
|
||||
return accessibilityOrder[(int)typeDef.Attributes & 7];
|
||||
}
|
||||
|
||||
public void onTypesRenamed() {
|
||||
public void OnTypesRenamed() {
|
||||
var newTypeRefToValue = new Dictionary<IType, TValue>(refToValue.Count);
|
||||
foreach (var kvp in refToValue)
|
||||
newTypeRefToValue[kvp.Key] = kvp.Value;
|
||||
|
@ -111,48 +111,48 @@ namespace de4dot.blocks {
|
|||
get { return tokenToValue.Count; }
|
||||
}
|
||||
|
||||
public IEnumerable<FieldDef> getKeys() {
|
||||
public IEnumerable<FieldDef> GetKeys() {
|
||||
return tokenToKey.Values;
|
||||
}
|
||||
|
||||
public IEnumerable<TValue> getValues() {
|
||||
public IEnumerable<TValue> GetValues() {
|
||||
return tokenToValue.Values;
|
||||
}
|
||||
|
||||
ScopeAndTokenKey getTokenKey(FieldDef fieldDef) {
|
||||
ScopeAndTokenKey GetTokenKey(FieldDef 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;
|
||||
var fieldDef = fieldRef as FieldDef;
|
||||
if (fieldDef != null)
|
||||
tokenToValue.TryGetValue(getTokenKey(fieldDef), out value);
|
||||
tokenToValue.TryGetValue(GetTokenKey(fieldDef), out value);
|
||||
else
|
||||
refToValue.TryGetValue(getRefKey(fieldRef), out value);
|
||||
refToValue.TryGetValue(GetRefKey(fieldRef), out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public TValue findAny(IField fieldRef) {
|
||||
public TValue FindAny(IField fieldRef) {
|
||||
TValue value;
|
||||
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;
|
||||
|
||||
refToValue.TryGetValue(getRefKey(fieldRef), out value);
|
||||
refToValue.TryGetValue(GetRefKey(fieldRef), out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void add(FieldDef fieldDef, TValue value) {
|
||||
var tokenKey = getTokenKey(fieldDef);
|
||||
public void Add(FieldDef fieldDef, TValue value) {
|
||||
var tokenKey = GetTokenKey(fieldDef);
|
||||
tokenToValue[tokenKey] = value;
|
||||
tokenToKey[tokenKey] = fieldDef;
|
||||
|
||||
var refKey = getRefKey(fieldDef);
|
||||
var refKey = GetRefKey(fieldDef);
|
||||
if (!refToValue.ContainsKey(refKey) ||
|
||||
getAccessibilityOrder(fieldDef) < getAccessibilityOrder(refToKey[refKey])) {
|
||||
GetAccessibilityOrder(fieldDef) < GetAccessibilityOrder(refToKey[refKey])) {
|
||||
refToKey[refKey] = fieldDef;
|
||||
refToValue[refKey] = value;
|
||||
}
|
||||
|
@ -169,26 +169,26 @@ namespace de4dot.blocks {
|
|||
0, // Public
|
||||
70, // <reserved>
|
||||
};
|
||||
static int getAccessibilityOrder(FieldDef fieldDef) {
|
||||
static int GetAccessibilityOrder(FieldDef fieldDef) {
|
||||
return accessibilityOrder[(int)fieldDef.Attributes & 7];
|
||||
}
|
||||
|
||||
public void onTypesRenamed() {
|
||||
public void OnTypesRenamed() {
|
||||
var newFieldRefToDef = new Dictionary<IFieldRefKey, TValue>(refToValue.Count);
|
||||
foreach (var kvp in refToValue)
|
||||
newFieldRefToDef[getRefKey((FieldDef)kvp.Key.FieldRef)] = kvp.Value;
|
||||
newFieldRefToDef[GetRefKey((FieldDef)kvp.Key.FieldRef)] = kvp.Value;
|
||||
refToValue = newFieldRefToDef;
|
||||
}
|
||||
}
|
||||
|
||||
public class FieldDefDict<TValue> : FieldDefDictBase<TValue> {
|
||||
internal override IFieldRefKey getRefKey(IField fieldRef) {
|
||||
internal override IFieldRefKey GetRefKey(IField fieldRef) {
|
||||
return new FieldRefKey(fieldRef);
|
||||
}
|
||||
}
|
||||
|
||||
public class FieldDefAndDeclaringTypeDict<TValue> : FieldDefDictBase<TValue> {
|
||||
internal override IFieldRefKey getRefKey(IField fieldRef) {
|
||||
internal override IFieldRefKey GetRefKey(IField fieldRef) {
|
||||
return new FieldRefAndDeclaringTypeKey(fieldRef);
|
||||
}
|
||||
}
|
||||
|
@ -203,48 +203,48 @@ namespace de4dot.blocks {
|
|||
get { return tokenToValue.Count; }
|
||||
}
|
||||
|
||||
public IEnumerable<MethodDef> getKeys() {
|
||||
public IEnumerable<MethodDef> GetKeys() {
|
||||
return tokenToKey.Values;
|
||||
}
|
||||
|
||||
public IEnumerable<TValue> getValues() {
|
||||
public IEnumerable<TValue> GetValues() {
|
||||
return tokenToValue.Values;
|
||||
}
|
||||
|
||||
ScopeAndTokenKey getTokenKey(MethodDef methodDef) {
|
||||
ScopeAndTokenKey GetTokenKey(MethodDef 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;
|
||||
var methodDef = methodRef as MethodDef;
|
||||
if (methodDef != null)
|
||||
tokenToValue.TryGetValue(getTokenKey(methodDef), out value);
|
||||
tokenToValue.TryGetValue(GetTokenKey(methodDef), out value);
|
||||
else
|
||||
refToValue.TryGetValue(getRefKey(methodRef), out value);
|
||||
refToValue.TryGetValue(GetRefKey(methodRef), out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public TValue findAny(IMethod methodRef) {
|
||||
public TValue FindAny(IMethod methodRef) {
|
||||
TValue value;
|
||||
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;
|
||||
|
||||
refToValue.TryGetValue(getRefKey(methodRef), out value);
|
||||
refToValue.TryGetValue(GetRefKey(methodRef), out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void add(MethodDef methodDef, TValue value) {
|
||||
var tokenKey = getTokenKey(methodDef);
|
||||
public void Add(MethodDef methodDef, TValue value) {
|
||||
var tokenKey = GetTokenKey(methodDef);
|
||||
tokenToValue[tokenKey] = value;
|
||||
tokenToKey[tokenKey] = methodDef;
|
||||
|
||||
var refKey = getRefKey(methodDef);
|
||||
var refKey = GetRefKey(methodDef);
|
||||
if (!refToValue.ContainsKey(refKey) ||
|
||||
getAccessibilityOrder(methodDef) < getAccessibilityOrder(refToKey[refKey])) {
|
||||
GetAccessibilityOrder(methodDef) < GetAccessibilityOrder(refToKey[refKey])) {
|
||||
refToKey[refKey] = methodDef;
|
||||
refToValue[refKey] = value;
|
||||
}
|
||||
|
@ -261,26 +261,26 @@ namespace de4dot.blocks {
|
|||
0, // Public
|
||||
70, // <reserved>
|
||||
};
|
||||
static int getAccessibilityOrder(MethodDef methodDef) {
|
||||
static int GetAccessibilityOrder(MethodDef methodDef) {
|
||||
return accessibilityOrder[(int)methodDef.Attributes & 7];
|
||||
}
|
||||
|
||||
public void onTypesRenamed() {
|
||||
public void OnTypesRenamed() {
|
||||
var newFieldRefToDef = new Dictionary<IMethodRefKey, TValue>(refToValue.Count);
|
||||
foreach (var kvp in refToValue)
|
||||
newFieldRefToDef[getRefKey((MethodDef)kvp.Key.MethodRef)] = kvp.Value;
|
||||
newFieldRefToDef[GetRefKey((MethodDef)kvp.Key.MethodRef)] = kvp.Value;
|
||||
refToValue = newFieldRefToDef;
|
||||
}
|
||||
}
|
||||
|
||||
public class MethodDefDict<TValue> : MethodDefDictBase<TValue> {
|
||||
internal override IMethodRefKey getRefKey(IMethod methodRef) {
|
||||
internal override IMethodRefKey GetRefKey(IMethod methodRef) {
|
||||
return new MethodRefKey(methodRef);
|
||||
}
|
||||
}
|
||||
|
||||
public class MethodDefAndDeclaringTypeDict<TValue> : MethodDefDictBase<TValue> {
|
||||
internal override IMethodRefKey getRefKey(IMethod methodRef) {
|
||||
internal override IMethodRefKey GetRefKey(IMethod methodRef) {
|
||||
return new MethodRefAndDeclaringTypeKey(methodRef);
|
||||
}
|
||||
}
|
||||
|
@ -294,59 +294,59 @@ namespace de4dot.blocks {
|
|||
get { return tokenToValue.Count; }
|
||||
}
|
||||
|
||||
public IEnumerable<EventDef> getKeys() {
|
||||
public IEnumerable<EventDef> GetKeys() {
|
||||
return tokenToKey.Values;
|
||||
}
|
||||
|
||||
public IEnumerable<TValue> getValues() {
|
||||
public IEnumerable<TValue> GetValues() {
|
||||
return tokenToValue.Values;
|
||||
}
|
||||
|
||||
ScopeAndTokenKey getTokenKey(EventDef eventRef) {
|
||||
ScopeAndTokenKey GetTokenKey(EventDef 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;
|
||||
tokenToValue.TryGetValue(getTokenKey(eventRef), out value);
|
||||
tokenToValue.TryGetValue(GetTokenKey(eventRef), out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public TValue findAny(EventDef eventRef) {
|
||||
public TValue FindAny(EventDef eventRef) {
|
||||
TValue value;
|
||||
if (tokenToValue.TryGetValue(getTokenKey(eventRef), out value))
|
||||
if (tokenToValue.TryGetValue(GetTokenKey(eventRef), out value))
|
||||
return value;
|
||||
|
||||
refToValue.TryGetValue(getRefKey(eventRef), out value);
|
||||
refToValue.TryGetValue(GetRefKey(eventRef), out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void add(EventDef eventDef, TValue value) {
|
||||
var tokenKey = getTokenKey(eventDef);
|
||||
public void Add(EventDef eventDef, TValue value) {
|
||||
var tokenKey = GetTokenKey(eventDef);
|
||||
tokenToValue[tokenKey] = value;
|
||||
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);
|
||||
foreach (var kvp in refToValue)
|
||||
newFieldRefToDef[getRefKey((EventDef)kvp.Key.EventDef)] = kvp.Value;
|
||||
newFieldRefToDef[GetRefKey((EventDef)kvp.Key.EventDef)] = kvp.Value;
|
||||
refToValue = newFieldRefToDef;
|
||||
}
|
||||
}
|
||||
|
||||
public class EventDefDict<TValue> : EventDefDictBase<TValue> {
|
||||
internal override IEventRefKey getRefKey(EventDef eventRef) {
|
||||
internal override IEventRefKey GetRefKey(EventDef eventRef) {
|
||||
return new EventRefKey(eventRef);
|
||||
}
|
||||
}
|
||||
|
||||
public class EventDefAndDeclaringTypeDict<TValue> : EventDefDictBase<TValue> {
|
||||
internal override IEventRefKey getRefKey(EventDef eventRef) {
|
||||
internal override IEventRefKey GetRefKey(EventDef eventRef) {
|
||||
return new EventRefAndDeclaringTypeKey(eventRef);
|
||||
}
|
||||
}
|
||||
|
@ -360,59 +360,59 @@ namespace de4dot.blocks {
|
|||
get { return tokenToValue.Count; }
|
||||
}
|
||||
|
||||
public IEnumerable<PropertyDef> getKeys() {
|
||||
public IEnumerable<PropertyDef> GetKeys() {
|
||||
return tokenToKey.Values;
|
||||
}
|
||||
|
||||
public IEnumerable<TValue> getValues() {
|
||||
public IEnumerable<TValue> GetValues() {
|
||||
return tokenToValue.Values;
|
||||
}
|
||||
|
||||
ScopeAndTokenKey getTokenKey(PropertyDef propertyRef) {
|
||||
ScopeAndTokenKey GetTokenKey(PropertyDef 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;
|
||||
tokenToValue.TryGetValue(getTokenKey(propRef), out value);
|
||||
tokenToValue.TryGetValue(GetTokenKey(propRef), out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public TValue findAny(PropertyDef propRef) {
|
||||
public TValue FindAny(PropertyDef propRef) {
|
||||
TValue value;
|
||||
if (tokenToValue.TryGetValue(getTokenKey(propRef), out value))
|
||||
if (tokenToValue.TryGetValue(GetTokenKey(propRef), out value))
|
||||
return value;
|
||||
|
||||
refToValue.TryGetValue(getRefKey(propRef), out value);
|
||||
refToValue.TryGetValue(GetRefKey(propRef), out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void add(PropertyDef propDef, TValue value) {
|
||||
var tokenKey = getTokenKey(propDef);
|
||||
public void Add(PropertyDef propDef, TValue value) {
|
||||
var tokenKey = GetTokenKey(propDef);
|
||||
tokenToValue[tokenKey] = value;
|
||||
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);
|
||||
foreach (var kvp in refToValue)
|
||||
newFieldRefToDef[getRefKey((PropertyDef)kvp.Key.PropertyDef)] = kvp.Value;
|
||||
newFieldRefToDef[GetRefKey((PropertyDef)kvp.Key.PropertyDef)] = kvp.Value;
|
||||
refToValue = newFieldRefToDef;
|
||||
}
|
||||
}
|
||||
|
||||
public class PropertyDefDict<TValue> : PropertyDefDictBase<TValue> {
|
||||
internal override IPropertyRefKey getRefKey(PropertyDef propRef) {
|
||||
internal override IPropertyRefKey GetRefKey(PropertyDef propRef) {
|
||||
return new PropertyRefKey(propRef);
|
||||
}
|
||||
}
|
||||
|
||||
public class PropertyDefAndDeclaringTypeDict<TValue> : PropertyDefDictBase<TValue> {
|
||||
internal override IPropertyRefKey getRefKey(PropertyDef propRef) {
|
||||
internal override IPropertyRefKey GetRefKey(PropertyDef propRef) {
|
||||
return new PropertyRefAndDeclaringTypeKey(propRef);
|
||||
}
|
||||
}
|
||||
|
@ -467,16 +467,16 @@ namespace de4dot.blocks {
|
|||
return true;
|
||||
if (a == null || b == null)
|
||||
return false;
|
||||
return getCanonicalizedScopeName(a) == getCanonicalizedScopeName(b);
|
||||
return GetCanonicalizedScopeName(a) == GetCanonicalizedScopeName(b);
|
||||
}
|
||||
|
||||
static int GetHashCode(IScope a) {
|
||||
if (a == null)
|
||||
return 0;
|
||||
return getCanonicalizedScopeName(a).GetHashCode();
|
||||
return GetCanonicalizedScopeName(a).GetHashCode();
|
||||
}
|
||||
|
||||
static string getAssemblyName(IScope a) {
|
||||
static string GetAssemblyName(IScope a) {
|
||||
switch (a.ScopeType) {
|
||||
case ScopeType.AssemblyRef:
|
||||
return ((AssemblyRef)a).Name.String;
|
||||
|
@ -489,10 +489,10 @@ namespace de4dot.blocks {
|
|||
return null;
|
||||
}
|
||||
|
||||
static string getCanonicalizedScopeName(IScope a) {
|
||||
static string GetCanonicalizedScopeName(IScope a) {
|
||||
if (a == null)
|
||||
return string.Empty;
|
||||
var asmName = getAssemblyName(a);
|
||||
var asmName = GetAssemblyName(a);
|
||||
if (asmName != null) {
|
||||
// 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.
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -32,52 +32,52 @@ namespace de4dot.blocks {
|
|||
set { baseBlocks = value; }
|
||||
}
|
||||
|
||||
public IEnumerable<BaseBlock> getBaseBlocks() {
|
||||
public IEnumerable<BaseBlock> GetBaseBlocks() {
|
||||
if (baseBlocks != null) {
|
||||
foreach (var bb in baseBlocks)
|
||||
yield return bb;
|
||||
}
|
||||
}
|
||||
|
||||
public List<BaseBlock> getAllBaseBlocks() {
|
||||
return getTheBlocks(new List<BaseBlock>());
|
||||
public List<BaseBlock> GetAllBaseBlocks() {
|
||||
return GetTheBlocks(new List<BaseBlock>());
|
||||
}
|
||||
|
||||
public List<Block> getAllBlocks() {
|
||||
return getTheBlocks(new List<Block>());
|
||||
public List<Block> GetAllBlocks() {
|
||||
return GetTheBlocks(new List<Block>());
|
||||
}
|
||||
|
||||
public List<Block> getAllBlocks(List<Block> allBlocks) {
|
||||
public List<Block> GetAllBlocks(List<Block> allBlocks) {
|
||||
allBlocks.Clear();
|
||||
return getTheBlocks(allBlocks);
|
||||
return GetTheBlocks(allBlocks);
|
||||
}
|
||||
|
||||
public List<ScopeBlock> getAllScopeBlocks() {
|
||||
return getTheBlocks(new List<ScopeBlock>());
|
||||
public List<ScopeBlock> GetAllScopeBlocks() {
|
||||
return GetTheBlocks(new List<ScopeBlock>());
|
||||
}
|
||||
|
||||
public List<T> getTheBlocks<T>(List<T> list) where T : BaseBlock {
|
||||
addBlocks(list, this);
|
||||
public List<T> GetTheBlocks<T>(List<T> list) where T : BaseBlock {
|
||||
AddBlocks(list, this);
|
||||
return list;
|
||||
}
|
||||
|
||||
void addBlocks<T>(IList<T> list, ScopeBlock scopeBlock) where T : BaseBlock {
|
||||
foreach (var bb in scopeBlock.getBaseBlocks()) {
|
||||
void AddBlocks<T>(IList<T> list, ScopeBlock scopeBlock) where T : BaseBlock {
|
||||
foreach (var bb in scopeBlock.GetBaseBlocks()) {
|
||||
T t = bb as T;
|
||||
if (t != null)
|
||||
list.Add(t);
|
||||
if (bb is ScopeBlock)
|
||||
addBlocks(list, (ScopeBlock)bb);
|
||||
AddBlocks(list, (ScopeBlock)bb);
|
||||
}
|
||||
}
|
||||
|
||||
List<Block> findBlocks() {
|
||||
return findBlocks(null);
|
||||
List<Block> FindBlocks() {
|
||||
return FindBlocks(null);
|
||||
}
|
||||
|
||||
List<Block> findBlocks(Func<Block, bool> blockChecker) {
|
||||
List<Block> FindBlocks(Func<Block, bool> blockChecker) {
|
||||
var blocks = new List<Block>();
|
||||
foreach (var bb in getBaseBlocks()) {
|
||||
foreach (var bb in GetBaseBlocks()) {
|
||||
Block block = bb as Block;
|
||||
if (block != null && (blockChecker == null || blockChecker(block)))
|
||||
blocks.Add(block);
|
||||
|
@ -85,7 +85,7 @@ namespace de4dot.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)
|
||||
value = instr.OpCode.Code - Code.Ldc_I4_0;
|
||||
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
|
||||
// are also removed.
|
||||
public void removeDeadBlock(Block block) {
|
||||
removeDeadBlocks(new List<Block> { block });
|
||||
public void RemoveDeadBlock(Block block) {
|
||||
RemoveDeadBlocks(new List<Block> { block });
|
||||
}
|
||||
|
||||
// Remove all dead blocks we can find
|
||||
public void removeDeadBlocks() {
|
||||
removeDeadBlocks(findBlocks());
|
||||
public void RemoveDeadBlocks() {
|
||||
RemoveDeadBlocks(FindBlocks());
|
||||
}
|
||||
|
||||
// Remove the blocks if they're dead blocks. If they have refs to other dead blocks,
|
||||
// those are also removed.
|
||||
public void removeDeadBlocks(List<Block> blocks) {
|
||||
public void RemoveDeadBlocks(List<Block> blocks) {
|
||||
while (blocks.Count != 0) {
|
||||
var block = blocks[blocks.Count - 1];
|
||||
blocks.RemoveAt(blocks.Count - 1);
|
||||
|
@ -122,7 +122,7 @@ namespace de4dot.blocks {
|
|||
continue; // Not dead
|
||||
if (block == baseBlocks[0])
|
||||
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
|
||||
|
||||
// It's a dead block we can delete!
|
||||
|
@ -131,27 +131,27 @@ namespace de4dot.blocks {
|
|||
blocks.Add(block.FallThrough);
|
||||
if (block.Targets != null)
|
||||
blocks.AddRange(block.Targets);
|
||||
block.removeDeadBlock();
|
||||
block.RemoveDeadBlock();
|
||||
if (!baseBlocks.Remove(block))
|
||||
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;
|
||||
}
|
||||
|
||||
// For each block, if it has only one target, and the target has only one source, then
|
||||
// merge them into one block.
|
||||
public int mergeBlocks() {
|
||||
public int MergeBlocks() {
|
||||
int mergedBlocks = 0;
|
||||
var blocks = findBlocks();
|
||||
var blocks = FindBlocks();
|
||||
for (int i = 0; i < blocks.Count; i++) {
|
||||
var block = blocks[i];
|
||||
var target = block.getOnlyTarget();
|
||||
if (!isOurBaseBlock(target))
|
||||
var target = block.GetOnlyTarget();
|
||||
if (!IsOurBaseBlock(target))
|
||||
continue; // Only merge blocks we own!
|
||||
if (!block.canMerge(target))
|
||||
if (!block.CanMerge(target))
|
||||
continue; // Can't merge them!
|
||||
if (target == baseBlocks[0])
|
||||
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)
|
||||
throw new ApplicationException("Could not remove target block from blocks");
|
||||
blocks.RemoveAt(targetIndex);
|
||||
block.merge(target);
|
||||
block.Merge(target);
|
||||
if (!baseBlocks.Remove(target))
|
||||
throw new ApplicationException("Could not remove merged block from baseBlocks");
|
||||
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
|
||||
// ScopeBlock that is a direct child, then return that ScopeBlock. Else return null.
|
||||
public BaseBlock toChild(BaseBlock bb) {
|
||||
if (isOurBaseBlock(bb))
|
||||
public BaseBlock ToChild(BaseBlock bb) {
|
||||
if (IsOurBaseBlock(bb))
|
||||
return bb;
|
||||
|
||||
for (var sb = bb.Parent; sb != null; sb = sb.Parent) {
|
||||
if (isOurBaseBlock(sb))
|
||||
if (IsOurBaseBlock(sb))
|
||||
return sb;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal void repartitionBlocks() {
|
||||
var newBaseBlocks = new BlocksSorter(this).sort();
|
||||
internal void RepartitionBlocks() {
|
||||
var newBaseBlocks = new BlocksSorter(this).Sort();
|
||||
|
||||
const bool insane = true;
|
||||
if (insane) {
|
||||
|
@ -206,7 +206,7 @@ namespace de4dot.blocks {
|
|||
|
||||
// Removes the TryBlock and all its TryHandlerBlocks. The code inside the try block
|
||||
// is not removed.
|
||||
public void removeTryBlock(TryBlock tryBlock) {
|
||||
public void RemoveTryBlock(TryBlock tryBlock) {
|
||||
int tryBlockIndex = baseBlocks.IndexOf(tryBlock);
|
||||
if (tryBlockIndex < 0)
|
||||
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
|
||||
var removedBlocks = new List<Block>();
|
||||
foreach (var handler in tryBlock.TryHandlerBlocks)
|
||||
handler.getTheBlocks(removedBlocks);
|
||||
if (!verifyNoExternalRefs(removedBlocks))
|
||||
handler.GetTheBlocks(removedBlocks);
|
||||
if (!VerifyNoExternalRefs(removedBlocks))
|
||||
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
|
||||
static bool verifyNoExternalRefs(IList<Block> removedBlocks) {
|
||||
static bool VerifyNoExternalRefs(IList<Block> removedBlocks) {
|
||||
var removedDict = new Dictionary<Block, bool>();
|
||||
foreach (var removedBlock in removedBlocks)
|
||||
removedDict[removedBlock] = true;
|
||||
|
@ -243,13 +243,13 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
// Remove all blocks in deadBlocks. They're guaranteed to be dead.
|
||||
void removeAllDeadBlocks(IEnumerable<BaseBlock> deadBlocks) {
|
||||
removeAllDeadBlocks(deadBlocks, null);
|
||||
void RemoveAllDeadBlocks(IEnumerable<BaseBlock> deadBlocks) {
|
||||
RemoveAllDeadBlocks(deadBlocks, null);
|
||||
}
|
||||
|
||||
// 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).
|
||||
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
|
||||
// dead, then they are dead.
|
||||
|
@ -260,7 +260,7 @@ namespace de4dot.blocks {
|
|||
allDeadBlocks.Add(bb as Block);
|
||||
else if (bb is ScopeBlock) {
|
||||
var sb = (ScopeBlock)bb;
|
||||
allDeadBlocks.AddRange(sb.getAllBlocks());
|
||||
allDeadBlocks.AddRange(sb.GetAllBlocks());
|
||||
}
|
||||
else
|
||||
throw new ApplicationException(string.Format("Unknown BaseBlock type {0}", bb.GetType()));
|
||||
|
@ -278,20 +278,20 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
foreach (var block in allDeadBlocks)
|
||||
block.removeGuaranteedDeadBlock();
|
||||
block.RemoveGuaranteedDeadBlock();
|
||||
foreach (var bb in deadBlocks) {
|
||||
if (!baseBlocks.Remove(bb))
|
||||
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))
|
||||
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)
|
||||
throw new ApplicationException("Block already has a parent");
|
||||
baseBlocks.Add(block);
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace de4dot.blocks {
|
|||
get { return handlerBlocks; }
|
||||
}
|
||||
|
||||
public void addTryHandler(TryHandlerBlock tryHandlerBlock) {
|
||||
public void AddTryHandler(TryHandlerBlock tryHandlerBlock) {
|
||||
handlerBlocks.Add(tryHandlerBlock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,21 +47,21 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
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>();
|
||||
for (int i = 0; i < objs.Count; i++)
|
||||
dict[objs[i]] = i;
|
||||
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>();
|
||||
foreach (var l in list)
|
||||
olist.Add(l);
|
||||
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.
|
||||
var dict = new Dictionary<T, bool>();
|
||||
foreach (var val in values)
|
||||
|
|
|
@ -31,11 +31,11 @@ namespace de4dot.blocks.cflow {
|
|||
branchEmulator = new BranchEmulator(instructionEmulator, this);
|
||||
}
|
||||
|
||||
protected override bool deobfuscate(Block block) {
|
||||
protected override bool Deobfuscate(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;
|
||||
instructionEmulator.init(blocks);
|
||||
instructionEmulator.Initialize(blocks);
|
||||
|
||||
var instructions = block.Instructions;
|
||||
if (instructions.Count == 0)
|
||||
|
@ -43,7 +43,7 @@ namespace de4dot.blocks.cflow {
|
|||
try {
|
||||
for (int i = 0; i < instructions.Count - 1; i++) {
|
||||
var instr = instructions[i].Instruction;
|
||||
instructionEmulator.emulate(instr);
|
||||
instructionEmulator.Emulate(instr);
|
||||
}
|
||||
}
|
||||
catch (NullReferenceException) {
|
||||
|
@ -51,28 +51,28 @@ namespace de4dot.blocks.cflow {
|
|||
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 and any pushed arguments. Insert the pops just before the bcc instr.
|
||||
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) {
|
||||
popPushedArgs(stackArgs);
|
||||
block.replaceBccWithBranch(isTaken);
|
||||
void IBranchHandler.HandleNormal(int stackArgs, bool isTaken) {
|
||||
PopPushedArgs(stackArgs);
|
||||
block.ReplaceBccWithBranch(isTaken);
|
||||
}
|
||||
|
||||
bool IBranchHandler.handleSwitch(Int32Value switchIndex) {
|
||||
var target = CflowUtils.getSwitchTarget(block.Targets, block.FallThrough, switchIndex);
|
||||
bool IBranchHandler.HandleSwitch(Int32Value switchIndex) {
|
||||
var target = CflowUtils.GetSwitchTarget(block.Targets, block.FallThrough, switchIndex);
|
||||
if (target == null)
|
||||
return false;
|
||||
|
||||
popPushedArgs(1);
|
||||
block.replaceSwitchWithBranch(target);
|
||||
PopPushedArgs(1);
|
||||
block.ReplaceSwitchWithBranch(target);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,17 +27,17 @@ namespace de4dot.blocks.cflow {
|
|||
|
||||
public bool ExecuteOnNoChange { get; set; }
|
||||
|
||||
public virtual void deobfuscateBegin(Blocks blocks) {
|
||||
public virtual void DeobfuscateBegin(Blocks blocks) {
|
||||
this.blocks = blocks;
|
||||
}
|
||||
|
||||
public bool deobfuscate(List<Block> allBlocks) {
|
||||
init(allBlocks);
|
||||
public bool Deobfuscate(List<Block> allBlocks) {
|
||||
Initialize(allBlocks);
|
||||
|
||||
bool changed = false;
|
||||
foreach (var block in allBlocks) {
|
||||
try {
|
||||
changed |= deobfuscate(block);
|
||||
changed |= Deobfuscate(block);
|
||||
}
|
||||
catch (NullReferenceException) {
|
||||
// Here if eg. invalid metadata token in a call instruction (operand is null)
|
||||
|
@ -46,10 +46,10 @@ namespace de4dot.blocks.cflow {
|
|||
return changed;
|
||||
}
|
||||
|
||||
protected virtual void init(List<Block> allBlocks) {
|
||||
protected virtual void Initialize(List<Block> allBlocks) {
|
||||
this.allBlocks = allBlocks;
|
||||
}
|
||||
|
||||
protected abstract bool deobfuscate(Block block);
|
||||
protected abstract bool Deobfuscate(Block block);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,15 +28,15 @@ namespace de4dot.blocks.cflow {
|
|||
List<IBlocksDeobfuscator> ourBlocksDeobfuscators = new List<IBlocksDeobfuscator>();
|
||||
|
||||
public BlocksCflowDeobfuscator() {
|
||||
init();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public BlocksCflowDeobfuscator(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscator) {
|
||||
init();
|
||||
add(blocksDeobfuscator);
|
||||
Initialize();
|
||||
Add(blocksDeobfuscator);
|
||||
}
|
||||
|
||||
void init() {
|
||||
void Initialize() {
|
||||
ourBlocksDeobfuscators.Add(new BlockCflowDeobfuscator { ExecuteOnNoChange = false });
|
||||
ourBlocksDeobfuscators.Add(new SwitchCflowDeobfuscator { ExecuteOnNoChange = false });
|
||||
ourBlocksDeobfuscators.Add(new DeadStoreRemover { ExecuteOnNoChange = false });
|
||||
|
@ -46,73 +46,73 @@ namespace de4dot.blocks.cflow {
|
|||
ourBlocksDeobfuscators.Add(new DupBlockCflowDeobfuscator { ExecuteOnNoChange = true });
|
||||
}
|
||||
|
||||
public void add(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscators) {
|
||||
public void Add(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscators) {
|
||||
foreach (var bd in blocksDeobfuscators)
|
||||
add(bd);
|
||||
Add(bd);
|
||||
}
|
||||
|
||||
public void add(IBlocksDeobfuscator blocksDeobfuscator) {
|
||||
public void Add(IBlocksDeobfuscator blocksDeobfuscator) {
|
||||
if (blocksDeobfuscator != null)
|
||||
userBlocksDeobfuscators.Add(blocksDeobfuscator);
|
||||
}
|
||||
|
||||
public void init(Blocks blocks) {
|
||||
public void Initialize(Blocks blocks) {
|
||||
this.blocks = blocks;
|
||||
}
|
||||
|
||||
public void deobfuscate() {
|
||||
public void Deobfuscate() {
|
||||
bool changed;
|
||||
int iterations = -1;
|
||||
|
||||
deobfuscateBegin(userBlocksDeobfuscators);
|
||||
deobfuscateBegin(ourBlocksDeobfuscators);
|
||||
DeobfuscateBegin(userBlocksDeobfuscators);
|
||||
DeobfuscateBegin(ourBlocksDeobfuscators);
|
||||
|
||||
do {
|
||||
iterations++;
|
||||
changed = false;
|
||||
removeDeadBlocks();
|
||||
mergeBlocks();
|
||||
RemoveDeadBlocks();
|
||||
MergeBlocks();
|
||||
|
||||
blocks.MethodBlocks.getAllBlocks(allBlocks);
|
||||
blocks.MethodBlocks.GetAllBlocks(allBlocks);
|
||||
|
||||
if (iterations == 0)
|
||||
changed |= fixDotfuscatorLoop();
|
||||
changed |= FixDotfuscatorLoop();
|
||||
|
||||
changed |= deobfuscate(userBlocksDeobfuscators, allBlocks);
|
||||
changed |= deobfuscate(ourBlocksDeobfuscators, allBlocks);
|
||||
changed |= deobfuscateNoChange(changed, userBlocksDeobfuscators, allBlocks);
|
||||
changed |= deobfuscateNoChange(changed, ourBlocksDeobfuscators, allBlocks);
|
||||
changed |= Deobfuscate(userBlocksDeobfuscators, allBlocks);
|
||||
changed |= Deobfuscate(ourBlocksDeobfuscators, allBlocks);
|
||||
changed |= DeobfuscateNoChange(changed, userBlocksDeobfuscators, allBlocks);
|
||||
changed |= DeobfuscateNoChange(changed, ourBlocksDeobfuscators, allBlocks);
|
||||
} while (changed);
|
||||
}
|
||||
|
||||
void deobfuscateBegin(IEnumerable<IBlocksDeobfuscator> bds) {
|
||||
void DeobfuscateBegin(IEnumerable<IBlocksDeobfuscator> 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;
|
||||
foreach (var bd in bds) {
|
||||
if (bd.ExecuteOnNoChange)
|
||||
continue;
|
||||
changed |= bd.deobfuscate(allBlocks);
|
||||
changed |= bd.Deobfuscate(allBlocks);
|
||||
}
|
||||
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) {
|
||||
if (changed)
|
||||
break;
|
||||
if (!bd.ExecuteOnNoChange)
|
||||
continue;
|
||||
changed |= bd.deobfuscate(allBlocks);
|
||||
changed |= bd.Deobfuscate(allBlocks);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
// Hack for old Dotfuscator
|
||||
bool fixDotfuscatorLoop() {
|
||||
bool FixDotfuscatorLoop() {
|
||||
/*
|
||||
blk1:
|
||||
...
|
||||
|
@ -136,7 +136,7 @@ namespace de4dot.blocks.cflow {
|
|||
continue;
|
||||
if (instructions[1].OpCode.Code != Code.Dup)
|
||||
continue;
|
||||
if (!instructions[2].isLdcI4())
|
||||
if (!instructions[2].IsLdcI4())
|
||||
continue;
|
||||
if (instructions[3].OpCode.Code != Code.Sub && instructions[3].OpCode.Code != Code.Add)
|
||||
continue;
|
||||
|
@ -148,32 +148,32 @@ namespace de4dot.blocks.cflow {
|
|||
var prev = block.Sources[0];
|
||||
if (prev == block)
|
||||
prev = block.Sources[1];
|
||||
if (prev == null || !prev.LastInstr.isLdcI4())
|
||||
if (prev == null || !prev.LastInstr.IsLdcI4())
|
||||
continue;
|
||||
var next = block.FallThrough;
|
||||
if (next.FirstInstr.OpCode.Code != Code.Pop)
|
||||
continue;
|
||||
block.replaceLastInstrsWithBranch(5, next);
|
||||
block.ReplaceLastInstrsWithBranch(5, next);
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool removeDeadBlocks() {
|
||||
return new DeadBlocksRemover(blocks.MethodBlocks).remove() > 0;
|
||||
bool RemoveDeadBlocks() {
|
||||
return new DeadBlocksRemover(blocks.MethodBlocks).Remove() > 0;
|
||||
}
|
||||
|
||||
bool mergeBlocks() {
|
||||
bool MergeBlocks() {
|
||||
bool changed = false;
|
||||
foreach (var scopeBlock in getAllScopeBlocks(blocks.MethodBlocks))
|
||||
changed |= scopeBlock.mergeBlocks() > 0;
|
||||
foreach (var scopeBlock in GetAllScopeBlocks(blocks.MethodBlocks))
|
||||
changed |= scopeBlock.MergeBlocks() > 0;
|
||||
return changed;
|
||||
}
|
||||
|
||||
IEnumerable<ScopeBlock> getAllScopeBlocks(ScopeBlock scopeBlock) {
|
||||
IEnumerable<ScopeBlock> GetAllScopeBlocks(ScopeBlock scopeBlock) {
|
||||
var list = new List<ScopeBlock>();
|
||||
list.Add(scopeBlock);
|
||||
list.AddRange(scopeBlock.getAllScopeBlocks());
|
||||
list.AddRange(scopeBlock.GetAllScopeBlocks());
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,10 +22,10 @@ using dnlib.DotNet.Emit;
|
|||
namespace de4dot.blocks.cflow {
|
||||
public interface IBranchHandler {
|
||||
// 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)
|
||||
bool handleSwitch(Int32Value switchIndex);
|
||||
bool HandleSwitch(Int32Value switchIndex);
|
||||
}
|
||||
|
||||
public class BranchEmulator {
|
||||
|
@ -37,216 +37,216 @@ namespace de4dot.blocks.cflow {
|
|||
this.branchHandler = branchHandler;
|
||||
}
|
||||
|
||||
public bool emulate(Instruction instr) {
|
||||
public bool Emulate(Instruction instr) {
|
||||
switch (instr.OpCode.Code) {
|
||||
case Code.Br:
|
||||
case Code.Br_S: return emulate_Br();
|
||||
case Code.Br_S: return Emulate_Br();
|
||||
case Code.Beq:
|
||||
case Code.Beq_S: return emulate_Beq();
|
||||
case Code.Beq_S: return Emulate_Beq();
|
||||
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_S: return emulate_Bge_Un();
|
||||
case Code.Bge_Un_S: return Emulate_Bge_Un();
|
||||
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_S: return emulate_Bgt_Un();
|
||||
case Code.Bgt_Un_S: return Emulate_Bgt_Un();
|
||||
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_S: return emulate_Ble_Un();
|
||||
case Code.Ble_Un_S: return Emulate_Ble_Un();
|
||||
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_S: return emulate_Blt_Un();
|
||||
case Code.Blt_Un_S: return Emulate_Blt_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_S:return emulate_Brfalse();
|
||||
case Code.Brfalse_S:return Emulate_Brfalse();
|
||||
case Code.Brtrue:
|
||||
case Code.Brtrue_S: return emulate_Brtrue();
|
||||
case Code.Switch: return emulate_Switch();
|
||||
case Code.Brtrue_S: return Emulate_Brtrue();
|
||||
case Code.Switch: return Emulate_Switch();
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool emulateBranch(int stackArgs, Bool3 cond) {
|
||||
bool EmulateBranch(int stackArgs, Bool3 cond) {
|
||||
if (cond == Bool3.Unknown)
|
||||
return false;
|
||||
return emulateBranch(stackArgs, cond == Bool3.True);
|
||||
return EmulateBranch(stackArgs, cond == Bool3.True);
|
||||
}
|
||||
|
||||
bool emulateBranch(int stackArgs, bool isTaken) {
|
||||
branchHandler.handleNormal(stackArgs, isTaken);
|
||||
bool EmulateBranch(int stackArgs, bool isTaken) {
|
||||
branchHandler.HandleNormal(stackArgs, isTaken);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool emulate_Br() {
|
||||
return emulateBranch(0, true);
|
||||
bool Emulate_Br() {
|
||||
return EmulateBranch(0, true);
|
||||
}
|
||||
|
||||
bool emulate_Beq() {
|
||||
var val2 = instructionEmulator.pop();
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Beq() {
|
||||
var val2 = instructionEmulator.Pop();
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32() && val2.isInt32())
|
||||
return emulateBranch(2, Int32Value.compareEq((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.isInt64() && val2.isInt64())
|
||||
return emulateBranch(2, Int64Value.compareEq((Int64Value)val1, (Int64Value)val2));
|
||||
else if (val1.isNull() && val2.isNull())
|
||||
return emulateBranch(2, true);
|
||||
if (val1.IsInt32() && val2.IsInt32())
|
||||
return EmulateBranch(2, Int32Value.CompareEq((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.IsInt64() && val2.IsInt64())
|
||||
return EmulateBranch(2, Int64Value.CompareEq((Int64Value)val1, (Int64Value)val2));
|
||||
else if (val1.IsNull() && val2.IsNull())
|
||||
return EmulateBranch(2, true);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Bne_Un() {
|
||||
var val2 = instructionEmulator.pop();
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Bne_Un() {
|
||||
var val2 = instructionEmulator.Pop();
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32() && val2.isInt32())
|
||||
return emulateBranch(2, Int32Value.compareNeq((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.isInt64() && val2.isInt64())
|
||||
return emulateBranch(2, Int64Value.compareNeq((Int64Value)val1, (Int64Value)val2));
|
||||
else if (val1.isNull() && val2.isNull())
|
||||
return emulateBranch(2, false);
|
||||
if (val1.IsInt32() && val2.IsInt32())
|
||||
return EmulateBranch(2, Int32Value.CompareNeq((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.IsInt64() && val2.IsInt64())
|
||||
return EmulateBranch(2, Int64Value.CompareNeq((Int64Value)val1, (Int64Value)val2));
|
||||
else if (val1.IsNull() && val2.IsNull())
|
||||
return EmulateBranch(2, false);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Bge() {
|
||||
var val2 = instructionEmulator.pop();
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Bge() {
|
||||
var val2 = instructionEmulator.Pop();
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32() && val2.isInt32())
|
||||
return emulateBranch(2, Int32Value.compareGe((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.isInt64() && val2.isInt64())
|
||||
return emulateBranch(2, Int64Value.compareGe((Int64Value)val1, (Int64Value)val2));
|
||||
if (val1.IsInt32() && val2.IsInt32())
|
||||
return EmulateBranch(2, Int32Value.CompareGe((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.IsInt64() && val2.IsInt64())
|
||||
return EmulateBranch(2, Int64Value.CompareGe((Int64Value)val1, (Int64Value)val2));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Bge_Un() {
|
||||
var val2 = instructionEmulator.pop();
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Bge_Un() {
|
||||
var val2 = instructionEmulator.Pop();
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32() && val2.isInt32())
|
||||
return emulateBranch(2, Int32Value.compareGe_Un((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.isInt64() && val2.isInt64())
|
||||
return emulateBranch(2, Int64Value.compareGe_Un((Int64Value)val1, (Int64Value)val2));
|
||||
if (val1.IsInt32() && val2.IsInt32())
|
||||
return EmulateBranch(2, Int32Value.CompareGe_Un((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.IsInt64() && val2.IsInt64())
|
||||
return EmulateBranch(2, Int64Value.CompareGe_Un((Int64Value)val1, (Int64Value)val2));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Bgt() {
|
||||
var val2 = instructionEmulator.pop();
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Bgt() {
|
||||
var val2 = instructionEmulator.Pop();
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32() && val2.isInt32())
|
||||
return emulateBranch(2, Int32Value.compareGt((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.isInt64() && val2.isInt64())
|
||||
return emulateBranch(2, Int64Value.compareGt((Int64Value)val1, (Int64Value)val2));
|
||||
if (val1.IsInt32() && val2.IsInt32())
|
||||
return EmulateBranch(2, Int32Value.CompareGt((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.IsInt64() && val2.IsInt64())
|
||||
return EmulateBranch(2, Int64Value.CompareGt((Int64Value)val1, (Int64Value)val2));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Bgt_Un() {
|
||||
var val2 = instructionEmulator.pop();
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Bgt_Un() {
|
||||
var val2 = instructionEmulator.Pop();
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32() && val2.isInt32())
|
||||
return emulateBranch(2, Int32Value.compareGt_Un((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.isInt64() && val2.isInt64())
|
||||
return emulateBranch(2, Int64Value.compareGt_Un((Int64Value)val1, (Int64Value)val2));
|
||||
if (val1.IsInt32() && val2.IsInt32())
|
||||
return EmulateBranch(2, Int32Value.CompareGt_Un((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.IsInt64() && val2.IsInt64())
|
||||
return EmulateBranch(2, Int64Value.CompareGt_Un((Int64Value)val1, (Int64Value)val2));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Ble() {
|
||||
var val2 = instructionEmulator.pop();
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Ble() {
|
||||
var val2 = instructionEmulator.Pop();
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32() && val2.isInt32())
|
||||
return emulateBranch(2, Int32Value.compareLe((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.isInt64() && val2.isInt64())
|
||||
return emulateBranch(2, Int64Value.compareLe((Int64Value)val1, (Int64Value)val2));
|
||||
if (val1.IsInt32() && val2.IsInt32())
|
||||
return EmulateBranch(2, Int32Value.CompareLe((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.IsInt64() && val2.IsInt64())
|
||||
return EmulateBranch(2, Int64Value.CompareLe((Int64Value)val1, (Int64Value)val2));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Ble_Un() {
|
||||
var val2 = instructionEmulator.pop();
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Ble_Un() {
|
||||
var val2 = instructionEmulator.Pop();
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32() && val2.isInt32())
|
||||
return emulateBranch(2, Int32Value.compareLe_Un((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.isInt64() && val2.isInt64())
|
||||
return emulateBranch(2, Int64Value.compareLe_Un((Int64Value)val1, (Int64Value)val2));
|
||||
if (val1.IsInt32() && val2.IsInt32())
|
||||
return EmulateBranch(2, Int32Value.CompareLe_Un((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.IsInt64() && val2.IsInt64())
|
||||
return EmulateBranch(2, Int64Value.CompareLe_Un((Int64Value)val1, (Int64Value)val2));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Blt() {
|
||||
var val2 = instructionEmulator.pop();
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Blt() {
|
||||
var val2 = instructionEmulator.Pop();
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32() && val2.isInt32())
|
||||
return emulateBranch(2, Int32Value.compareLt((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.isInt64() && val2.isInt64())
|
||||
return emulateBranch(2, Int64Value.compareLt((Int64Value)val1, (Int64Value)val2));
|
||||
if (val1.IsInt32() && val2.IsInt32())
|
||||
return EmulateBranch(2, Int32Value.CompareLt((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.IsInt64() && val2.IsInt64())
|
||||
return EmulateBranch(2, Int64Value.CompareLt((Int64Value)val1, (Int64Value)val2));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Blt_Un() {
|
||||
var val2 = instructionEmulator.pop();
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Blt_Un() {
|
||||
var val2 = instructionEmulator.Pop();
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32() && val2.isInt32())
|
||||
return emulateBranch(2, Int32Value.compareLt_Un((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.isInt64() && val2.isInt64())
|
||||
return emulateBranch(2, Int64Value.compareLt_Un((Int64Value)val1, (Int64Value)val2));
|
||||
if (val1.IsInt32() && val2.IsInt32())
|
||||
return EmulateBranch(2, Int32Value.CompareLt_Un((Int32Value)val1, (Int32Value)val2));
|
||||
else if (val1.IsInt64() && val2.IsInt64())
|
||||
return EmulateBranch(2, Int64Value.CompareLt_Un((Int64Value)val1, (Int64Value)val2));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Brfalse() {
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Brfalse() {
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32())
|
||||
return emulateBranch(1, Int32Value.compareFalse((Int32Value)val1));
|
||||
else if (val1.isInt64())
|
||||
return emulateBranch(1, Int64Value.compareFalse((Int64Value)val1));
|
||||
else if (val1.isNull())
|
||||
return emulateBranch(1, true);
|
||||
else if (val1.isObject() || val1.isString())
|
||||
return emulateBranch(1, false);
|
||||
if (val1.IsInt32())
|
||||
return EmulateBranch(1, Int32Value.CompareFalse((Int32Value)val1));
|
||||
else if (val1.IsInt64())
|
||||
return EmulateBranch(1, Int64Value.CompareFalse((Int64Value)val1));
|
||||
else if (val1.IsNull())
|
||||
return EmulateBranch(1, true);
|
||||
else if (val1.IsObject() || val1.IsString())
|
||||
return EmulateBranch(1, false);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Brtrue() {
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Brtrue() {
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (val1.isInt32())
|
||||
return emulateBranch(1, Int32Value.compareTrue((Int32Value)val1));
|
||||
else if (val1.isInt64())
|
||||
return emulateBranch(1, Int64Value.compareTrue((Int64Value)val1));
|
||||
else if (val1.isNull())
|
||||
return emulateBranch(1, false);
|
||||
else if (val1.isObject() || val1.isString())
|
||||
return emulateBranch(1, true);
|
||||
if (val1.IsInt32())
|
||||
return EmulateBranch(1, Int32Value.CompareTrue((Int32Value)val1));
|
||||
else if (val1.IsInt64())
|
||||
return EmulateBranch(1, Int64Value.CompareTrue((Int64Value)val1));
|
||||
else if (val1.IsNull())
|
||||
return EmulateBranch(1, false);
|
||||
else if (val1.IsObject() || val1.IsString())
|
||||
return EmulateBranch(1, true);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool emulate_Switch() {
|
||||
var val1 = instructionEmulator.pop();
|
||||
bool Emulate_Switch() {
|
||||
var val1 = instructionEmulator.Pop();
|
||||
|
||||
if (!val1.isInt32())
|
||||
if (!val1.IsInt32())
|
||||
return false;
|
||||
return branchHandler.handleSwitch((Int32Value)val1);
|
||||
return branchHandler.HandleSwitch((Int32Value)val1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,19 +31,19 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
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)
|
||||
cflowDeobfuscator.add(bd);
|
||||
cflowDeobfuscator.Add(bd);
|
||||
}
|
||||
|
||||
public void add(IBlocksDeobfuscator blocksDeobfuscator) {
|
||||
cflowDeobfuscator.add(blocksDeobfuscator);
|
||||
public void Add(IBlocksDeobfuscator blocksDeobfuscator) {
|
||||
cflowDeobfuscator.Add(blocksDeobfuscator);
|
||||
}
|
||||
|
||||
public MethodDef deobfuscate(MethodDef method) {
|
||||
public MethodDef Deobfuscate(MethodDef method) {
|
||||
MethodDef deobfuscatedMethod;
|
||||
if (deobfuscated.TryGetValue(method, out deobfuscatedMethod))
|
||||
return deobfuscatedMethod;
|
||||
|
@ -53,22 +53,22 @@ namespace de4dot.blocks.cflow {
|
|||
return method;
|
||||
}
|
||||
|
||||
deobfuscatedMethod = DotNetUtils.clone(method);
|
||||
deobfuscatedMethod = DotNetUtils.Clone(method);
|
||||
deobfuscated[method] = deobfuscatedMethod;
|
||||
|
||||
var blocks = new Blocks(deobfuscatedMethod);
|
||||
deobfuscate(blocks);
|
||||
Deobfuscate(blocks);
|
||||
IList<Instruction> allInstructions;
|
||||
IList<ExceptionHandler> allExceptionHandlers;
|
||||
blocks.getCode(out allInstructions, out allExceptionHandlers);
|
||||
DotNetUtils.restoreBody(deobfuscatedMethod, allInstructions, allExceptionHandlers);
|
||||
blocks.GetCode(out allInstructions, out allExceptionHandlers);
|
||||
DotNetUtils.RestoreBody(deobfuscatedMethod, allInstructions, allExceptionHandlers);
|
||||
|
||||
return deobfuscatedMethod;
|
||||
}
|
||||
|
||||
void deobfuscate(Blocks blocks) {
|
||||
cflowDeobfuscator.init(blocks);
|
||||
cflowDeobfuscator.deobfuscate();
|
||||
void Deobfuscate(Blocks blocks) {
|
||||
cflowDeobfuscator.Initialize(blocks);
|
||||
cflowDeobfuscator.Deobfuscate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,30 +29,30 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
public CflowDeobfuscator(IBlocksDeobfuscator blocksDeobfuscator) {
|
||||
cflowDeobfuscator.add(blocksDeobfuscator);
|
||||
cflowDeobfuscator.Add(blocksDeobfuscator);
|
||||
}
|
||||
|
||||
public void deobfuscate(MethodDef method) {
|
||||
deobfuscate(method, (blocks) => {
|
||||
cflowDeobfuscator.init(blocks);
|
||||
cflowDeobfuscator.deobfuscate();
|
||||
public void Deobfuscate(MethodDef method) {
|
||||
Deobfuscate(method, (blocks) => {
|
||||
cflowDeobfuscator.Initialize(blocks);
|
||||
cflowDeobfuscator.Deobfuscate();
|
||||
});
|
||||
}
|
||||
|
||||
static bool hasNonEmptyBody(MethodDef method) {
|
||||
static bool HasNonEmptyBody(MethodDef method) {
|
||||
return method.Body != null && method.Body.Instructions.Count > 0;
|
||||
}
|
||||
|
||||
void deobfuscate(MethodDef method, Action<Blocks> handler) {
|
||||
if (hasNonEmptyBody(method)) {
|
||||
void Deobfuscate(MethodDef method, Action<Blocks> handler) {
|
||||
if (HasNonEmptyBody(method)) {
|
||||
var blocks = new Blocks(method);
|
||||
|
||||
handler(blocks);
|
||||
|
||||
IList<Instruction> allInstructions;
|
||||
IList<ExceptionHandler> allExceptionHandlers;
|
||||
blocks.getCode(out allInstructions, out allExceptionHandlers);
|
||||
DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers);
|
||||
blocks.GetCode(out allInstructions, out allExceptionHandlers);
|
||||
DotNetUtils.RestoreBody(method, allInstructions, allExceptionHandlers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ using System.Collections.Generic;
|
|||
|
||||
namespace de4dot.blocks.cflow {
|
||||
static class CflowUtils {
|
||||
public static Block getSwitchTarget(IList<Block> targets, Block fallThrough, Int32Value intValue) {
|
||||
if (!intValue.allBitsValid())
|
||||
public static Block GetSwitchTarget(IList<Block> targets, Block fallThrough, Int32Value intValue) {
|
||||
if (!intValue.AllBitsValid())
|
||||
return null;
|
||||
|
||||
int index = intValue.value;
|
||||
|
|
|
@ -29,15 +29,15 @@ namespace de4dot.blocks.cflow {
|
|||
InstructionEmulator instructionEmulator = new InstructionEmulator();
|
||||
IList<Parameter> args;
|
||||
|
||||
protected override void init(List<Block> allBlocks) {
|
||||
base.init(allBlocks);
|
||||
protected override void Initialize(List<Block> allBlocks) {
|
||||
base.Initialize(allBlocks);
|
||||
args = blocks.Method.Parameters;
|
||||
}
|
||||
|
||||
protected override bool deobfuscate(Block block) {
|
||||
protected override bool Deobfuscate(Block block) {
|
||||
bool changed = false;
|
||||
|
||||
instructionEmulator.init(blocks);
|
||||
instructionEmulator.Initialize(blocks);
|
||||
var instrs = block.Instructions;
|
||||
for (int i = 0; i < instrs.Count; i++) {
|
||||
var instr = instrs[i];
|
||||
|
@ -49,7 +49,7 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Ldarg_2:
|
||||
case Code.Ldarg_3:
|
||||
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;
|
||||
|
||||
case Code.Ldloc:
|
||||
|
@ -58,22 +58,22 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Ldloc_2:
|
||||
case Code.Ldloc_3:
|
||||
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;
|
||||
|
||||
case Code.Ldarga:
|
||||
case Code.Ldarga_S:
|
||||
instructionEmulator.makeArgUnknown((Parameter)instr.Operand);
|
||||
instructionEmulator.MakeArgUnknown((Parameter)instr.Operand);
|
||||
break;
|
||||
|
||||
case Code.Ldloca:
|
||||
case Code.Ldloca_S:
|
||||
instructionEmulator.makeLocalUnknown((Local)instr.Operand);
|
||||
instructionEmulator.MakeLocalUnknown((Local)instr.Operand);
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
instructionEmulator.emulate(instr.Instruction);
|
||||
instructionEmulator.Emulate(instr.Instruction);
|
||||
}
|
||||
catch (NullReferenceException) {
|
||||
// Here if eg. invalid metadata token in a call instruction (operand is null)
|
||||
|
@ -84,17 +84,17 @@ namespace de4dot.blocks.cflow {
|
|||
return changed;
|
||||
}
|
||||
|
||||
bool fixLoadInstruction(Block block, int index, Value value) {
|
||||
if (value.isInt32()) {
|
||||
bool FixLoadInstruction(Block block, int index, Value value) {
|
||||
if (value.IsInt32()) {
|
||||
var intValue = (Int32Value)value;
|
||||
if (!intValue.allBitsValid())
|
||||
if (!intValue.AllBitsValid())
|
||||
return false;
|
||||
block.Instructions[index] = new Instr(Instruction.CreateLdcI4(intValue.value));
|
||||
return true;
|
||||
}
|
||||
else if (value.isInt64()) {
|
||||
else if (value.IsInt64()) {
|
||||
var intValue = (Int64Value)value;
|
||||
if (!intValue.allBitsValid())
|
||||
if (!intValue.AllBitsValid())
|
||||
return false;
|
||||
block.Instructions[index] = new Instr(OpCodes.Ldc_I8.ToInstruction(intValue.value));
|
||||
return true;
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace de4dot.blocks.cflow {
|
|||
List<int> allDeadInstructions = new List<int>();
|
||||
InstructionExpressionFinder instructionExpressionFinder = new InstructionExpressionFinder();
|
||||
|
||||
protected override bool deobfuscate(Block block) {
|
||||
protected override bool Deobfuscate(Block block) {
|
||||
allDeadInstructions.Clear();
|
||||
|
||||
bool changed = false;
|
||||
|
@ -56,10 +56,10 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Leave_S:
|
||||
case Code.Endfinally:
|
||||
case Code.Pop:
|
||||
instructionExpressionFinder.init(block, false);
|
||||
if (!instructionExpressionFinder.find(i))
|
||||
instructionExpressionFinder.Initialize(block, false);
|
||||
if (!instructionExpressionFinder.Find(i))
|
||||
continue;
|
||||
if (!okInstructions(block, instructionExpressionFinder.DeadInstructions))
|
||||
if (!OkInstructions(block, instructionExpressionFinder.DeadInstructions))
|
||||
continue;
|
||||
allDeadInstructions.AddRange(instructionExpressionFinder.DeadInstructions);
|
||||
break;
|
||||
|
@ -70,14 +70,14 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
if (allDeadInstructions.Count > 0) {
|
||||
block.remove(allDeadInstructions);
|
||||
block.Remove(allDeadInstructions);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool okInstructions(Block block, IEnumerable<int> indexes) {
|
||||
bool OkInstructions(Block block, IEnumerable<int> indexes) {
|
||||
foreach (var index in indexes) {
|
||||
var instr = block.Instructions[index];
|
||||
switch (instr.OpCode.Code) {
|
||||
|
@ -318,27 +318,27 @@ namespace de4dot.blocks.cflow {
|
|||
get { return deadInstructions; }
|
||||
}
|
||||
|
||||
public void init(Block block, bool methodHasReturnValue) {
|
||||
public void Initialize(Block block, bool methodHasReturnValue) {
|
||||
deadInstructions.Clear();
|
||||
this.block = block;
|
||||
this.methodHasReturnValue = methodHasReturnValue;
|
||||
}
|
||||
|
||||
public bool find(int index) {
|
||||
return find(ref index, true);
|
||||
public bool Find(int index) {
|
||||
return Find(ref index, true);
|
||||
}
|
||||
|
||||
bool find(ref int index, bool addIt) {
|
||||
bool Find(ref int index, bool addIt) {
|
||||
if (index < 0)
|
||||
return false;
|
||||
|
||||
var startInstr = block.Instructions[index];
|
||||
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)
|
||||
if (addIt && startInstrPops >= 0)
|
||||
addIndex(index);
|
||||
AddIndex(index);
|
||||
|
||||
if (startInstrPops == 0)
|
||||
return true;
|
||||
|
@ -349,19 +349,19 @@ namespace de4dot.blocks.cflow {
|
|||
break;
|
||||
|
||||
int pushes, pops;
|
||||
calculateStackUsage(instr.Instruction, methodHasReturnValue, out pushes, out pops);
|
||||
CalculateStackUsage(instr.Instruction, methodHasReturnValue, out pushes, out pops);
|
||||
if (pops < 0)
|
||||
break; // eg. leave
|
||||
index--;
|
||||
|
||||
if (pops > 0) { // if instr uses any args
|
||||
bool otherExpr = pops > 0 && pushes == 0;
|
||||
if (!find(ref index, addIt && !otherExpr))
|
||||
if (!Find(ref index, addIt && !otherExpr))
|
||||
break;
|
||||
}
|
||||
else if (pushes != 0 || pops != 0) {
|
||||
if (addIt)
|
||||
addIndex(index);
|
||||
AddIndex(index);
|
||||
}
|
||||
if (pushes > 0 && startInstrPops >= 0) {
|
||||
if (pushes > startInstrPops)
|
||||
|
@ -373,12 +373,12 @@ namespace de4dot.blocks.cflow {
|
|||
return startInstrPops <= 0;
|
||||
}
|
||||
|
||||
void addIndex(int index) {
|
||||
void AddIndex(int 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,16 +41,16 @@ namespace de4dot.blocks.cflow {
|
|||
|
||||
public bool ExecuteOnNoChange { get; set; }
|
||||
|
||||
public void deobfuscateBegin(Blocks blocks) {
|
||||
public void DeobfuscateBegin(Blocks blocks) {
|
||||
this.blocks = blocks;
|
||||
}
|
||||
|
||||
public bool deobfuscate(List<Block> allBlocks) {
|
||||
public bool Deobfuscate(List<Block> allBlocks) {
|
||||
this.allBlocks = allBlocks;
|
||||
return remove();
|
||||
return Remove();
|
||||
}
|
||||
|
||||
bool remove() {
|
||||
bool Remove() {
|
||||
if (blocks.Locals.Count == 0)
|
||||
return false;
|
||||
|
||||
|
@ -61,7 +61,7 @@ namespace de4dot.blocks.cflow {
|
|||
deadLocals.Add(false);
|
||||
}
|
||||
|
||||
findLoadStores();
|
||||
FindLoadStores();
|
||||
|
||||
bool deadStores = false;
|
||||
for (int i = 0; i < blocks.Locals.Count; i++) {
|
||||
|
@ -74,10 +74,10 @@ namespace de4dot.blocks.cflow {
|
|||
if (!deadStores)
|
||||
return false;
|
||||
|
||||
return removeDeadStores();
|
||||
return RemoveDeadStores();
|
||||
}
|
||||
|
||||
void findLoadStores() {
|
||||
void FindLoadStores() {
|
||||
foreach (var block in allBlocks) {
|
||||
foreach (var instr in block.Instructions) {
|
||||
Local local;
|
||||
|
@ -89,7 +89,7 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Ldloc_1:
|
||||
case Code.Ldloc_2:
|
||||
case Code.Ldloc_3:
|
||||
local = Instr.getLocalVar(blocks.Locals, instr);
|
||||
local = Instr.GetLocalVar(blocks.Locals, instr);
|
||||
flags = AccessFlags.Read;
|
||||
break;
|
||||
|
||||
|
@ -99,7 +99,7 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Stloc_1:
|
||||
case Code.Stloc_2:
|
||||
case Code.Stloc_3:
|
||||
local = Instr.getLocalVar(blocks.Locals, instr);
|
||||
local = Instr.GetLocalVar(blocks.Locals, instr);
|
||||
flags = AccessFlags.Write;
|
||||
break;
|
||||
|
||||
|
@ -122,7 +122,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
}
|
||||
|
||||
bool removeDeadStores() {
|
||||
bool RemoveDeadStores() {
|
||||
bool changed = false;
|
||||
foreach (var block in allBlocks) {
|
||||
var instructions = block.Instructions;
|
||||
|
@ -136,7 +136,7 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Stloc_1:
|
||||
case Code.Stloc_2:
|
||||
case Code.Stloc_3:
|
||||
local = Instr.getLocalVar(blocks.Locals, instr);
|
||||
local = Instr.GetLocalVar(blocks.Locals, instr);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -25,22 +25,22 @@ namespace de4dot.blocks.cflow {
|
|||
// 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.
|
||||
class DupBlockCflowDeobfuscator : BlockDeobfuscator {
|
||||
protected override bool deobfuscate(Block block) {
|
||||
protected override bool Deobfuscate(Block block) {
|
||||
if (block.Instructions.Count != 2)
|
||||
return false;
|
||||
if (block.Instructions[0].OpCode.Code != Code.Dup)
|
||||
return false;
|
||||
if (!block.LastInstr.isConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch)
|
||||
if (!block.LastInstr.IsConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch)
|
||||
return false;
|
||||
|
||||
bool modified = false;
|
||||
foreach (var source in new List<Block>(block.Sources)) {
|
||||
if (source.getOnlyTarget() != block)
|
||||
if (source.GetOnlyTarget() != block)
|
||||
continue;
|
||||
if (!source.canAppend(block))
|
||||
if (!source.CanAppend(block))
|
||||
continue;
|
||||
|
||||
source.append(block);
|
||||
source.Append(block);
|
||||
modified = true;
|
||||
}
|
||||
return modified;
|
||||
|
|
|
@ -23,9 +23,9 @@ namespace de4dot.blocks.cflow {
|
|||
public interface IBlocksDeobfuscator {
|
||||
bool ExecuteOnNoChange { get; }
|
||||
|
||||
void deobfuscateBegin(Blocks blocks);
|
||||
void DeobfuscateBegin(Blocks blocks);
|
||||
|
||||
// Returns true if something was updated
|
||||
bool deobfuscate(List<Block> allBlocks);
|
||||
bool Deobfuscate(List<Block> allBlocks);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,6 @@ using dnlib.DotNet;
|
|||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public interface ICflowDeobfuscator {
|
||||
void deobfuscate(MethodDef method);
|
||||
void Deobfuscate(MethodDef method);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -40,75 +40,75 @@ namespace de4dot.blocks.cflow {
|
|||
this.validMask = validMask;
|
||||
}
|
||||
|
||||
public bool hasUnknownBits() {
|
||||
public bool HasUnknownBits() {
|
||||
return validMask != NO_UNKNOWN_BITS;
|
||||
}
|
||||
|
||||
public bool allBitsValid() {
|
||||
return !hasUnknownBits();
|
||||
public bool AllBitsValid() {
|
||||
return !HasUnknownBits();
|
||||
}
|
||||
|
||||
bool isBitValid(int n) {
|
||||
return isBitValid(validMask, n);
|
||||
bool IsBitValid(int n) {
|
||||
return IsBitValid(validMask, n);
|
||||
}
|
||||
|
||||
static bool isBitValid(uint validMask, int n) {
|
||||
static bool IsBitValid(uint validMask, int n) {
|
||||
return (validMask & (1U << n)) != 0;
|
||||
}
|
||||
|
||||
public static Int32Value createUnknownBool() {
|
||||
public static Int32Value CreateUnknownBool() {
|
||||
return new Int32Value(0, NO_UNKNOWN_BITS << 1);
|
||||
}
|
||||
|
||||
public static Int32Value createUnknownUInt8() {
|
||||
public static Int32Value CreateUnknownUInt8() {
|
||||
return new Int32Value(0, NO_UNKNOWN_BITS << 8);
|
||||
}
|
||||
|
||||
public static Int32Value createUnknownUInt16() {
|
||||
public static Int32Value CreateUnknownUInt16() {
|
||||
return new Int32Value(0, NO_UNKNOWN_BITS << 16);
|
||||
}
|
||||
|
||||
public static Int32Value createUnknown() {
|
||||
public static Int32Value CreateUnknown() {
|
||||
return new Int32Value(0, 0U);
|
||||
}
|
||||
|
||||
public bool isZero() {
|
||||
return hasValue(0);
|
||||
public bool IsZero() {
|
||||
return HasValue(0);
|
||||
}
|
||||
|
||||
public bool isNonZero() {
|
||||
public bool IsNonZero() {
|
||||
return (value & validMask) != 0;
|
||||
}
|
||||
|
||||
public bool hasValue(int value) {
|
||||
return allBitsValid() && this.value == value;
|
||||
public bool HasValue(int value) {
|
||||
return AllBitsValid() && this.value == value;
|
||||
}
|
||||
|
||||
public bool hasValue(uint value) {
|
||||
return hasValue((int)value);
|
||||
public bool HasValue(uint value) {
|
||||
return HasValue((int)value);
|
||||
}
|
||||
|
||||
public Int32Value toBoolean() {
|
||||
if (isNonZero())
|
||||
public Int32Value ToBoolean() {
|
||||
if (IsNonZero())
|
||||
return new Int32Value(1, NO_UNKNOWN_BITS);
|
||||
if (isZero())
|
||||
if (IsZero())
|
||||
return this;
|
||||
return createUnknownBool();
|
||||
return CreateUnknownBool();
|
||||
}
|
||||
|
||||
public Int32Value toInt8() {
|
||||
public Int32Value ToInt8() {
|
||||
return Conv_I1(this);
|
||||
}
|
||||
|
||||
public Int32Value toUInt8() {
|
||||
public Int32Value ToUInt8() {
|
||||
return Conv_U1(this);
|
||||
}
|
||||
|
||||
public Int32Value toInt16() {
|
||||
public Int32Value ToInt16() {
|
||||
return Conv_I2(this);
|
||||
}
|
||||
|
||||
public Int32Value toUInt16() {
|
||||
public Int32Value ToUInt16() {
|
||||
return Conv_U2(this);
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ namespace de4dot.blocks.cflow {
|
|||
|
||||
public static Int32Value Conv_I1(int value, uint validMask) {
|
||||
value = (int)(sbyte)value;
|
||||
if (isBitValid(validMask, 7))
|
||||
if (IsBitValid(validMask, 7))
|
||||
validMask |= NO_UNKNOWN_BITS << 8;
|
||||
else
|
||||
validMask &= ~(NO_UNKNOWN_BITS << 8);
|
||||
|
@ -179,7 +179,7 @@ namespace de4dot.blocks.cflow {
|
|||
|
||||
public static Int32Value Conv_I2(int value, uint validMask) {
|
||||
value = (int)(short)value;
|
||||
if (isBitValid(validMask, 15))
|
||||
if (IsBitValid(validMask, 15))
|
||||
validMask |= NO_UNKNOWN_BITS << 16;
|
||||
else
|
||||
validMask &= ~(NO_UNKNOWN_BITS << 16);
|
||||
|
@ -215,97 +215,97 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
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);
|
||||
if (ReferenceEquals(a, b))
|
||||
return new Int32Value(a.value << 1, (a.validMask << 1) | 1);
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
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);
|
||||
if (ReferenceEquals(a, b))
|
||||
return zero;
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
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);
|
||||
if (a.isZero() || b.isZero())
|
||||
if (a.IsZero() || b.IsZero())
|
||||
return zero;
|
||||
if (a.hasValue(1))
|
||||
if (a.HasValue(1))
|
||||
return b;
|
||||
if (b.hasValue(1))
|
||||
if (b.HasValue(1))
|
||||
return a;
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int32Value Div(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid()) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid()) {
|
||||
try {
|
||||
return new Int32Value(a.value / b.value);
|
||||
}
|
||||
catch (ArithmeticException) {
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
}
|
||||
if (ReferenceEquals(a, b) && a.isNonZero())
|
||||
if (ReferenceEquals(a, b) && a.IsNonZero())
|
||||
return one;
|
||||
if (b.hasValue(1))
|
||||
if (b.HasValue(1))
|
||||
return a;
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int32Value Div_Un(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid()) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid()) {
|
||||
try {
|
||||
return new Int32Value((int)((uint)a.value / (uint)b.value));
|
||||
}
|
||||
catch (ArithmeticException) {
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
}
|
||||
if (ReferenceEquals(a, b) && a.isNonZero())
|
||||
if (ReferenceEquals(a, b) && a.IsNonZero())
|
||||
return one;
|
||||
if (b.hasValue(1))
|
||||
if (b.HasValue(1))
|
||||
return a;
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int32Value Rem(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid()) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid()) {
|
||||
try {
|
||||
return new Int32Value(a.value % b.value);
|
||||
}
|
||||
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 createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int32Value Rem_Un(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid()) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid()) {
|
||||
try {
|
||||
return new Int32Value((int)((uint)a.value % (uint)b.value));
|
||||
}
|
||||
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 createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int32Value Neg(Int32Value a) {
|
||||
if (a.allBitsValid())
|
||||
if (a.AllBitsValid())
|
||||
return new Int32Value(-a.value);
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int32Value And(Int32Value a, Int32Value b) {
|
||||
|
@ -333,38 +333,38 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
public static Int32Value Shl(Int32Value a, Int32Value b) {
|
||||
if (b.hasUnknownBits())
|
||||
return createUnknown();
|
||||
if (b.HasUnknownBits())
|
||||
return CreateUnknown();
|
||||
if (b.value == 0)
|
||||
return a;
|
||||
if (b.value < 0 || b.value >= sizeof(int) * 8)
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
int shift = b.value;
|
||||
uint validMask = (a.validMask << shift) | (uint.MaxValue >> (sizeof(int) * 8 - shift));
|
||||
return new Int32Value(a.value << shift, validMask);
|
||||
}
|
||||
|
||||
public static Int32Value Shr(Int32Value a, Int32Value b) {
|
||||
if (b.hasUnknownBits())
|
||||
return createUnknown();
|
||||
if (b.HasUnknownBits())
|
||||
return CreateUnknown();
|
||||
if (b.value == 0)
|
||||
return a;
|
||||
if (b.value < 0 || b.value >= sizeof(int) * 8)
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
int shift = b.value;
|
||||
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));
|
||||
return new Int32Value(a.value >> shift, validMask);
|
||||
}
|
||||
|
||||
public static Int32Value Shr_Un(Int32Value a, Int32Value b) {
|
||||
if (b.hasUnknownBits())
|
||||
return createUnknown();
|
||||
if (b.HasUnknownBits())
|
||||
return CreateUnknown();
|
||||
if (b.value == 0)
|
||||
return a;
|
||||
if (b.value < 0 || b.value >= sizeof(int) * 8)
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
int shift = b.value;
|
||||
uint validMask = (a.validMask >> shift) | (uint.MaxValue << (sizeof(int) * 8 - shift));
|
||||
return new Int32Value((int)((uint)a.value >> shift), validMask);
|
||||
|
@ -374,32 +374,32 @@ namespace de4dot.blocks.cflow {
|
|||
switch (b) {
|
||||
case Bool3.False: return zero;
|
||||
case Bool3.True: return one;
|
||||
default: return createUnknownBool();
|
||||
default: return CreateUnknownBool();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
return create(compareGt(a, b));
|
||||
return create(CompareGt(a, 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) {
|
||||
return create(compareLt(a, b));
|
||||
return create(CompareLt(a, 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) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareEq(Int32Value a, Int32Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
return a.value == b.value ? Bool3.True : Bool3.False;
|
||||
if (ReferenceEquals(a, b))
|
||||
return Bool3.True;
|
||||
|
@ -408,8 +408,8 @@ namespace de4dot.blocks.cflow {
|
|||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareNeq(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareNeq(Int32Value a, Int32Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
return a.value != b.value ? Bool3.True : Bool3.False;
|
||||
if (ReferenceEquals(a, b))
|
||||
return Bool3.False;
|
||||
|
@ -418,96 +418,96 @@ namespace de4dot.blocks.cflow {
|
|||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareGt(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareGt(Int32Value a, Int32Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(int.MaxValue))
|
||||
if (b.HasValue(int.MaxValue))
|
||||
return Bool3.False; // x > max => false
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareGt_Un(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareGt_Un(Int32Value a, Int32Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(uint.MaxValue))
|
||||
if (b.HasValue(uint.MaxValue))
|
||||
return Bool3.False; // x > max => false
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareGe(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareGe(Int32Value a, Int32Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(int.MinValue))
|
||||
if (b.HasValue(int.MinValue))
|
||||
return Bool3.True; // x >= min => true
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareGe_Un(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareGe_Un(Int32Value a, Int32Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(uint.MinValue))
|
||||
if (b.HasValue(uint.MinValue))
|
||||
return Bool3.True; // x >= min => true
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareLe(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareLe(Int32Value a, Int32Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(int.MaxValue))
|
||||
if (b.HasValue(int.MaxValue))
|
||||
return Bool3.True; // x <= max => true
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareLe_Un(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareLe_Un(Int32Value a, Int32Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(uint.MaxValue))
|
||||
if (b.HasValue(uint.MaxValue))
|
||||
return Bool3.True; // x <= max => true
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareLt(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareLt(Int32Value a, Int32Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(int.MinValue))
|
||||
if (b.HasValue(int.MinValue))
|
||||
return Bool3.False; // x < min => false
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareLt_Un(Int32Value a, Int32Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareLt_Un(Int32Value a, Int32Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(uint.MinValue))
|
||||
if (b.HasValue(uint.MinValue))
|
||||
return Bool3.False; // x < min => false
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareTrue(Int32Value a) {
|
||||
if (a.allBitsValid())
|
||||
public static Bool3 CompareTrue(Int32Value a) {
|
||||
if (a.AllBitsValid())
|
||||
return a.value != 0 ? Bool3.True : Bool3.False;
|
||||
if ((a.value & a.validMask) != 0)
|
||||
return Bool3.True;
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareFalse(Int32Value a) {
|
||||
if (a.allBitsValid())
|
||||
public static Bool3 CompareFalse(Int32Value a) {
|
||||
if (a.AllBitsValid())
|
||||
return a.value == 0 ? Bool3.True : Bool3.False;
|
||||
if ((a.value & a.validMask) != 0)
|
||||
return Bool3.False;
|
||||
|
@ -515,7 +515,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
public override string ToString() {
|
||||
if (allBitsValid())
|
||||
if (AllBitsValid())
|
||||
return value.ToString();
|
||||
return string.Format("0x{0:X8}({1:X8})", value, validMask);
|
||||
}
|
||||
|
|
|
@ -40,40 +40,40 @@ namespace de4dot.blocks.cflow {
|
|||
this.validMask = validMask;
|
||||
}
|
||||
|
||||
bool hasUnknownBits() {
|
||||
bool HasUnknownBits() {
|
||||
return validMask != NO_UNKNOWN_BITS;
|
||||
}
|
||||
|
||||
public bool allBitsValid() {
|
||||
return !hasUnknownBits();
|
||||
public bool AllBitsValid() {
|
||||
return !HasUnknownBits();
|
||||
}
|
||||
|
||||
bool isBitValid(int n) {
|
||||
return isBitValid(validMask, n);
|
||||
bool IsBitValid(int n) {
|
||||
return IsBitValid(validMask, n);
|
||||
}
|
||||
|
||||
static bool isBitValid(ulong validMask, int n) {
|
||||
static bool IsBitValid(ulong validMask, int n) {
|
||||
return (validMask & (1UL << n)) != 0;
|
||||
}
|
||||
|
||||
public static Int64Value createUnknown() {
|
||||
public static Int64Value CreateUnknown() {
|
||||
return new Int64Value(0, 0UL);
|
||||
}
|
||||
|
||||
public bool isZero() {
|
||||
return hasValue(0);
|
||||
public bool IsZero() {
|
||||
return HasValue(0);
|
||||
}
|
||||
|
||||
public bool isNonZero() {
|
||||
public bool IsNonZero() {
|
||||
return ((ulong)value & validMask) != 0;
|
||||
}
|
||||
|
||||
public bool hasValue(long value) {
|
||||
return allBitsValid() && this.value == value;
|
||||
public bool HasValue(long value) {
|
||||
return AllBitsValid() && this.value == value;
|
||||
}
|
||||
|
||||
public bool hasValue(ulong value) {
|
||||
return hasValue((long)value);
|
||||
public bool HasValue(ulong value) {
|
||||
return HasValue((long)value);
|
||||
}
|
||||
|
||||
public static Int64Value Conv_U8(Int32Value a) {
|
||||
|
@ -93,7 +93,7 @@ namespace de4dot.blocks.cflow {
|
|||
public static Int64Value Conv_I8(Int32Value a) {
|
||||
long value = a.value;
|
||||
ulong validMask = a.validMask;
|
||||
if (isBitValid(validMask, 31))
|
||||
if (IsBitValid(validMask, 31))
|
||||
validMask |= NO_UNKNOWN_BITS << 32;
|
||||
else
|
||||
validMask &= ~(NO_UNKNOWN_BITS << 32);
|
||||
|
@ -109,97 +109,97 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
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);
|
||||
if (ReferenceEquals(a, b))
|
||||
return new Int64Value(a.value << 1, (a.validMask << 1) | 1);
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
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);
|
||||
if (ReferenceEquals(a, b))
|
||||
return zero;
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
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);
|
||||
if (a.isZero() || b.isZero())
|
||||
if (a.IsZero() || b.IsZero())
|
||||
return zero;
|
||||
if (a.hasValue(1))
|
||||
if (a.HasValue(1))
|
||||
return b;
|
||||
if (b.hasValue(1))
|
||||
if (b.HasValue(1))
|
||||
return a;
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int64Value Div(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid()) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid()) {
|
||||
try {
|
||||
return new Int64Value(a.value / b.value);
|
||||
}
|
||||
catch (ArithmeticException) {
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
}
|
||||
if (ReferenceEquals(a, b) && a.isNonZero())
|
||||
if (ReferenceEquals(a, b) && a.IsNonZero())
|
||||
return one;
|
||||
if (b.hasValue(1))
|
||||
if (b.HasValue(1))
|
||||
return a;
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int64Value Div_Un(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid()) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid()) {
|
||||
try {
|
||||
return new Int64Value((long)((ulong)a.value / (ulong)b.value));
|
||||
}
|
||||
catch (ArithmeticException) {
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
}
|
||||
if (ReferenceEquals(a, b) && a.isNonZero())
|
||||
if (ReferenceEquals(a, b) && a.IsNonZero())
|
||||
return one;
|
||||
if (b.hasValue(1))
|
||||
if (b.HasValue(1))
|
||||
return a;
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int64Value Rem(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid()) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid()) {
|
||||
try {
|
||||
return new Int64Value(a.value % b.value);
|
||||
}
|
||||
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 createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int64Value Rem_Un(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid()) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid()) {
|
||||
try {
|
||||
return new Int64Value((long)((ulong)a.value % (ulong)b.value));
|
||||
}
|
||||
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 createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int64Value Neg(Int64Value a) {
|
||||
if (a.allBitsValid())
|
||||
if (a.AllBitsValid())
|
||||
return new Int64Value(-a.value);
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
}
|
||||
|
||||
public static Int64Value And(Int64Value a, Int64Value b) {
|
||||
|
@ -227,73 +227,73 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
public static Int64Value Shl(Int64Value a, Int32Value b) {
|
||||
if (b.hasUnknownBits())
|
||||
return createUnknown();
|
||||
if (b.HasUnknownBits())
|
||||
return CreateUnknown();
|
||||
if (b.value == 0)
|
||||
return a;
|
||||
if (b.value < 0 || b.value >= sizeof(long) * 8)
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
int shift = b.value;
|
||||
ulong validMask = (a.validMask << shift) | (ulong.MaxValue >> (sizeof(long) * 8 - shift));
|
||||
return new Int64Value(a.value << shift, validMask);
|
||||
}
|
||||
|
||||
public static Int64Value Shr(Int64Value a, Int32Value b) {
|
||||
if (b.hasUnknownBits())
|
||||
return createUnknown();
|
||||
if (b.HasUnknownBits())
|
||||
return CreateUnknown();
|
||||
if (b.value == 0)
|
||||
return a;
|
||||
if (b.value < 0 || b.value >= sizeof(long) * 8)
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
int shift = b.value;
|
||||
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));
|
||||
return new Int64Value(a.value >> shift, validMask);
|
||||
}
|
||||
|
||||
public static Int64Value Shr_Un(Int64Value a, Int32Value b) {
|
||||
if (b.hasUnknownBits())
|
||||
return createUnknown();
|
||||
if (b.HasUnknownBits())
|
||||
return CreateUnknown();
|
||||
if (b.value == 0)
|
||||
return a;
|
||||
if (b.value < 0 || b.value >= sizeof(long) * 8)
|
||||
return createUnknown();
|
||||
return CreateUnknown();
|
||||
int shift = b.value;
|
||||
ulong validMask = (a.validMask >> shift) | (ulong.MaxValue << (sizeof(long) * 8 - shift));
|
||||
return new Int64Value((long)((ulong)a.value >> shift), validMask);
|
||||
}
|
||||
|
||||
static Int32Value create(Bool3 b) {
|
||||
static Int32Value Create(Bool3 b) {
|
||||
switch (b) {
|
||||
case Bool3.False: return Int32Value.zero;
|
||||
case Bool3.True: return Int32Value.one;
|
||||
default: return Int32Value.createUnknownBool();
|
||||
default: return Int32Value.CreateUnknownBool();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
return create(compareGt(a, b));
|
||||
return Create(CompareGt(a, 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) {
|
||||
return create(compareLt(a, b));
|
||||
return Create(CompareLt(a, 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) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareEq(Int64Value a, Int64Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
return a.value == b.value ? Bool3.True : Bool3.False;
|
||||
if (ReferenceEquals(a, b))
|
||||
return Bool3.True;
|
||||
|
@ -302,8 +302,8 @@ namespace de4dot.blocks.cflow {
|
|||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareNeq(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareNeq(Int64Value a, Int64Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
return a.value != b.value ? Bool3.True : Bool3.False;
|
||||
if (ReferenceEquals(a, b))
|
||||
return Bool3.False;
|
||||
|
@ -312,96 +312,96 @@ namespace de4dot.blocks.cflow {
|
|||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareGt(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareGt(Int64Value a, Int64Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(long.MaxValue))
|
||||
if (b.HasValue(long.MaxValue))
|
||||
return Bool3.False; // x > max => false
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareGt_Un(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareGt_Un(Int64Value a, Int64Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(ulong.MaxValue))
|
||||
if (b.HasValue(ulong.MaxValue))
|
||||
return Bool3.False; // x > max => false
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareGe(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareGe(Int64Value a, Int64Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(long.MinValue))
|
||||
if (b.HasValue(long.MinValue))
|
||||
return Bool3.True; // x >= min => true
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareGe_Un(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareGe_Un(Int64Value a, Int64Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(ulong.MinValue))
|
||||
if (b.HasValue(ulong.MinValue))
|
||||
return Bool3.True; // x >= min => true
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareLe(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareLe(Int64Value a, Int64Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(long.MaxValue))
|
||||
if (b.HasValue(long.MaxValue))
|
||||
return Bool3.True; // x <= max => true
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareLe_Un(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareLe_Un(Int64Value a, Int64Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(ulong.MaxValue))
|
||||
if (b.HasValue(ulong.MaxValue))
|
||||
return Bool3.True; // x <= max => true
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareLt(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareLt(Int64Value a, Int64Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(long.MinValue))
|
||||
if (b.HasValue(long.MinValue))
|
||||
return Bool3.False; // x < min => false
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareLt_Un(Int64Value a, Int64Value b) {
|
||||
if (a.allBitsValid() && b.allBitsValid())
|
||||
public static Bool3 CompareLt_Un(Int64Value a, Int64Value b) {
|
||||
if (a.AllBitsValid() && b.AllBitsValid())
|
||||
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
|
||||
if (b.hasValue(ulong.MinValue))
|
||||
if (b.HasValue(ulong.MinValue))
|
||||
return Bool3.False; // x < min => false
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareTrue(Int64Value a) {
|
||||
if (a.allBitsValid())
|
||||
public static Bool3 CompareTrue(Int64Value a) {
|
||||
if (a.AllBitsValid())
|
||||
return a.value != 0 ? Bool3.True : Bool3.False;
|
||||
if (((ulong)a.value & a.validMask) != 0)
|
||||
return Bool3.True;
|
||||
return Bool3.Unknown;
|
||||
}
|
||||
|
||||
public static Bool3 compareFalse(Int64Value a) {
|
||||
if (a.allBitsValid())
|
||||
public static Bool3 CompareFalse(Int64Value a) {
|
||||
if (a.AllBitsValid())
|
||||
return a.value == 0 ? Bool3.True : Bool3.False;
|
||||
if (((ulong)a.value & a.validMask) != 0)
|
||||
return Bool3.False;
|
||||
|
@ -409,7 +409,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
public override string ToString() {
|
||||
if (allBitsValid())
|
||||
if (AllBitsValid())
|
||||
return value.ToString();
|
||||
return string.Format("0x{0:X8}L({1:X8})", value, validMask);
|
||||
}
|
||||
|
|
|
@ -29,18 +29,18 @@ namespace de4dot.blocks.cflow {
|
|||
this.inlineInstanceMethods = inlineInstanceMethods;
|
||||
}
|
||||
|
||||
protected override bool deobfuscateInternal() {
|
||||
protected override bool DeobfuscateInternal() {
|
||||
bool changed = false;
|
||||
var instructions = block.Instructions;
|
||||
for (int i = 0; i < instructions.Count; i++) {
|
||||
var instr = instructions[i].Instruction;
|
||||
if (instr.OpCode.Code == Code.Call)
|
||||
changed |= inlineMethod(instr, i);
|
||||
changed |= InlineMethod(instr, i);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
protected virtual bool canInline(MethodDef method) {
|
||||
protected virtual bool CanInline(MethodDef method) {
|
||||
if (method.GenericParameters.Count > 0)
|
||||
return false;
|
||||
if (method == blocks.Method)
|
||||
|
@ -55,19 +55,19 @@ namespace de4dot.blocks.cflow {
|
|||
return inlineInstanceMethods;
|
||||
}
|
||||
|
||||
bool inlineMethod(Instruction callInstr, int instrIndex) {
|
||||
bool InlineMethod(Instruction callInstr, int instrIndex) {
|
||||
var methodToInline = callInstr.Operand as MethodDef;
|
||||
if (methodToInline == null)
|
||||
return false;
|
||||
|
||||
if (!canInline(methodToInline))
|
||||
if (!CanInline(methodToInline))
|
||||
return false;
|
||||
var body = methodToInline.Body;
|
||||
if (body == null)
|
||||
return false;
|
||||
|
||||
int index = 0;
|
||||
var instr = DotNetUtils.getInstruction(body.Instructions, ref index);
|
||||
var instr = DotNetUtils.GetInstruction(body.Instructions, ref index);
|
||||
if (instr == null)
|
||||
return false;
|
||||
|
||||
|
@ -83,7 +83,7 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Call:
|
||||
case Code.Callvirt:
|
||||
case Code.Newobj:
|
||||
return inlineOtherMethod(instrIndex, methodToInline, instr, index);
|
||||
return InlineOtherMethod(instrIndex, methodToInline, instr, index);
|
||||
|
||||
case Code.Ldc_I4:
|
||||
case Code.Ldc_I4_0:
|
||||
|
@ -106,17 +106,17 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Ldtoken:
|
||||
case Code.Ldsfld:
|
||||
case Code.Ldsflda:
|
||||
return inlineLoadMethod(instrIndex, methodToInline, instr, index);
|
||||
return InlineLoadMethod(instrIndex, methodToInline, instr, index);
|
||||
|
||||
default:
|
||||
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))
|
||||
return true;
|
||||
if (isValueType(newType) || isValueType(origType))
|
||||
if (IsValueType(newType) || IsValueType(origType))
|
||||
return false;
|
||||
return newType.FullName == "System.Object";
|
||||
}
|
||||
|
|
|
@ -33,24 +33,24 @@ namespace de4dot.blocks.cflow {
|
|||
|
||||
public bool ExecuteOnNoChange { get; set; }
|
||||
|
||||
public void deobfuscateBegin(Blocks blocks) {
|
||||
public void DeobfuscateBegin(Blocks blocks) {
|
||||
this.blocks = blocks;
|
||||
iteration = 0;
|
||||
}
|
||||
|
||||
public bool deobfuscate(List<Block> allBlocks) {
|
||||
public bool Deobfuscate(List<Block> allBlocks) {
|
||||
if (iteration++ >= MAX_ITERATIONS)
|
||||
return false;
|
||||
|
||||
bool changed = false;
|
||||
foreach (var block in allBlocks) {
|
||||
this.block = block;
|
||||
changed |= deobfuscateInternal();
|
||||
changed |= DeobfuscateInternal();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
protected abstract bool deobfuscateInternal();
|
||||
protected abstract bool DeobfuscateInternal();
|
||||
|
||||
protected class InstructionPatcher {
|
||||
readonly int patchIndex;
|
||||
|
@ -64,53 +64,53 @@ namespace de4dot.blocks.cflow {
|
|||
this.clonedInstr = new Instr(lastInstr.Clone());
|
||||
}
|
||||
|
||||
public void patch(Block block) {
|
||||
public void Patch(Block block) {
|
||||
block.Instructions[patchIndex] = clonedInstr;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool inlineLoadMethod(int patchIndex, MethodDef methodToInline, Instruction loadInstr, int instrIndex) {
|
||||
if (!isReturn(methodToInline, instrIndex))
|
||||
protected bool InlineLoadMethod(int patchIndex, MethodDef methodToInline, Instruction loadInstr, int instrIndex) {
|
||||
if (!IsReturn(methodToInline, instrIndex))
|
||||
return false;
|
||||
|
||||
int methodArgsCount = DotNetUtils.getArgsCount(methodToInline);
|
||||
int methodArgsCount = DotNetUtils.GetArgsCount(methodToInline);
|
||||
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());
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool inlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) {
|
||||
return inlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0);
|
||||
protected bool InlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) {
|
||||
return InlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0);
|
||||
}
|
||||
|
||||
protected bool inlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
|
||||
return patchMethod(methodToInline, tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, popLastArgs));
|
||||
protected bool InlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int 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)
|
||||
return false;
|
||||
|
||||
if (!isReturn(methodToInline, patcher.afterIndex))
|
||||
if (!IsReturn(methodToInline, patcher.afterIndex))
|
||||
return false;
|
||||
|
||||
patcher.patch(block);
|
||||
patcher.Patch(block);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) {
|
||||
return tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0);
|
||||
protected InstructionPatcher TryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 methodArgsCount = DotNetUtils.getArgsCount(methodToInline);
|
||||
int methodArgsCount = DotNetUtils.GetArgsCount(methodToInline);
|
||||
bool foundLdarga = false;
|
||||
while (instr != null && loadIndex < methodArgsCount) {
|
||||
bool isLdarg = true;
|
||||
|
@ -136,8 +136,8 @@ namespace de4dot.blocks.cflow {
|
|||
if (instr.GetParameterIndex() != loadIndex)
|
||||
return null;
|
||||
loadIndex++;
|
||||
instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
|
||||
instr = onAfterLoadArg(methodToInline, instr, ref instrIndex);
|
||||
instr = DotNetUtils.GetInstruction(methodToInline.Body.Instructions, ref instrIndex);
|
||||
instr = OnAfterLoadArg(methodToInline, instr, ref instrIndex);
|
||||
}
|
||||
if (instr == null || loadIndex != methodArgsCount - popLastArgs)
|
||||
return null;
|
||||
|
@ -150,13 +150,13 @@ namespace de4dot.blocks.cflow {
|
|||
if (calledMethod == null)
|
||||
return null;
|
||||
|
||||
if (!isCompatibleType(-1, calledMethod.MethodSig.RetType, methodToInline.MethodSig.RetType))
|
||||
if (!IsCompatibleType(-1, calledMethod.MethodSig.RetType, methodToInline.MethodSig.RetType))
|
||||
return null;
|
||||
|
||||
if (!checkSameMethods(calledMethod, methodToInline, popLastArgs))
|
||||
if (!CheckSameMethods(calledMethod, methodToInline, popLastArgs))
|
||||
return null;
|
||||
|
||||
if (!hasAccessTo(instr.Operand))
|
||||
if (!HasAccessTo(instr.Operand))
|
||||
return null;
|
||||
|
||||
return new InstructionPatcher(patchIndex, instrIndex, callInstr);
|
||||
|
@ -169,19 +169,19 @@ namespace de4dot.blocks.cflow {
|
|||
if (ctor == null)
|
||||
return null;
|
||||
|
||||
if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodSig.RetType))
|
||||
if (!IsCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodSig.RetType))
|
||||
return null;
|
||||
|
||||
var methodArgs = methodToInline.Parameters;
|
||||
var calledMethodArgs = DotNetUtils.getArgs(ctor);
|
||||
var calledMethodArgs = DotNetUtils.GetArgs(ctor);
|
||||
if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count)
|
||||
return null;
|
||||
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;
|
||||
}
|
||||
|
||||
if (!hasAccessTo(instr.Operand))
|
||||
if (!HasAccessTo(instr.Operand))
|
||||
return null;
|
||||
|
||||
return new InstructionPatcher(patchIndex, instrIndex, newobjInstr);
|
||||
|
@ -192,7 +192,7 @@ namespace de4dot.blocks.cflow {
|
|||
if (methodArgsCount != 1)
|
||||
return null;
|
||||
|
||||
if (!hasAccessTo(instr.Operand))
|
||||
if (!HasAccessTo(instr.Operand))
|
||||
return null;
|
||||
|
||||
return new InstructionPatcher(patchIndex, instrIndex, ldInstr);
|
||||
|
@ -201,36 +201,36 @@ namespace de4dot.blocks.cflow {
|
|||
return null;
|
||||
}
|
||||
|
||||
bool hasAccessTo(object operand) {
|
||||
bool HasAccessTo(object operand) {
|
||||
if (operand == null)
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
|
||||
protected virtual bool isReturn(MethodDef methodToInline, int instrIndex) {
|
||||
var instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
|
||||
protected virtual bool IsReturn(MethodDef methodToInline, int instrIndex) {
|
||||
var instr = DotNetUtils.GetInstruction(methodToInline.Body.Instructions, ref instrIndex);
|
||||
return instr != null && instr.OpCode.Code == Code.Ret;
|
||||
}
|
||||
|
||||
protected bool checkSameMethods(IMethod method, MethodDef methodToInline) {
|
||||
return checkSameMethods(method, methodToInline, 0);
|
||||
protected bool CheckSameMethods(IMethod method, MethodDef methodToInline) {
|
||||
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 methodArgs = DotNetUtils.getArgs(method);
|
||||
var methodArgs = DotNetUtils.GetArgs(method);
|
||||
bool hasImplicitThis = method.MethodSig.ImplicitThis;
|
||||
if (methodToInlineArgs.Count - ignoreLastMethodToInlineArgs != methodArgs.Count)
|
||||
return false;
|
||||
for (int i = 0; i < methodArgs.Count; i++) {
|
||||
var methodArg = methodArgs[i];
|
||||
var methodToInlineArg = getArgType(methodToInline, methodToInlineArgs[i].Type);
|
||||
if (!isCompatibleType(i, methodArg, methodToInlineArg)) {
|
||||
var methodToInlineArg = GetArgType(methodToInline, methodToInlineArgs[i].Type);
|
||||
if (!IsCompatibleType(i, methodArg, methodToInlineArg)) {
|
||||
if (i != 0 || !hasImplicitThis)
|
||||
return false;
|
||||
if (!isCompatibleValueThisPtr(methodArg, methodToInlineArg))
|
||||
|
@ -241,7 +241,7 @@ namespace de4dot.blocks.cflow {
|
|||
return true;
|
||||
}
|
||||
|
||||
static TypeSig getArgType(MethodDef method, TypeSig arg) {
|
||||
static TypeSig GetArgType(MethodDef method, TypeSig arg) {
|
||||
if (arg.GetElementType() != ElementType.MVar)
|
||||
return arg;
|
||||
var mvar = (GenericMVar)arg;
|
||||
|
@ -254,7 +254,7 @@ namespace de4dot.blocks.cflow {
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -262,12 +262,12 @@ namespace de4dot.blocks.cflow {
|
|||
var newByRef = newType as ByRefSig;
|
||||
if (newByRef == null)
|
||||
return false;
|
||||
if (!isValueType(newByRef.Next) || !isValueType(origType))
|
||||
if (!IsValueType(newByRef.Next) || !IsValueType(origType))
|
||||
return false;
|
||||
return new SigComparer().Equals(origType, newByRef.Next);
|
||||
}
|
||||
|
||||
protected static bool isValueType(IType type) {
|
||||
protected static bool IsValueType(IType type) {
|
||||
if (type == null)
|
||||
return false;
|
||||
var ts = type as TypeSig;
|
||||
|
|
|
@ -26,12 +26,12 @@ namespace de4dot.blocks.cflow {
|
|||
class StLdlocFixer : BlockDeobfuscator {
|
||||
IList<Local> locals;
|
||||
|
||||
protected override void init(List<Block> allBlocks) {
|
||||
base.init(allBlocks);
|
||||
protected override void Initialize(List<Block> allBlocks) {
|
||||
base.Initialize(allBlocks);
|
||||
locals = blocks.Locals;
|
||||
}
|
||||
|
||||
protected override bool deobfuscate(Block block) {
|
||||
protected override bool Deobfuscate(Block block) {
|
||||
bool changed = false;
|
||||
var instructions = block.Instructions;
|
||||
for (int i = 0; i < instructions.Count; i++) {
|
||||
|
@ -47,12 +47,12 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Stloc_3:
|
||||
if (i + 1 >= instructions.Count)
|
||||
break;
|
||||
if (!instructions[i + 1].isLdloc())
|
||||
if (!instructions[i + 1].IsLdloc())
|
||||
break;
|
||||
var local = Instr.getLocalVar(locals, instr);
|
||||
var local = Instr.GetLocalVar(locals, instr);
|
||||
if (local.Type.ElementType != ElementType.Boolean)
|
||||
continue;
|
||||
if (local != Instr.getLocalVar(locals, instructions[i + 1]))
|
||||
if (local != Instr.GetLocalVar(locals, instructions[i + 1]))
|
||||
break;
|
||||
instructions[i] = new Instr(OpCodes.Dup.ToInstruction());
|
||||
instructions[i + 1] = instr;
|
||||
|
|
|
@ -26,50 +26,50 @@ namespace de4dot.blocks.cflow {
|
|||
class SwitchCflowDeobfuscator : BlockDeobfuscator {
|
||||
InstructionEmulator instructionEmulator = new InstructionEmulator();
|
||||
|
||||
protected override bool deobfuscate(Block switchBlock) {
|
||||
protected override bool Deobfuscate(Block switchBlock) {
|
||||
if (switchBlock.LastInstr.OpCode.Code != Code.Switch)
|
||||
return false;
|
||||
|
||||
if (isSwitchTopOfStack(switchBlock) && deobfuscateTos(switchBlock))
|
||||
if (IsSwitchTopOfStack(switchBlock) && DeobfuscateTOS(switchBlock))
|
||||
return true;
|
||||
|
||||
if (isLdlocBranch(switchBlock, true) && deobfuscateLdloc(switchBlock))
|
||||
if (IsLdlocBranch(switchBlock, true) && DeobfuscateLdloc(switchBlock))
|
||||
return true;
|
||||
|
||||
if (isStLdlocBranch(switchBlock, true) && deobfuscateStLdloc(switchBlock))
|
||||
if (IsStLdlocBranch(switchBlock, true) && DeobfuscateStLdloc(switchBlock))
|
||||
return true;
|
||||
|
||||
if (isSwitchType1(switchBlock) && deobfuscateType1(switchBlock))
|
||||
if (IsSwitchType1(switchBlock) && DeobfuscateType1(switchBlock))
|
||||
return true;
|
||||
|
||||
if (isSwitchType2(switchBlock) && deobfuscateType2(switchBlock))
|
||||
if (IsSwitchType2(switchBlock) && DeobfuscateType2(switchBlock))
|
||||
return true;
|
||||
|
||||
if (switchBlock.FirstInstr.isLdloc() && fixSwitchBranch(switchBlock))
|
||||
if (switchBlock.FirstInstr.IsLdloc() && FixSwitchBranch(switchBlock))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isSwitchTopOfStack(Block switchBlock) {
|
||||
static bool IsSwitchTopOfStack(Block switchBlock) {
|
||||
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);
|
||||
return switchBlock.Instructions.Count == numInstrs && switchBlock.Instructions[0].isLdloc();
|
||||
return switchBlock.Instructions.Count == numInstrs && switchBlock.Instructions[0].IsLdloc();
|
||||
}
|
||||
|
||||
static bool isSwitchType1(Block switchBlock) {
|
||||
return switchBlock.FirstInstr.isLdloc();
|
||||
static bool IsSwitchType1(Block switchBlock) {
|
||||
return switchBlock.FirstInstr.IsLdloc();
|
||||
}
|
||||
|
||||
bool isSwitchType2(Block switchBlock) {
|
||||
bool IsSwitchType2(Block switchBlock) {
|
||||
Local local = null;
|
||||
foreach (var instr in switchBlock.Instructions) {
|
||||
if (!instr.isLdloc())
|
||||
if (!instr.IsLdloc())
|
||||
continue;
|
||||
local = Instr.getLocalVar(blocks.Locals, instr);
|
||||
local = Instr.GetLocalVar(blocks.Locals, instr);
|
||||
break;
|
||||
}
|
||||
if (local == null)
|
||||
|
@ -79,12 +79,12 @@ namespace de4dot.blocks.cflow {
|
|||
var instrs = source.Instructions;
|
||||
for (int i = 1; i < instrs.Count; i++) {
|
||||
var ldci4 = instrs[i - 1];
|
||||
if (!ldci4.isLdcI4())
|
||||
if (!ldci4.IsLdcI4())
|
||||
continue;
|
||||
var stloc = instrs[i];
|
||||
if (!stloc.isStloc())
|
||||
if (!stloc.IsStloc())
|
||||
continue;
|
||||
if (Instr.getLocalVar(blocks.Locals, stloc) != local)
|
||||
if (Instr.GetLocalVar(blocks.Locals, stloc) != local)
|
||||
continue;
|
||||
|
||||
return true;
|
||||
|
@ -94,29 +94,29 @@ namespace de4dot.blocks.cflow {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool isStLdlocBranch(Block switchBlock, bool isSwitch) {
|
||||
bool IsStLdlocBranch(Block switchBlock, bool isSwitch) {
|
||||
int numInstrs = 2 + (isSwitch ? 1 : 0);
|
||||
return switchBlock.Instructions.Count == numInstrs &&
|
||||
switchBlock.Instructions[0].isStloc() &&
|
||||
switchBlock.Instructions[1].isLdloc() &&
|
||||
Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[0]) == Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[1]);
|
||||
switchBlock.Instructions[0].IsStloc() &&
|
||||
switchBlock.Instructions[1].IsLdloc() &&
|
||||
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;
|
||||
if (switchBlock.Targets == null)
|
||||
return changed;
|
||||
var targets = new List<Block>(switchBlock.Targets);
|
||||
|
||||
changed |= deobfuscateTos(targets, switchBlock.FallThrough, switchBlock);
|
||||
changed |= DeobfuscateTOS(targets, switchBlock.FallThrough, switchBlock);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool deobfuscateLdloc(Block switchBlock) {
|
||||
bool DeobfuscateLdloc(Block switchBlock) {
|
||||
bool changed = false;
|
||||
|
||||
var switchVariable = Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[0]);
|
||||
var switchVariable = Instr.GetLocalVar(blocks.Locals, switchBlock.Instructions[0]);
|
||||
if (switchVariable == null)
|
||||
return changed;
|
||||
|
||||
|
@ -124,15 +124,15 @@ namespace de4dot.blocks.cflow {
|
|||
return changed;
|
||||
var targets = new List<Block>(switchBlock.Targets);
|
||||
|
||||
changed |= deobfuscateLdloc(targets, switchBlock.FallThrough, switchBlock, switchVariable);
|
||||
changed |= DeobfuscateLdloc(targets, switchBlock.FallThrough, switchBlock, switchVariable);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool deobfuscateStLdloc(Block switchBlock) {
|
||||
bool DeobfuscateStLdloc(Block switchBlock) {
|
||||
bool changed = false;
|
||||
|
||||
var switchVariable = Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[0]);
|
||||
var switchVariable = Instr.GetLocalVar(blocks.Locals, switchBlock.Instructions[0]);
|
||||
if (switchVariable == null)
|
||||
return changed;
|
||||
|
||||
|
@ -140,7 +140,7 @@ namespace de4dot.blocks.cflow {
|
|||
return changed;
|
||||
var targets = new List<Block>(switchBlock.Targets);
|
||||
|
||||
changed |= deobfuscateStLdloc(targets, switchBlock.FallThrough, switchBlock);
|
||||
changed |= DeobfuscateStLdloc(targets, switchBlock.FallThrough, switchBlock);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
@ -153,19 +153,19 @@ namespace de4dot.blocks.cflow {
|
|||
// stloc N
|
||||
// ldloc N
|
||||
// switch (......)
|
||||
bool deobfuscateStLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block) {
|
||||
bool DeobfuscateStLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block) {
|
||||
bool changed = false;
|
||||
foreach (var source in new List<Block>(block.Sources)) {
|
||||
if (!isBranchBlock(source))
|
||||
continue;
|
||||
instructionEmulator.init(blocks);
|
||||
instructionEmulator.emulate(source.Instructions);
|
||||
instructionEmulator.Initialize(blocks);
|
||||
instructionEmulator.Emulate(source.Instructions);
|
||||
|
||||
var target = getSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.pop());
|
||||
var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.Pop());
|
||||
if (target == null)
|
||||
continue;
|
||||
source.replaceLastNonBranchWithBranch(0, target);
|
||||
source.add(new Instr(OpCodes.Pop.ToInstruction()));
|
||||
source.ReplaceLastNonBranchWithBranch(0, target);
|
||||
source.Add(new Instr(OpCodes.Pop.ToInstruction()));
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
|
@ -179,32 +179,32 @@ namespace de4dot.blocks.cflow {
|
|||
// swblk:
|
||||
// ldloc N
|
||||
// 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;
|
||||
foreach (var source in new List<Block>(block.Sources)) {
|
||||
if (isBranchBlock(source)) {
|
||||
instructionEmulator.init(blocks);
|
||||
instructionEmulator.emulate(source.Instructions);
|
||||
instructionEmulator.Initialize(blocks);
|
||||
instructionEmulator.Emulate(source.Instructions);
|
||||
|
||||
var target = getSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.getLocal(switchVariable));
|
||||
var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.GetLocal(switchVariable));
|
||||
if (target == null)
|
||||
continue;
|
||||
source.replaceLastNonBranchWithBranch(0, target);
|
||||
source.ReplaceLastNonBranchWithBranch(0, target);
|
||||
changed = true;
|
||||
}
|
||||
else if (isBccBlock(source)) {
|
||||
instructionEmulator.init(blocks);
|
||||
instructionEmulator.emulate(source.Instructions);
|
||||
else if (IsBccBlock(source)) {
|
||||
instructionEmulator.Initialize(blocks);
|
||||
instructionEmulator.Emulate(source.Instructions);
|
||||
|
||||
var target = getSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.getLocal(switchVariable));
|
||||
var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.GetLocal(switchVariable));
|
||||
if (target == null)
|
||||
continue;
|
||||
if (source.Targets[0] == block) {
|
||||
source.setNewTarget(0, target);
|
||||
source.SetNewTarget(0, target);
|
||||
changed = true;
|
||||
}
|
||||
if (source.FallThrough == block) {
|
||||
source.setNewFallThrough(target);
|
||||
source.SetNewFallThrough(target);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
@ -218,21 +218,21 @@ namespace de4dot.blocks.cflow {
|
|||
// br swblk
|
||||
// swblk:
|
||||
// switch (......)
|
||||
bool deobfuscateTos(IList<Block> switchTargets, Block switchFallThrough, Block block) {
|
||||
bool DeobfuscateTOS(IList<Block> switchTargets, Block switchFallThrough, Block block) {
|
||||
bool changed = false;
|
||||
foreach (var source in new List<Block>(block.Sources)) {
|
||||
if (!isBranchBlock(source))
|
||||
continue;
|
||||
instructionEmulator.init(blocks);
|
||||
instructionEmulator.emulate(source.Instructions);
|
||||
instructionEmulator.Initialize(blocks);
|
||||
instructionEmulator.Emulate(source.Instructions);
|
||||
|
||||
var target = getSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.pop());
|
||||
var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.Pop());
|
||||
if (target == null) {
|
||||
changed |= deobfuscateTos_Ldloc(switchTargets, switchFallThrough, source);
|
||||
changed |= DeobfuscateTos_Ldloc(switchTargets, switchFallThrough, source);
|
||||
}
|
||||
else {
|
||||
source.replaceLastNonBranchWithBranch(0, target);
|
||||
source.add(new Instr(OpCodes.Pop.ToInstruction()));
|
||||
source.ReplaceLastNonBranchWithBranch(0, target);
|
||||
source.Add(new Instr(OpCodes.Pop.ToInstruction()));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
@ -245,15 +245,15 @@ namespace de4dot.blocks.cflow {
|
|||
// stloc N
|
||||
// ldloc N
|
||||
// br swblk
|
||||
bool deobfuscateTos_Ldloc(IList<Block> switchTargets, Block switchFallThrough, Block block) {
|
||||
if (isLdlocBranch(block, false)) {
|
||||
var switchVariable = Instr.getLocalVar(blocks.Locals, block.Instructions[0]);
|
||||
bool DeobfuscateTos_Ldloc(IList<Block> switchTargets, Block switchFallThrough, Block block) {
|
||||
if (IsLdlocBranch(block, false)) {
|
||||
var switchVariable = Instr.GetLocalVar(blocks.Locals, block.Instructions[0]);
|
||||
if (switchVariable == null)
|
||||
return false;
|
||||
return deobfuscateLdloc(switchTargets, switchFallThrough, block, switchVariable);
|
||||
return DeobfuscateLdloc(switchTargets, switchFallThrough, block, switchVariable);
|
||||
}
|
||||
else if (isStLdlocBranch(block, false))
|
||||
return deobfuscateStLdloc(switchTargets, switchFallThrough, block);
|
||||
else if (IsStLdlocBranch(block, false))
|
||||
return DeobfuscateStLdloc(switchTargets, switchFallThrough, block);
|
||||
|
||||
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)
|
||||
return false;
|
||||
if (block.FallThrough == null)
|
||||
|
@ -309,91 +309,91 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
}
|
||||
|
||||
bool deobfuscateType1(Block switchBlock) {
|
||||
bool DeobfuscateType1(Block switchBlock) {
|
||||
Block target;
|
||||
if (!emulateGetTarget(switchBlock, out target) || target != null)
|
||||
if (!EmulateGetTarget(switchBlock, out target) || target != null)
|
||||
return false;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
foreach (var source in new List<Block>(switchBlock.Sources)) {
|
||||
if (!source.canAppend(switchBlock))
|
||||
if (!source.CanAppend(switchBlock))
|
||||
continue;
|
||||
if (!willHaveKnownTarget(switchBlock, source))
|
||||
if (!WillHaveKnownTarget(switchBlock, source))
|
||||
continue;
|
||||
|
||||
source.append(switchBlock);
|
||||
source.Append(switchBlock);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool deobfuscateType2(Block switchBlock) {
|
||||
bool DeobfuscateType2(Block switchBlock) {
|
||||
bool changed = false;
|
||||
|
||||
var bccSources = new List<Block>();
|
||||
foreach (var source in new List<Block>(switchBlock.Sources)) {
|
||||
if (source.LastInstr.isConditionalBranch()) {
|
||||
if (source.LastInstr.IsConditionalBranch()) {
|
||||
bccSources.Add(source);
|
||||
continue;
|
||||
}
|
||||
if (!source.canAppend(switchBlock))
|
||||
if (!source.CanAppend(switchBlock))
|
||||
continue;
|
||||
if (!willHaveKnownTarget(switchBlock, source))
|
||||
if (!WillHaveKnownTarget(switchBlock, source))
|
||||
continue;
|
||||
|
||||
source.append(switchBlock);
|
||||
source.Append(switchBlock);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
foreach (var bccSource in bccSources) {
|
||||
if (!willHaveKnownTarget(switchBlock, bccSource))
|
||||
if (!WillHaveKnownTarget(switchBlock, bccSource))
|
||||
continue;
|
||||
var consts = getBccLocalConstants(bccSource);
|
||||
var consts = GetBccLocalConstants(bccSource);
|
||||
if (consts.Count == 0)
|
||||
continue;
|
||||
var newFallThrough = createBlock(consts, bccSource.FallThrough);
|
||||
var newTarget = createBlock(consts, bccSource.Targets[0]);
|
||||
var newFallThrough = CreateBlock(consts, bccSource.FallThrough);
|
||||
var newTarget = CreateBlock(consts, bccSource.Targets[0]);
|
||||
var oldFallThrough = bccSource.FallThrough;
|
||||
var oldTarget = bccSource.Targets[0];
|
||||
bccSource.setNewFallThrough(newFallThrough);
|
||||
bccSource.setNewTarget(0, newTarget);
|
||||
newFallThrough.setNewFallThrough(oldFallThrough);
|
||||
newTarget.setNewFallThrough(oldTarget);
|
||||
bccSource.SetNewFallThrough(newFallThrough);
|
||||
bccSource.SetNewTarget(0, newTarget);
|
||||
newFallThrough.SetNewFallThrough(oldFallThrough);
|
||||
newTarget.SetNewFallThrough(oldTarget);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static Block createBlock(Dictionary<Local, int> consts, Block fallThrough) {
|
||||
static Block CreateBlock(Dictionary<Local, int> consts, Block fallThrough) {
|
||||
var block = new Block();
|
||||
foreach (var kv in consts) {
|
||||
block.Instructions.Add(new Instr(Instruction.CreateLdcI4(kv.Value)));
|
||||
block.Instructions.Add(new Instr(OpCodes.Stloc.ToInstruction(kv.Key)));
|
||||
}
|
||||
fallThrough.Parent.add(block);
|
||||
fallThrough.Parent.Add(block);
|
||||
return block;
|
||||
}
|
||||
|
||||
Dictionary<Local, int> getBccLocalConstants(Block block) {
|
||||
Dictionary<Local, int> GetBccLocalConstants(Block block) {
|
||||
var dict = new Dictionary<Local, int>();
|
||||
var instrs = block.Instructions;
|
||||
for (int i = 0; i < instrs.Count; i++) {
|
||||
var instr = instrs[i];
|
||||
if (instr.isStloc()) {
|
||||
var local = Instr.getLocalVar(blocks.Locals, instr);
|
||||
if (instr.IsStloc()) {
|
||||
var local = Instr.GetLocalVar(blocks.Locals, instr);
|
||||
if (local == null)
|
||||
continue;
|
||||
var ldci4 = i == 0 ? null : instrs[i - 1];
|
||||
if (ldci4 == null || !ldci4.isLdcI4())
|
||||
if (ldci4 == null || !ldci4.IsLdcI4())
|
||||
dict.Remove(local);
|
||||
else
|
||||
dict[local] = ldci4.getLdcI4Value();
|
||||
dict[local] = ldci4.GetLdcI4Value();
|
||||
}
|
||||
else if (instr.isLdloc()) {
|
||||
var local = Instr.getLocalVar(blocks.Locals, instr);
|
||||
else if (instr.IsLdloc()) {
|
||||
var local = Instr.GetLocalVar(blocks.Locals, instr);
|
||||
if (local != null)
|
||||
dict.Remove(local);
|
||||
}
|
||||
|
@ -406,47 +406,47 @@ namespace de4dot.blocks.cflow {
|
|||
return dict;
|
||||
}
|
||||
|
||||
bool emulateGetTarget(Block switchBlock, out Block target) {
|
||||
instructionEmulator.init(blocks);
|
||||
bool EmulateGetTarget(Block switchBlock, out Block target) {
|
||||
instructionEmulator.Initialize(blocks);
|
||||
try {
|
||||
instructionEmulator.emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1);
|
||||
instructionEmulator.Emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1);
|
||||
}
|
||||
catch (NullReferenceException) {
|
||||
// Here if eg. invalid metadata token in a call instruction (operand is null)
|
||||
target = null;
|
||||
return false;
|
||||
}
|
||||
target = getTarget(switchBlock);
|
||||
target = GetTarget(switchBlock);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool willHaveKnownTarget(Block switchBlock, Block source) {
|
||||
instructionEmulator.init(blocks);
|
||||
bool WillHaveKnownTarget(Block switchBlock, Block source) {
|
||||
instructionEmulator.Initialize(blocks);
|
||||
try {
|
||||
instructionEmulator.emulate(source.Instructions);
|
||||
instructionEmulator.emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1);
|
||||
instructionEmulator.Emulate(source.Instructions);
|
||||
instructionEmulator.Emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1);
|
||||
}
|
||||
catch (NullReferenceException) {
|
||||
// Here if eg. invalid metadata token in a call instruction (operand is null)
|
||||
return false;
|
||||
}
|
||||
return getTarget(switchBlock) != null;
|
||||
return GetTarget(switchBlock) != null;
|
||||
}
|
||||
|
||||
Block getTarget(Block switchBlock) {
|
||||
var val1 = instructionEmulator.pop();
|
||||
if (!val1.isInt32())
|
||||
Block GetTarget(Block switchBlock) {
|
||||
var val1 = instructionEmulator.Pop();
|
||||
if (!val1.IsInt32())
|
||||
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) {
|
||||
if (!value.isInt32())
|
||||
static Block GetSwitchTarget(IList<Block> targets, Block fallThrough, Value value) {
|
||||
if (!value.IsInt32())
|
||||
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:
|
||||
// blk1:
|
||||
// ldc.i4 XXX
|
||||
|
@ -467,11 +467,11 @@ namespace de4dot.blocks.cflow {
|
|||
foreach (var commonSource in new List<Block>(switchBlock.Sources)) {
|
||||
if (commonSource.Instructions.Count != 1)
|
||||
continue;
|
||||
if (!commonSource.FirstInstr.isStloc())
|
||||
if (!commonSource.FirstInstr.IsStloc())
|
||||
continue;
|
||||
foreach (var blk in new List<Block>(commonSource.Sources)) {
|
||||
if (blk.canAppend(commonSource)) {
|
||||
blk.append(commonSource);
|
||||
if (blk.CanAppend(commonSource)) {
|
||||
blk.Append(commonSource);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,35 +38,35 @@ namespace de4dot.blocks.cflow {
|
|||
public abstract class Value {
|
||||
public readonly ValueType valueType;
|
||||
|
||||
public bool isUnknown() {
|
||||
public bool IsUnknown() {
|
||||
return valueType == ValueType.Unknown;
|
||||
}
|
||||
|
||||
public bool isNull() {
|
||||
public bool IsNull() {
|
||||
return valueType == ValueType.Null;
|
||||
}
|
||||
|
||||
public bool isObject() {
|
||||
public bool IsObject() {
|
||||
return valueType == ValueType.Object;
|
||||
}
|
||||
|
||||
public bool isBoxed() {
|
||||
public bool IsBoxed() {
|
||||
return valueType == ValueType.Boxed;
|
||||
}
|
||||
|
||||
public bool isInt32() {
|
||||
public bool IsInt32() {
|
||||
return valueType == ValueType.Int32;
|
||||
}
|
||||
|
||||
public bool isInt64() {
|
||||
public bool IsInt64() {
|
||||
return valueType == ValueType.Int64;
|
||||
}
|
||||
|
||||
public bool isReal8() {
|
||||
public bool IsReal8() {
|
||||
return valueType == ValueType.Real8;
|
||||
}
|
||||
|
||||
public bool isString() {
|
||||
public bool IsString() {
|
||||
return valueType == ValueType.String;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,43 +29,43 @@ namespace de4dot.blocks.cflow {
|
|||
get { return stack.Count; }
|
||||
}
|
||||
|
||||
public void init() {
|
||||
public void Initialize() {
|
||||
stack.Clear();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
public void Clear() {
|
||||
stack.Clear();
|
||||
}
|
||||
|
||||
public void push(Value value) {
|
||||
public void Push(Value value) {
|
||||
stack.Add(value);
|
||||
}
|
||||
|
||||
public Value peek() {
|
||||
public Value Peek() {
|
||||
if (stack.Count == 0)
|
||||
return new UnknownValue();
|
||||
return stack[stack.Count - 1];
|
||||
}
|
||||
|
||||
public Value pop() {
|
||||
Value value = peek();
|
||||
public Value Pop() {
|
||||
Value value = Peek();
|
||||
if (stack.Count != 0)
|
||||
stack.RemoveAt(stack.Count - 1);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void push(int count) {
|
||||
public void Push(int count) {
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
for (int i = 0; i < count; i++)
|
||||
pushUnknown();
|
||||
PushUnknown();
|
||||
}
|
||||
|
||||
public void pushUnknown() {
|
||||
push(new UnknownValue());
|
||||
public void PushUnknown() {
|
||||
Push(new UnknownValue());
|
||||
}
|
||||
|
||||
public void pop(int count) {
|
||||
public void Pop(int count) {
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
if (count >= stack.Count)
|
||||
|
@ -74,8 +74,8 @@ namespace de4dot.blocks.cflow {
|
|||
stack.RemoveRange(stack.Count - count, count);
|
||||
}
|
||||
|
||||
public void copyTop() {
|
||||
push(peek());
|
||||
public void CopyTop() {
|
||||
Push(Peek());
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
namespace de4dot_x64 {
|
||||
class Program {
|
||||
static int Main(string[] args) {
|
||||
return de4dot.cui.Program.main(args);
|
||||
return de4dot.cui.Program.Main2(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -43,13 +43,13 @@ namespace de4dot.code.AssemblyClient {
|
|||
this.loader = loader;
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
loader.loadServer();
|
||||
service = loader.createService();
|
||||
public void Connect() {
|
||||
loader.LoadServer();
|
||||
service = loader.CreateService();
|
||||
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
|
||||
// server has had time to start... This only seems to be needed when starting a
|
||||
// server in a different process, though.
|
||||
|
@ -61,7 +61,7 @@ namespace de4dot.code.AssemblyClient {
|
|||
var startTime = DateTime.UtcNow;
|
||||
while (true) {
|
||||
try {
|
||||
service.doNothing();
|
||||
service.DoNothing();
|
||||
break;
|
||||
}
|
||||
catch (RemotingException) {
|
||||
|
@ -77,7 +77,7 @@ namespace de4dot.code.AssemblyClient {
|
|||
public void Dispose() {
|
||||
if (service != null) {
|
||||
try {
|
||||
service.exit();
|
||||
service.Exit();
|
||||
}
|
||||
catch (RemotingException) {
|
||||
// Couldn't connect
|
||||
|
|
|
@ -21,17 +21,17 @@ using dnlib.DotNet;
|
|||
|
||||
namespace de4dot.code.AssemblyClient {
|
||||
public interface IAssemblyClientFactory {
|
||||
IAssemblyClient create();
|
||||
IAssemblyClient Create();
|
||||
}
|
||||
|
||||
public class SameAppDomainAssemblyClientFactory : IAssemblyClientFactory {
|
||||
public IAssemblyClient create() {
|
||||
public IAssemblyClient Create() {
|
||||
return new AssemblyClient(new SameAppDomainAssemblyServerLoader());
|
||||
}
|
||||
}
|
||||
|
||||
public class NewAppDomainAssemblyClientFactory : IAssemblyClientFactory {
|
||||
public IAssemblyClient create() {
|
||||
public IAssemblyClient Create() {
|
||||
return new AssemblyClient(new NewAppDomainAssemblyServerLoader());
|
||||
}
|
||||
}
|
||||
|
@ -47,15 +47,15 @@ namespace de4dot.code.AssemblyClient {
|
|||
this.serverVersion = serverVersion;
|
||||
}
|
||||
|
||||
public IAssemblyClient create(ModuleDef module) {
|
||||
return new AssemblyClient(new NewProcessAssemblyServerLoader(getServerClrVersion(module)));
|
||||
public IAssemblyClient Create(ModuleDef module) {
|
||||
return new AssemblyClient(new NewProcessAssemblyServerLoader(GetServerClrVersion(module)));
|
||||
}
|
||||
|
||||
public IAssemblyClient create() {
|
||||
public IAssemblyClient Create() {
|
||||
return new AssemblyClient(new NewProcessAssemblyServerLoader(serverVersion));
|
||||
}
|
||||
|
||||
internal static ServerClrVersion getServerClrVersion(ModuleDef module) {
|
||||
internal static ServerClrVersion GetServerClrVersion(ModuleDef module) {
|
||||
switch (module.GetPointerSize()) {
|
||||
default:
|
||||
case 4:
|
||||
|
|
|
@ -23,7 +23,7 @@ using AssemblyData;
|
|||
namespace de4dot.code.AssemblyClient {
|
||||
public interface IAssemblyClient : IDisposable {
|
||||
IAssemblyService Service { get; }
|
||||
void connect();
|
||||
void waitConnected();
|
||||
void Connect();
|
||||
void WaitConnected();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ using AssemblyData;
|
|||
|
||||
namespace de4dot.code.AssemblyClient {
|
||||
interface IAssemblyServerLoader : IDisposable {
|
||||
void loadServer();
|
||||
IAssemblyService createService();
|
||||
void LoadServer();
|
||||
IAssemblyService CreateService();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,13 +42,13 @@ namespace de4dot.code.AssemblyClient {
|
|||
}
|
||||
|
||||
protected IpcAssemblyServerLoader(ServerClrVersion serverVersion) {
|
||||
assemblyServerFilename = getServerName(serverVersion);
|
||||
ipcName = Utils.randomName(15, 20);
|
||||
ipcUri = Utils.randomName(15, 20);
|
||||
assemblyServerFilename = GetServerName(serverVersion);
|
||||
ipcName = Utils.RandomName(15, 20);
|
||||
ipcUri = Utils.RandomName(15, 20);
|
||||
url = string.Format("ipc://{0}/{1}", ipcName, ipcUri);
|
||||
}
|
||||
|
||||
static string getServerName(ServerClrVersion serverVersion) {
|
||||
static string GetServerName(ServerClrVersion serverVersion) {
|
||||
if (serverVersion == ServerClrVersion.CLR_ANY_ANYCPU)
|
||||
serverVersion = IntPtr.Size == 4 ? ServerClrVersion.CLR_ANY_x86 : ServerClrVersion.CLR_ANY_x64;
|
||||
switch (serverVersion) {
|
||||
|
@ -62,13 +62,13 @@ namespace de4dot.code.AssemblyClient {
|
|||
}
|
||||
}
|
||||
|
||||
public void loadServer() {
|
||||
loadServer(Utils.getPathOfOurFile(assemblyServerFilename));
|
||||
public void LoadServer() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,11 @@ namespace de4dot.code.AssemblyClient {
|
|||
AppDomain appDomain;
|
||||
Thread thread;
|
||||
|
||||
public override void loadServer(string filename) {
|
||||
public override void LoadServer(string filename) {
|
||||
if (appDomain != null)
|
||||
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(() => {
|
||||
try {
|
||||
appDomain.ExecuteAssembly(filename, null, new string[] { ipcName, ipcUri });
|
||||
|
@ -41,14 +41,14 @@ namespace de4dot.code.AssemblyClient {
|
|||
catch (AppDomainUnloadedException) {
|
||||
// Here if it was unloaded by Dispose()
|
||||
}
|
||||
unloadAppDomain(appDomain);
|
||||
UnloadAppDomain(appDomain);
|
||||
appDomain = null;
|
||||
}));
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
unloadAppDomain(appDomain);
|
||||
UnloadAppDomain(appDomain);
|
||||
if (thread != null) {
|
||||
try {
|
||||
if (!thread.Join(100))
|
||||
|
@ -60,11 +60,11 @@ namespace de4dot.code.AssemblyClient {
|
|||
thread = null;
|
||||
}
|
||||
// It could still be loaded if the thread was aborted so do it again
|
||||
unloadAppDomain(appDomain);
|
||||
UnloadAppDomain(appDomain);
|
||||
appDomain = null;
|
||||
}
|
||||
|
||||
static void unloadAppDomain(AppDomain appDomain) {
|
||||
static void UnloadAppDomain(AppDomain appDomain) {
|
||||
if (appDomain != null) {
|
||||
try {
|
||||
AppDomain.Unload(appDomain);
|
||||
|
|
|
@ -32,18 +32,18 @@ namespace de4dot.code.AssemblyClient {
|
|||
: base(version) {
|
||||
}
|
||||
|
||||
public override void loadServer(string filename) {
|
||||
public override void LoadServer(string filename) {
|
||||
if (process != null)
|
||||
throw new ApplicationException("Server is already loaded");
|
||||
|
||||
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,
|
||||
ErrorDialog = false,
|
||||
FileName = filename,
|
||||
LoadUserProfile = false,
|
||||
UseShellExecute = false,
|
||||
WorkingDirectory = Utils.getOurBaseDir(),
|
||||
WorkingDirectory = Utils.GetOurBaseDir(),
|
||||
};
|
||||
process = Process.Start(psi);
|
||||
if (process == null)
|
||||
|
|
|
@ -25,13 +25,13 @@ namespace de4dot.code.AssemblyClient {
|
|||
class SameAppDomainAssemblyServerLoader : IAssemblyServerLoader {
|
||||
IAssemblyService service;
|
||||
|
||||
public void loadServer() {
|
||||
public void LoadServer() {
|
||||
if (service != null)
|
||||
throw new ApplicationException("Server already loaded");
|
||||
service = new AssemblyService();
|
||||
}
|
||||
|
||||
public IAssemblyService createService() {
|
||||
public IAssemblyService CreateService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,27 +31,27 @@ namespace de4dot.code {
|
|||
ModuleContext moduleContext;
|
||||
|
||||
public AssemblyModule(string filename, ModuleContext moduleContext) {
|
||||
this.filename = Utils.getFullPath(filename);
|
||||
this.filename = Utils.GetFullPath(filename);
|
||||
this.moduleContext = moduleContext;
|
||||
}
|
||||
|
||||
public ModuleDefMD load() {
|
||||
return setModule(ModuleDefMD.Load(filename, moduleContext));
|
||||
public ModuleDefMD Load() {
|
||||
return SetModule(ModuleDefMD.Load(filename, moduleContext));
|
||||
}
|
||||
|
||||
public ModuleDefMD load(byte[] fileData) {
|
||||
return setModule(ModuleDefMD.Load(fileData, moduleContext));
|
||||
public ModuleDefMD Load(byte[] fileData) {
|
||||
return SetModule(ModuleDefMD.Load(fileData, moduleContext));
|
||||
}
|
||||
|
||||
ModuleDefMD setModule(ModuleDefMD newModule) {
|
||||
ModuleDefMD SetModule(ModuleDefMD newModule) {
|
||||
module = newModule;
|
||||
TheAssemblyResolver.Instance.addModule(module);
|
||||
TheAssemblyResolver.Instance.AddModule(module);
|
||||
module.EnableTypeDefFindCache = true;
|
||||
module.Location = filename;
|
||||
return module;
|
||||
}
|
||||
|
||||
public void save(string newFilename, MetaDataFlags mdFlags, IModuleWriterListener writerListener) {
|
||||
public void Save(string newFilename, MetaDataFlags mdFlags, IModuleWriterListener writerListener) {
|
||||
if (module.IsILOnly) {
|
||||
var writerOptions = new ModuleWriterOptions(module, writerListener);
|
||||
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);
|
||||
var mod = ModuleDefMD.Load(newModuleData, moduleContext);
|
||||
if (dumpedMethodsRestorer != null)
|
||||
|
@ -77,7 +77,7 @@ namespace de4dot.code {
|
|||
mod.MethodDecrypter = dumpedMethodsRestorer;
|
||||
mod.TablesStream.ColumnReader = dumpedMethodsRestorer;
|
||||
mod.TablesStream.MethodRowReader = dumpedMethodsRestorer;
|
||||
return setModule(mod);
|
||||
return SetModule(mod);
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
|
|
|
@ -27,16 +27,16 @@ namespace de4dot.code {
|
|||
EnableTypeDefCache = true;
|
||||
}
|
||||
|
||||
public void addSearchDirectory(string dir) {
|
||||
public void AddSearchDirectory(string dir) {
|
||||
if (!PostSearchPaths.Contains(dir))
|
||||
PostSearchPaths.Add(dir);
|
||||
}
|
||||
|
||||
public void addModule(ModuleDef module) {
|
||||
public void AddModule(ModuleDef module) {
|
||||
AddToCache(module.Assembly);
|
||||
}
|
||||
|
||||
public void removeModule(ModuleDef module) {
|
||||
public void RemoveModule(ModuleDef module) {
|
||||
var assembly = module.Assembly;
|
||||
if (assembly == null)
|
||||
return;
|
||||
|
@ -44,7 +44,7 @@ namespace de4dot.code {
|
|||
Remove(module.Assembly);
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
public void ClearAll() {
|
||||
//TODO: cache.Clear();
|
||||
//TODO: resetSearchPaths();
|
||||
}
|
||||
|
|
|
@ -28,25 +28,25 @@ namespace de4dot.code {
|
|||
public class DeobfuscatorContext : IDeobfuscatorContext {
|
||||
Dictionary<string, object> dataDict = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
|
||||
public void clear() {
|
||||
public void Clear() {
|
||||
dataDict.Clear();
|
||||
}
|
||||
|
||||
public void setData(string name, object data) {
|
||||
public void SetData(string name, object data) {
|
||||
dataDict[name] = data;
|
||||
}
|
||||
|
||||
public object getData(string name) {
|
||||
public object GetData(string name) {
|
||||
object value;
|
||||
dataDict.TryGetValue(name, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void clearData(string name) {
|
||||
public void ClearData(string name) {
|
||||
dataDict.Remove(name);
|
||||
}
|
||||
|
||||
static ITypeDefOrRef getNonGenericTypeRef(ITypeDefOrRef typeRef) {
|
||||
static ITypeDefOrRef GetNonGenericTypeRef(ITypeDefOrRef typeRef) {
|
||||
var ts = typeRef as TypeSpec;
|
||||
if (ts == null)
|
||||
return typeRef;
|
||||
|
@ -56,10 +56,10 @@ namespace de4dot.code {
|
|||
return gis.GenericType.TypeDefOrRef;
|
||||
}
|
||||
|
||||
public TypeDef resolveType(ITypeDefOrRef type) {
|
||||
public TypeDef ResolveType(ITypeDefOrRef type) {
|
||||
if (type == null)
|
||||
return null;
|
||||
type = getNonGenericTypeRef(type);
|
||||
type = GetNonGenericTypeRef(type);
|
||||
|
||||
var typeDef = type as TypeDef;
|
||||
if (typeDef != null)
|
||||
|
@ -72,7 +72,7 @@ namespace de4dot.code {
|
|||
return null;
|
||||
}
|
||||
|
||||
public MethodDef resolveMethod(IMethod method) {
|
||||
public MethodDef ResolveMethod(IMethod method) {
|
||||
if (method == null)
|
||||
return null;
|
||||
|
||||
|
@ -84,14 +84,14 @@ namespace de4dot.code {
|
|||
if (mr == null || !mr.IsMethodRef)
|
||||
return null;
|
||||
|
||||
var type = resolveType(mr.DeclaringType);
|
||||
var type = ResolveType(mr.DeclaringType);
|
||||
if (type == null)
|
||||
return null;
|
||||
|
||||
return type.Resolve(mr) as MethodDef;
|
||||
}
|
||||
|
||||
public FieldDef resolveField(IField field) {
|
||||
public FieldDef ResolveField(IField field) {
|
||||
if (field == null)
|
||||
return null;
|
||||
|
||||
|
@ -103,7 +103,7 @@ namespace de4dot.code {
|
|||
if (mr == null || !mr.IsFieldRef)
|
||||
return null;
|
||||
|
||||
var type = resolveType(mr.DeclaringType);
|
||||
var type = ResolveType(mr.DeclaringType);
|
||||
if (type == null)
|
||||
return null;
|
||||
|
||||
|
|
|
@ -37,12 +37,12 @@ namespace de4dot.code {
|
|||
this.dumpedMethods = dumpedMethods;
|
||||
}
|
||||
|
||||
DumpedMethod getDumpedMethod(uint rid) {
|
||||
return dumpedMethods.get(0x06000000 | rid);
|
||||
DumpedMethod GetDumpedMethod(uint rid) {
|
||||
return dumpedMethods.Get(0x06000000 | rid);
|
||||
}
|
||||
|
||||
public RawMethodRow ReadRow(uint rid) {
|
||||
var dm = getDumpedMethod(rid);
|
||||
var dm = GetDumpedMethod(rid);
|
||||
if (dm == null)
|
||||
return null;
|
||||
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) {
|
||||
return getDumpedMethod(rid) != null;
|
||||
return GetDumpedMethod(rid) != null;
|
||||
}
|
||||
|
||||
public MethodBody GetMethodBody(uint rid, RVA rva, IList<Parameter> parameters) {
|
||||
var dm = getDumpedMethod(rid);
|
||||
var dm = GetDumpedMethod(rid);
|
||||
if (dm == null)
|
||||
return null;
|
||||
return MethodBodyReader.Create(module, dm.code, dm.extraSections, parameters, dm.mhFlags, dm.mhMaxStack, dm.mhCodeSize, dm.mhLocalVarSigTok);
|
||||
|
|
|
@ -21,12 +21,12 @@ using dnlib.DotNet;
|
|||
|
||||
namespace de4dot.code {
|
||||
public interface IDeobfuscatorContext {
|
||||
void clear();
|
||||
void setData(string name, object data);
|
||||
object getData(string name);
|
||||
void clearData(string name);
|
||||
TypeDef resolveType(ITypeDefOrRef type);
|
||||
MethodDef resolveMethod(IMethod method);
|
||||
FieldDef resolveField(IField field);
|
||||
void Clear();
|
||||
void SetData(string name, object data);
|
||||
object GetData(string name);
|
||||
void ClearData(string name);
|
||||
TypeDef ResolveType(ITypeDefOrRef type);
|
||||
MethodDef ResolveMethod(IMethod method);
|
||||
FieldDef ResolveField(IField field);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,12 +35,12 @@ namespace de4dot.code {
|
|||
bool RemoveNamespaceWithOneType { get; }
|
||||
bool RenameResourceKeys { get; }
|
||||
|
||||
void deobfuscateBegin();
|
||||
void deobfuscate();
|
||||
void deobfuscateEnd();
|
||||
void deobfuscateCleanUp();
|
||||
void DeobfuscateBegin();
|
||||
void Deobfuscate();
|
||||
void DeobfuscateEnd();
|
||||
void DeobfuscateCleanUp();
|
||||
|
||||
void load(IList<IDeobfuscator> deobfuscators);
|
||||
void save();
|
||||
void Load(IList<IDeobfuscator> deobfuscators);
|
||||
void Save();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace de4dot.code {
|
|||
if (indentLevel == value)
|
||||
return;
|
||||
indentLevel = value;
|
||||
initIndentString();
|
||||
InitIndentString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,20 +66,20 @@ namespace de4dot.code {
|
|||
this.canIgnoreMessages = canIgnoreMessages;
|
||||
}
|
||||
|
||||
void initIndentString() {
|
||||
void InitIndentString() {
|
||||
if (indentLevel < 0)
|
||||
indentLevel = 0;
|
||||
indentString = new string(' ', indentLevel * indentSize);
|
||||
}
|
||||
|
||||
public void indent() {
|
||||
public void Indent() {
|
||||
indentLevel++;
|
||||
initIndentString();
|
||||
InitIndentString();
|
||||
}
|
||||
|
||||
public void deIndent() {
|
||||
public void DeIndent() {
|
||||
indentLevel--;
|
||||
initIndentString();
|
||||
InitIndentString();
|
||||
}
|
||||
|
||||
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) {
|
||||
if (IgnoresEvent(loggerEvent))
|
||||
return;
|
||||
if (canIgnore && ignoreMessage(loggerEvent, format, args))
|
||||
if (canIgnore && IgnoreMessage(loggerEvent, format, args))
|
||||
return;
|
||||
|
||||
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)
|
||||
return false;
|
||||
if (!canIgnoreMessages)
|
||||
|
@ -138,7 +138,7 @@ namespace de4dot.code {
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,13 +41,13 @@ namespace de4dot.code {
|
|||
Dictionary<Instruction, ExInfo> exInfos = new Dictionary<Instruction, ExInfo>();
|
||||
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 {
|
||||
this.loggerEvent = loggerEvent;
|
||||
this.allInstructions = allInstructions;
|
||||
this.allExceptionHandlers = allExceptionHandlers;
|
||||
lastExInfo = new ExInfo();
|
||||
print();
|
||||
Print();
|
||||
}
|
||||
finally {
|
||||
this.allInstructions = null;
|
||||
|
@ -59,27 +59,27 @@ namespace de4dot.code {
|
|||
}
|
||||
}
|
||||
|
||||
void initTargets() {
|
||||
void InitTargets() {
|
||||
foreach (var instr in allInstructions) {
|
||||
switch (instr.OpCode.OperandType) {
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
setTarget(instr.Operand as Instruction);
|
||||
SetTarget(instr.Operand as Instruction);
|
||||
break;
|
||||
|
||||
case OperandType.InlineSwitch:
|
||||
foreach (var targetInstr in (Instruction[])instr.Operand)
|
||||
setTarget(targetInstr);
|
||||
SetTarget(targetInstr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var ex in allExceptionHandlers) {
|
||||
setTarget(ex.TryStart);
|
||||
setTarget(ex.TryEnd);
|
||||
setTarget(ex.FilterStart);
|
||||
setTarget(ex.HandlerStart);
|
||||
setTarget(ex.HandlerEnd);
|
||||
SetTarget(ex.TryStart);
|
||||
SetTarget(ex.TryEnd);
|
||||
SetTarget(ex.FilterStart);
|
||||
SetTarget(ex.HandlerStart);
|
||||
SetTarget(ex.HandlerEnd);
|
||||
}
|
||||
|
||||
var sortedTargets = new List<Instruction>(targets.Keys);
|
||||
|
@ -88,27 +88,27 @@ namespace de4dot.code {
|
|||
labels[sortedTargets[i]] = string.Format("label_{0}", i);
|
||||
}
|
||||
|
||||
void setTarget(Instruction instr) {
|
||||
void SetTarget(Instruction instr) {
|
||||
if (instr != null)
|
||||
targets[instr] = true;
|
||||
}
|
||||
|
||||
void initExHandlers() {
|
||||
void InitExHandlers() {
|
||||
foreach (var ex in allExceptionHandlers) {
|
||||
if (ex.TryStart != null) {
|
||||
getExInfo(ex.TryStart).tryStarts.Add(ex);
|
||||
getExInfo(ex.TryEnd).tryEnds.Add(ex);
|
||||
GetExInfo(ex.TryStart).tryStarts.Add(ex);
|
||||
GetExInfo(ex.TryEnd).tryEnds.Add(ex);
|
||||
}
|
||||
if (ex.FilterStart != null)
|
||||
getExInfo(ex.FilterStart).filterStarts.Add(ex);
|
||||
GetExInfo(ex.FilterStart).filterStarts.Add(ex);
|
||||
if (ex.HandlerStart != null) {
|
||||
getExInfo(ex.HandlerStart).handlerStarts.Add(ex);
|
||||
getExInfo(ex.HandlerEnd).handlerEnds.Add(ex);
|
||||
GetExInfo(ex.HandlerStart).handlerStarts.Add(ex);
|
||||
GetExInfo(ex.HandlerEnd).handlerEnds.Add(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExInfo getExInfo(Instruction instruction) {
|
||||
ExInfo GetExInfo(Instruction instruction) {
|
||||
if (instruction == null)
|
||||
return lastExInfo;
|
||||
ExInfo exInfo;
|
||||
|
@ -117,49 +117,49 @@ namespace de4dot.code {
|
|||
return exInfo;
|
||||
}
|
||||
|
||||
void print() {
|
||||
initTargets();
|
||||
initExHandlers();
|
||||
void Print() {
|
||||
InitTargets();
|
||||
InitExHandlers();
|
||||
|
||||
Logger.Instance.indent();
|
||||
Logger.Instance.Indent();
|
||||
foreach (var instr in allInstructions) {
|
||||
if (targets.ContainsKey(instr)) {
|
||||
Logger.Instance.deIndent();
|
||||
Logger.log(loggerEvent, "{0}:", getLabel(instr));
|
||||
Logger.Instance.indent();
|
||||
Logger.Instance.DeIndent();
|
||||
Logger.Log(loggerEvent, "{0}:", GetLabel(instr));
|
||||
Logger.Instance.Indent();
|
||||
}
|
||||
ExInfo exInfo;
|
||||
if (exInfos.TryGetValue(instr, out exInfo))
|
||||
printExInfo(exInfo);
|
||||
PrintExInfo(exInfo);
|
||||
var instrString = instr.OpCode.Name;
|
||||
var operandString = getOperandString(instr);
|
||||
var operandString = GetOperandString(instr);
|
||||
var memberRef = instr.Operand as ITokenOperand;
|
||||
if (operandString == "")
|
||||
Logger.log(loggerEvent, "{0}", instrString);
|
||||
Logger.Log(loggerEvent, "{0}", instrString);
|
||||
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
|
||||
Logger.log(loggerEvent, "{0,-9} {1}", instrString, Utils.removeNewlines(operandString));
|
||||
Logger.Log(loggerEvent, "{0,-9} {1}", instrString, Utils.RemoveNewlines(operandString));
|
||||
}
|
||||
printExInfo(lastExInfo);
|
||||
Logger.Instance.deIndent();
|
||||
PrintExInfo(lastExInfo);
|
||||
Logger.Instance.DeIndent();
|
||||
}
|
||||
|
||||
string getOperandString(Instruction instr) {
|
||||
string GetOperandString(Instruction instr) {
|
||||
if (instr.Operand is Instruction)
|
||||
return getLabel((Instruction)instr.Operand);
|
||||
return GetLabel((Instruction)instr.Operand);
|
||||
else if (instr.Operand is Instruction[]) {
|
||||
var sb = new StringBuilder();
|
||||
var targets = (Instruction[])instr.Operand;
|
||||
for (int i = 0; i < targets.Length; i++) {
|
||||
if (i > 0)
|
||||
sb.Append(',');
|
||||
sb.Append(getLabel(targets[i]));
|
||||
sb.Append(GetLabel(targets[i]));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
else if (instr.Operand is string)
|
||||
return Utils.toCsharpString((string)instr.Operand);
|
||||
return Utils.ToCsharpString((string)instr.Operand);
|
||||
else if (instr.Operand is Parameter) {
|
||||
var arg = (Parameter)instr.Operand;
|
||||
var s = InstructionPrinter.GetOperandString(instr);
|
||||
|
@ -171,36 +171,36 @@ namespace de4dot.code {
|
|||
return InstructionPrinter.GetOperandString(instr);
|
||||
}
|
||||
|
||||
void printExInfo(ExInfo exInfo) {
|
||||
Logger.Instance.deIndent();
|
||||
void PrintExInfo(ExInfo exInfo) {
|
||||
Logger.Instance.DeIndent();
|
||||
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)
|
||||
Logger.log(loggerEvent, "// try end: {0}", getExceptionString(ex));
|
||||
Logger.Log(loggerEvent, "// try end: {0}", GetExceptionString(ex));
|
||||
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)
|
||||
Logger.log(loggerEvent, "// handler start: {0}", getExceptionString(ex));
|
||||
Logger.Log(loggerEvent, "// handler start: {0}", GetExceptionString(ex));
|
||||
foreach (var ex in exInfo.handlerEnds)
|
||||
Logger.log(loggerEvent, "// handler end: {0}", getExceptionString(ex));
|
||||
Logger.Instance.indent();
|
||||
Logger.Log(loggerEvent, "// handler end: {0}", GetExceptionString(ex));
|
||||
Logger.Instance.Indent();
|
||||
}
|
||||
|
||||
string getExceptionString(ExceptionHandler ex) {
|
||||
string GetExceptionString(ExceptionHandler ex) {
|
||||
var sb = new StringBuilder();
|
||||
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)
|
||||
sb.Append(string.Format(", FILTER: {0}", getLabel(ex.FilterStart)));
|
||||
sb.Append(string.Format(", FILTER: {0}", GetLabel(ex.FilterStart)));
|
||||
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));
|
||||
if (ex.CatchType != null)
|
||||
sb.Append(string.Format(", CATCH: {0}", ex.CatchType));
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
string getLabel(Instruction instr) {
|
||||
string GetLabel(Instruction instr) {
|
||||
if (instr == null)
|
||||
return "<end>";
|
||||
return labels[instr];
|
||||
|
|
|
@ -35,24 +35,24 @@ namespace de4dot.code {
|
|||
object value;
|
||||
bool unknownValue = false;
|
||||
|
||||
public bool isValid() {
|
||||
public bool IsValid() {
|
||||
return !unknownValue && writes == 1;
|
||||
}
|
||||
|
||||
public object Value {
|
||||
get {
|
||||
if (!isValid())
|
||||
if (!IsValid())
|
||||
throw new ApplicationException("Unknown variable value");
|
||||
return value;
|
||||
}
|
||||
set { this.value = value; }
|
||||
}
|
||||
|
||||
public void addWrite() {
|
||||
public void AddWrite() {
|
||||
writes++;
|
||||
}
|
||||
|
||||
public void setUnknown() {
|
||||
public void SetUnknown() {
|
||||
unknownValue = true;
|
||||
}
|
||||
}
|
||||
|
@ -60,10 +60,10 @@ namespace de4dot.code {
|
|||
public VariableValues(IList<Local> locals, IList<Block> allBlocks) {
|
||||
this.locals = locals;
|
||||
this.allBlocks = allBlocks;
|
||||
init();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void init() {
|
||||
void Initialize() {
|
||||
foreach (var variable in locals)
|
||||
variableToValue[variable] = new Variable();
|
||||
|
||||
|
@ -78,12 +78,12 @@ namespace de4dot.code {
|
|||
case Code.Stloc_1:
|
||||
case Code.Stloc_2:
|
||||
case Code.Stloc_3:
|
||||
var variable = Instr.getLocalVar(locals, instr);
|
||||
var variable = Instr.GetLocalVar(locals, instr);
|
||||
var val = variableToValue[variable];
|
||||
val.addWrite();
|
||||
val.AddWrite();
|
||||
object obj;
|
||||
if (!getValue(block, i, out obj))
|
||||
val.setUnknown();
|
||||
if (!GetValue(block, i, out obj))
|
||||
val.SetUnknown();
|
||||
val.Value = obj;
|
||||
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) {
|
||||
if (index <= 0) {
|
||||
obj = null;
|
||||
|
@ -135,7 +135,7 @@ namespace de4dot.code {
|
|||
}
|
||||
}
|
||||
|
||||
public Variable getValue(Local variable) {
|
||||
public Variable GetValue(Local variable) {
|
||||
return variableToValue[variable];
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ namespace de4dot.code {
|
|||
this.callEndIndex = callEndIndex;
|
||||
}
|
||||
|
||||
public IMethod getMethodRef() {
|
||||
public IMethod GetMethodRef() {
|
||||
return (IMethod)block.Instructions[callEndIndex].Operand;
|
||||
}
|
||||
}
|
||||
|
@ -180,18 +180,18 @@ namespace de4dot.code {
|
|||
get { return theMethod; }
|
||||
}
|
||||
|
||||
protected abstract void inlineAllCalls();
|
||||
protected abstract void InlineAllCalls();
|
||||
|
||||
// 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)
|
||||
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)
|
||||
return 0;
|
||||
try {
|
||||
|
@ -199,9 +199,9 @@ namespace de4dot.code {
|
|||
callResults = new List<CallResult>();
|
||||
this.allBlocks = allBlocks;
|
||||
|
||||
findAllCallResults();
|
||||
inlineAllCalls();
|
||||
inlineReturnValues();
|
||||
FindAllCallResults();
|
||||
InlineAllCalls();
|
||||
InlineReturnValues();
|
||||
return callResults.Count;
|
||||
}
|
||||
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)
|
||||
variableValues = new VariableValues(theMethod.Body.Variables, allBlocks);
|
||||
var val = variableValues.getValue(variable);
|
||||
if (!val.isValid()) {
|
||||
var val = variableValues.GetValue(variable);
|
||||
if (!val.IsValid()) {
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
@ -228,12 +228,12 @@ namespace de4dot.code {
|
|||
return true;
|
||||
}
|
||||
|
||||
void findAllCallResults() {
|
||||
void FindAllCallResults() {
|
||||
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++) {
|
||||
var instr = block.Instructions[i];
|
||||
if (instr.OpCode != OpCodes.Call)
|
||||
|
@ -246,31 +246,31 @@ namespace de4dot.code {
|
|||
var gim = method as MethodSpec;
|
||||
if (gim != null)
|
||||
elementMethod = gim.Method;
|
||||
var callResult = createCallResult(elementMethod, gim, block, i);
|
||||
var callResult = CreateCallResult(elementMethod, gim, block, i);
|
||||
if (callResult == null)
|
||||
continue;
|
||||
|
||||
if (findArgs(callResult))
|
||||
if (FindArgs(callResult))
|
||||
callResults.Add(callResult);
|
||||
}
|
||||
}
|
||||
|
||||
bool findArgs(CallResult callResult) {
|
||||
bool FindArgs(CallResult callResult) {
|
||||
var block = callResult.block;
|
||||
var method = callResult.getMethodRef();
|
||||
var methodArgs = DotNetUtils.getArgs(method);
|
||||
var method = callResult.GetMethodRef();
|
||||
var methodArgs = DotNetUtils.GetArgs(method);
|
||||
int numArgs = methodArgs.Count;
|
||||
var args = new object[numArgs];
|
||||
|
||||
int instrIndex = callResult.callEndIndex - 1;
|
||||
for (int i = numArgs - 1; i >= 0; i--) {
|
||||
object arg = null;
|
||||
if (!getArg(method, block, ref arg, ref instrIndex))
|
||||
if (!GetArg(method, block, ref arg, ref instrIndex))
|
||||
return false;
|
||||
if (arg is int)
|
||||
arg = fixIntArg(methodArgs[i], (int)arg);
|
||||
arg = FixIntArg(methodArgs[i], (int)arg);
|
||||
else if (arg is long)
|
||||
arg = fixIntArg(methodArgs[i], (long)arg);
|
||||
arg = FixIntArg(methodArgs[i], (long)arg);
|
||||
args[i] = arg;
|
||||
}
|
||||
|
||||
|
@ -279,7 +279,7 @@ namespace de4dot.code {
|
|||
return true;
|
||||
}
|
||||
|
||||
object fixIntArg(TypeSig type, long value) {
|
||||
object FixIntArg(TypeSig type, long value) {
|
||||
switch (type.ElementType) {
|
||||
case ElementType.Boolean: return value != 0;
|
||||
case ElementType.Char: return (char)value;
|
||||
|
@ -295,14 +295,14 @@ namespace de4dot.code {
|
|||
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) {
|
||||
if (instrIndex < 0) {
|
||||
// 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
|
||||
// merged because one is outside the exception handler (eg. buggy obfuscator).
|
||||
Logger.w("Could not find all arguments to method {0} ({1:X8})",
|
||||
Utils.removeNewlines(method),
|
||||
Utils.RemoveNewlines(method),
|
||||
method.MDToken.ToInt32());
|
||||
errors++;
|
||||
return false;
|
||||
|
@ -342,7 +342,7 @@ namespace de4dot.code {
|
|||
case Code.Ldloc_1:
|
||||
case Code.Ldloc_2:
|
||||
case Code.Ldloc_3:
|
||||
getLocalVariableValue(instr.Instruction.GetLocal(theMethod.Body.Variables), out arg);
|
||||
GetLocalVariableValue(instr.Instruction.GetLocal(theMethod.Body.Variables), out arg);
|
||||
break;
|
||||
|
||||
case Code.Ldfld:
|
||||
|
@ -355,7 +355,7 @@ namespace de4dot.code {
|
|||
instr.Instruction.CalculateStackUsage(false, out pushes, out pops);
|
||||
if (!useUnknownArgs || pushes != 1) {
|
||||
Logger.w("Could not find all arguments to method {0} ({1:X8}), instr: {2}",
|
||||
Utils.removeNewlines(method),
|
||||
Utils.RemoveNewlines(method),
|
||||
method.MDToken.ToInt32(),
|
||||
instr);
|
||||
errors++;
|
||||
|
@ -363,7 +363,7 @@ namespace de4dot.code {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
arg = null;
|
||||
|
@ -375,8 +375,8 @@ namespace de4dot.code {
|
|||
return true;
|
||||
}
|
||||
|
||||
void inlineReturnValues() {
|
||||
callResults = removeNulls(callResults);
|
||||
void InlineReturnValues() {
|
||||
callResults = RemoveNulls(callResults);
|
||||
callResults.Sort((a, b) => {
|
||||
int i1 = allBlocks.FindIndex((x) => a.block == x);
|
||||
int i2 = allBlocks.FindIndex((x) => b.block == x);
|
||||
|
@ -386,10 +386,10 @@ namespace de4dot.code {
|
|||
return a.callStartIndex.CompareTo(b.callStartIndex);
|
||||
});
|
||||
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);
|
||||
foreach (var callResult in inList) {
|
||||
if (callResult.returnValue != null)
|
||||
|
@ -398,6 +398,6 @@ namespace de4dot.code {
|
|||
return outList;
|
||||
}
|
||||
|
||||
protected abstract void inlineReturnValues(IList<CallResult> callResults);
|
||||
protected abstract void InlineReturnValues(IList<CallResult> callResults);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace de4dot.code {
|
|||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -60,10 +60,10 @@ namespace de4dot.code {
|
|||
}
|
||||
|
||||
public NameRegexes(string regex) {
|
||||
set(regex);
|
||||
Set(regex);
|
||||
}
|
||||
|
||||
public void set(string regexesString) {
|
||||
public void Set(string regexesString) {
|
||||
regexes = new List<NameRegex>();
|
||||
if (regexesString != "") {
|
||||
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) {
|
||||
if (regex.isMatch(s))
|
||||
if (regex.IsMatch(s))
|
||||
return regex.MatchValue;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,27 +55,27 @@ namespace de4dot.code {
|
|||
|
||||
public SavedMethodBody(MethodDef method) {
|
||||
this.method = method;
|
||||
DotNetUtils.copyBody(method, out instructions, out exceptionHandlers);
|
||||
DotNetUtils.CopyBody(method, out instructions, out exceptionHandlers);
|
||||
}
|
||||
|
||||
public void restore() {
|
||||
DotNetUtils.restoreBody(method, instructions, exceptionHandlers);
|
||||
public void Restore() {
|
||||
DotNetUtils.RestoreBody(method, instructions, exceptionHandlers);
|
||||
}
|
||||
}
|
||||
|
||||
public void save(MethodDef method) {
|
||||
if (isSaved(method))
|
||||
public void Save(MethodDef method) {
|
||||
if (IsSaved(method))
|
||||
return;
|
||||
savedMethodBodies[method] = new SavedMethodBody(method);
|
||||
}
|
||||
|
||||
public void restoreAll() {
|
||||
public void RestoreAll() {
|
||||
foreach (var smb in savedMethodBodies.Values)
|
||||
smb.restore();
|
||||
smb.Restore();
|
||||
savedMethodBodies.Clear();
|
||||
}
|
||||
|
||||
public bool isSaved(MethodDef method) {
|
||||
public bool IsSaved(MethodDef method) {
|
||||
return savedMethodBodies.ContainsKey(method);
|
||||
}
|
||||
}
|
||||
|
@ -139,17 +139,17 @@ namespace de4dot.code {
|
|||
this.assemblyClientFactory = assemblyClientFactory;
|
||||
this.options = options;
|
||||
userStringDecrypterMethods = options.StringDecrypterMethods.Count > 0;
|
||||
options.Filename = Utils.getFullPath(options.Filename);
|
||||
options.Filename = Utils.GetFullPath(options.Filename);
|
||||
assemblyModule = new AssemblyModule(options.Filename, moduleContext);
|
||||
|
||||
if (options.NewFilename == null)
|
||||
options.NewFilename = getDefaultNewFilename();
|
||||
options.NewFilename = GetDefaultNewFilename();
|
||||
|
||||
if (string.Equals(options.Filename, options.NewFilename, StringComparison.OrdinalIgnoreCase))
|
||||
throw new UserException(string.Format("filename is same as new filename! ({0})", options.Filename));
|
||||
}
|
||||
|
||||
string getDefaultNewFilename() {
|
||||
string GetDefaultNewFilename() {
|
||||
int dotIndex = options.Filename.LastIndexOf('.');
|
||||
string noExt, ext;
|
||||
if (dotIndex != -1) {
|
||||
|
@ -163,15 +163,15 @@ namespace de4dot.code {
|
|||
return noExt + "-cleaned" + ext;
|
||||
}
|
||||
|
||||
public void load(IList<IDeobfuscator> deobfuscators) {
|
||||
public void Load(IList<IDeobfuscator> deobfuscators) {
|
||||
try {
|
||||
loadModule(deobfuscators);
|
||||
TheAssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(Filename));
|
||||
TheAssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(NewFilename));
|
||||
detectObfuscator(deobfuscators);
|
||||
LoadModule(deobfuscators);
|
||||
TheAssemblyResolver.Instance.AddSearchDirectory(Utils.GetDirName(Filename));
|
||||
TheAssemblyResolver.Instance.AddSearchDirectory(Utils.GetDirName(NewFilename));
|
||||
DetectObfuscator(deobfuscators);
|
||||
if (deob == null)
|
||||
throw new ApplicationException("Could not detect obfuscator!");
|
||||
initializeDeobfuscator();
|
||||
InitializeDeobfuscator();
|
||||
}
|
||||
finally {
|
||||
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;
|
||||
try {
|
||||
module = assemblyModule.load();
|
||||
module = assemblyModule.Load();
|
||||
}
|
||||
catch (BadImageFormatException) {
|
||||
if (!unpackNativeImage(deobfuscators))
|
||||
if (!UnpackNativeImage(deobfuscators))
|
||||
throw new BadImageFormatException();
|
||||
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)) {
|
||||
foreach (var deob in deobfuscators) {
|
||||
byte[] unpackedData = null;
|
||||
try {
|
||||
unpackedData = deob.unpackNativeFile(peImage);
|
||||
unpackedData = deob.UnpackNativeFile(peImage);
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ namespace de4dot.code {
|
|||
|
||||
var oldModule = module;
|
||||
try {
|
||||
module = assemblyModule.load(unpackedData);
|
||||
module = assemblyModule.Load(unpackedData);
|
||||
}
|
||||
catch {
|
||||
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;
|
||||
}
|
||||
|
||||
void initializeDeobfuscator() {
|
||||
void InitializeDeobfuscator() {
|
||||
if (options.StringDecrypterType == DecrypterType.Default)
|
||||
options.StringDecrypterType = deob.DefaultDecrypterType;
|
||||
if (options.StringDecrypterType == DecrypterType.Default)
|
||||
options.StringDecrypterType = DecrypterType.Static;
|
||||
|
||||
deob.Operations = createOperations();
|
||||
deob.Operations = CreateOperations();
|
||||
}
|
||||
|
||||
IOperations createOperations() {
|
||||
IOperations CreateOperations() {
|
||||
var op = new Operations();
|
||||
|
||||
switch (options.StringDecrypterType) {
|
||||
|
@ -260,7 +260,7 @@ namespace de4dot.code {
|
|||
return op;
|
||||
}
|
||||
|
||||
void detectObfuscator(IEnumerable<IDeobfuscator> deobfuscators) {
|
||||
void DetectObfuscator(IEnumerable<IDeobfuscator> deobfuscators) {
|
||||
|
||||
// The deobfuscators may call methods to deobfuscate control flow and decrypt
|
||||
// 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
|
||||
if (this.deob != null) {
|
||||
deob.init(module);
|
||||
deob.Initialize(module);
|
||||
deob.DeobfuscatedFile = this;
|
||||
deob.detect();
|
||||
deob.Detect();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var deob in deobfuscators) {
|
||||
deob.init(module);
|
||||
deob.Initialize(module);
|
||||
deob.DeobfuscatedFile = this;
|
||||
}
|
||||
|
||||
|
@ -284,16 +284,16 @@ namespace de4dot.code {
|
|||
foreach (var deob in deobfuscators) {
|
||||
if (string.Equals(options.ForcedObfuscatorType, deob.Type, StringComparison.OrdinalIgnoreCase)) {
|
||||
this.deob = deob;
|
||||
deob.detect();
|
||||
deob.Detect();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
this.deob = detectObfuscator2(deobfuscators);
|
||||
this.deob = DetectObfuscator2(deobfuscators);
|
||||
}
|
||||
|
||||
IDeobfuscator detectObfuscator2(IEnumerable<IDeobfuscator> deobfuscators) {
|
||||
IDeobfuscator DetectObfuscator2(IEnumerable<IDeobfuscator> deobfuscators) {
|
||||
var allDetected = new List<IDeobfuscator>();
|
||||
IDeobfuscator detected = null;
|
||||
int detectVal = 0;
|
||||
|
@ -301,7 +301,7 @@ namespace de4dot.code {
|
|||
this.deob = deob; // So we can call deob.CanInlineMethods in deobfuscate()
|
||||
int val;
|
||||
try {
|
||||
val = deob.detect();
|
||||
val = deob.Detect();
|
||||
}
|
||||
catch {
|
||||
val = deob.Type == "un" ? 1 : 0;
|
||||
|
@ -318,16 +318,16 @@ namespace de4dot.code {
|
|||
|
||||
if (allDetected.Count > 1) {
|
||||
Logger.n("More than one obfuscator detected:");
|
||||
Logger.Instance.indent();
|
||||
Logger.Instance.Indent();
|
||||
foreach (var deob in allDetected)
|
||||
Logger.n("{0} (use: -p {1})", deob.Name, deob.Type);
|
||||
Logger.Instance.deIndent();
|
||||
Logger.Instance.DeIndent();
|
||||
}
|
||||
|
||||
return detected;
|
||||
}
|
||||
|
||||
MetaDataFlags getMetaDataFlags() {
|
||||
MetaDataFlags GetMetaDataFlags() {
|
||||
var mdFlags = options.MetaDataFlags | deob.MetaDataFlags;
|
||||
|
||||
// Always preserve tokens if it's an unknown obfuscator
|
||||
|
@ -341,15 +341,15 @@ namespace de4dot.code {
|
|||
return mdFlags;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
public void Save() {
|
||||
Logger.n("Saving {0}", options.NewFilename);
|
||||
var mdFlags = getMetaDataFlags();
|
||||
var mdFlags = GetMetaDataFlags();
|
||||
if (!options.ControlFlowDeobfuscation)
|
||||
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>();
|
||||
|
||||
foreach (var type in module.GetTypes()) {
|
||||
|
@ -360,25 +360,25 @@ namespace de4dot.code {
|
|||
return list;
|
||||
}
|
||||
|
||||
public void deobfuscateBegin() {
|
||||
public void DeobfuscateBegin() {
|
||||
switch (options.StringDecrypterType) {
|
||||
case DecrypterType.None:
|
||||
checkSupportedStringDecrypter(StringFeatures.AllowNoDecryption);
|
||||
CheckSupportedStringDecrypter(StringFeatures.AllowNoDecryption);
|
||||
break;
|
||||
|
||||
case DecrypterType.Static:
|
||||
checkSupportedStringDecrypter(StringFeatures.AllowStaticDecryption);
|
||||
CheckSupportedStringDecrypter(StringFeatures.AllowStaticDecryption);
|
||||
break;
|
||||
|
||||
case DecrypterType.Delegate:
|
||||
case DecrypterType.Emulate:
|
||||
checkSupportedStringDecrypter(StringFeatures.AllowDynamicDecryption);
|
||||
CheckSupportedStringDecrypter(StringFeatures.AllowDynamicDecryption);
|
||||
var newProcFactory = assemblyClientFactory as NewProcessAssemblyClientFactory;
|
||||
if (newProcFactory != null)
|
||||
assemblyClient = newProcFactory.create(module);
|
||||
assemblyClient = newProcFactory.Create(module);
|
||||
else
|
||||
assemblyClient = assemblyClientFactory.create();
|
||||
assemblyClient.connect();
|
||||
assemblyClient = assemblyClientFactory.Create();
|
||||
assemblyClient.Connect();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -386,73 +386,73 @@ namespace de4dot.code {
|
|||
}
|
||||
}
|
||||
|
||||
public void checkSupportedStringDecrypter(StringFeatures feature) {
|
||||
public void CheckSupportedStringDecrypter(StringFeatures feature) {
|
||||
if ((deob.StringFeatures & feature) == feature)
|
||||
return;
|
||||
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);
|
||||
initAssemblyClient();
|
||||
InitAssemblyClient();
|
||||
|
||||
for (int i = 0; ; i++) {
|
||||
byte[] fileData = null;
|
||||
DumpedMethods dumpedMethods = null;
|
||||
if (!deob.getDecryptedModule(i, ref fileData, ref dumpedMethods))
|
||||
if (!deob.GetDecryptedModule(i, ref fileData, ref dumpedMethods))
|
||||
break;
|
||||
reloadModule(fileData, dumpedMethods);
|
||||
ReloadModule(fileData, dumpedMethods);
|
||||
}
|
||||
|
||||
deob.deobfuscateBegin();
|
||||
deobfuscateMethods();
|
||||
deob.deobfuscateEnd();
|
||||
deob.DeobfuscateBegin();
|
||||
DeobfuscateMethods();
|
||||
deob.DeobfuscateEnd();
|
||||
}
|
||||
|
||||
void reloadModule(byte[] newModuleData, DumpedMethods dumpedMethods) {
|
||||
void ReloadModule(byte[] newModuleData, DumpedMethods dumpedMethods) {
|
||||
Logger.v("Reloading decrypted assembly (original filename: {0})", Filename);
|
||||
simpleDeobfuscatorFlags.Clear();
|
||||
using (var oldModule = module) {
|
||||
module = assemblyModule.reload(newModuleData, createDumpedMethodsRestorer(dumpedMethods), deob as IStringDecrypter);
|
||||
deob = deob.moduleReloaded(module);
|
||||
module = assemblyModule.Reload(newModuleData, CreateDumpedMethodsRestorer(dumpedMethods), deob as IStringDecrypter);
|
||||
deob = deob.ModuleReloaded(module);
|
||||
}
|
||||
initializeDeobfuscator();
|
||||
InitializeDeobfuscator();
|
||||
deob.DeobfuscatedFile = this;
|
||||
updateDynamicStringInliner();
|
||||
UpdateDynamicStringInliner();
|
||||
}
|
||||
|
||||
DumpedMethodsRestorer createDumpedMethodsRestorer(DumpedMethods dumpedMethods) {
|
||||
DumpedMethodsRestorer CreateDumpedMethodsRestorer(DumpedMethods dumpedMethods) {
|
||||
if (dumpedMethods == null || dumpedMethods.Count == 0)
|
||||
return null;
|
||||
return new DumpedMethodsRestorer(dumpedMethods);
|
||||
}
|
||||
|
||||
void initAssemblyClient() {
|
||||
void InitAssemblyClient() {
|
||||
if (assemblyClient == null)
|
||||
return;
|
||||
|
||||
assemblyClient.waitConnected();
|
||||
assemblyClient.Service.loadAssembly(options.Filename);
|
||||
assemblyClient.WaitConnected();
|
||||
assemblyClient.Service.LoadAssembly(options.Filename);
|
||||
|
||||
if (options.StringDecrypterType == DecrypterType.Delegate)
|
||||
assemblyClient.Service.setStringDecrypterType(AssemblyData.StringDecrypterType.Delegate);
|
||||
assemblyClient.Service.SetStringDecrypterType(AssemblyData.StringDecrypterType.Delegate);
|
||||
else if (options.StringDecrypterType == DecrypterType.Emulate)
|
||||
assemblyClient.Service.setStringDecrypterType(AssemblyData.StringDecrypterType.Emulate);
|
||||
assemblyClient.Service.SetStringDecrypterType(AssemblyData.StringDecrypterType.Emulate);
|
||||
else
|
||||
throw new ApplicationException(string.Format("Invalid string decrypter type '{0}'", options.StringDecrypterType));
|
||||
|
||||
dynamicStringInliner = new DynamicStringInliner(assemblyClient);
|
||||
updateDynamicStringInliner();
|
||||
UpdateDynamicStringInliner();
|
||||
}
|
||||
|
||||
void updateDynamicStringInliner() {
|
||||
void UpdateDynamicStringInliner() {
|
||||
if (dynamicStringInliner != null)
|
||||
dynamicStringInliner.init(getMethodTokens());
|
||||
dynamicStringInliner.Initialize(GetMethodTokens());
|
||||
}
|
||||
|
||||
IEnumerable<int> getMethodTokens() {
|
||||
IEnumerable<int> GetMethodTokens() {
|
||||
if (!userStringDecrypterMethods)
|
||||
return deob.getStringDecrypterMethods();
|
||||
return deob.GetStringDecrypterMethods();
|
||||
|
||||
var tokens = new List<int>();
|
||||
|
||||
|
@ -464,18 +464,18 @@ namespace de4dot.code {
|
|||
if (int.TryParse(tokenStr, NumberStyles.HexNumber, null, out methodToken))
|
||||
tokens.Add(methodToken);
|
||||
else
|
||||
tokens.AddRange(findMethodTokens(val));
|
||||
tokens.AddRange(FindMethodTokens(val));
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
IEnumerable<int> findMethodTokens(string methodDesc) {
|
||||
IEnumerable<int> FindMethodTokens(string methodDesc) {
|
||||
var tokens = new List<int>();
|
||||
|
||||
string typeString, methodName;
|
||||
string[] argsStrings;
|
||||
splitMethodDesc(methodDesc, out typeString, out methodName, out argsStrings);
|
||||
SplitMethodDesc(methodDesc, out typeString, out methodName, out argsStrings);
|
||||
|
||||
foreach (var type in module.GetTypes()) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ namespace de4dot.code {
|
|||
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;
|
||||
args = null;
|
||||
type = null;
|
||||
|
@ -555,20 +555,20 @@ namespace de4dot.code {
|
|||
name = null;
|
||||
}
|
||||
|
||||
public void deobfuscateEnd() {
|
||||
deobfuscateCleanUp();
|
||||
public void DeobfuscateEnd() {
|
||||
DeobfuscateCleanUp();
|
||||
}
|
||||
|
||||
public void deobfuscateCleanUp() {
|
||||
public void DeobfuscateCleanUp() {
|
||||
if (assemblyClient != null) {
|
||||
assemblyClient.Dispose();
|
||||
assemblyClient = null;
|
||||
}
|
||||
}
|
||||
|
||||
void deobfuscateMethods() {
|
||||
void DeobfuscateMethods() {
|
||||
if (savedMethodBodies != null) {
|
||||
savedMethodBodies.restoreAll();
|
||||
savedMethodBodies.RestoreAll();
|
||||
savedMethodBodies = null;
|
||||
}
|
||||
deob.DeobfuscatedFile = null;
|
||||
|
@ -584,21 +584,21 @@ namespace de4dot.code {
|
|||
Logger.v("Deobfuscating methods");
|
||||
var methodPrinter = new MethodPrinter();
|
||||
var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators);
|
||||
foreach (var method in getAllMethods()) {
|
||||
foreach (var method in GetAllMethods()) {
|
||||
if (isVerbose) {
|
||||
Logger.v("Deobfuscating {0} ({1:X8})", Utils.removeNewlines(method), method.MDToken.ToUInt32());
|
||||
Logger.Instance.indent();
|
||||
Logger.v("Deobfuscating {0} ({1:X8})", Utils.RemoveNewlines(method), method.MDToken.ToUInt32());
|
||||
Logger.Instance.Indent();
|
||||
}
|
||||
|
||||
int oldIndentLevel = Logger.Instance.IndentLevel;
|
||||
try {
|
||||
deobfuscate(method, cflowDeobfuscator, methodPrinter, isVerbose, isVV);
|
||||
Deobfuscate(method, cflowDeobfuscator, methodPrinter, isVerbose, isVV);
|
||||
}
|
||||
catch (ApplicationException) {
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (!canLoadMethodBody(method)) {
|
||||
if (!CanLoadMethodBody(method)) {
|
||||
if (isVerbose)
|
||||
Logger.v("Invalid method body. {0:X8}", method.MDToken.ToInt32());
|
||||
method.Body = new CilBody();
|
||||
|
@ -612,14 +612,14 @@ namespace de4dot.code {
|
|||
finally {
|
||||
Logger.Instance.IndentLevel = oldIndentLevel;
|
||||
}
|
||||
removeNoInliningAttribute(method);
|
||||
RemoveNoInliningAttribute(method);
|
||||
|
||||
if (isVerbose)
|
||||
Logger.Instance.deIndent();
|
||||
Logger.Instance.DeIndent();
|
||||
}
|
||||
}
|
||||
|
||||
static bool canLoadMethodBody(MethodDef method) {
|
||||
static bool CanLoadMethodBody(MethodDef method) {
|
||||
try {
|
||||
var body = method.Body;
|
||||
return true;
|
||||
|
@ -631,39 +631,39 @@ namespace de4dot.code {
|
|||
|
||||
bool CanOptimizeLocals() {
|
||||
// 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) {
|
||||
if (!hasNonEmptyBody(method))
|
||||
void Deobfuscate(MethodDef method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter, bool isVerbose, bool isVV) {
|
||||
if (!HasNonEmptyBody(method))
|
||||
return;
|
||||
|
||||
var blocks = new Blocks(method);
|
||||
int numRemovedLocals = 0;
|
||||
int oldNumInstructions = method.Body.Instructions.Count;
|
||||
|
||||
deob.deobfuscateMethodBegin(blocks);
|
||||
deob.DeobfuscateMethodBegin(blocks);
|
||||
if (options.ControlFlowDeobfuscation) {
|
||||
cflowDeobfuscator.init(blocks);
|
||||
cflowDeobfuscator.deobfuscate();
|
||||
cflowDeobfuscator.Initialize(blocks);
|
||||
cflowDeobfuscator.Deobfuscate();
|
||||
}
|
||||
|
||||
if (deob.deobfuscateOther(blocks) && options.ControlFlowDeobfuscation)
|
||||
cflowDeobfuscator.deobfuscate();
|
||||
if (deob.DeobfuscateOther(blocks) && options.ControlFlowDeobfuscation)
|
||||
cflowDeobfuscator.Deobfuscate();
|
||||
|
||||
if (options.ControlFlowDeobfuscation) {
|
||||
if (CanOptimizeLocals())
|
||||
numRemovedLocals = blocks.optimizeLocals();
|
||||
blocks.repartitionBlocks();
|
||||
numRemovedLocals = blocks.OptimizeLocals();
|
||||
blocks.RepartitionBlocks();
|
||||
}
|
||||
|
||||
deobfuscateStrings(blocks);
|
||||
deob.deobfuscateMethodEnd(blocks);
|
||||
DeobfuscateStrings(blocks);
|
||||
deob.DeobfuscateMethodEnd(blocks);
|
||||
|
||||
IList<Instruction> allInstructions;
|
||||
IList<ExceptionHandler> allExceptionHandlers;
|
||||
blocks.getCode(out allInstructions, out allExceptionHandlers);
|
||||
DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers);
|
||||
blocks.GetCode(out allInstructions, out allExceptionHandlers);
|
||||
DotNetUtils.RestoreBody(method, allInstructions, allExceptionHandlers);
|
||||
|
||||
if (isVerbose && numRemovedLocals > 0)
|
||||
Logger.v("Removed {0} unused local(s)", numRemovedLocals);
|
||||
|
@ -672,29 +672,29 @@ namespace de4dot.code {
|
|||
Logger.v("Removed {0} dead instruction(s)", numRemovedInstructions);
|
||||
|
||||
if (isVV) {
|
||||
Logger.log(LoggerEvent.VeryVerbose, "Deobfuscated code:");
|
||||
Logger.Instance.indent();
|
||||
methodPrinter.print(LoggerEvent.VeryVerbose, allInstructions, allExceptionHandlers);
|
||||
Logger.Instance.deIndent();
|
||||
Logger.Log(LoggerEvent.VeryVerbose, "Deobfuscated code:");
|
||||
Logger.Instance.Indent();
|
||||
methodPrinter.Print(LoggerEvent.VeryVerbose, allInstructions, allExceptionHandlers);
|
||||
Logger.Instance.DeIndent();
|
||||
}
|
||||
}
|
||||
|
||||
bool hasNonEmptyBody(MethodDef method) {
|
||||
bool HasNonEmptyBody(MethodDef method) {
|
||||
return method.HasBody && method.Body.Instructions.Count > 0;
|
||||
}
|
||||
|
||||
void deobfuscateStrings(Blocks blocks) {
|
||||
void DeobfuscateStrings(Blocks blocks) {
|
||||
switch (options.StringDecrypterType) {
|
||||
case DecrypterType.None:
|
||||
break;
|
||||
|
||||
case DecrypterType.Static:
|
||||
deob.deobfuscateStrings(blocks);
|
||||
deob.DeobfuscateStrings(blocks);
|
||||
break;
|
||||
|
||||
case DecrypterType.Delegate:
|
||||
case DecrypterType.Emulate:
|
||||
dynamicStringInliner.decrypt(blocks);
|
||||
dynamicStringInliner.Decrypt(blocks);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -702,14 +702,14 @@ namespace de4dot.code {
|
|||
}
|
||||
}
|
||||
|
||||
void removeNoInliningAttribute(MethodDef method) {
|
||||
void RemoveNoInliningAttribute(MethodDef method) {
|
||||
method.IsNoInlining = false;
|
||||
for (int i = 0; i < method.CustomAttributes.Count; i++) {
|
||||
var cattr = method.CustomAttributes[i];
|
||||
if (cattr.TypeFullName != "System.Runtime.CompilerServices.MethodImplAttribute")
|
||||
continue;
|
||||
int options = 0;
|
||||
if (!getMethodImplOptions(cattr, ref options))
|
||||
if (!GetMethodImplOptions(cattr, ref options))
|
||||
continue;
|
||||
if (options != 0 && options != (int)MethodImplAttributes.NoInlining)
|
||||
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)
|
||||
return false;
|
||||
if (cattr.ConstructorArguments.Count != 1)
|
||||
|
@ -751,21 +751,21 @@ namespace de4dot.code {
|
|||
HasDeobfuscated = 0x1,
|
||||
}
|
||||
Dictionary<MethodDef, SimpleDeobFlags> simpleDeobfuscatorFlags = new Dictionary<MethodDef, SimpleDeobFlags>();
|
||||
bool check(MethodDef method, SimpleDeobFlags flag) {
|
||||
bool Check(MethodDef method, SimpleDeobFlags flag) {
|
||||
SimpleDeobFlags oldFlags;
|
||||
simpleDeobfuscatorFlags.TryGetValue(method, out oldFlags);
|
||||
simpleDeobfuscatorFlags[method] = oldFlags | 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)
|
||||
savedMethodBodies.save(method);
|
||||
savedMethodBodies.Save(method);
|
||||
|
||||
Logger.v("{0}: {1} ({2:X8})", msg, Utils.removeNewlines(method), method.MDToken.ToUInt32());
|
||||
Logger.Instance.indent();
|
||||
Logger.v("{0}: {1} ({2:X8})", msg, Utils.RemoveNewlines(method), method.MDToken.ToUInt32());
|
||||
Logger.Instance.Indent();
|
||||
|
||||
if (hasNonEmptyBody(method)) {
|
||||
if (HasNonEmptyBody(method)) {
|
||||
try {
|
||||
var blocks = new Blocks(method);
|
||||
|
||||
|
@ -773,55 +773,55 @@ namespace de4dot.code {
|
|||
|
||||
IList<Instruction> allInstructions;
|
||||
IList<ExceptionHandler> allExceptionHandlers;
|
||||
blocks.getCode(out allInstructions, out allExceptionHandlers);
|
||||
DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers);
|
||||
blocks.GetCode(out allInstructions, out allExceptionHandlers);
|
||||
DotNetUtils.RestoreBody(method, allInstructions, allExceptionHandlers);
|
||||
}
|
||||
catch {
|
||||
Logger.v("Could not deobfuscate {0:X8}", method.MDToken.ToInt32());
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Instance.deIndent();
|
||||
Logger.Instance.DeIndent();
|
||||
}
|
||||
|
||||
void ISimpleDeobfuscator.deobfuscate(MethodDef method) {
|
||||
((ISimpleDeobfuscator)this).deobfuscate(method, false);
|
||||
void ISimpleDeobfuscator.Deobfuscate(MethodDef method) {
|
||||
((ISimpleDeobfuscator)this).Deobfuscate(method, false);
|
||||
}
|
||||
|
||||
void ISimpleDeobfuscator.deobfuscate(MethodDef method, bool force) {
|
||||
if (!force && check(method, SimpleDeobFlags.HasDeobfuscated))
|
||||
void ISimpleDeobfuscator.Deobfuscate(MethodDef method, bool force) {
|
||||
if (!force && Check(method, SimpleDeobFlags.HasDeobfuscated))
|
||||
return;
|
||||
|
||||
deobfuscate(method, "Deobfuscating control flow", (blocks) => {
|
||||
Deobfuscate(method, "Deobfuscating control flow", (blocks) => {
|
||||
var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators);
|
||||
cflowDeobfuscator.init(blocks);
|
||||
cflowDeobfuscator.deobfuscate();
|
||||
cflowDeobfuscator.Initialize(blocks);
|
||||
cflowDeobfuscator.Deobfuscate();
|
||||
});
|
||||
}
|
||||
|
||||
void ISimpleDeobfuscator.decryptStrings(MethodDef method, IDeobfuscator theDeob) {
|
||||
deobfuscate(method, "Static string decryption", (blocks) => theDeob.deobfuscateStrings(blocks));
|
||||
void ISimpleDeobfuscator.DecryptStrings(MethodDef method, IDeobfuscator theDeob) {
|
||||
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)
|
||||
extension = ".dll";
|
||||
var baseDir = Utils.getDirName(options.NewFilename);
|
||||
var baseDir = Utils.GetDirName(options.NewFilename);
|
||||
var newName = Path.Combine(baseDir, assemblyName + extension);
|
||||
Logger.n("Creating file {0}", newName);
|
||||
File.WriteAllBytes(newName, data);
|
||||
}
|
||||
|
||||
void IDeobfuscatedFile.stringDecryptersAdded() {
|
||||
updateDynamicStringInliner();
|
||||
void IDeobfuscatedFile.StringDecryptersAdded() {
|
||||
UpdateDynamicStringInliner();
|
||||
}
|
||||
|
||||
void IDeobfuscatedFile.setDeobfuscator(IDeobfuscator deob) {
|
||||
void IDeobfuscatedFile.SetDeobfuscator(IDeobfuscator deob) {
|
||||
this.deob = deob;
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
deobfuscateCleanUp();
|
||||
DeobfuscateCleanUp();
|
||||
if (module != null)
|
||||
module.Dispose();
|
||||
if (deob != null)
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace de4dot.code {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
if (shortName != null)
|
||||
|
@ -79,7 +79,7 @@ namespace de4dot.code {
|
|||
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) ||
|
||||
string.Equals(newVal, "off", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(newVal, "0", StringComparison.OrdinalIgnoreCase)) {
|
||||
|
@ -107,7 +107,7 @@ namespace de4dot.code {
|
|||
get { return "int"; }
|
||||
}
|
||||
|
||||
public override bool set(string newVal, out string error) {
|
||||
public override bool Set(string newVal, out string error) {
|
||||
int newInt;
|
||||
if (!int.TryParse(newVal, out newInt)) {
|
||||
error = string.Format("Not an integer: '{0}'", newVal);
|
||||
|
@ -135,7 +135,7 @@ namespace de4dot.code {
|
|||
Default = this.val = val;
|
||||
}
|
||||
|
||||
public override bool set(string newVal, out string error) {
|
||||
public override bool Set(string newVal, out string error) {
|
||||
val = newVal;
|
||||
error = "";
|
||||
return true;
|
||||
|
@ -158,10 +158,10 @@ namespace de4dot.code {
|
|||
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 {
|
||||
var regexes = new NameRegexes();
|
||||
regexes.set(newVal);
|
||||
regexes.Set(newVal);
|
||||
val = regexes;
|
||||
}
|
||||
catch (ArgumentException) {
|
||||
|
@ -189,7 +189,7 @@ namespace de4dot.code {
|
|||
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 {
|
||||
val = new Regex(newVal);
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ namespace de4dot.code {
|
|||
this.action = action;
|
||||
}
|
||||
|
||||
public override bool set(string val, out string error) {
|
||||
public override bool Set(string val, out string error) {
|
||||
triggered = true;
|
||||
if (action != null)
|
||||
action();
|
||||
|
@ -251,7 +251,7 @@ namespace de4dot.code {
|
|||
Default = null;
|
||||
}
|
||||
|
||||
public override bool set(string val, out string error) {
|
||||
public override bool Set(string val, out string error) {
|
||||
action(val);
|
||||
error = "";
|
||||
return true;
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyVersion("2.0.3.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.3405")]
|
||||
|
|
|
@ -26,7 +26,7 @@ using de4dot.blocks;
|
|||
|
||||
namespace de4dot.code {
|
||||
abstract class StringInlinerBase : MethodReturnValueInliner {
|
||||
protected override void inlineReturnValues(IList<CallResult> callResults) {
|
||||
protected override void InlineReturnValues(IList<CallResult> callResults) {
|
||||
foreach (var callResult in callResults) {
|
||||
var block = callResult.block;
|
||||
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
|
@ -36,13 +36,13 @@ namespace de4dot.code {
|
|||
continue;
|
||||
|
||||
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 (ldstrIndex + 1 < block.Instructions.Count) {
|
||||
var instr = block.Instructions[ldstrIndex + 1];
|
||||
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
|
||||
|
@ -52,12 +52,12 @@ namespace de4dot.code {
|
|||
var calledMethod = instr.Operand as IMethod;
|
||||
if (calledMethod != null &&
|
||||
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;
|
||||
}
|
||||
|
||||
public void init(IEnumerable<int> methodTokens) {
|
||||
public void Initialize(IEnumerable<int> methodTokens) {
|
||||
methodTokenToId.Clear();
|
||||
foreach (var methodToken in methodTokens) {
|
||||
if (methodTokenToId.ContainsKey(methodToken))
|
||||
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;
|
||||
if (!methodTokenToId.TryGetValue(method.MDToken.ToInt32(), out methodId))
|
||||
return null;
|
||||
return new MyCallResult(block, callInstrIndex, methodId, gim);
|
||||
}
|
||||
|
||||
protected override void inlineAllCalls() {
|
||||
protected override void InlineAllCalls() {
|
||||
var sortedCalls = new Dictionary<int, List<MyCallResult>>();
|
||||
foreach (var tmp in callResults) {
|
||||
var callResult = (MyCallResult)tmp;
|
||||
|
@ -114,13 +114,13 @@ namespace de4dot.code {
|
|||
var list = sortedCalls[methodId];
|
||||
var args = new object[list.Count];
|
||||
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;
|
||||
}
|
||||
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)
|
||||
throw new ApplicationException("Invalid decrypted strings array length");
|
||||
AssemblyData.SimpleData.unpack(decryptedStrings);
|
||||
AssemblyData.SimpleData.Unpack(decryptedStrings);
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
list[i].returnValue = (string)decryptedStrings[i];
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ namespace de4dot.code {
|
|||
}
|
||||
|
||||
public IEnumerable<MethodDef> Methods {
|
||||
get { return stringDecrypters.getKeys(); }
|
||||
get { return stringDecrypters.GetKeys(); }
|
||||
}
|
||||
|
||||
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)
|
||||
stringDecrypters.add(method, handler);
|
||||
stringDecrypters.Add(method, handler);
|
||||
}
|
||||
|
||||
protected override void inlineAllCalls() {
|
||||
protected override void InlineAllCalls() {
|
||||
foreach (var tmp in callResults) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
protected override CallResult createCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex) {
|
||||
if (stringDecrypters.find(method) == null)
|
||||
protected override CallResult CreateCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex) {
|
||||
if (stringDecrypters.Find(method) == null)
|
||||
return null;
|
||||
return new MyCallResult(block, callInstrIndex, method, gim);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace de4dot.code {
|
|||
public static class Utils {
|
||||
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.
|
||||
var dict = new Dictionary<T, bool>();
|
||||
foreach (var val in values)
|
||||
|
@ -63,30 +63,30 @@ namespace de4dot.code {
|
|||
return dict.Keys;
|
||||
}
|
||||
|
||||
public static string toCsharpString(UTF8String s) {
|
||||
return toCsharpString(UTF8String.ToSystemStringOrEmpty(s));
|
||||
public static string ToCsharpString(UTF8String 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);
|
||||
sb.Append('"');
|
||||
foreach (var c in s) {
|
||||
if ((int)c < 0x20) {
|
||||
switch (c) {
|
||||
case '\a': appendEscape(sb, 'a'); break;
|
||||
case '\b': appendEscape(sb, 'b'); break;
|
||||
case '\f': appendEscape(sb, 'f'); break;
|
||||
case '\n': appendEscape(sb, 'n'); break;
|
||||
case '\r': appendEscape(sb, 'r'); break;
|
||||
case '\t': appendEscape(sb, 't'); break;
|
||||
case '\v': appendEscape(sb, 'v'); break;
|
||||
case '\a': AppendEscape(sb, 'a'); break;
|
||||
case '\b': AppendEscape(sb, 'b'); break;
|
||||
case '\f': AppendEscape(sb, 'f'); break;
|
||||
case '\n': AppendEscape(sb, 'n'); break;
|
||||
case '\r': AppendEscape(sb, 'r'); break;
|
||||
case '\t': AppendEscape(sb, 't'); break;
|
||||
case '\v': AppendEscape(sb, 'v'); break;
|
||||
default:
|
||||
sb.Append(string.Format(@"\u{0:X4}", (int)c));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (c == '\\' || c == '"') {
|
||||
appendEscape(sb, c);
|
||||
AppendEscape(sb, c);
|
||||
}
|
||||
else
|
||||
sb.Append(c);
|
||||
|
@ -95,12 +95,12 @@ namespace de4dot.code {
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string shellEscape(string s) {
|
||||
public static string ShellEscape(string s) {
|
||||
var sb = new StringBuilder(s.Length + 2);
|
||||
sb.Append('"');
|
||||
foreach (var c in s) {
|
||||
if (c == '"')
|
||||
appendEscape(sb, c);
|
||||
AppendEscape(sb, c);
|
||||
else
|
||||
sb.Append(c);
|
||||
}
|
||||
|
@ -108,20 +108,20 @@ namespace de4dot.code {
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
static void appendEscape(StringBuilder sb, char c) {
|
||||
static void AppendEscape(StringBuilder sb, char c) {
|
||||
sb.Append('\\');
|
||||
sb.Append(c);
|
||||
}
|
||||
|
||||
public static string removeNewlines(object o) {
|
||||
return removeNewlines(o.ToString());
|
||||
public static string RemoveNewlines(object o) {
|
||||
return RemoveNewlines(o.ToString());
|
||||
}
|
||||
|
||||
public static string removeNewlines(string s) {
|
||||
public static string RemoveNewlines(string s) {
|
||||
return s.Replace('\n', ' ').Replace('\r', ' ');
|
||||
}
|
||||
|
||||
public static string getFullPath(string path) {
|
||||
public static string GetFullPath(string path) {
|
||||
try {
|
||||
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);
|
||||
var sb = new StringBuilder(numChars);
|
||||
int numLower = 0;
|
||||
|
@ -150,26 +150,26 @@ namespace de4dot.code {
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string getBaseName(string name) {
|
||||
public static string GetBaseName(string name) {
|
||||
int index = name.LastIndexOf(Path.DirectorySeparatorChar);
|
||||
if (index < 0)
|
||||
return name;
|
||||
return name.Substring(index + 1);
|
||||
}
|
||||
|
||||
public static string getDirName(string name) {
|
||||
public static string GetDirName(string name) {
|
||||
return Path.GetDirectoryName(name);
|
||||
}
|
||||
|
||||
static string ourBaseDir = null;
|
||||
public static string getOurBaseDir() {
|
||||
public static string GetOurBaseDir() {
|
||||
if (ourBaseDir != null)
|
||||
return ourBaseDir;
|
||||
return ourBaseDir = getDirName(typeof(Utils).Assembly.Location);
|
||||
return ourBaseDir = GetDirName(typeof(Utils).Assembly.Location);
|
||||
}
|
||||
|
||||
public static string getPathOfOurFile(string filename) {
|
||||
return Path.Combine(getOurBaseDir(), filename);
|
||||
public static string GetPathOfOurFile(string filename) {
|
||||
return Path.Combine(GetOurBaseDir(), filename);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
public static string getAssemblySimpleName(string name) {
|
||||
public static string GetAssemblySimpleName(string name) {
|
||||
int i = name.IndexOf(',');
|
||||
if (i < 0)
|
||||
return name;
|
||||
return name.Substring(0, i);
|
||||
}
|
||||
|
||||
public static bool pathExists(string path) {
|
||||
public static bool PathExists(string path) {
|
||||
try {
|
||||
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 {
|
||||
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)
|
||||
return false;
|
||||
for (int i = 0; i < a.Length; i++) {
|
||||
|
@ -215,7 +215,7 @@ namespace de4dot.code {
|
|||
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
|
||||
// offset in the file! Tested: VMware 8, Win7 x64.
|
||||
const int MAX_BYTES_READ = 0x200000;
|
||||
|
|
|
@ -63,26 +63,26 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
|
||||
public CliSecureRtType(ModuleDefMD module, CliSecureRtType oldOne) {
|
||||
this.module = module;
|
||||
cliSecureRtType = lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type");
|
||||
postInitializeMethod = lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method");
|
||||
initializeMethod = lookup(oldOne.initializeMethod, "Could not find initializeMethod method");
|
||||
stringDecrypterMethod = lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod method");
|
||||
loadMethod = lookup(oldOne.loadMethod, "Could not find loadMethod method");
|
||||
cliSecureRtType = Lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type");
|
||||
postInitializeMethod = Lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method");
|
||||
initializeMethod = Lookup(oldOne.initializeMethod, "Could not find initializeMethod method");
|
||||
stringDecrypterMethod = Lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod method");
|
||||
loadMethod = Lookup(oldOne.loadMethod, "Could not find loadMethod method");
|
||||
foundSig = oldOne.foundSig;
|
||||
}
|
||||
|
||||
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
|
||||
return DeobUtils.lookup(module, def, errorMessage);
|
||||
T Lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
|
||||
return DeobUtils.Lookup(module, def, errorMessage);
|
||||
}
|
||||
|
||||
public void find(byte[] moduleBytes) {
|
||||
public void Find(byte[] moduleBytes) {
|
||||
if (cliSecureRtType != null)
|
||||
return;
|
||||
if (find2())
|
||||
if (Find2())
|
||||
return;
|
||||
if (find3())
|
||||
if (Find3())
|
||||
return;
|
||||
findNativeCode(moduleBytes);
|
||||
FindNativeCode(moduleBytes);
|
||||
}
|
||||
|
||||
static readonly string[] requiredFields1 = new string[] {
|
||||
|
@ -101,23 +101,23 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
"System.Reflection.Assembly",
|
||||
"System.Byte[]",
|
||||
};
|
||||
bool find2() {
|
||||
foreach (var cctor in DeobUtils.getInitCctors(module, 3)) {
|
||||
foreach (var calledMethod in DotNetUtils.getCalledMethods(module, cctor)) {
|
||||
bool Find2() {
|
||||
foreach (var cctor in DeobUtils.GetInitCctors(module, 3)) {
|
||||
foreach (var calledMethod in DotNetUtils.GetCalledMethods(module, cctor)) {
|
||||
var type = calledMethod.DeclaringType;
|
||||
if (type.IsPublic)
|
||||
continue;
|
||||
var fieldTypes = new FieldTypes(type);
|
||||
if (!fieldTypes.exactly(requiredFields1) && !fieldTypes.exactly(requiredFields2) &&
|
||||
!fieldTypes.exactly(requiredFields3) && !fieldTypes.exactly(requiredFields4))
|
||||
if (!fieldTypes.Exactly(requiredFields1) && !fieldTypes.Exactly(requiredFields2) &&
|
||||
!fieldTypes.Exactly(requiredFields3) && !fieldTypes.Exactly(requiredFields4))
|
||||
continue;
|
||||
if (!hasInitializeMethod(type, "_Initialize") && !hasInitializeMethod(type, "_Initialize64"))
|
||||
if (!HasInitializeMethod(type, "_Initialize") && !HasInitializeMethod(type, "_Initialize64"))
|
||||
continue;
|
||||
|
||||
stringDecrypterMethod = findStringDecrypterMethod(type);
|
||||
stringDecrypterMethod = FindStringDecrypterMethod(type);
|
||||
initializeMethod = calledMethod;
|
||||
postInitializeMethod = findMethod(type, "System.Void", "PostInitialize", "()");
|
||||
loadMethod = findMethod(type, "System.IntPtr", "Load", "()");
|
||||
postInitializeMethod = FindMethod(type, "System.Void", "PostInitialize", "()");
|
||||
loadMethod = FindMethod(type, "System.IntPtr", "Load", "()");
|
||||
cliSecureRtType = type;
|
||||
return true;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool find3() {
|
||||
bool Find3() {
|
||||
foreach (var type in module.Types) {
|
||||
if (type.Fields.Count != 1)
|
||||
continue;
|
||||
|
@ -148,11 +148,11 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
return false;
|
||||
}
|
||||
|
||||
static MethodDef findStringDecrypterMethod(TypeDef type) {
|
||||
static MethodDef FindStringDecrypterMethod(TypeDef type) {
|
||||
foreach (var method in type.Methods) {
|
||||
if (method.Body == null || !method.IsStatic)
|
||||
continue;
|
||||
if (!DotNetUtils.isMethod(method, "System.String", "(System.String)"))
|
||||
if (!DotNetUtils.IsMethod(method, "System.String", "(System.String)"))
|
||||
continue;
|
||||
|
||||
return method;
|
||||
|
@ -161,7 +161,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
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;
|
||||
foreach (var method in type.Methods) {
|
||||
if (method.Body == null || !method.IsStatic)
|
||||
|
@ -175,8 +175,8 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
return null;
|
||||
}
|
||||
|
||||
static bool hasInitializeMethod(TypeDef type, string name) {
|
||||
var method = DotNetUtils.getPInvokeMethod(type, name);
|
||||
static bool HasInitializeMethod(TypeDef type, string name) {
|
||||
var method = DotNetUtils.GetPInvokeMethod(type, name);
|
||||
if (method == null)
|
||||
return false;
|
||||
var sig = method.MethodSig;
|
||||
|
@ -190,17 +190,17 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool findNativeCode(byte[] moduleBytes) {
|
||||
var bytes = moduleBytes != null ? moduleBytes : DeobUtils.readModule(module);
|
||||
bool FindNativeCode(byte[] moduleBytes) {
|
||||
var bytes = moduleBytes != null ? moduleBytes : DeobUtils.ReadModule(module);
|
||||
using (var peImage = new MyPEImage(bytes))
|
||||
return foundSig = MethodsDecrypter.detect(peImage);
|
||||
return foundSig = MethodsDecrypter.Detect(peImage);
|
||||
}
|
||||
|
||||
public bool isAtLeastVersion50() {
|
||||
return DotNetUtils.hasPinvokeMethod(cliSecureRtType, "LoadLibraryA");
|
||||
public bool IsAtLeastVersion50() {
|
||||
return DotNetUtils.HasPinvokeMethod(cliSecureRtType, "LoadLibraryA");
|
||||
}
|
||||
|
||||
public void findStringDecrypterMethod() {
|
||||
public void FindStringDecrypterMethod() {
|
||||
if (cliSecureRtType != null)
|
||||
return;
|
||||
|
||||
|
@ -210,7 +210,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
if (type.Methods.Count != 1)
|
||||
continue;
|
||||
var cs = type.Methods[0];
|
||||
if (!isOldStringDecrypterMethod(cs))
|
||||
if (!IsOldStringDecrypterMethod(cs))
|
||||
continue;
|
||||
|
||||
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)
|
||||
return false;
|
||||
if (!DotNetUtils.isMethod(method, "System.String", "(System.String)"))
|
||||
if (!DotNetUtils.IsMethod(method, "System.String", "(System.String)"))
|
||||
return false;
|
||||
if (!DeobUtils.hasInteger(method, 0xFF))
|
||||
if (!DeobUtils.HasInteger(method, 0xFF))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
: 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;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
xl ^= P[i];
|
||||
|
@ -38,7 +38,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
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;
|
||||
for (int i = 17; i >= 2; i--) {
|
||||
xl ^= P[i];
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user