0x00 前言
咕了许久,重拾本就会的不多的pwn,发现不太顺手了。
之前也接触过ORW的题目,但没去深入的了解其细节,只抄了个EXP拿了个flag就完事了。
今天用这道题目详细记录一下ORW类型的题目。
题目原出处是在pwnable.tw, BUUCTF上面也有。
0x01 题目分析
保护与main函数
1 | Arch: i386-32-little |
主函数逻辑也特别简单,读取我们的输入存到变量shellcode处,然后执行shellcode()
。
如果忽视掉第3行的orw_seccomp()
那么就可以直接向程序输入一段shellcode就能getshell。
seccomp
第3行的内容也便是ORW这类题目的重点所在。
关于seccomp:
seccomp 是 secure computing 的缩写,其是 Linux kernel 从2.6.23版本引入的一种简洁的 sandboxing 机制。在 Linux 系统里,大量的系统调用(system call)直接暴露给用户态程序。但是,并不是所有的系统调用都被需要,而且不安全的代码滥用系统调用会对系统造成安全威胁。
seccomp安全机制能使一个进程进入到一种“安全”运行模式,该模式下的进程只能调用4种系统调用(system call),即 read(), write(), exit() 和 sigreturn(),否则进程便会被终止。
seccomp 简单来说就是一个白名单,每个进程进行系统调用(system call)时,kernal 都会检查对应的白名单以确认该进程是否有权限使用这个系统调用。这个白名单是用 berkeley package filter(BPF)格式书写的。
具体可以参考如下链接:
PS: 第一个博客里也讲到了这道题目是如何实现seccomp的了,是与prctl
有关。
PS: 而我第一次遇到ORW的题目是在极客大挑战2019 的 babyshellcode和Not bad这俩题目,这俩题目都是通过seccomp_rule_add
来实现seccomp的。
也就是说,这个程序相当于禁用了system。
这段程序中,unk_8048640位置存储的即为“白名单”,通过这个白名单,可以看到这个程序允许的系统调用。
之前看到过一篇博文,有师傅手动把这个白名单提取出来了,但是我找不到博文链接了。
工具seccomp-tools
用工具seccomp-tools
能更直观更便捷的查看这个“白名单”。
安装seccomp-tools步骤(环境Ubuntu 16.04):
首先需要gem和ruby(版本>=2.4):
我用的阿里云的源,通过apt-get 安装的ruby版本是2.3,死活安不上2.4,Google了一番找到了安装方法:
1 | $ sudo apt-add-repository ppa:brightbox/ruby-ng |
然后sudo gem install seccomp-tools
即可。
终端执行命令$ seccomp-tools dump ./orw
即可查看“白名单”
绿色的即为允许的系统调用。
可以看到该程序可以进行open read write等系统调用。
解题思路
结合前面的分析,这道题目的解题策略可以确定为ORW即open、read、write,也就是先打开存放flag的文件,将其内容读取到某块缓冲区,然后通过write打印出来。
0x02 Do it!
关于系统调用
对于32位来说:
1 | 系统调用号:EAX |
对于64位来说:
1 | 系统调用号:RAX |
对于我们的ORW(32位)来说:
系统调用号:eax | Name | args1:ebx | args2:ecx | args3:edx |
---|---|---|---|---|
3 | sys_read | unsigned int fd | char *buf | size_t count |
4 | sys_write | unsigned int fd | char *buf | size_t count |
5 | sys_open | char __user *filename | int flags | int mode |
编写shellcode
首先我们需要open,由于BUUOJ上面存放flag的文件名就叫flag,这也就为我们open提供了便利。
1 | //open(flag,0,0) |
这段汇编应该挺容易理解的,然后就没啥难点了…
同样还可以利用pwntools的shellcraft来构造,需要指明context.arch
,32位就i386,64位就amd64
1 | sh = shellcraft.pushstr('flag') |
0x03完整EXP
1 | from pwn import * |
这段EXP在BUUOJ上是可以打通的,如果想在pwnable.tw打通,需要修改一下 open 那块的汇编,应该向ebx传入flag文件的绝对路径。