Quantum Scrambler – picoCTF Walkthrough
Challenge: Quantum Scrambler (picoCTF)
Description:
We invented a new cypher that uses “quantum entanglement” to encode the flag. Do you have what it takes to decode it?
Hints:
- Run
eval
on the cypher to interpret it as a Python object- Print the outer list one object per line
- Feed in a known plaintext through the scrambler
Observation once connected
When I connected to the VM running the challenge, I got something like this:
1
2
3
4
5
[[‘0x70’, ‘0x69’],
[‘0x63’, [], ‘0x6f’],
[‘0x43’, [[‘0x70’, ‘0x69’]], ‘0x54’],
…
]
This looked very weird at first — some kind of nested Python list where every value was either a hexadecimal character, a list, or both. Definitely not your average cipher.
Thought Process
Step 1: Spotting the Hex
The output was full of strings like ‘0x70’, ‘0x69’, etc.
I knew immediately these were ASCII codes in hexadecimal. For example:
1
chr(int('0x70', 16)) == 'p'
This means that the flag characters are hidden inside this tree, in hex form.
Step 2: Realising it’s a Tree
1
2
3
['0x70', '0x69']
['0x63', [], '0x6f']
['0x46', [[...], [...]], '0x7b']
This made me realize: each element is a node in a tree, and the leaf nodes are hex values.
Step 3: Saving the Output
When I ran the challenge and saw that huge nested structure dumped into the terminal, I copied the full output and saved it locally:
1
2
nano output.txt
# (Paste everything from the challenge)
This gave me a static file to experiment on locally.
Step 4: Evaluating the Structure
The hint mentioned to use eval() - so I did:
1
2
with open("output.txt") as f:
data = eval(f.read())
I then printed the first few lines to confirm:
1
2
for item in data[:5]:
print(item)
This confirmed that the structure was exactly what I saw on the server: deeply nested lists containing hex strings and more lists.
Step 5: Understanding the Scramble
Before jumping into reversing the actual flag, I wanted to understand what the scrambler was doing. So, I modified the get_flag() function in quantum_scrambler.py to return a simple test string like “abcde”
1
2
3
4
5
6
def get_flag():
test = "abcde"
hex_flag = []
for c in test:
hex_flag.append([str(hex(ord(c)))])
return hex_flag
This produced:
1
[['0x61'], ['0x62'], ['0x63'], ['0x64'], ['0x65']]
After running the scrmabler() function on it, I observed the following:
1
[['0x61', '0x62'], ['0x63', [], '0x64'], ['0x65', [['0x61', '0x62']]]]
- The list shrinks as elements are merged.
- Earlier items absorb later ones.
- The scrambler appends a breadcrumb slice (A[:i-2]) into the current item.
- The final result is a tree-like object with nested structures.
Dissecting quantum_scrambler.py
The key logic in the scrambler was:
1
2
3
4
5
6
7
def scramble(L):
A = L
i = 2
while (i < len(A)):
A[i-2] += A.pop(i-1)
A[i-1].append(A[:i-2])
i += 1
What This Does:
- Merge A[i-2] += A.pop(i-1) – combines two elements, shrinking the list
- Track: A[i-1].append(A[:i-2]) – logs a reference to the previous structure
- The result is a deeply nested list that contains all transformation history
Building unscramble.py - Reversing the Process
Knowing how the scramble worked, I wrote the reverse logic to:
- Walk backwards from the end of the list.
- Pop off the “breadcrumb” log.
- Reconstruct the original values from the merged item.
- Insert the split pieces back in
Here is my unscramble.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import sys
def unscramble(L):
A = L
i = len(A) - 1
while i >= 2:
prefix = A[i-1].pop()
n = len(A[i-1])
original = A[i-2][-n:]
A[i-2] = A[i-2][:-n]
A.insert(i-1, original)
i -= 1
return A
def main(file):
scrambled_flag = eval(open(file, 'r').read())
flag_hex = unscramble(scrambled_flag)
for c in flag_hex:
print(chr(int(c[0], 16)), end='')
if __name__ == '__main__':
main(sys.argv[1])
Output
Running the script:
1
python3 unscramble.py output.txt
Returned:
1
picoCTF{python_is_weirdaa2ca6fc}
Lessons Learned:
- How to analyse recursive list manipulation in Python
- Feeding a unknown plaintext is a powerful strategy to understand a black-box logic
- Reverse engineering does not require reverse encryption - sometimes it is just smart data transformation
- Strucure carries more meaning than it first appears
Hint Reflection
1
2
3
4
5
6
7
8
"Run eval on cypher..."
- Essential for treating the object as Python
"Print the outerlist one object per line..."
- Helped visually understand the tree structure
"Feed in a unknown plaintext..."
- Cruicial for revealing how scrambling actually works
Files
Download unscramble.py Download ouput.txt
Summary
The Quantum Scrambler challenge was about decoding structure, not cryptography. With a clear test input, a careful read of the scramble logic, and a methodical reversal, I was able to extract the flag cleanly. This one sharpened my skills in Python, recursion, and debugging by dissection.