$ cat writeup.md…
$ cat writeup.md…
broncoctf2026
Task: a 300x300 60fps monochrome TV-static MP4 with no audio; the pun 'now that's dynamic' points to inter-frame motion, not per-pixel temporal aggregates. Solution: detect the telecine cadence where frame[i] and frame[i+2] are bit-identical except inside a fixed banner box, XOR the thresholded near-duplicate pairs to cancel the frozen noise and reveal one flag glyph per ~10-frame block, majority-vote and concatenate 25 glyphs.
"It's not often that you do static analysis outside of Reversing, is it?"
Artifact:
static.mp4
English summary: We are given static.mp4, a 300x300, 60fps, 1500-frame,
yuv420p, monochrome "TV static" white-noise video with no audio and a single
video stream (~58 MB, ~18 Mbps — a bitrate high enough to preserve the noise
nearly losslessly). The flag is hidden somewhere in the noise; the goal is to
recover it.
bronco{REDACTED}.The obvious first attack on a stack of noise frames is to reduce them per pixel over time (mean, median, min/max, mode, std, white-probability, bit-plane counts, temporal FFT). Every single one of these produced pure noise:
Conclusion: no information is carried by the marginal distribution of any single pixel. The data must live in the temporal correlation structure between frames.
Comparing thresholded frames revealed that most frames are bit-identical to
the frame two positions later: threshold(frame[i]) == threshold(frame[i+2]).
The video is a telecine-style cadence — a frozen noise background is repeated on
a fixed period. Treated as a bitstream (i == i+2 or not) this cadence is a
perfectly periodic square wave (period 60, "111111100000..."); it is pure
structure and carries no data by itself. This is a decoy: it tells you the
video is built from repeated frozen frames, nothing more.
In 25 evenly spaced blocks of ~10 consecutive frames each (block start frames
33, 93, 153, ..., 1473; period 60, hence 25 blocks), the pair (i, i+2) is
not identical — but the difference is confined to a small fixed
rectangular box (e.g. around x=88–215, y=232–263 for one block). Outside that
box the two frames are the same frozen noise.
Because the background noise is identical in both frames of a near-duplicate
pair, threshold(frame[i]) ^ threshold(frame[i+2]) cancels the frozen
background and leaves only the box — which contains a single flag glyph
(one character). 25 blocks → 25 characters → the full flag.
Averaging the XOR mask over all ~10 pairs in a block (majority vote) removes the residual per-pixel noise flicker inside the box and yields a clean glyph.
(i, i+2) pair whose Hamming distance is nonzero but small
(0 < d < 20000) — these are the near-duplicate-but-different pairs.threshold(frame[i]) ^ threshold(frame[i+2]) and
majority-vote to a clean glyph.#!/usr/bin/env python3 import subprocess, numpy as np, cv2 # 1. dump all 1500 frames as raw 8-bit grayscale raw = subprocess.check_output( ['ffmpeg', '-v', 'error', '-i', 'static.mp4', '-f', 'rawvideo', '-pix_fmt', 'gray', '-']) a = np.frombuffer(raw, np.uint8).reshape(-1, 300, 300) th = a > 127 # 2. threshold -> boolean # 3. near-duplicate telecine pairs (i, i+2): differ, but only slightly pairs = [] for i in range(len(a) - 2): d = np.count_nonzero(th[i] ^ th[i + 2]) if 0 < d < 20000: pairs.append((i, i + 2, d)) # 4. group consecutive pairs (step 3) into per-character blocks blocks, cur = [], [pairs[0]] for p in pairs[1:]: if p[0] - cur[-1][0] <= 3: cur.append(p) else: blocks.append(cur); cur = [p] blocks.append(cur) # 5. per block: majority-vote XOR mask -> one glyph crops = [] for blk in blocks: acc = np.zeros((300, 300), int) for (i, j, d) in blk: acc += (th[i] ^ th[j]) g = (acc > len(blk) // 2).astype('uint8') * 255 ys, xs = np.where(g > 0) crops.append(g[ys.min():ys.max() + 1, xs.min():xs.max() + 1]) # 6. crop + concatenate all 25 glyphs in order H = max(c.shape[0] for c in crops) row = [np.pad(c, ((0, H - c.shape[0]), (3, 3))) for c in crops] cv2.imwrite('flag_strip.png', np.hstack(row)) # reads: bronco{REDACTED}
The output image flag_strip.png spells the flag left-to-right across its 25
glyphs.
All of the following produced only noise:
==0/==255/>=240. (White-prob range
0.43–0.57 = expected spread of 1500 Bernoulli samples; no embedded bias image.)i == i+2): a perfectly periodic
square-wave (period 60) — telecine structure, carries no data by itself.ftyp/free/mdat/moov,
no trailing/appended data, no extra tracks/metadata); MPEG-4 user_data only
holds the encoder string; codec QP uniform.The signal is only in the near-duplicate-but-different (i, i+2) pairs.
$ cat /etc/motd
Liked this one?
Pro unlocks every writeup, every flag, and API access. $9/mo.
$ cat pricing.md$ grep --similar