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);
|
||||
if (methodInfo == null)
|
||||
throw new ApplicationException(string.Format("Could not find method {0:X8}", methodToken));
|
||||
if (methodInfo.ReturnType != typeof(string))
|
||||
throw new ApplicationException(string.Format("Method return type must be string: {0}", methodInfo));
|
||||
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);
|
||||
}
|
||||
|
||||
public object[] decryptStrings(int stringDecrypterMethod, object[] args) {
|
||||
public object[] decryptStrings(int stringDecrypterMethod, object[] args, int callerToken) {
|
||||
checkStringDecrypter();
|
||||
var caller = assembly.GetModules()[0].ResolveMethod(callerToken);
|
||||
foreach (var arg in args)
|
||||
SimpleData.unpack((object[])arg);
|
||||
return SimpleData.pack(stringDecrypter.decryptStrings(stringDecrypterMethod, args));
|
||||
return SimpleData.pack(stringDecrypter.decryptStrings(stringDecrypterMethod, args, caller));
|
||||
}
|
||||
|
||||
public void exit() {
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace AssemblyData {
|
|||
return stringDecryptMethods.Count - 1;
|
||||
}
|
||||
|
||||
public object[] decryptStrings(int stringDecrypterMethod, object[] args) {
|
||||
public object[] decryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller) {
|
||||
if (stringDecrypterMethod > stringDecryptMethods.Count)
|
||||
throw new ApplicationException("Invalid string decrypter method");
|
||||
|
||||
|
|
|
@ -41,11 +41,12 @@ namespace AssemblyData {
|
|||
return decryptInfos.Count - 1;
|
||||
}
|
||||
|
||||
public object[] decryptStrings(int stringDecrypterMethod, object[] args) {
|
||||
public object[] decryptStrings(int stringDecrypterMethod, object[] args, MethodBase caller) {
|
||||
var decryptInfo = decryptInfos[stringDecrypterMethod];
|
||||
if (decryptInfo.decryptString == null)
|
||||
decryptInfo.decryptString = createDecryptString(decryptInfo.method);
|
||||
|
||||
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]);
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace AssemblyData {
|
|||
void loadAssembly(string filename);
|
||||
void setStringDecrypterType(StringDecrypterType type);
|
||||
int defineStringDecrypter(int methodToken);
|
||||
object[] decryptStrings(int stringDecrypterMethod, object[] args);
|
||||
object[] decryptStrings(int stringDecrypterMethod, object[] args, int callerToken);
|
||||
void exit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,6 @@ using System.Reflection;
|
|||
namespace AssemblyData {
|
||||
interface IStringDecrypter {
|
||||
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 {
|
||||
MethodsFinder methodsFinder = new MethodsFinder();
|
||||
Dictionary<MethodBase, NewMethodInfo> realMethodToNewMethod = new Dictionary<MethodBase, NewMethodInfo>();
|
||||
Dictionary<NewMethodInfo, MethodBase> newStackMethodDict = new Dictionary<NewMethodInfo, MethodBase>();
|
||||
List<NewMethodInfo> newMethodInfos = new List<NewMethodInfo>();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
public void setCaller(RewrittenMethod rewrittenMethod, MethodBase caller) {
|
||||
var newMethodInfo = getNewMethodInfo(rewrittenMethod.Method.Name);
|
||||
newStackMethodDict[newMethodInfo] = caller;
|
||||
}
|
||||
|
||||
string getDelegateMethodName(MethodBase method) {
|
||||
string name = null;
|
||||
do {
|
||||
|
@ -229,6 +235,12 @@ namespace AssemblyData.methodsrewriter {
|
|||
i += 2;
|
||||
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) {
|
||||
|
@ -359,30 +371,45 @@ namespace AssemblyData.methodsrewriter {
|
|||
|
||||
var newFrames = new List<StackFrame>(frames.Length);
|
||||
foreach (var frame in frames) {
|
||||
var method = frame.GetMethod();
|
||||
var info = getNewMethodInfo(method.Name);
|
||||
if (info == null) {
|
||||
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");
|
||||
}
|
||||
fixStackFrame(frame);
|
||||
newFrames.Add(frame);
|
||||
}
|
||||
|
||||
framesField.SetValue(stackTrace, newFrames.ToArray());
|
||||
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()
|
||||
Assembly rtGetAssembly(int delegateIndex) {
|
||||
return newMethodInfos[delegateIndex].oldMethod.Module.Assembly;
|
||||
|
|
Loading…
Reference in New Issue
Block a user