moectf2020 write up for rop1
前言
第一次开始尝试ROP,还真是一门神奇的技术呢Or2…
0x00.什么是ROP
ROP即为Return-Oriented Programming ——返回导向编程, 是一种可以用来绕过现代操作系统的各种通用防御(比如内存不可执行和代码签名等)的高级的内存攻击技术。
其主要思想是在栈缓冲区溢出的基础上,利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程。所谓 gadgets 就是以 ret 结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,方便控制程序的执行流程。
0x01.安全检查
首先在Linux下使用checksec
指令分析,发现其开启了栈不可执行保护
0x02.逆向分析
将程序拖入IDA分析,发现存在gets
函数,很明显存在栈溢出
0x03.漏洞利用
我们尝试将断点下在call _gets
,即0x40087f
的地以计算偏移量
1 | gdb |
由lea rax, [rbp-0x80]
我们可以看到该字符串为基于rbp的索引,故其相对于返回地址的偏移即为0x80+8
,也就是128个字节再加上8字节的rbp,之后就是函数的返回地址
因此我们构造的payload基础模型应当是:
1 | target_addr = p64(addr_of_target) |
然后我们就应该开始寻找需要用的gadget(程序小片段)了
一般来说只要找到system("/bin/sh")
就可以getshell了
然而我们不难看出,程序中虽然存在着system函数,但是却是system("eqqie")
。。。
尝试了一下eqqie师傅并没有设置额外的eqqie
命令,因此很明显我们不能直接返回到这个函数的地址上
但是这也告诉我们有system函数
的gadget,接下来只需要再找到/bin/sh
字符串就可以凑出system('/bin/sh')
我们很容易在.data
段找到"/bin/sh"
那么我们只需要先在rdi寄存器
内写入"/bin/sh"
的地址再调用system函数即可getshell
但是我们直接找似乎找不到pop rdi
别慌www,在IDA内我们可以找到一段指令是
1 | pop r15 |
按下D
展开变成数据
再按下C
变成指令
得到指令:
1 | pop rdi |
于是我们就成功得到了改变rdi寄存器的gadget的地址
接下来我们就可以构造payload了
1 | from pwn import * |
连接服务器,使用我们的payload来getshell
得到flag
1 | moectf{67d14388-9052-4182-869c-5e5f0cdac4e5} |
注:也可以使用工具
ROPgadget
来寻找gadgetLinux下,上面寻找gadget的步骤也可以如下:
1 ROPgadget --binary rop1 --string '/bin/sh'
1 ROPgadget --binary rop1 --only 'pop|ret'
moectf2020 write up for rop1
http://meteorpursuer.github.io/2020/11/26/moectf2020 write up for rop1/
1.RWCTF2023体验赛 write up for Digging into kernel 3
2.utctf2021 write up for 2Smol
3.minilctf2020 write up for easycpp
4.moectf2020 write up for baby canary
5.moectf2020 write up for baby migration
6.GWCTF 2019 write up for xxor
7.dmctf2020 write up for re4
8.moectf2020 write up for rop2