3.2 ; FREQUENCY
Challenge Description
Two encrypted calibration reports recovered from NODE 07. The diagnostic system used to generate them was decommissioned in 2024 but never patched.
Files provided: calibration_report_A.bin, calibration_report_B.bin
Overview
Both files are AES-128-GCM encrypted with the same key and the same nonce. GCM is a stream cipher mode: the keystream is derived entirely from the key and nonce. Reusing a nonce means both plaintexts were XORed against an identical keystream. XORing the ciphertexts together cancels the keystream, leaving the XOR of the two plaintexts. The plaintext of Report A is recoverable from a legacy diagnostic endpoint left running on the SECRET tier. With one plaintext known, the other follows immediately.
Step 1: Parse the Files
Each file follows the format: [12 bytes nonce][ciphertext][16 bytes GCM tag].
def parse_bin(path):
data = open(path, "rb").read()
return data[:12], data[12:-16], data[-16:]
nonce_a, ct_a, _ = parse_bin("calibration_report_A.bin")
nonce_b, ct_b, _ = parse_bin("calibration_report_B.bin")
print(nonce_a.hex()) # 4543484c4f4e303100000000
print(nonce_b.hex()) # 4543484c4f4e303100000000
# Nonces are identical: vulnerability confirmed
Note that the GCM authentication tags will not verify for either file since we do not have the key. In this attack that does not matter, authentication is irrelevant once we are working directly with the ciphertext XOR.
Step 2: Cancel the Keystream
In AES-GCM: ct = pt XOR keystream. Since both files used the same keystream:
ct_a XOR ct_b = (pt_a XOR ks) XOR (pt_b XOR ks) = pt_a XOR pt_b
min_len = min(len(ct_a), len(ct_b))
ct_xor = bytes(a ^ b for a, b in zip(ct_a[:min_len], ct_b[:min_len]))
ct_xor now contains the XOR of the two plaintexts across the overlapping region.
Step 3: Recover Report A Plaintext
The challenge description says the diagnostic system was decommissioned but never
patched. The SSRF response from 3.1 ; PHANTOM NODE included a legacy_endpoint
field pointing to /api/v1/diagnostics. Fetching it returns the plaintext of
the most recent NOMINAL calibration report:
curl -b cookies.txt https://echelon.two-shoes.org/api/v1/diagnostics
Save the response to a file:
curl -b cookies.txt https://echelon.two-shoes.org/api/v1/diagnostics -o report_a_plain.txt
This is the full plaintext of calibration_report_A.bin.
Step 4: Recover Report B
With Report A's full plaintext known, XOR it against ct_xor to recover Report B:
known_a = open("report_a_plain.txt", "rb").read()
recovered_b = bytes(a ^ b for a, b in zip(ct_xor, known_a[:min_len]))
print(recovered_b.decode())
Report B is the anomaly report from 2026-03-14T03:17:22Z. It contains an access certificate and operator private key archived during the incident, followed by the flag.
Key Takeaways
GCM nonce reuse is a catastrophic failure mode. Unlike CBC where reuse leaks only the XOR of the first blocks, GCM nonce reuse exposes the entire XOR of both plaintexts across their shared length. Additionally, the GCM authentication tag is computed using the nonce, meaning a nonce-reuse attacker can also forge authenticated ciphertexts without knowing the key (Forbidden Attack; https://eprint.iacr.org/2016/475.pdf).
The decommissioned diagnostic endpoint is exactly the kind of legacy surface that makes nonce reuse exploitable in practice, the system was patched against new vulnerabilities but the old plaintext oracle was never removed.
The cert and operator key recovered from Report B are required for 3.3 ; COLD CASE.
noncechalant
This challenge was the catalyst for noncechalant, a crib drag tool built during the event to assist with exactly this attack. noncechalant handles GCM, ChaCha20, AES-CTR, RC4, and several other stream cipher modes, with interactive byte-by-byte recovery, beam search for natural language plaintexts, wordlist-guided token scoring, and one-shot recovery via known plaintext. For this challenge specifically, the --known-a flag recovers Report B in a single pass once you have the diagnostics endpoint output. The nonce reuse attack is the same regardless of the tool, but noncechalant makes the mechanics visible.
Flag
ECHELON{0racles_d0nt_lie}