arrow_backUS Cyber Games 2026
Cryptomedium

Noncesense

by Pavel Knespl (capyplivl)

The encryption oracle uses AES-CTR with a fixed key and nonce for every call, so the flag and any chosen plaintext are encrypted under the same keystream. That keystream reuse is a two-time pad, broken by XOR.

Solve

  1. The handler prints the encrypted flag, then encrypts one plaintext you send. Since the keystream K is identical for both, sending an all-zero plaintext of len(enc_flag) makes the returned ciphertext equal K directly, so FLAG = enc_flag XOR K.
  2. solve.py (in the challenge dir) implements this with a local self-test:
from pwn import *
import sys

io = remote(sys.argv[1], int(sys.argv[2]))
io.recvuntil(b'Encrypted flag: ')
enc_flag = bytes.fromhex(io.recvline().strip().decode())
io.sendline(b'00' * len(enc_flag))
io.recvuntil(b'Ciphertext: ')
ks = bytes.fromhex(io.recvline().strip().decode())
print(xor(enc_flag, ks).decode())
  1. Run against the live instance: python3 solve.py HOST PORT. The XOR yields the flag.

Flag: SVIBGR{3t_7u_k3y$7r34m}