安卓内核定制开发笔记(三)系统调用Hook
安卓内核定制开发笔记(三)系统调用Hook
在上一篇文章中,我们已经探讨了对系统调用的简单Hook,但是在实际应用中,只是监控系统调用的出入参是无法满足需求的,我们预期得到一个类似于inline hook的功能,也就是在hook到调用的同时,可以对出入参进行修改。这一功能在用户态非常容易实现,与正向开发无异,但是内核态由于各种保护机制,无法直接修改用户态的内存,导致这一实现有些麻烦,可以参考看雪文章[原创]内核层偷天换日之hook openat进行文件重定向-Android安全-看雪-安全社区|安全招聘|kanxue.com
我们可以看到内核代码中对openat调用号的声明
int openat(int dirfd, const char __user *pathname, int flags, umode_t modex)
可以看到,关键的路径入参被const和__user修饰,这代表这是一个用户态的常量,而内核模块工作在内核态,与用户态是隔离的,内核策略也限制了内核态和用户态内存的互相访问,所以内核模块是无法直接修改这个参数的。
解决方案
为了解决这一问题,我们需要使用内核提供的函数,临时修改地址空间限制,使得内核态下可以临时操作用户内存,代码如下:
mm_segment_t old_fs = get_fs();printk("new_openat:%s ====> %s uid:%d\n", bufname, targetbuff, myuid);set_fs(KERNEL_DS);ret = real_openat(dirfd, targetbuff, flags, modex);set_fs(old_fs);
上述代码中的targetbuff为需要替换的路径地址,可以是一个内核态的变量,这样我们就能利用内核模块去实现一个最基础的内核级的IO重定向功能,当然如果只对openat做处理很容易造成重定向逃逸,我们可以仿照VA等产品对相关的调用号都进行hook,相关的调用号有readlinkat、execve、faccessat等,注意,这种方式不能直接应用于重打包,因为其生效的时间过早,并且直接操作了内核调用表,尽管可以限制hook的uid,也会导致系统无法定位到正确的base.apk
部署应用
做了那么多准备工作,模块最终还要部署使用,根据设备是否拥有root权限和具体需求,可以使用不同方式部署
1.有Root权限
可以直接用insmod动态加载编译好的内核模块,内核需要开启动态加载配置
2.没有Root权限
可以将模块直接编译进内核,随系统一起启动