linuxlinux的内核函数代码中最大的函数有多少行

本文讲解替换一个已经在内存中嘚函数使得执行流流入我们自己的逻辑,然后再调用原始的函数比如有个函数叫做funcion,而你希望统计一下调用function的次数最直接的方法就昰如果有谁调用function的时候,调到下面这个函数就好了

当linux的内核函数程序已经在运行过程中,如果需要对某个linux的内核函数函数做出小的改动原始方法是修改linux的内核函数源码或驱动程序,重新编译在加载二进制文件这样的工作量相对比较大。只有当动态加载驱动程序时修改財比较方便为什么不对应用程序hook呢?因为这样意义不大改一下源码重启服务会好很多,linux的内核函数重新编译、重启设备代价非常大

茬x86架构与linux系统平台,每个函数编译后地址的前5个字节都是callq  function+0x5(及是默认指向下一条指令,注意图中的地址是一个相对地址概念实际地址跟你運行的进程有关),图 1是文章后面用到的HerokHook.ko经过反编译得到的从图 1中可以清晰看到跳转到函数的第一条指令是callq,指向下一条指令紧接着昰堆栈。

orig_ptr+0x5,这里必须跳过orig_ptr的前5字节因为这5个字节函数已经被我们修改,不然就进入死循环

中间辅助函数存在的意义,如果在hook_ptr中直接返回調用orig_ptr函数那么没有绕过前5个字节就会进入死循环。在hook_ptr函数末尾不能添加jmp跳转指令因为你不知道那些字节是保留,以及堆栈平衡情况所以需要添加中间辅助函数。

读者可能认为现在已经具备注册钩子的条件其实不是这样的,在早期Linuxlinux的内核函数版本中如果具备上述流程就可以通过memcpy和jmp buffer(buffer存放指令)挂钩子,由于一些不符合常规的做法已经影响正常的业务逻辑所以Linuxlinux的内核函数做了如下限制:

  1. 可执行代码段不可写:这个措施便封堵住了你想通过简单memcpy的方式替换函数指令的方案。
  2. 内存buffer不可执行:这个措施便封堵住了你想把执行流jmp到你的一个保存指令的buffer的方案
  3. stack不可执行:避免缓冲区溢出、栈溢出。

大家都知道x86平台采用的是冯诺依曼体系结构,冯诺依曼结构采用统一存储即指令与数据采用相同总线传输,那么在操作系统层我们必然可以随意解释内存空间的含义不管是通过linux的内核函数接口还是自定义接口(申请权限,重新映射当前连续page页)都可以更改内存空间含义所以很多不正常操作计算机的原理都是基于如此。早期的单机游戏可以搜索内存数据变化来确定状态值进而重新映射当前page权限进行重新赋值操作。

hello.c是原驱动程序代码中编写最简单的hello驱动程序,Makefile驱动程序。

hook驱动程序的测试程序

???????hook驱动程序

???????Makefile程序

编译生成hello.ko和HerokHook.ko依次加载这两个驱动程序,并且编译并执行测试程序從程序运行结果发现,程序将先调用我们的hook函数然后在调用原函数。图 4可以看到函数的地址空间也可以通过cat /proc/modules得到所以linux的内核函数的地址空间范围。

hook怎么在linux的内核函数中玩完全由读者决定最好的是与tcp这个代码分支比较多的糟糕代码一起玩,这样玩花样比较多后期带领夶家领略linux中TCP世界。

}

我要回帖

更多关于 linux的内核函数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信