I will give the code:
public class Base { public virtual void test() { } } public class Target : Base { public override void test() { Console.WriteLine("Target.test()"); } public void test3() { Console.WriteLine("Target.test3()"); } } public class Target2 { public void test() { Console.WriteLine("Target.test2()"); } } public class Injection { public static void replace() { MethodInfo methodToReplace = typeof(Target).GetMethod("test", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); MethodInfo methodToInject = typeof(Target2).GetMethod("test", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle); RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle); ReplaceInner(methodToReplace, methodToInject); } static void ReplaceInner(MethodInfo methodToReplace, MethodInfo methodToInject) { unsafe { if (IntPtr.Size == 4) { int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer(); int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer(); *tar = *inj; } else { ulong* inj = (ulong*)methodToInject.MethodHandle.Value.ToPointer() + 1; ulong* tar = (ulong*)methodToReplace.MethodHandle.Value.ToPointer() + 1; *tar = *inj; } } } } class Program { static void Main(string[] args) { Injection.replace(); Target target = new Target(); target.test(); Console.Read(); } } When replacing a pointer of a non-redefined (non-virtual) method, everything works, i.e. instead of the test () method of the Target class, the test () method of the Target2 class is called. In the case of replacing a virtual method pointer, the same overridden method is called.
In other words, if you replace a pointer, such as the test3 () method from the Target class with the test () method pointer from the Target2 class, then when you call target.test (), the test () method from the Target2 class is called. But with virtual methods this does not work.