DotNetDetour icon indicating copy to clipboard operation
DotNetDetour copied to clipboard

可以支持.net core吗

Open hxbb00 opened this issue 4 years ago • 3 comments

如题,需要在.net core中使用,可以发布.net core nuget包吗?

hxbb00 avatar Jun 13 '20 00:06 hxbb00

同问,作者好像不在了?没有见到关于项目的任何回复

mchudie avatar May 10 '23 04:05 mchudie

不出意外应该是不支持的。根据仓库动态我猜测这个最开始为.Net Framewrok设计的。然而,在dotnet/runtime仓库中,RuntimeMethodHandle.Value对应的MonoMethod*+8字节后并不是函数入口地址。

如果想要支持需要改写目标地址,获取ValuePtr(MonoMethod*)后,lookup_method(MonoMethod*)能获取到JitInfo*,而lookup_method需要根据code hash查表。遗憾的是lookup_method并不是export function

see https://github.com/dotnet/runtime/blob/main/src/mono/mono/mini/mini-runtime.c#L1908 入口查找代码 see https://github.com/dotnet/runtime/blob/8aea53e25f1e78bfbc31f91c6342177eb548eaa5/src/mono/mono/metadata/jit-info.h#L200 JitInfo结构体

好在发现了一个mono_jit_info_table_find(MonoDomain*,void*)方法,可以通过ftnptr获取jitInfo。第一个参数接收MonoDomain,直接使用AppDomain.CurrentDomain肯定是不行的,需要拿到底层对象的地址,这就需要另外一个mono_domain_get函数。

最终的代码如下,可供参考:

// Unity 编辑器环境
[DllImport("mono-2.0-bdwgc", EntryPoint = "mono_jit_info_table_find", CharSet = CharSet.Unicode)]
extern static IntPtr FindJitInfo(IntPtr ptrDomain, IntPtr ptrFunc);

[DllImport("mono-2.0-bdwgc", EntryPoint = "mono_domain_get", CharSet = CharSet.Unicode)]
extern static IntPtr GetDomain();


static unsafe void SetFunctionPtr(MethodInfo mi,nint addr)
{
    RuntimeHelpers.PrepareMethod(mi.MethodHandle);
    var monoDomain = GetDomain();
    var funcPtr = mi.MethodHandle.GetFunctionPointer();
    var jitInfoPtr = (int*)FindJitInfo(monoDomain, funcPtr).ToPointer();
    jitInfoPtr += IntPtr.Size / 4 * 2;
    *(nint*)jitInfoPtr = addr; // overwrite me!
}

测试代码:

public static void Test1()
{
    Debug.Log("Test1");
}

public static void Test2()
{
    Debug.Log("Test2");
}

[InitializeOnLoadMethod]
static void HookMethods()
{
    var mi1 = ((Action)Test1).Method;
    var mi2 = ((Action)Test2).Method;
    RuntimeHelpers.PrepareMethod(mi1.MethodHandle);
    RuntimeHelpers.PrepareMethod(mi2.MethodHandle);
    SetFunctionPtr(mi1, mi2.MethodHandle.GetFunctionPointer());
    Test1(); // output: Test2
}

纯C#环境同理,需要判断下运行时类型,如果是mono或.net core,就执行此逻辑。需要根据实际情况修改入口点。

labbbirder avatar Apr 16 '24 15:04 labbbirder

btw, 可以参考MonoHook的实现,不修改入口,直接修改originMethod jit code。也是一个可行的方法。

labbbirder avatar Apr 17 '24 04:04 labbbirder