TexSaw2025 Who‐Made‐This‐Anyway writeup - Pez1181/CTF GitHub Wiki
🧩 Challenge: "Ciphers Through Time"
Category: Cryptography
Vulnerability: Misattributed historical cipher (Vigenère)
Protection Bypassed: Polyalphabetic substitution
🔍 Recon
The challenge description gave us an immediate historical hint:
"Giovan Battista Bellaso introduced this polyalphabetic substitution cipher in his 1553 book..."
This is a dead giveaway for the Vigenère cipher, often incorrectly attributed to Blaise de Vigenère, but first published by Bellaso.
A .txt
file was provided, containing the ciphertext:
GMCAIVQOQYMDMRAWSRLTDXGFHHAKXEWKARAXKNPMSLZANWXLXIJWAXKIP...
🔬 Vulnerability Analysis
This was a textbook example of a Vigenère cipher: a polyalphabetic substitution cipher where each letter of the plaintext is shifted by a different Caesar cipher based on a repeating key.
Our first task was to identify the key length. We used:
- Index of Coincidence (IC) graphing to find periodic spikes
- Friedman's test to mathematically estimate the key length, which gave us ≈ 5
Multiple lengths (4–8) were explored with frequency analysis and brute-force on common shifts, under the assumption that each column of the ciphertext corresponds to Caesar-shifted English.
🎯 Exploit Strategy
- Brute-force candidate keys of likely lengths (6, 5, 8), using top 3 letter frequencies per column.
- Search for
texsaw{...}
in each decrypted candidate. - Fallback scoring using a list of common English trigrams (
THE
,AND
, etc.) to rank outputs even if flag format didn’t appear.
The best-scoring decryption (key = SAWTEX
) produced readable, enthusiastic plaintext:
OMG HEY YOU FIGURED OUT THE CIPHER ... THE FLAG IS EXAMPLESPOILERFREETEXT
🧪 Example Code
def vigenere_decrypt(ciphertext, key):
decrypted = []
key = key.upper()
for i, c in enumerate(ciphertext):
shift = ord(key[i % len(key)]) - ord('A')
dec = chr((ord(c) - shift - ord('A')) % 26 + ord('A'))
decrypted.append(dec)
return ''.join(decrypted)
print(vigenere_decrypt(ciphertext, "SAWTEX"))
✍️ Final Notes
This challenge was a fun blend of classical crypto with some hands-on frequency analysis. Vigenère ciphers remain popular in CTFs due to their balance of history, logic, and brute-force resistance (until they're not).