UMass CTF 2026 - The Accursed Lego Bin
I dropped my message into the bin of Legos. It’s all scrambled up now. Please help.
Initial Analysis
The challenge provides a Python script encoder.py and
its corresponding output output.txt. The goal is to recover
a flag that has had its bits scrambled based on a seed derived from a
hardcoded string.
Seed Generation
The script uses RSA to “encrypt” the string
"I_LOVE_RNG":
1 | text = "I_LOVE_RNG" |
The RSA_enc function calculates
seed = pow(plain_num, e, n). In the main
function, it then calculates enc_seed = pow(seed, e, n).
Since e = 7 is very small and
the plaintext "I_LOVE_RNG" is short, the value me (where m is the integer representation of
the text) is much smaller than the 4096-bit RSA modulus n. This means
pow(m, e, n) is simply me without any
modular reduction.
Bit Shuffling
1 | flag_bits = get_flag_bits(flag) |
The flag is converted into a list of bits and shuffled 10 times using
Python’s random.shuffle. Each shuffle is seeded with a
value derived from the seed identified above.
Solution
To recover the flag, we follow these steps:
- Recover the Seed: Calculate the integer value of
"I_LOVE_RNG"and raise it to the 7th power to get theseed. We can verify this againstenc_seedin the output file by checking ifseed**7 == enc_seed. - Reverse the Shuffle: Since
random.shuffleis deterministic when the seed is known, we can track how the positions change. Instead of shuffling the bits directly, we shuffle a list of indices[0, 1, 2, ..., len(bits)-1]. - Reconstruct the Flag: After 10 shuffles, the index list tells us where each original bit ended up. We map the bits from the encoded flag back to their original positions and convert the bit array back into a string.
Solution Script
1 | import random |