Cryptography / Sea of Secrets CTF 2026

The Forgotten Vault

01 Nov 2026 · 1 min read

We get challenge.py, output.txt (a 64-byte hex ciphertext) and wordlist.txt (5,460 words). The vault is AES-128-ECB, and the key is MD5(password) where the password is a wordlist word,…

Crypto, Easy, 100 pts

Flag: HACKITUP{md5_k3y_d3r1v4t10n_w1th_p1n_m4ngl1ng_15_f4r_t00_w34k}

We get challenge.py, output.txt (a 64-byte hex ciphertext) and wordlist.txt (5,460 words). The vault is AES-128-ECB, and the key is MD5(password) where the password is a wordlist word, first letter capitalized, followed by a 2-digit PIN:

python
def format_password(word, pin):
    return f"{word.capitalize()}{pin:02d}"

def derive_key(password):
    return hashlib.md5(password.strip().encode("utf-8")).digest()

That is 5,460 * 100 = 546,000 possible passwords, and MD5 with no salt costs nothing, so the whole space can be searched. ECB doesn't matter here. We never need the block structure, only a way to tell a right key from a wrong one: after decrypting, check for valid PKCS#7 padding and the string HACKITUP in the plaintext.

python
for word in words:
    cap = word.capitalize()
    for pin in range(100):
        pw = f"{cap}{pin:02d}"
        key = hashlib.md5(pw.encode()).digest()
        pt = AES.new(key, AES.MODE_ECB).decrypt(ct)
        padlen = pt[-1]
        if 1 <= padlen <= 16 and pt.endswith(bytes([padlen]) * padlen):
            text = pt[:-padlen].decode(errors="ignore")
            if "HACKITUP" in text:
                print(pw, text)

The full script is solve.py. It finishes in a couple of seconds and finds word keystone, PIN 42, password Keystone42:

text
HACKITUP{md5_k3y_d3r1v4t10n_w1th_p1n_m4ngl1ng_15_f4r_t00_w34k}