inline hook的核心思想是:通过替换目标函数头部指令实现在函数执行之前跳转到其他的指令区域,执行完毕跳转回到原来的函数,跳转到的指令区域通常是我们自己编写的函数。inline hook技术对于编写外挂和外挂式补丁意义重大。
github:csharp_InlineHook
使用net这么久 ,做InlineHook只能使用c++写,因为之前使用过c++的clr,所以脑洞一下可以利用clr当作跳板, 注入我们的托管dll到目标进程然后干奇怪的事情。 具体大家可以看源码, 我这里说一说大体实现流程。
-
首先使用c++写一个跳板,引入固定的托管dll,然后运行该托管dll的指定类方法作为启动方法,这里直接运行是clr
((WeChetHook^)WeChet)->Start(str, Int, Module);
-
到这里我们的托管dll已经注入到目标进程了,可以直接读写宿主内存,注入不注入都能读写,所以我们的关键是实现inline hook,对他的任意点hook 回调到托管的函数内部处理,通过net的Marshal.GetDelegateForFunctionPointer方法我们可以拿到net方法的函数指针,使用跳板call是可以成功传参调用的
-
到这里我们就可以注入并从托管调用到非托管函数,当然其中的各种调试崩溃这里就不提了,现在可以从非托管调用到托管我们就可以hook任意点 劫持到跳板再跳到net函数。
-
Inline_Hook.cs1. 接下来的事和跳板没关系了,全部net实现,首先我简单实现了一个Inline_Hook.cs,具体原理就不讲解了。可以自行看代码。
-
接下来就写一个demo来测试是否可行,
byte[] jmp_inst =
{
233,0,0,0,0,//JMP Address
};
textBox3.Text = (3212659 + int.Parse(label1.Text)).ToString();//为了调试直接在窗体拿数据,label1.Text这内容是基址地址,3212659这是hook地址的偏移
List<byte> byteSource = new List<byte>();
byteSource.AddRange(new byte[] { 199, 134, 236, 2, 0, 0 });//mov dword [esi+0x000002EC],这里我觉得有问题我使用了寄存器存需要跳回的地址
byteSource.AddRange(BitConverter.GetBytes(int.Parse(textBox3.Text) + 5));需要返回的地址
byteSource.AddRange(jmp_inst);//跳转模板
//这部分根据实际情况填写
byteSource.Add(185);//补充替换的汇编指令
byteSource.AddRange(BitConverter.GetBytes(int.Parse(label1.Text) + 19255272));//补充替换的汇编指令地址
剩下的都在代码里面这里贴一下效果图 此代码仅用于研究学习。