首页
社区
课程
招聘
分享一款自己写的linux kernel inline hook引擎
2022-12-10 17:16 20820

分享一款自己写的linux kernel inline hook引擎

2022-12-10 17:16
20820

Linux Kernel Inline Hook

1. 项目地址

https://github.com/stdhu/kernel-inline-hook

2. 项目介绍

该内核模块是一个支持不同架构的linux内核inline hook模块。 用于inline hook linux 内核函数。 该模块主要可用于在调用某个内核函数之前或之后插入自定义代码,实现类似函数监控的功能。

3. 支持情况

  1. 调用原函数之前的回调 -> 调用原函数 -> 调用原函数之后的回调 -> 返回到正常流程
  2. 调用原函数之前的回调 -> 调用原函数 -> 返回到正常流程

4. 限制

该模块目前支持的架构:

  1. x86 (测试通过)
  2. x86_64 (测试通过)
  3. Arm (arm模式测试通过但是thumb模式没有进行测试)
  4. Arm64 (测试通过)

该模块目前支持hook的函数情况:

  1. 目前支持hook参数为8个及8个以下的内核函数

5. 额外功能

  1. 可以在前回调中修改调用原函数的参数
  2. 可以在前回调中获取调用原函数的参数,作相关的验证
  3. 可以在后回调中查看原函数的返回值,也可以修改原函数的返回值

6. 构建

  1. 正常构建先make再insmod加载模块
  2. 如果要在x86架构的机器上构建arm架构下的内核模块:make ARCH=arm64 or arm CROSS_COMPILE=交叉编译工具链
  3. 如果要添加hook函数,需要在Makefile中添加相应的.o文件路径,在install/p_install中添加相应的头文件,在hook文件夹中添加相应的文件,并在p_lkrg_main.c中添加对应的信息

7. 注意

  1. 如果内核版本大于5.7.0,加载模块时需要传入参数。 例如:insmod hook_engine.ko kallsyms_lookup_name_address=0xffffffc0100d4dc8
  2. 如果钩子函数很多,卸载的时候系统会卡顿一会,因为在等待内存释放,才会进行卸载。

8. 示例

hook函数结构示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//普通函数
static struct p_hook_struct p_generic_permission_hook={
    .entry_fn=p_generic_permission_entry, //前回调函数地址
    .ret_fn=p_generic_permission_ret, //后回调函数地址
    .name="generic_permission", //函数名称
};
 
//系统调用表中的函数
static struct p_hook_struct p_generic_permission_hook={
    .entry_fn=p_generic_permission_entry,
    .ret_fn=p_generic_permission_ret,
    .name="__x64_sys_read",
    .sys_call_number=__NR_read //系统调用号
};

回调函数示例

1
2
3
//parameter1: 调用原函数后的返回地址
//parameter2: 调用原函数时寄存器的情况
int p_generic_permission_ret(unsigned long ret_addr,hk_regs * regs);

hook函数数组信息示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static const struct p_functions_hooks{
    const char *name;
    int (*install)(int p_isra);
    void (*uninstall)(void);
    int is_sys;
}p_functions_hooks_array[]={
    {
        "generic_permission",
        p_install_generic_permission_hook,
        p_uninstall_generic_permission_hook,
        0
    },
    {NULL,NULL,NULL,0} //数组结尾
};

9. 演示

图片描述

10. 使用场景

  1. 当linux内核不支持kprobe等自带的监控时,可以使用该项目进行函数监控

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2022-12-10 17:16 被榆一编辑 ,原因:
收藏
点赞7
打赏
分享
最新回复 (6)
雪    币: 3797
活跃值: (5570)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huangjw 2022-12-10 17:20
2
0
很实用的hook
雪    币: 29
活跃值: (5115)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
不吃早饭 2022-12-10 18:37
3
0

看了一下,其实就是用户空间的那套inlinehook,而且不支持pc relative指令。不知道有没有兴趣开一个项目,把substrate或者dobby之类的内核模块化的想法?把内存申请释放,权限修改等替换为内核函数

最后于 2022-12-10 19:48 被不吃早饭编辑 ,原因:
雪    币: 2604
活跃值: (2019)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Glaoro 2022-12-18 21:07
4
0
不错  感谢分享
雪    币: 12058
活跃值: (15384)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
pureGavin 2 2022-12-19 11:00
5
0
感谢分享
雪    币: 47
活跃值: (207)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lanliqiang 2023-1-18 09:42
6
0
代码写得很漂亮。作者很用心也费了不少心血,如果不是一点一点测试,不会有那么多的版本条件编译。棒棒的!!!作者绝对可以为之自豪。
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_mokddikt 2023-8-24 16:16
7
0
支持 redhat吗,执行到下面代码会崩溃
 new_target = vm_map_ram(&page, 1, -1,PAGE_KERNEL_EXEC);
    
    if (!new_target) {
        p_print_log("Remap address %p failed\n", target);
        return -EFAULT;
    } else {
        memcpy(new_target + ((unsigned long)target & (~ PAGE_MASK)), source, size);
        vm_unmap_ram(new_target, 1);
        flush_icache_range((unsigned long)target, (unsigned long)target + size);
        
        return 0;
    }
游客
登录 | 注册 方可回帖
返回