关于 kernel-RW Any Memory 的学习总结
通过 2019STARCTF hackeme
这道题目的学习,了解到了在内核中内存具有任意地址读写的能力后,可以利用的手法。
前置知识
modprobe
是一个 Linux
程序,用于在 Linux
内核中添加或移除一个可加载内核模块,该程序的路径是内核全局变量,默认为 /sbin/modprobe
,存在在内核符号 modprobe_path
下(此处内存有可写权限)。
当执行的文件类型为系统未知的类型时(也就是未知的文件魔术头),将通过 modprobe_path
来执行 modprobe
程序。需要注意的是,modprobe_path
中存储的路径并不会被判断是否正常,无论路径指向的是哪个文件,都会将其执行,因为系统仍然处于内核模式,所以是以 root
权限执行的目标文件,如果目标文件是我们编写的 shell
脚本,那么就相当于我们具有了 root
权限下的任意执行命令的能力。
因此如果有任意地址读写的能力,可以考虑覆盖 modprobe_path
,它比起调用commit_creds(prepare_kernel_cred(0))
更方便。
题目是 2019STARCTF hackeme 链接:https://github.com/cc-sir/ctf-challenge/tree/master/2019%20STARCTF%20hackme
逆向分析
通过下面的 _kmalloc
函数,可以分析出来 v19
是 size
而程序最开始有一个 copy_from_user
函数, copy
了 32
个字节的数据,正好是可以控制从 v17
开始到 v20
,考虑到上面 v19
是个 size
,我们可以猜测这四个变量都是一个结构体中的成员变量
通过这三行代码,可以猜测出来 v17
是一个 index
,其决定了申请出来堆块的地址放到 pool
数组的哪个位置( pool
数组就是来存放申请的堆块地址的)
这里将 v18
中的数据 copy
到了刚刚申请的堆块中,所以我们判断 v18
是 data_ptr
程序中的 v20
,刚开始看感觉很奇怪,具体啥作用也说不上来,因为 v4
已经是堆地址了,所以加上的 v20
我们姑且称之为 offset
四个变量名字确定之后,开始分析程序
delete
首先是 delete
部分(如上),发现这个 kfree()
很奇怪,因为 IDA
生成的伪代码看不到参数,溯源一下汇编发现 kfree
的参数其实就是 v14
(如下)
add
这个 add
部分可以发现 v12[0]
存放的是申请的 chunk_addr
,v12[1]
存放的是 size
,而 v12
本身就是 pool[2*index]
数组的地址,因此 chunk_addr
和 size
都记录在了 pool
数组中。通过 copy_from_user
函数向堆块中写入数据。
show
如上图所示, v5[1]
是 idx
对应堆块的 size
,这里的 offset+size
只判断了是否小于 v5[1]
,但是忘记判断了 offset+size
要大于 0
,所以这里的 offset
可以为负值,如果 offset
为负数的话,就导致了 offset+chunk_addr
拷贝的并不是当前指定的堆块中数据,可能是上一个堆块(低地址处)的数据,在这个 show
部分相当于任意地址读
edit
和上面 show
部分的漏洞一样, offset
值可以为负,从而可以任意地址写。
利用思路
slub
分配器是 Linux
内核中的一种内存分配器,其分配原理和 fastbin
原理类似,不过这里分配的堆块没有堆块头,也就是不加 0x10
,申请多少就是多少。
利用思路就是类似于 fastbin attack
的手法,数组索引向上(低地址)溢出,覆盖 fd
指针,从而实现任意地址申请和泄露。首先去泄露出内核基地址,然后加上 mod_tree
在内核中的偏移( mod_tree
在内核中,而里面有模块的指针,所以通常我们用它来泄露出模块的基地址)得到 mod_tree
地址,将其申请出来,泄露出模块的基地址。有了模块的地址,我们就可以将 pool
数组申请出来写入 modprobe_path
指针(该指针在内核中),用 edit
功能实现任意地址写(我猜测无法直接将 fd
指针控制为 modprobe_path
申请出来然后写入数据的原因是这样会破坏原本内核中的堆结构,如果利用 pool
数组任意写的话,可以将之前的堆结构再恢复)
上面的过程和做 glibc
堆题的思想基本一致,具体过程就不再赘述。
但我一直不明白为什么我的脚本会导致内核崩溃,就是执行完篡改 modprobe_path
都没有崩溃,可以看到下图是改写成功的
此时也没有崩溃,但是再返回到用户态调用函数或者再运行一次脚本,内核就会崩溃重启。
可能是我破坏了某些堆结构?可是我将之前全部破坏的指针又用任意地址写恢复了,emmm 因为是完全自己写的,所以可能是某个奇奇怪怪的地方搞坏了,不过最终思想是没问题的,因为确实是成功改掉了路径。
下面放一下我这个会崩溃的 EXP
… 也算记录一下
EXP
|
下面是 P4nda 师傅的脚本,我和他的思路差不多
|
参考文章
(47条消息) linux kernal pwn STARCTF 2019 hackme(一) 劫持modprobe_path_yongbaoii的博客-CSDN博客
XCTF - *CTF 2019 - hack_me | kileak
(´∇`) 天亮了~ 【KERNEL PWN】STARCTF 2019 hackme 解题思路 | p4nda’s blog
[原创]Linux Kernel Exploit 内核漏洞学习(4)-RW Any Memory-二进制漏洞-看雪论坛-安全社区|安全招聘|bbs.pediy.com (kanxue.com)