Already asked this question. How to replace the pointer to the overridden (virtual) method in the pointer of my method? (Release x64 and x86) Thanks @Machine Learning, solved the problem. But a new problem arose. If the system inherited from the class, such as "Systems.Windows.Forms", then the change does not work. Example:
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
namespace ReplaceHandles
{
public class Target1 : UserControl
{
public void test()
{
Console.WriteLine("Target1.test()");
}
}
public class Target2
{
public void test()
{
Console.WriteLine("Target2.test()");
}
}
class Program
{
static void Main(string[] args)
{
Injection.Replace();
var target = new Target1();
target.test();
Console.Read();
}
}
}
Class that replaces pointers
public class Injection
{
public static void Replace()
{
var methodToReplace = typeof(Target1).GetMethod("test", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var methodToInject = typeof(Target2).GetMethod("test", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);
if (methodToReplace.IsVirtual) ReplaceVirtualInner(methodToReplace, methodToInject);
else ReplaceInner(methodToReplace, methodToInject);
}
Replacing the virtual methods
static void ReplaceVirtualInner(MethodInfo methodToReplace, MethodInfo methodToInject)
{
unsafe
{
var methodDesc = (UInt64*)(methodToReplace.MethodHandle.Value.ToPointer());
var index = (int)(((*methodDesc) >> 32) & 0xFF);
if (IntPtr.Size == 4)
{
if (methodToReplace.DeclaringType != null)
{
var classStart = (uint*)methodToReplace.DeclaringType.TypeHandle.Value.ToPointer();
classStart += 10;
classStart = (uint*)*classStart;
var tar = classStart + index;
var inj = (uint*)methodToInject.MethodHandle.Value.ToPointer() + 2;
#if DEBUG
var injInst = (byte*)*inj;
var tarInst = (byte*)*tar;
var injSrc = (int*)(injInst + 1);
var tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
*tar = *inj;
#endif
}
}
else
{
if (methodToReplace.DeclaringType != null)
{
var classStart = (ulong*)methodToReplace.DeclaringType.TypeHandle.Value.ToPointer();
classStart += 8;
classStart = (ulong*)*classStart;
var tar = classStart + index;
var inj = (ulong*)methodToInject.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
var injInst = (byte*)*inj;
var tarInst = (byte*)*tar;
var injSrc = (int*)(injInst + 1);
var tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
*tar = *inj;
#endif
}
}
}
}
and replacing not virtual methods
static void ReplaceInner(MethodInfo methodToReplace, MethodInfo methodToInject)
{
unsafe
{
if (IntPtr.Size == 4)
{
var inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
var tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
#if DEBUG
var injInst = (byte*)*inj;
var tarInst = (byte*)*tar;
var injSrc = (int*)(injInst + 1);
var tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
*tar = *inj;
#endif
}
else
{
ulong* inj = (ulong*)methodToInject.MethodHandle.Value.ToPointer() + 1;
ulong* tar = (ulong*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
var injInst = (byte*)*inj;
var tarInst = (byte*)*tar;
var injSrc = (int*)(injInst + 1);
var tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
*tar = *inj;
#endif
}
}
}
}