托管函数的挂钩

很早以前就想研究一下托管函数的挂钩,但是一直没有成功。前段时间又尝试了一次,竟然成功了,这让我十分的困惑——因为我几乎没有对代码做任何改变!

 

这次实验距离以前已经有很长时间了,我实在想不出有什么不同之处,唯一的区别就是以前用的是控制台程序,这次是WinForm程序,但我想不可能是这个原因吧?不过我还是尝试了一下,未曾料到竟真是如此!

 

我当然不会相信这样的灵异事件!

 

于是我想,我平时写代码很随意,一般不自己定义类,直接在自动生成的类里定义函数,会不会是这个原因呢?

于是我将控制台的类派生之Form,果然,挂钩成功。

但是很显然,不可能是因为Form类,于是我很自然的想到了继承树上更高层次的MarshalByRefObject类,并验证了一下,正如我所料,代码如下:

 

namespace CLR_Hook

{

    unsafe class Program

    {

        static void Main()

        {

            CsToD ctd = new CsToD();

            Hook(ctd.My, ctd.You);

            ctd.My();

            Console.ReadKey();

        }

        static void Hook(Action my,Action you)

        {

            IntPtr myAddress = my.Method.MethodHandle.GetFunctionPointer();

            IntPtr youAddress = you.Method.MethodHandle.GetFunctionPointer();

            *(int*)myAddress = *(int*)youAddress;

        }

    }

    class CsToD:MarshalByRefObject

    {

        public void My()

        {

            Console.WriteLine("My");

        }

        public void You()

        {

            Console.WriteLine("You");

        }

    }

}

 

可以看到,我明明调用的是CsToD类的My方法,但是输出结果告诉我们,实际调用的是You方法,说明挂钩成功了。

 

而如果我在挂钩之前已经调用过该方法,则挂钩失败:

 

        static void Main()

        {

            CsToD ctd = new CsToD();

            ctd.My();//挂钩之前先请用该方法

            Hook(ctd.My, ctd.You);

            ctd.My();//挂钩失败,仍调用My方法

            Console.ReadKey();

        }

 

这让我十分困惑,唯一能想到的理由是:

My方法的地址最初被存放在内存中的A地址,当My方法被调用后,又在内存中的B地址存了一份拷贝,以后再调用时,直接到B地址去读取My方法的地址。

这样的话,虽然我们修改了A地址中的数据,但并不影响My方法的调用。

 

当然,这只是我的猜测。

 

此路不通,我想了另一个方法——直接修改函数体,用经典的Jmp指令跳转。

但是,又失败了,因为该内存受保护,根本不能写:

 

        static void Hook(Action my, Action you)

        {

            IntPtr myAddress = my.Method.MethodHandle.GetFunctionPointer();

            IntPtr youAddress = you.Method.MethodHandle.GetFunctionPointer();

            *(int*)*(int*)myAddress = 0;//该地址根本不能写,赋什么值都无所谓

        }

 

本来以为修改一下保护属性就行了,结果连查询保护属性都失败,VirtualQueryVirtualProtect统统调用失败。

我也尝试用Marshal类,UnmanagedMemoryStream类,和WriteProcessMemory函数来修改内存,全部失败。

 

另外,静态函数无法挂钩。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值