$ cd ..

impossible-rot13

2026-09-27

seedlingctf2026 · crypto

Utilizing the fact that the flag only contains lowercase english words, put the randomized flag into a monoalphabetic decoder.

cryptorot13

writeup

Challenge

Decrypt a rot13 encoded flag that uses a randomized alphabet

Files: server.py

TL;DR

Intended method is to use the fact that characters cannot repeat. I just plugged in the randomized flag into a decoder and then guessed what the flag was with the similarity of english words.

Recon

The challenge uses a monoalphabetic cypher, where I assumed it would have used the most used characters of the English Language. Therefore, I opted to use one of the substitution ciphers like this. At first it didn't make strings following typical English grammar conventions as the decoder would insert spaces, but after disabling that, it gave me something like: evenrandomness.... What remained was to just fix the spelling of the words, and was the actual string!

Solution

The key is to use the fact that a character in the plain alphabet cannot be mapped to itself. Then we just sample the flags repeatedly, until each index is left with one possible character. With 200 tries, to probability of finding all of the flags is actually < 1%, so this should be able to get the flag pretty quickly.

while True:
    # r = remote(HOST, PORT)
    r = process("./server.py")
    r.recvuntil(b"flag(rot13): ")
    ct = r.recvline().strip().decode()
    r.close()
    n += 1

    if seen is None:
        seen = [set() for _ in ct]
    for i, ch in enumerate(ct):
        seen[i].add(ch)

    cands = [set(ascii_lowercase) - s for s in seen]
    if all(len(c) == 1 for c in cands):
        break
    if n % 25 == 0:
        unresolved = sum(len(c) > 1 for c in cands)
        print(f"{n} samples, {unresolved} positions unresolved")

flag = "".join(c.pop() for c in cands)
print(f"{n} samples -> maple{{{flag}}}")