Kernel Pwn Heap UAF and Struct cred
UAF overwrite ptr
和用户态一样, 控持程序流的一个最有效的方法就是覆盖函数指针. 在用户态, 我们可能会去覆盖一些 hook 函数指针, 或者是 FILE vtable 的指针. 在内核态也是一样的. 下面会结合例题来介绍一些可以利用的结构体中的函数指针.
例题 CISCN_2017 - babydriver
检查启动脚本和 init, 仅开启 smep, kallsyms 可读, 显示 dmesg. 加载了一个 babydriver.ko 到 /dev/babydev.
检查 ko 的保护, 只开启了 NX. 设备注册了 open, close, read, write, ioctl, open 的时候会 kmalloc 一个 chunk, 指针在全局变量上. ioctl 里可以重新 kmalloc 一个任意大小的 chunk, 覆盖全局变量上的指针. read 和 write 正常读写. close 的时候 kfree, 但是没有将指针置零. 由于指针是在全局变量上, 所以我们打开两次设备, 申请一块我们可以控制大小的空间, 关闭一次设备, 将其释放, 这样没有关闭的那个还可以进行读写操作, 也就是 UAF.
cred
kernel 4.4.72 时, cred 结构体没有专门的一个 kmem_cache (slub allocator) 来分配. struct cred 大小是 0xa8, 会使用 kmalloc-192 这个 kmem_cache 来分配. 而我们知道, cred 中保存了 uid, gid, 等, 如果可以改变这些, 那么就可以成功提权.