Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
166 views
Welcome To Ask or Share your Answers For Others

1 Answer

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;
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...