$ cat writeup.md…
$ cat writeup.md…
umdctf
Task: submit a float32 window close to a provided reference so it passes three RealNVP-based acceptance checks. Solution: use a white-box adversarial perturbation, changing one coordinate of the reference by +0.03 to push the flow_1 likelihood and margin far above the required thresholds while staying inside the L-infinity budget.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
submit base64(numpy float32 array, shape (5, 64)):
The service loads a reference window and checks whether our submitted float32 array stays within EPS = 0.08 in L-infinity distance. It then evaluates the sample under two RealNVP flows and only prints the flag if the sample looks realistic to flow_1 and strongly prefers class 1 over class 0.
challenge.py exposes the full decision rule:
(5, 64)reference_window.npylinf <= 0.08margin = log q1 - log q0 >= 30log q1 >= 932.8031log_det1 must lie in [1367.1451, 1595.0465]The important point is that this is a white-box setting. We have the reference input, the model code, and both flow checkpoints. The reference sample itself is not close to the target class boundary in the right direction: its margin is about -1.90, so we must meaningfully increase log q1 - log q0 while keeping the perturbation tiny.
In practice, no numerical trick was needed. A simple coordinate search was enough: flatten the reference array and add +0.03 at index 205, which is element [3, 13] in the original (5, 64) layout.
That single change already satisfies every condition:
...
$ grep --similar