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
- The handler prints the encrypted flag, then encrypts one plaintext you send. Since the keystream
Kis identical for both, sending an all-zero plaintext oflen(enc_flag)makes the returned ciphertext equalKdirectly, soFLAG = enc_flag XOR K. 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())
- Run against the live instance:
python3 solve.py HOST PORT. The XOR yields the flag.
Flag: SVIBGR{3t_7u_k3y$7r34m}