$ cat writeup.md…
$ cat writeup.md…
umdctf
Task: a Python jail executes attacker input only if every distinct character appears a unique power-of-two number of times, while quotes, whitespace, and comments are banned. Solution: build a 16-character first stage that rewires pydoc help into an eval gadget, then use the help prompt as a second-stage interpreter to read /app/flag_*.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
No separate organizer description was present in the provided workspace files.
English summary: the service reads up to 100000 bytes of Python, enforces a very unusual character-frequency rule, bans quotes/whitespace/comments, and then executes the payload with exec(c). The goal is to turn those constraints into code execution that can still reach the randomized flag file.
The challenge logic is short but extremely restrictive:
from collections import Counter c = input("> ")[:100000] def gen(): s = 1 while True: yield s s *= 2 assert all(i==j for i,j in zip(sorted(Counter(c).values()),gen())) assert all("~">=i not in "#'\" \t\n\r\x0c\x0b" for i in c) exec(c)
Two checks matter.
Counter(c).values() is sorted and compared against the generator 1, 2, 4, 8, .... So if the payload uses k distinct characters, their multiplicities must be exactly:
1, 2, 4, 8, ..., 2^(k-1)
Since the input length is capped at 100000, the largest possible k is 16 because:
1 + 2 + 4 + ... + 32768 = 65535 1 + 2 + 4 + ... + 65536 = 131071 > 100000
So the entire exploit must fit into at most 16 distinct characters.
The second assert bans:
' and "#That kills ordinary string literals and most pleasant Python syntax.
A normal Python jail escape usually spends lots of alphabet budget on things like:
__builtins____import__globalsopenread...
$ grep --similar