diff --git a/AssemblyData/AssemblyData.csproj b/AssemblyData/AssemblyData.csproj index 10fd66a4..7cfd4201 100644 --- a/AssemblyData/AssemblyData.csproj +++ b/AssemblyData/AssemblyData.csproj @@ -40,6 +40,18 @@ + + + + + + + + + + + + diff --git a/AssemblyData/EmuStringDecrypter.cs b/AssemblyData/EmuStringDecrypter.cs index 7f6da146..b949b0e2 100644 --- a/AssemblyData/EmuStringDecrypter.cs +++ b/AssemblyData/EmuStringDecrypter.cs @@ -19,18 +19,17 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Reflection; -using System.Reflection.Emit; +using AssemblyData.methodsrewriter; namespace AssemblyData { class EmuStringDecrypter : IStringDecrypter { - delegate string DecryptString(object[] args); List decryptInfos = new List(); + MethodsRewriter methodsRewriter = new MethodsRewriter(); class DecryptInfo { public MethodInfo method; - public DecryptString decryptString; + public RewrittenMethod decryptString; public DecryptInfo(MethodInfo method) { this.method = method; @@ -53,8 +52,9 @@ namespace AssemblyData { return result; } - DecryptString createDecryptString(MethodInfo method) { - throw new System.NotImplementedException(); //TODO: + RewrittenMethod createDecryptString(MethodInfo method) { + methodsRewriter.createMethod(method); + return methodsRewriter.createDelegate(method); } } } diff --git a/AssemblyData/Utils.cs b/AssemblyData/Utils.cs index 3acf3ec6..5d7233b7 100644 --- a/AssemblyData/Utils.cs +++ b/AssemblyData/Utils.cs @@ -23,9 +23,30 @@ using System.Reflection.Emit; using System.Text; namespace AssemblyData { + // Yes, I did type this by hand. internal delegate void Action(); + internal delegate void Action(T1 arg1); + internal delegate void Action(T1 arg1, T2 arg2); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17, T18 arg18); + internal delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17, T18 arg18, T19 arg19); + // No that was a lie. internal delegate TResult Func(); - internal delegate TResult Func(T1 arg); + internal delegate TResult Func(T1 arg1); internal delegate TResult Func(T1 arg1, T2 arg2); internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); @@ -34,30 +55,78 @@ namespace AssemblyData { internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); + internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); + internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); + internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); + internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); + internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); + internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); + internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); + internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17); + internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17, T18 arg18); + internal delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17, T18 arg18, T19 arg19); static class Utils { static Random random = new Random(); - public static Type getDelegateType(MethodInfo method) { - var parameters = method.GetParameters(); - var types = new Type[parameters.Length + 1]; - for (int i = 0; i < parameters.Length; i++) - types[i] = parameters[i].ParameterType; - types[types.Length - 1] = method.ReturnType; + public static Type getDelegateType(Type returnType, Type[] args) { + Type[] types; + if (returnType == typeof(void)) { + types = args; + switch (types.Length) { + case 0: return typeof(Action).MakeGenericType(types); + case 1: return typeof(Action<>).MakeGenericType(types); + case 2: return typeof(Action<,>).MakeGenericType(types); + case 3: return typeof(Action<,,>).MakeGenericType(types); + case 4: return typeof(Action<,,,>).MakeGenericType(types); + case 5: return typeof(Action<,,,,>).MakeGenericType(types); + case 6: return typeof(Action<,,,,,>).MakeGenericType(types); + case 7: return typeof(Action<,,,,,,>).MakeGenericType(types); + case 8: return typeof(Action<,,,,,,,>).MakeGenericType(types); + case 9: return typeof(Action<,,,,,,,,>).MakeGenericType(types); + case 10: return typeof(Action<,,,,,,,,,>).MakeGenericType(types); + case 11: return typeof(Action<,,,,,,,,,,>).MakeGenericType(types); + case 12: return typeof(Action<,,,,,,,,,,,>).MakeGenericType(types); + case 13: return typeof(Action<,,,,,,,,,,,,>).MakeGenericType(types); + case 14: return typeof(Action<,,,,,,,,,,,,,>).MakeGenericType(types); + case 15: return typeof(Action<,,,,,,,,,,,,,,>).MakeGenericType(types); + case 16: return typeof(Action<,,,,,,,,,,,,,,,>).MakeGenericType(types); + case 17: return typeof(Action<,,,,,,,,,,,,,,,,>).MakeGenericType(types); + case 18: return typeof(Action<,,,,,,,,,,,,,,,,,>).MakeGenericType(types); + case 19: return typeof(Action<,,,,,,,,,,,,,,,,,,>).MakeGenericType(types); + default: + throw new ApplicationException(string.Format("Too many delegate type arguments: {0}", types.Length)); + } + } + else { + types = new Type[args.Length + 1]; + Array.Copy(args, types, args.Length); + types[types.Length - 1] = returnType; - switch (types.Length) { - case 1: return typeof(Func<>).MakeGenericType(types); - case 2: return typeof(Func<,>).MakeGenericType(types); - case 3: return typeof(Func<,,>).MakeGenericType(types); - case 4: return typeof(Func<,,,>).MakeGenericType(types); - case 5: return typeof(Func<,,,,>).MakeGenericType(types); - case 6: return typeof(Func<,,,,,>).MakeGenericType(types); - case 7: return typeof(Func<,,,,,,>).MakeGenericType(types); - case 8: return typeof(Func<,,,,,,,>).MakeGenericType(types); - case 9: return typeof(Func<,,,,,,,,>).MakeGenericType(types); - case 10:return typeof(Func<,,,,,,,,,>).MakeGenericType(types); - default: - throw new ApplicationException(string.Format("Too many arguments: {0}", method)); + switch (types.Length) { + case 1: return typeof(Func<>).MakeGenericType(types); + case 2: return typeof(Func<,>).MakeGenericType(types); + case 3: return typeof(Func<,,>).MakeGenericType(types); + case 4: return typeof(Func<,,,>).MakeGenericType(types); + case 5: return typeof(Func<,,,,>).MakeGenericType(types); + case 6: return typeof(Func<,,,,,>).MakeGenericType(types); + case 7: return typeof(Func<,,,,,,>).MakeGenericType(types); + case 8: return typeof(Func<,,,,,,,>).MakeGenericType(types); + case 9: return typeof(Func<,,,,,,,,>).MakeGenericType(types); + case 10: return typeof(Func<,,,,,,,,,>).MakeGenericType(types); + case 11: return typeof(Func<,,,,,,,,,,>).MakeGenericType(types); + case 12: return typeof(Func<,,,,,,,,,,,>).MakeGenericType(types); + case 13: return typeof(Func<,,,,,,,,,,,,>).MakeGenericType(types); + case 14: return typeof(Func<,,,,,,,,,,,,,>).MakeGenericType(types); + case 15: return typeof(Func<,,,,,,,,,,,,,,>).MakeGenericType(types); + case 16: return typeof(Func<,,,,,,,,,,,,,,,>).MakeGenericType(types); + case 17: return typeof(Func<,,,,,,,,,,,,,,,,>).MakeGenericType(types); + case 18: return typeof(Func<,,,,,,,,,,,,,,,,,>).MakeGenericType(types); + case 19: return typeof(Func<,,,,,,,,,,,,,,,,,,>).MakeGenericType(types); + case 20: return typeof(Func<,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types); + default: + throw new ApplicationException(string.Format("Too many delegate type arguments: {0}", types.Length)); + } } } diff --git a/AssemblyData/methodsrewriter/AssemblyResolver.cs b/AssemblyData/methodsrewriter/AssemblyResolver.cs new file mode 100644 index 00000000..0ada1bcd --- /dev/null +++ b/AssemblyData/methodsrewriter/AssemblyResolver.cs @@ -0,0 +1,136 @@ +/* + Copyright (C) 2011 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Reflection; +using Mono.Cecil; +using de4dot.blocks; + +namespace AssemblyData.methodsrewriter { + class MGenericParameter { + } + + class AssemblyResolver { + Dictionary> types = new Dictionary>(StringComparer.Ordinal); + List globalMethods; + List globalFields; + Assembly assembly; + + public AssemblyResolver(string asmName) { + assembly = Assembly.Load(new AssemblyName(asmName)); + initTypes(); + } + + void initTypes() { + foreach (var type in assembly.GetTypes()) { + string key = (type.Namespace ?? "") + "." + type.Name; + List list; + if (!types.TryGetValue(key, out list)) + types[key] = list = new List(); + list.Add(new TypeResolver(type)); + } + } + + TypeResolver getTypeResolver(TypeReference typeReference) { + var key = typeReference.Namespace + "." + typeReference.Name; + List list; + if (!types.TryGetValue(key, out list)) + return null; + + foreach (var resolver in list) { + if (ResolverUtils.compareTypes(resolver.type, typeReference)) + return resolver; + } + + return null; + } + + public FieldInfo resolve(FieldReference fieldReference) { + var resolver = getTypeResolver(fieldReference.DeclaringType); + if (resolver != null) + return resolver.resolve(fieldReference); + return resolveGlobalField(fieldReference); + } + + FieldInfo resolveGlobalField(FieldReference fieldReference) { + initGlobalFields(); + foreach (var globalField in globalFields) { + if (ResolverUtils.compareFields(globalField, fieldReference)) + return globalField; + } + return null; + } + + void initGlobalFields() { + if (globalFields != null) + return; + globalFields = new List(); + + var flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; + foreach (var module in assembly.GetModules(true)) { + foreach (var method in module.GetFields(flags)) + globalFields.Add(method); + } + } + + public MethodBase resolve(MethodReference methodReference) { + var resolver = getTypeResolver(methodReference.DeclaringType); + if (resolver != null) + return resolver.resolve(methodReference); + return resolveGlobalMethod(methodReference); + } + + MethodBase resolveGlobalMethod(MethodReference methodReference) { + initGlobalMethods(); + foreach (var globalMethod in globalMethods) { + if (ResolverUtils.compareMethods(globalMethod, methodReference)) + return globalMethod; + } + return null; + } + + void initGlobalMethods() { + if (globalMethods != null) + return; + globalMethods = new List(); + + var flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; + foreach (var module in assembly.GetModules(true)) { + foreach (var method in module.GetMethods(flags)) + globalMethods.Add(method); + } + } + + public Type resolve(TypeReference typeReference) { + var resolver = getTypeResolver(typeReference); + if (resolver != null) + return resolver.type; + + if (typeReference.IsGenericParameter) + return typeof(MGenericParameter); + + return null; + } + + public override string ToString() { + return assembly.ToString(); + } + } +} diff --git a/AssemblyData/methodsrewriter/CodeGenerator.cs b/AssemblyData/methodsrewriter/CodeGenerator.cs new file mode 100644 index 00000000..8dab19c1 --- /dev/null +++ b/AssemblyData/methodsrewriter/CodeGenerator.cs @@ -0,0 +1,293 @@ +/* + Copyright (C) 2011 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Reflection.Emit; +using Mono.Cecil; +using Mono.Cecil.Cil; +using de4dot.blocks; + +using OpCode = Mono.Cecil.Cil.OpCode; +using OpCodes = Mono.Cecil.Cil.OpCodes; +using OperandType = Mono.Cecil.Cil.OperandType; +using ROpCode = System.Reflection.Emit.OpCode; +using ROpCodes = System.Reflection.Emit.OpCodes; + +namespace AssemblyData.methodsrewriter { + class CodeGenerator { + static Dictionary cecilToReflection = new Dictionary(); + static CodeGenerator() { + var refDict = new Dictionary(0x100); + foreach (var f in typeof(ROpCodes).GetFields(BindingFlags.Static | BindingFlags.Public)) { + if (f.FieldType != typeof(ROpCode)) + continue; + var ropcode = (ROpCode)f.GetValue(null); + refDict[ropcode.Value] = ropcode; + } + + foreach (var f in typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public)) { + if (f.FieldType != typeof(OpCode)) + continue; + var opcode = (OpCode)f.GetValue(null); + ROpCode ropcode; + if (!refDict.TryGetValue(opcode.Value, out ropcode)) + continue; + cecilToReflection[opcode] = ropcode; + } + } + + IMethodsRewriter methodsRewriter; + IList allInstructions; + IList allExceptionHandlers; + ILGenerator ilg; + Type methodReturnType; + Type[] methodParameters; + Type delegateType; + MMethod methodInfo; + LocalBuilder tempObjLocal; + LocalBuilder tempObjArrayLocal; + int thisArgIndex; + List locals; + List