问题
I am trying to replace a method in a plugin loader(Like Bukkit for Minecraft) during run-time. I cannot modify the assembly file directly in this instance. The whole purpose is to be able to tell when the methods are being called. And cancel them if necessary. Once my plugin is loaded I run the following code:
public static void PluginLoaded()
{
replace();
}
public static void replace()
{
MethodInfo oldMethod, newMethod;
oldMethod = typeof(<other assembly>).GetMethod("<method name>", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic,null,new Type[]{typeof(ushort)},null);
newMethod = typeof(NewEvents).GetMethod("<method name>", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(ushort) }, null);
RuntimeHelpers.PrepareMethod(oldMethod.MethodHandle);
RuntimeHelpers.PrepareMethod(newMethod.MethodHandle);
ReplaceInner(oldMethod, newMethod);
}
static void ReplaceInner(MethodInfo methodToReplace, MethodInfo methodToInject)
{
unsafe
{
if (IntPtr.Size == 4)
{
int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
*tar = *inj;
}
else
{
ulong* inj = (ulong*)methodToInject.MethodHandle.Value.ToPointer() + 1;
ulong* tar = (ulong*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
*tar = *inj;
}
}
}
It works fine until the original program tries to call the changed method. When it does this the whole program stops and I get a access volation. How do I fix this?
回答1:
The functionality you have provided is specific for the memory mapping of the CLR starting in .Net version 4.0. Here are your options:
Option 1. Upgrade the .NET Framework on your machine. This should fix your issue without the need to upgrade visual studio. https://www.microsoft.com/en-us/download/details.aspx?id=42643
Option 2. Update your ReplaceInner()
method to reflect the memory mapping of Types and Methods before the .NET framework 4.0:
static void ReplaceInner(MethodInfo methodToReplace, MethodInfo methodToInject)
{
unsafe
{
if (IntPtr.Size == 4)
{
uint* tarPtr = (uint*)methodToReplace.MethodHandle.Value.ToPointer();
uint* injPtr = (uint*)methodToInject.MethodHandle.Value.ToPointer();
uint* tar = (uint*)*(tarPtr + 5) + 12;
uint* inj = (uint*)*(injPtr + 5) + 12;
*tar = *inj;
}
else
{
ulong* tarPtr = (ulong*)methodToReplace.MethodHandle.Value.ToPointer();
ulong* injPtr = (ulong*)methodToInject.MethodHandle.Value.ToPointer();
ulong* tar = (ulong*)*(tarPtr + 5) + 12;
ulong* inj = (ulong*)*(injPtr + 5) + 12;
*tar = *inj;
}
}
}
来源:https://stackoverflow.com/questions/39213674/c-sharp-changing-methods-pointers-net-3-5