Update stack emulation
- Allow System.Object string decrypter return type - Fix for StackFrame.GetMethod() - Caller method is updated in stack frame
This commit is contained in:
parent
93d801997e
commit
e1a81d0b31
|
@ -76,16 +76,17 @@ namespace AssemblyData {
|
||||||
var methodInfo = findMethod(methodToken);
|
var methodInfo = findMethod(methodToken);
|
||||||
if (methodInfo == null)
|
if (methodInfo == null)
|
||||||
throw new ApplicationException(string.Format("Could not find method {0:X8}", methodToken));
|
throw new ApplicationException(string.Format("Could not find method {0:X8}", methodToken));
|
||||||
if (methodInfo.ReturnType != typeof(string))
|
if (methodInfo.ReturnType != typeof(string) && methodInfo.ReturnType != typeof(object))
|
||||||
throw new ApplicationException(string.Format("Method return type must be string: {0}", methodInfo));
|
throw new ApplicationException(string.Format("Method return type must be string or object: {0}", methodInfo));
|
||||||
return stringDecrypter.defineStringDecrypter(methodInfo);
|
return stringDecrypter.defineStringDecrypter(methodInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object[] decryptStrings(int stringDecrypterMethod, object[] args) {
|
public object[] decryptStrings(int stringDecrypterMethod, object[] args, int callerToken) {
|
||||||
checkStringDecrypter();
|
checkStringDecrypter();
|
||||||
|
var caller = assembly.GetModules()[0].ResolveMethod(callerToken);
|
||||||
foreach (var arg in args)
|
foreach (var arg in args)
|
||||||
SimpleData.unpack((object[])arg);
|
SimpleData.unpack((object[])arg);
|
||||||
return SimpleData.pack(stringDecrypter.decryptStrings(stringDecrypterMethod, args));
|
return SimpleData.pack(stringDecrypter.decryptStrings(stringDecrypterMethod, args, caller));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exit() {
|
public void exit() {
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace AssemblyData {
|
||||||
return stringDecryptMethods.Count - 1;
|
return stringDecryptMethods.Count - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object[] decryptStrings(int stringDecrypterMethod, object[] args) {
|
public object[] decryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller) {
|
||||||
if (stringDecrypterMethod > stringDecryptMethods.Count)
|
if (stringDecrypterMethod > stringDecryptMethods.Count)
|
||||||
throw new ApplicationException("Invalid string decrypter method");
|
throw new ApplicationException("Invalid string decrypter method");
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,12 @@ namespace AssemblyData {
|
||||||
return decryptInfos.Count - 1;
|
return decryptInfos.Count - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object[] decryptStrings(int stringDecrypterMethod, object[] args) {
|
public object[] decryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller) {
|
||||||
var decryptInfo = decryptInfos[stringDecrypterMethod];
|
var decryptInfo = decryptInfos[stringDecrypterMethod];
|
||||||
if (decryptInfo.decryptString == null)
|
if (decryptInfo.decryptString == null)
|
||||||
decryptInfo.decryptString = createDecryptString(decryptInfo.method);
|
decryptInfo.decryptString = createDecryptString(decryptInfo.method);
|
||||||
|
|
||||||
|
methodsRewriter.setCaller(decryptInfo.decryptString, caller);
|
||||||
var result = new object[args.Length];
|
var result = new object[args.Length];
|
||||||
for (int i = 0; i < args.Length; i++)
|
for (int i = 0; i < args.Length; i++)
|
||||||
result[i] = decryptInfo.decryptString((object[])args[i]);
|
result[i] = decryptInfo.decryptString((object[])args[i]);
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace AssemblyData {
|
||||||
void loadAssembly(string filename);
|
void loadAssembly(string filename);
|
||||||
void setStringDecrypterType(StringDecrypterType type);
|
void setStringDecrypterType(StringDecrypterType type);
|
||||||
int defineStringDecrypter(int methodToken);
|
int defineStringDecrypter(int methodToken);
|
||||||
object[] decryptStrings(int stringDecrypterMethod, object[] args);
|
object[] decryptStrings(int stringDecrypterMethod, object[] args, int callerToken);
|
||||||
void exit();
|
void exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,6 @@ using System.Reflection;
|
||||||
namespace AssemblyData {
|
namespace AssemblyData {
|
||||||
interface IStringDecrypter {
|
interface IStringDecrypter {
|
||||||
int defineStringDecrypter(MethodInfo method);
|
int defineStringDecrypter(MethodInfo method);
|
||||||
object[] decryptStrings(int stringDecrypterMethod, object[] args);
|
object[] decryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ namespace AssemblyData.methodsrewriter {
|
||||||
class MethodsRewriter : IMethodsRewriter {
|
class MethodsRewriter : IMethodsRewriter {
|
||||||
MethodsFinder methodsFinder = new MethodsFinder();
|
MethodsFinder methodsFinder = new MethodsFinder();
|
||||||
Dictionary<MethodBase, NewMethodInfo> realMethodToNewMethod = new Dictionary<MethodBase, NewMethodInfo>();
|
Dictionary<MethodBase, NewMethodInfo> realMethodToNewMethod = new Dictionary<MethodBase, NewMethodInfo>();
|
||||||
|
Dictionary<NewMethodInfo, MethodBase> newStackMethodDict = new Dictionary<NewMethodInfo, MethodBase>();
|
||||||
List<NewMethodInfo> newMethodInfos = new List<NewMethodInfo>();
|
List<NewMethodInfo> newMethodInfos = new List<NewMethodInfo>();
|
||||||
|
|
||||||
// There's no documented way to get a dynamic method's MethodInfo. If we name the
|
// There's no documented way to get a dynamic method's MethodInfo. If we name the
|
||||||
|
@ -163,6 +164,11 @@ namespace AssemblyData.methodsrewriter {
|
||||||
return newMethodInfo.rewrittenMethod;
|
return newMethodInfo.rewrittenMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCaller(RewrittenMethod rewrittenMethod, MethodBase caller) {
|
||||||
|
var newMethodInfo = getNewMethodInfo(rewrittenMethod.Method.Name);
|
||||||
|
newStackMethodDict[newMethodInfo] = caller;
|
||||||
|
}
|
||||||
|
|
||||||
string getDelegateMethodName(MethodBase method) {
|
string getDelegateMethodName(MethodBase method) {
|
||||||
string name = null;
|
string name = null;
|
||||||
do {
|
do {
|
||||||
|
@ -229,6 +235,12 @@ namespace AssemblyData.methodsrewriter {
|
||||||
i += 2;
|
i += 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (MemberReferenceHelper.verifyType(ctor.DeclaringType, "mscorlib", "System.Diagnostics.StackFrame")) {
|
||||||
|
insertLoadThis(block, i + 1);
|
||||||
|
insertCallOurMethod(block, i + 2, "static_rtFixStackFrame");
|
||||||
|
i += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instr.OpCode == OpCodes.Call || instr.OpCode == OpCodes.Callvirt) {
|
if (instr.OpCode == OpCodes.Call || instr.OpCode == OpCodes.Callvirt) {
|
||||||
|
@ -359,30 +371,45 @@ namespace AssemblyData.methodsrewriter {
|
||||||
|
|
||||||
var newFrames = new List<StackFrame>(frames.Length);
|
var newFrames = new List<StackFrame>(frames.Length);
|
||||||
foreach (var frame in frames) {
|
foreach (var frame in frames) {
|
||||||
var method = frame.GetMethod();
|
fixStackFrame(frame);
|
||||||
var info = getNewMethodInfo(method.Name);
|
|
||||||
if (info == null) {
|
|
||||||
newFrames.Add(frame);
|
newFrames.Add(frame);
|
||||||
}
|
}
|
||||||
else if (info.isRewrittenMethod(method.Name)) {
|
|
||||||
// Write random method from the same module
|
|
||||||
writeMethodBase(frame, methodsFinder.getMethod(info.oldMethod.Module));
|
|
||||||
newFrames.Add(frame);
|
|
||||||
}
|
|
||||||
else if (info.isDelegateMethod(method.Name)) {
|
|
||||||
// Write original method
|
|
||||||
writeMethodBase(frame, info.oldMethod);
|
|
||||||
newFrames.Add(frame);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new ApplicationException("BUG: Shouldn't be here");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
framesField.SetValue(stackTrace, newFrames.ToArray());
|
framesField.SetValue(stackTrace, newFrames.ToArray());
|
||||||
return stackTrace;
|
return stackTrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static StackFrame static_rtFixStackFrame(StackFrame stackFrame, MethodsRewriter self) {
|
||||||
|
return self.rtFixStackFrame(stackFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
StackFrame rtFixStackFrame(StackFrame frame) {
|
||||||
|
fixStackFrame(frame);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fixStackFrame(StackFrame frame) {
|
||||||
|
var method = frame.GetMethod();
|
||||||
|
var info = getNewMethodInfo(method.Name);
|
||||||
|
if (info == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MethodBase stackMethod;
|
||||||
|
if (newStackMethodDict.TryGetValue(info, out stackMethod)) {
|
||||||
|
writeMethodBase(frame, stackMethod);
|
||||||
|
}
|
||||||
|
else if (info.isRewrittenMethod(method.Name)) {
|
||||||
|
// Write random method from the same module
|
||||||
|
writeMethodBase(frame, methodsFinder.getMethod(info.oldMethod.Module));
|
||||||
|
}
|
||||||
|
else if (info.isDelegateMethod(method.Name)) {
|
||||||
|
// Write original method
|
||||||
|
writeMethodBase(frame, info.oldMethod);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new ApplicationException("BUG: Shouldn't be here");
|
||||||
|
}
|
||||||
|
|
||||||
// Called when the code calls GetCallingAssembly(), GetEntryAssembly(), or GetExecutingAssembly()
|
// Called when the code calls GetCallingAssembly(), GetEntryAssembly(), or GetExecutingAssembly()
|
||||||
Assembly rtGetAssembly(int delegateIndex) {
|
Assembly rtGetAssembly(int delegateIndex) {
|
||||||
return newMethodInfos[delegateIndex].oldMethod.Module.Assembly;
|
return newMethodInfos[delegateIndex].oldMethod.Module.Assembly;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user