jbczzz 发表于 2024-11-1 16:56

KernelPatchModule开发学习-编译kpm、如何进行内核hook

本帖最后由 jbczzz 于 2024-11-1 17:07 编辑

0x0 前言
随着安卓逆向研究已经开始进入内核时代,现在内核相关的开发软件和资料也是越来越多。最近发现apatch的kpm挺好用的,不依赖内核源码,编译也很方便,还有现成的几种内核hook方式。但是在学习的过程中发现目前相关资料还是比较少,于是想用文章记录一下自己的学习过程。
0x1 简介、环境
什么是KernelPatchModule?
官网的简介:一些代码在内核空间运行,类似于Loadable Kernel Modules(LKM)。此外,KPM提供在内核空间进行内联hook、系统调用表hook的能力。KPM 是一个 ELF 文件,可由 KernelPatch 在内核空间内加载和运行。
官方GitHub地址
https://github.com/bmax121/KernelPatch/tree/dev
环境、工具版本:
Ubuntu 22.04.2 LTS
gcc-arm-11.2-2022.02-x86_64-aarch64-none-elf.tar
GNU Make 4.3
0x2 编译
首先在官网下一份源码

我们这里只需要关心kpms里的例子是怎么写的
然后是在这下载GNU tools ,建议使用aarch64-none-elf,我之前使用linux自带的aarch64-linux-gnu编译出来无法正常使用。
https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads/11-2-2022-02进入/kpms/demo-hello这个目录下
export TARGET_COMPILE=$(yourPath)/aarch64-none-elf-
make

输出的.kpm就是编译出来的模块
在apatch里内核模块->右下角图标->加载->选择hello.kpm,加载成功后会显示

使用demsg|grep kp就能看到模块加载的信息

0x3 kpm代码的基本结构
需要关注的是这些地方
///< The name of the module, each KPM must has a unique name.
KPM_NAME("kpm-hello-demo");

///< The version of the module.
KPM_VERSION("1.0.0");

///< The license type.
KPM_LICENSE("GPL v2");

///< The author.
KPM_AUTHOR("AKI");

///< The description.
KPM_DESCRIPTION("KernelPatch Module AKI Test");

#define KPM_INIT(fn) \
    static mod_initcall_t __kpm_initcall_##fn __attribute__((__used__)) __attribute__((__section__(".kpm.init"))) = fn

#define KPM_CTL0(fn) \
    static mod_ctl0call_t __kpm_ctlmodule_##fn __attribute__((__used__)) __attribute__((__section__(".kpm.ctl0"))) = fn

#define KPM_CTL1(fn) \
    static mod_ctl1call_t __kpm_ctlmodule_##fn __attribute__((__used__)) __attribute__((__section__(".kpm.ctl1"))) = fn

#define KPM_EXIT(fn) \
    static mod_exitcall_t __kpm_exitcall_##fn __attribute__((__used__)) __attribute__((__section__(".kpm.exit"))) = fn

#endif
KPM_INIT(hello_init);
KPM_CTL0(hello_control0);
KPM_CTL1(hello_control1);
KPM_EXIT(hello_exit);

其中:
KPM_INIT(hello_init);   //kpm加载时调用的函数KPM_CTL0(hello_control0);//在apatch中传入参数调用的函数
KPM_CTL1(hello_control1);//在apatch中传入参数调用的函数
KPM_EXIT(hello_exit); //卸载kpm调用的函数
0x4 根据内核符号地址hook内核函数
以hook process_vm_rw为例子,这个函数在/ mm / process_vm_access.c。
首先需要找到函数原型,可以结合我上一篇还原内核符号的文章和那个查看内核符号的网站使用。
函数原型:
static ssize_t process_vm_rw(pid_t pid,
                           const struct iovec __user *lvec,
                           unsigned long liovcnt,
                           const struct iovec __user *rvec,
                           unsigned long riovcnt,
                           unsigned long flags, int vm_write) //5.4.210内核源码的函数原型
想要hook这个函数,首先在文件中按照原来的代码构建一个原型:
ssize_t (*process_vm_rw)(pid_t pid, const struct iovec __user *lvec, unsigned long liovcnt,
                     const struct iovec __user *rvec, unsigned long riovcnt, unsigned long flags, int vm_write) = 0;
使用kallsyms_lookup_name,在/kernel/include/kallsyms.h中,作用是寻找返回所查找的内核函数地址,找不到返回0。具体详见https://blog.csdn.net/weixin_45030965/article/details/132497956
查找内核符号地址:
process_vm_rw = (typeof(process_vm_rw))kallsyms_lookup_name("process_vm_rw");
进行inline hook,hook_wrapX,这个X代表的是需要几个参数,里面调用的是hook_wrap()。before是调用前执行的函数,after是调用后执行的函数:
hook_wrap8((void *)process_vm_rw, before, after, 0);
0x5 syscallHook
根据系统调用号hook内核函数,以例子中的__task_pid_nr_ns这个函数为例,这个内核函数在/kernel/pid.c
根据系统调用号进行hook,分两种function_pointer_hook和inline_hook,他们调用的方式都是类似的
#define __NR_openat 56
err = inline_hook_syscalln(__NR_openat, 4, before_openat_0, 0, 0);
err = fp_hook_syscalln(__NR_openat, 4, before_openat_0, 0, 0);

关于这个工具hook syscall的具体原理流程后续随缘更新,这里就只讲使用。
0x6 小结
如果想知道具体kpm是如何加载运行的话,需要先了解APatch是如何运行的,这个现在还在看kptools的源码,还是后续随缘更新,感兴趣的可以先看看https://bbs.kanxue.com/homepage-935696.htm这个大佬的文章。

debug_cat 发表于 2024-11-1 19:55

#define KPM_INIT(fn) \
    static mod_initcall_t __kpm_initcall_##fn __attribute__((__used__)) __attribute__((__section__(".kpm.init"))) = fn

在官方的hello demo中没有发现上面的代码,这用途是?

ytfrdfiw 发表于 2024-11-8 15:49

jyz20010903 发表于 2024-11-2 11:41
对抗设备环境检测、反调试、process_vm_readv检测之类的,能更方便的监控应用行为,辅助分析

一般android中这个hook的权限能获取到吗?即全局的hook是可行的吗?
这个是不是像您提的,当有调试来的时候,直接退出程序?
我不是太明白,感谢您的分享,解答。

ytfrdfiw 发表于 2024-11-1 17:39

请问一下楼主,android内核的hook一般是什么应用场景,感谢分享。

jbczzz 发表于 2024-11-1 17:53

ytfrdfiw 发表于 2024-11-1 17:39
请问一下楼主,android内核的hook一般是什么应用场景,感谢分享。

比如说对抗设备环境检测、反调试、process_vm_readv检测之类的,能更方便的监控应用行为,辅助分析

chuanyipai 发表于 2024-11-1 18:02

不错,学习一下

junxin 发表于 2024-11-1 18:55

学到了,感谢楼主

lmx352470462 发表于 2024-11-1 20:11


谢谢分享{:1_927:}

asd885522 发表于 2024-11-1 21:38

学到了,感谢楼主{:1_926:}

yan999 发表于 2024-11-2 10:44

学习下,感谢分享

jyz20010903 发表于 2024-11-2 11:41

ytfrdfiw 发表于 2024-11-1 17:39
请问一下楼主,android内核的hook一般是什么应用场景,感谢分享。

对抗设备环境检测、反调试、process_vm_readv检测之类的,能更方便的监控应用行为,辅助分析
页: [1] 2
查看完整版本: KernelPatchModule开发学习-编译kpm、如何进行内核hook