Kernel ROP basic
Kernel!主要是复现arttnba3大佬的博客*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。
ps:这道题是在老爹请客的那天做的,做的时候不断犯病且现在写博客的时候记忆几乎为零,所以重做一遍当作整理和回忆(最近记忆力真的好差不知道为什么/(ㄒoㄒ)/~~)
Kernel ROP-basic
整个提权的过程如下:
1 |
|
状态保存
先了解一下用户态和内核态的切换过程
用户态→内核态
- 切换GS段寄存器:swapgs切换GS寄存器,
- 保存用户态栈帧信息:记录rsp
- 保存用户态寄存器信息:通过 push 保存各寄存器值到栈上,以便后续“着陆”回用户态
内核态→用户态
恢复用户空间信息
swapgs指令恢复用户态GS寄存器
iretq恢复到用户空间,iretq栈布局如下
1
2
3
4
5
6
7
8
9
10
11|----------------------|
| RIP |<== low mem
|----------------------|
| CS |
|----------------------|
| RFLAGS |
|----------------------|
| RSP |
|----------------------|
| SS |<== high mem
|----------------------|
所以需要保存以下寄存器的值:eflags(状态标志寄存器)、cs(代码段寄存器)、rsp和ss(栈段寄存器)
状态保存函数(使用内联汇编,编译时需指定参数-masm=intel)
1 |
|
拿root权限
通过构造ROP链执行函数commit_creds(prepare_kernel_cred(&init_task))或commit_creds(&init_cred)(老版本commit_creds(prepare_kernel_cred(NULL)))
返回用户态,拿shell
根据👆iretq栈布局,ROP链的构造如下:
1 |
|
例题:强网杯2018-core
启动初始化脚本分析
先看启动脚本,start.sh(更改过的):
1 |
|
启动不起来的时候改一下分配的内存
- 开启了KASLR保护(地址随机化)
打包解包相关命令
解包命令:
1
cpio -idmv < core.cpio
打包命令
1
find . | cpio -o --format=newc > ../../core.cpio
查看init文件
1 |
|
- kptr_restrict
- 0:root和普通用户都可以读取内核符号地址(/proc/kallsyms接口)
- 1:root用户有权限读取, 普通用户没有权限
- 2:内核将符号地址打印为全0, root和普通用户都没有权限
- 但将kptr_restrict置为0还是不能读取内核符号地址,还需要将perf_event_paranoid置0
更改后的init脚本(需要查看函数地址以便进行调试)如下
1 |
|
- 开始时内核符号表被复制了一份到/tmp/kalsyms中,利用这个我们可以获得内核中所有函数的地址
- core.ko就是存在漏洞的内核模块
- 改变权限前设置了定时关机poweroff -d 120 -f,调试的时候可以把时间改长(注释掉会启动不了,我也不知道为什么)
exp
编译指令:
1 |
|
分析过程就不写了,大佬博客里都有,只贴一个exp
1 |
|
跟踪调试
跟踪一下rop链执行的过程(最好每一步都打一个断点,内核态进入用户态的时候ni会直接继续执行)
start.sh中的kaslr选项改为nokaslr才是关闭地址随机化!!!
调试内核时的.gdbinit:
1 |
|
内核态:开始执行ROP链
栈布局
内核态执行用户态函数:进行提权
内核态:执行swapgs和iretq
用户态:拿shell
Kernel ROP basic
http://akaieurus.github.io/2023/08/03/Kernel-ROP-basic/