题目分析
这道题依旧是一道kernel的堆题,题目很简单这里简单分析一下
1 | __int64 __fastcall hackme_ioctl(__int64 a1, unsigned int a2, __int64 a3) |
1 | 00000000 arg struc ; (sizeof=0x20, mappedto_4) ; XREF: hackme_ioctl/r |
下面是分析出来的结构体,可以看到题目实现了四个较为基本的功能,增加堆块,删除堆块,修改堆块,读取堆块。
漏洞分析
这里需要注意的对于读写的时候检测offset的方式是 offset+size<(unsigned __int64)size
这里可以看出来存在向上溢出任意地址的读和写。
kernel使用的堆分配机制是Buddy System和Slab分配器。而Slab分配器是类似于ptmalloc中的fastbin。kmem_cache_cpu中的freelist指向一个slab中第一个空闲的object,接着object存在指针指向后面空闲的object。而这个指针是很类似于fastbin,我们如果修改的话可以实现任意地址分配堆块。
modprobe_path利用原理
首先,什么是modprobe呢?根据维基百科的说法:“modprobe是一个Linux程序,最初由Rusty Russell编写,用于在Linux内核中添加一个可加载的内核模块,或者从内核中移除一个可加载的内核模块”。也就是说,它是我们在Linux内核中安装或卸载新模块时都要执行的一个程序。该程序的路径是一个内核全局变量,默认为/sbin/modprobe
modprobe的路径, 默认是/sbin/modprobe, 存放在内核本身的符号modprobe_path下, 同时,它位于一个可写的内存页中。我们可以通过读取/proc/kallsyms得到它的地址
其次,当我们执行的文件的类型是系统未知的类型时,将执行modprobe程序(其路径存储在modprobe_path中)。 更准确地说,如果我们对文件签名(又称魔术头)为系统未知的文件调用execve()函数时,它将调用下列函数,并最终调用modprobe
do_execve()
=>do_execveat_common()
=>bprm_execve()
=>exec_binprm()
=>search_binary_handler()
=>request_module()
=>call_modprobe()
所有这些调用最终将执行下面的代码:
1 | static int call_modprobe(char *module_name, int wait) |
在这篇文章中 kernel pwn内存任意读写提升权限[2] 提到了call_usermodehelper函数,这个函数可以在内核中直接新建和运行用户空间程序,并且该程序具有root权限,因此只要将参数传递正确就可以执行任意命令。然而这个函数的定义可以看出来也是调用了call_usermodehelper_setup和call_usermodehelper_exec,所以猜测这一函数也可以达到一样的效果,结果也证明事实确实如此
1 | int call_usermodehelper(char *path, char **argv, char **envp, int wait) |
利用思路
所以我们的思路就是覆盖掉modprobe_path值为我们期望的值即可。
那么首先还是需要泄露地址,这里泄露堆地址就不再提了,存在向上任意溢出所以随便怎么泄露都可。
内核基址的读取需要一点猜测的成分在,可知0
号内存0xffff88800017a500
之前是已经在用的系统块,那么一定存在一些内核的指针。
可以看到这上面确实存在一个固定函数地址,所以可以跟他计算出基地值。
虽然我们可以直接泄露出来modprobe_path的地址,并且实现任意分配堆地址分配到指定位置,但是这样会破坏很多周围的数据,我们的想法肯定是值修改modprobe_path的值,所以我们还需要进一步利用。接下来的思路就是将堆块分配到pool上,那么我们就可以篡改pool上的堆指针为modprobe_path的地址,那我们就可以只修改他的值了,那么现在的问题是怎么获取到pool的值呢?
在mod_tree内存的附近处会存留驱动的地址
所以我们可以任意堆分配到这里然后泄露出驱动地址,紧接着任意堆分配到pool最后修改pool中的指针为modprobe_path地址,最后修改modprobe_path的值即可
综上,exp
1 |
|
当然其实在劫持到pool这一步也是可以直接使用 WCTF 2018 klist 这道题的利用方式,利用堆溢出泄漏出cred然后修改cred结构体即可,因为这道题目的漏洞相对来说比较严重,所以ptmx劫持栈什么的都是可以的。这篇文章主要是记录没有遇到过的利用方法。
参考链接:http://p4nda.top/2019/05/01/starctf-2019-hackme/#%E6%9D%83%E9%99%90%E6%8F%90%E5%8D%87