The challenge
A dozen photographs have been resized, renamed, and shuffled. Reconstruct their true dimensions and find the image whose presentation does not match its structure.
One question per file: "Determine jpeg.sof_dimensions_pixels for camera-NNN.jpg." Exact text, trimmed, with no format stated.
| Mode | answer_id |
File |
|---|---|---|
| Single Solve | d04- |
camera- |
| Time Trial | d04- |
camera- |
| Mastery | set1., set2. |
camera-, camera- (two zips) |
Reading the prompt: what it said we'd need
| Clue | What it pointed to | What I did about it |
|---|---|---|
| "Resized, renamed" | File names and anything a viewer reports may lie about size | Ignore names and EXIF; read the frame header |
"True dimensions" + the field jpeg. |
The SOF (Start Of Frame) header, the JPEG's own record of its pixel grid | Parse the marker segments and read SOFn |
| "Presentation does not match its structure" | Something that changes how a photo is shown without changing its pixels, most likely EXIF Orientation (a viewer rotates the image, swapping width and height on screen) | Report orientation in the inventory; answer only from the SOF |
| Same zips and member names as Days 1–3 | The Metadata lane keeps compounding | Build on BOM Voyage's solver |
How a JPEG records its size
A JPEG is a chain of segments, each starting with a 2-byte marker FF xx, then a 2-byte length:
| Marker | Name | What it holds |
|---|---|---|
FF D8 |
SOI | Start of image (no length) |
FF E0–FF EF |
APP0–APP15 | JFIF, EXIF (APP1, which can contain a whole thumbnail JPEG, SOF and all), ICC… |
FF FE |
COM | A comment |
FF DB |
DQT | Quantisation tables |
FF C0–FF CF (not C4/C8/CC) |
SOFn | The frame header: precision, then height, then width (big-endian) |
FF C4 |
DHT | Huffman tables |
FF DA |
SOS | Start of scan; the compressed pixels follow |
Two traps for a naive reader:
- Searching the bytes for FF C0 can hit a thumbnail inside EXIF, or a decoy in a comment, before the real frame.
- Height comes before width in the SOF, so the answer must be swapped into width x height.
What was in the files
Every photo was a minimal baseline JPEG: quantisation tables, SOF0, Huffman tables, scan. No APP segments at all: no JFIF, no EXIF, no comment.
| Mode | File | Bytes | Segments | SOF0 (h, w) | Answer |
|---|---|---|---|---|---|
| Single Solve | camera- |
3,025 | DB C0 C4 DA |
146, 257 | 257x146 |
| Time Trial | camera- |
3,140 | DB C0 C4 DA |
157, 274 | 274x157 |
| Mastery set 1 | camera- |
2,535 | DB C0 C4 DA |
168, 291 | 291x168 |
| Mastery set 2 | camera- |
3,599 | DB C0 C4 DA |
179, 308 | 308x179 |
The deceptive image wasn't among them. The prompt's "dozen photographs" is the pool, and each mode drew one or two. With no EXIF at all, nothing in these four could disagree with its structure. The solver reads EXIF orientation anyway, ready for a variant that has it.
A pattern worth noting: the dimensions step up by exactly +17 wide and +11 high per photo (257×146, 274×157, 291×168, 308×179). They're generated from a counter, so the "dozen" likely runs to camera-012 in the same way.
Single Solve: CORRECT in 18 seconds
Started at 15:35:40 UTC. The zip's SHA-256 matched. Walking camera-001.jpg's segments gave SOF0 with height 146 and width 257. The format wasn't stated, so I prepared two spellings: 257x146, then 257 x 146. 257x146 was CORRECT at 15:35:58, flag e406e875…6bb3.
The solver
Our Day 4 solver loads BOM Voyage's solver by path, so it keeps three days of zip handling: names from the zip's own headers, the local/central name check, nested and stored zips, per-set scoping.
It adds the field …-jpeg-sof-dimensions-pixels:
- It walks the segment chain, with fill bytes and standalone markers handled, and skips every APPn and COM payload whole.
- It takes the first SOFn of any type (baseline, progressive, lossless…), swaps it to width x height, and stops at SOS.
- A file that isn't a JPEG stops the run before submitting.
7 tests, all passing before any timed run:
- the real file;
- width/height order;
- progressive SOF2;
- an EXIF thumbnail with its own SOF, plus a fake FF C0 in a comment, both ignored (and orientation 6 read);
- fill bytes;
- the Mastery shape, with a decoy member named camera-1920x1080.jpg;
- a PNG named .jpg, refused.
Time Trial: 1.80 s of a 6-second clock
started_at 2026-10-07T15:36:44.152Z deadline 2026-10-07T15:36:50.152Z
artifact metadata-day-04-evidence.zip 1919 bytes sha256 3eae0bb30063aaa6… (checked)
d04-jpeg-002-jpeg-sof-dimensions-pixels: 274x157
start 446 ms
artifact 614 ms
solve 1 ms
submit 740 ms
TOTAL 1801 ms
result CORRECT flag 2dbebdd1…f5a0
Mastery: 1.49 s of a 6-second clock, first attempt
started_at 2026-10-07T15:36:49.575Z deadline 2026-10-07T15:36:55.575Z
artifact metadata-forensics-day-04-picture-this-mastery.zip 3075 bytes sha256 b3768c4d4d5039a2… (checked)
set1.d04-jpeg-003-jpeg-sof-dimensions-pixels: 291x168
set2.d04-jpeg-004-jpeg-sof-dimensions-pixels: 308x179
start 597 ms
artifact 289 ms
solve 1 ms
submit 600 ms
TOTAL 1487 ms
result CORRECT flag 5a846b8c…bb60
The Mastery start took 0.6 s this time, against about 1.8 s for every Mastery start earlier in the day. The earlier slowness looks like server load, not something every Mastery start costs.
Time to solve
All three modes were solved on 2026-10-07 by 15:36:57 UTC, 1 min 17 s after the first start. The Single Solve took 18 s, the solver was extended in under a minute, and the Time Trial (1.80 s of 6 s) and the Mastery (1.49 s of 6 s) each went through on the first submit.
Takeaways
- Structure beats presentation. The SOF frame header is the image's real pixel grid. File names, EXIF tags, thumbnails, and what a viewer shows can all differ from it.
- Parse; don't grep. A byte search for
FF C0can land in an EXIF thumbnail or a comment. Walking the segment chain and skipping APP and COM payloads finds the real frame every time. - Mind the field order. The SOF stores height first. The answer convention is width × height.
- Compounding pays off. Four days of Metadata solvers stack, so this challenge needed one new field and took 77 seconds end to end.