Crane.MethodHook
1.0.8
dotnet add package Crane.MethodHook --version 1.0.8
NuGet\Install-Package Crane.MethodHook -Version 1.0.8
<PackageReference Include="Crane.MethodHook" Version="1.0.8" />
paket add Crane.MethodHook --version 1.0.8
#r "nuget: Crane.MethodHook, 1.0.8"
// Install Crane.MethodHook as a Cake Addin
#addin nuget:?package=Crane.MethodHook&version=1.0.8
// Install Crane.MethodHook as a Cake Tool
#tool nuget:?package=Crane.MethodHook&version=1.0.8
介绍
此库尝试通过汇编JMP
指令实现.net中方法钩子。
This library implement .net method hooking by using native JMP
directive.
调用方法
如果要在控制台中显示hook细节,请调用这个方法
Crane.MethodHook.MethodHookManager.Instance.ShowHookDetails(true);
添加MethodHook示例,可以添加多个MethodHook
var sourceMethod = typeof(string).GetMethod("Compare", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(string) }, null);
var targetMethod = typeof(Program).GetMethod(nameof(NewCompare), BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(string) }, null);
Crane.MethodHook.MethodHookManager.Instance.AddHook(new MethodHook(sourceMethod, targetMethod));
要让所有的Hook生效,就必须开启Hook
Crane.MethodHook.MethodHookManager.Instance.StartHook();
Hook开启后,可以随时关闭Hook
Crane.MethodHook.MethodHookManager.Instance.StopHook();
这里需要注意一点,当前MethodHookManager设计为静态类型,碰到同一共享方法在多AppDomain进行Hook时,请确保在AppDomain切换时只保持一个AppDomain中进行Hook,其他已经Hook了的域需要进行StopHook处理,否则可能会报错。
获取当前方法所绑定的MethodHook,然后可以使用InvokeOriginal
来调用Hook前的原始方法。
下面这个例子string.Compare
Hook生效后,在新方法中希望调用原始的string.Compare
方法,就可以这样:
public static int NewCompare(string a, string b)
{
var methodHook = Crane.MethodHook.MethodHookManager.Instance.GetHook(System.Reflection.MethodBase.GetCurrentMethod());
return -1 * methodHook.InvokeOriginal<int>(null,a,b);
}
特别说明
这个库Hook时原方法和目标方法不验证签名,意思是对象的实例方法也可以Hook到一个静态方法,私有方法也可以Hook到公共方法,很无脑。
实现方法是在定义时将静态方法的第一个参数设置为实例对象,其他参数在后面依次添加。如下示例:
var sourceMethod = typeof(Person).GetMethod("ShowPersonAge", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { }, null);
var targetMethod = typeof(Program).GetMethod(nameof(ShowPersonAgeNew), BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Person) }, null);
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public void ShowPersonAge()
{
Console.WriteLine(Name + " is " + Age.ToString() + " years old.");
}
}
public static void ShowPersonAgeNew(Person a)
{
if (a.Name == "John")
{
Console.WriteLine(a.Name + " is " + a.Age.ToString() + " years old.");
}
else
{
Console.WriteLine(a.Name + " is 999 years old.");
}
}
V1.0.7版增加了跨平台支持,可以用在Linux/Unix下。 V1.0.8版完善了NET4x下全面支持,在NET6/8下方法的HOOK支持覆盖度不如NET4x,待后续再慢慢完善。 Hook管理器被设置为静态类型,因此在单个AppDomain中只需要操作一次即可生效。如果是跨多个AppDomain进行Hook,请在离开旧域前StopHook,然后在新域中重新StartHook,否则可能会出现异常。 如果有技术上的问题,请联系我扣扣252502568,长久交流。
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Framework | net472 is compatible. net48 was computed. net481 was computed. |
-
.NETFramework 4.7.2
- System.Runtime.CompilerServices.Unsafe (>= 6.0.0)
-
net6.0
- System.Runtime.CompilerServices.Unsafe (>= 6.0.0)
-
net8.0
- System.Runtime.CompilerServices.Unsafe (>= 6.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
最新版支持 .Net 4x/6/8,如有技术疑问加我扣扣252502568详细交流。