必须是JIT过的函数,也就是进行过编译;(为什么ios不能用,编译器不同啦)
RuntimeMethodHandle.GetFunctionPointer 方法
、
NativeAPI.VirtualProtect
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace MethodHookSample
{
class Program
{
static void Main(string[] args)
{
Target target = new Target();
var methodAdd = typeof(Target).GetMethod("Add", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var methodMinus = typeof(Target).GetMethod("Minus", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
MethodHooker.HookMethod(methodAdd, methodMinus);
var result = target.Add(5, 4);
Console.Write("5 + 4 = " + result);
Console.Read();
}
}
public class Target
{
[MethodImpl(MethodImplOptions.NoInlining)]
public int Add(int a, int b)
{
return a + b;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public int Minus(int a, int b)
{
return a - b;
}
}
public class MethodHooker
{
public static void HookMethod(MethodInfo sourceMethod, MethodInfo destinationMethod)
{
RuntimeHelpers.PrepareMethod(sourceMethod.MethodHandle);
RuntimeHelpers.PrepareMethod(destinationMethod.MethodHandle);
if (sourceMethod.IsVirtual)
{
HookVirtualMethod(sourceMethod, destinationMethod);
return;
}
unsafe
{
if (IntPtr.Size == 4)
{
int* inj = (int*)destinationMethod.MethodHandle.Value.ToPointer() + 2;
int* tar = (int*)sourceMethod.MethodHandle.Value.ToPointer() + 2;
#if DEBUG
Console.WriteLine("\nVersion x86 Debug\n");
byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar;
int* injSrc = (int*)(injInst + 1);
int* tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
Console.WriteLine("\nVersion x86 Release\n");
*tar = *inj;
#endif
}
else
{
long* inj = (long*)destinationMethod.MethodHandle.Value.ToPointer() + 1;
long* tar = (long*)sourceMethod.MethodHandle.Value.ToPointer() + 1;
Console.WriteLine("\nVersion x64 Release\n");
*tar = *inj;
}
}
}
static void HookVirtualMethod(MethodInfo sourceMethod, MethodInfo destinationMethod)
{
unsafe
{
UInt64* methodDesc = (UInt64*)(sourceMethod.MethodHandle.Value.ToPointer());
int index = (int)(((*methodDesc) >> 32) & 0xFF);
if (IntPtr.Size == 4)
{
uint* classStart = (uint*)sourceMethod.DeclaringType.TypeHandle.Value.ToPointer();
classStart += 10;
classStart = (uint*)*classStart;
uint* tar = classStart + index;
uint* inj = (uint*)destinationMethod.MethodHandle.Value.ToPointer() + 2;
*tar = *inj;
}
else
{
ulong* classStart = (ulong*)sourceMethod.DeclaringType.TypeHandle.Value.ToPointer();
classStart += 8;
classStart = (ulong*)*classStart;
ulong* tar = classStart + index;
ulong* inj = (ulong*)destinationMethod.MethodHandle.Value.ToPointer() + 1;
*tar = *inj;
}
}
}
}
}