前言
早些年的时候,当时使用了一个商业库。功能很强大,论坛有关于破解的帖子,当时大概看了一下,需要修改.NET Framework自带程序集的一些代码,绕过验证。
后面我没有去尝试了,就到网上找了一个现成的库玩了一下。
当时我反编译了那个程序集,发现里面使用了一种Hook 函数的机制,
在前面的文章中,我介绍过如何使用minHook来Hook win32函数(https://www.cnblogs.com/zhaotianff/p/18073138),但是Hook CLR函数的倒是没尝试过。
这里刚好详细讲解一下,如何在C#中Hook CLR函数。
使用替换方法表中指针的方式实现替换
这里我们先大概了解一下思路
在 .NET 中,每个引用类型对象都包含一个指向 类型句柄(TypeHandle) 的指针。类型句柄指向一个 方法表(MethodTable),其中包含该类型的所有方法信息。对于虚方法,方法表中会有一个槽位(slot)存储方法的入口地址(经过 JIT 编译后的本机代码地址)。
Hook 虚方法的思路:
-
获取目标对象的方法表地址。
-
在方法表中定位到目标虚方法的槽位索引。
-
获取槽位当前地址。
-
将槽位内容替换为自定义方法的地址。
-
后续对该虚方法的调用将跳转到自定义代码。
限制:
-
只能 Hook 虚方法 或 接口方法(接口方法在实现类的方法表中也有槽位)。
-
不能 Hook 静态方法、实例非虚方法(它们不通过虚表调用)。
-
替换必须发生在目标方法被 JIT 编译之后。
-
自定义方法必须与被 Hook 方法具有完全相同的签名,否则调用时栈会损坏。
这里我们创建一个程序集LibTest,增加一个函数Add
使用DispatchProxy Hook 接口方法
使用动态派生类并重写虚方法
使用Harmony包
