C#交换方法指针

被引用的dll是testDllFr.dll,其代码为:


namespace testDLLFr
{
    public class TestA
    {
        public static void TestAM()
        {
            Console.WriteLine("TestAM");
        }
    }
    public class Test
    {
        public static void TestDLl()
        {
            TestA.TestAM();
        }
    }
}

引用者为FrameWorkTest.dll,其代码为:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using testDLLFr;

namespace FrameWorkTest
{
    public class TestB
    {
        public static void TestBM()
        {
            Console.WriteLine("testbm");
        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            Assembly assm = Assembly.GetAssembly(typeof(testDLLFr.TestA));
            Type[] ts = assm.GetTypes();
            var ta = ts.Where(n => n.Name == "TestA").FirstOrDefault();
            MethodInfo tm = ta.GetMethod("TestAM"), tmb = typeof(TestB).GetMethod("TestBM");
            ExchangeMethod(tm, tmb);
            testDLLFr.Test.TestDLl();
            Console.ReadKey();
        }
        private static bool ExchangeMethod(MethodInfo targetMethod, MethodInfo injectMethod)
        {
            if (targetMethod == null || injectMethod == null)
            {
                return false;
            }
            RuntimeHelpers.PrepareMethod(targetMethod.MethodHandle);
            RuntimeHelpers.PrepareMethod(injectMethod.MethodHandle);
            unsafe
            {
                if (IntPtr.Size == 4)
                {
                    int* tar = (int*)targetMethod.MethodHandle.Value.ToPointer() + 2;
                    int* inj = (int*)injectMethod.MethodHandle.Value.ToPointer() + 2;
                    var relay = *tar;
                    *tar = *inj;
                    *inj = relay;
                }
                else
                {
                    long* tar = (long*)targetMethod.MethodHandle.Value.ToPointer() + 1;
                    var a = targetMethod.MethodHandle;
                    var b = a.Value;
                    var c = b.ToPointer();
                    var d = (long*)c;
                    var e = d + 1;
                    long* inj = (long*)injectMethod.MethodHandle.Value.ToPointer() + 1;
                    var relay = *tar;
                    *tar = *inj;
                    *inj = relay;
                }
            }
            return true;
        }
    }
}

FrameworkTest中调用了testDLLFr中Test的TestDLL方法,而该方法调用了TestA的TestAM方法,现在我们想用我们自己的TestB的TestBM方法来替换TestAM的指针。
运行发现:

testbm

即,交换成功。

posted @ 2022-09-29 19:03  JohnYang819  阅读(107)  评论(0编辑  收藏  举报