cryptofreeeasy

Six Seven

metactf

Task: a custom stream cipher XORs the flag against a deterministic keystream whose only random input is a single byte from os.urandom(1). Solution: brute-force all 256 possible seeds and select the candidate whose decryption starts with the known prefix DawgCTF{.

$ ls tags/ techniques/
exhaustive_seed_brute_forceknown_plaintext_validationdeterministic_keystream_recovery

Six Seven — metactf (DawgCTF SP26)

Description

I heard something about streaming before in my crypto book, idk what twitch has to do with crypto, but I decided to add my favorite brainrot to it.

Files provided:

  • chall.py — encryption script
  • output.txt — ciphertext as hex

Source: https://github.com/UMBCCyberDawgs/dawgctf-sp26/tree/main/Six%20Seven

Challenge Source

from Crypto.Util.strxor import strxor from secrets import flag import os assert flag[:8] == b"DawgCTF{" def gen(start): return (((6 * 7) * (start - 6) * 7) + ((start * 6) - 7) * (start ^ 6)) % 255 def encrypt(message): start = os.urandom(1); key = start; for i in range(1, len(message)): key += gen(key[i-1]).to_bytes(1, "big") return strxor(key, message) ct = encrypt(flag) print("ct =", ct.hex())

Ciphertext (67 bytes):

9f2eadbd998e9ca1aab6bfbba9bf85afa9bf85a9bfb9a8bfaea985b3b485a3b5afa885a9aea8bfbbb785b9b3aab2bfa8a985ece3b8bcbfebe3eebbbceee9bceab9bea7

Summary

The custom stream cipher draws exactly one byte of entropy from os.urandom(1) as the seed. Every subsequent keystream byte is fully determined by the recurrence key[i] = gen(key[i-1]). Because the seed has only 256 possible values, the entire keystream has only 256 possible instantiations. We brute-force all of them and use the known plaintext prefix DawgCTF{ to recognise the correct one.

Recon

Reading chall.py:

  • The function gen is the brainrot joke — it packs "six" and "seven" (6, 7, 42) into an arithmetic expression and reduces mod 255. It is deterministic.
  • encrypt seeds the key with one random byte and then chains gen to produce as many keystream bytes as the plaintext has.
  • The plaintext is XORed against that keystream with strxor.

The cryptographic weakness is immediate: the random seed space is 2^8 = 256, not 2^128 or similar. No matter how complex gen looks, the total entropy of the keystream cannot exceed that of the seed.

...

🔒

Permission denied (requires auth)

Sign in to read this free writeup

This writeup is free — just sign in with GitHub to read it.

$ssh [email protected]