相当于结合了 Dirty PageTable 和 Dirty PageDirectory ,算是有一点点创新,姑且厚着脸皮命个名并称之为一个 “New Exploitation Technique” :)
Introduction
笔者偶然整出个品相算不错的 0day ,闲着无聊 exploit 一下 RHEL ,靠这个备战一下明年的 GeekPwn ,希望别被别人先报了 :p
对于 Linux Kernel,当我们有一个 oob write vulnerability
时,如何利用?
笔者想尝试开发一个不依赖内核的通用 exp,所以更青睐 data-only attack
其实这个问题 @arttnba3 已经在 D^3CTF2023 的 d3kcache 中给出了解答:用 oob write
制造 pipe_buffer->page
的 overlap 从而转化为 page uaf
但笔者实际环境中操作下来有点困难:难以理想控制页风水,使得改写 pipe_buffer->page
后刚好 overlap with 另一个 pipe 的 pipe_buffer->page
(也可能是菜😥)
如果这个 oob 的条件足够宽裕——允许使 oob offset 处递增 0x1000,Dirty PageTable 倒是可行,但在后半部分利用时面临着无法分配 sharing page
的问题:
- 一般的 Linux 发行版中
/dev/dma_buf/system
需要root
特权才能open
- 在 RHEL 的环境中关了
io_uring
也许还有其他笔者不知道的可用的 sharing page
,欢迎 dm 我😊
Technique
审视 Dirty PageTable
的流程,为什么需要 sharing page
:
- 因为
pte entry
映射的mmap
出来的一般的anonymous page
位于Movable
区域,而pte page
处于Unmovable
区域,将pte entry
递增 0x1000 只能使得其指向另一个anonymous page
- 而
sharing page
处于Unmovable
区域,便可以控制物理页排布使sharing page
与pte page
相邻,将pte entry
映射到sharing page
,递增pte entry
就能使其指向一个pte page
Dirty PageTable
将 pte page
作为 spray
以及 oob victim
的对象,如果 spray
的是 pmd page
呢?
触发一次缺页异常时,如果没有已有的 pmd
映射到这个地址,则会分配一个 pmd page
以及一个 pte page
,写对应位置的 pmd entry
以及 pte entry
以建立映射
每隔一个 pmd page
映射的范围触发一次缺页异常,从而分配大量的 pmd page
以及 pte page
,由于 pmd page
和 pte page
是交替分配的,那么大概率形成以下的物理页布局:

此时再修改 pmd entry
,能使其从原先指向的 pte page
到指向相邻的 pmd page
:

victim pmd entry
最终就会将 pte page
解析为可读写的 anon page
,类似于 Dirty PageDirectory ,我们可以从 victim pmd entry
地址读写 pte page
的内容,再从 victim pte entry
读写,从而获得任意物理地址读写原语 :)
Drawback
pmd page
和 pte page
是交替分配的,所以将 pmd page
喷到相邻 vuln obj
处的概率为 1/2
不过笔者的 0day 可以多次触发,因此可以一直尝试
由于尝试失败后会破坏内核的数据结构且无法恢复,因此取得了 root 之后的环境不太稳定,由于以上原因该 Technique 并不能算优秀
!!Warning!!
不要在真机中尝试以避免不可逆的后果
笔者在研究过程中就打崩过他的虚拟机:

看起来是文件系统坏了,而且重启无法恢复😱
还好笔者之前拍了快照,但还是丢失了 exp 的进度