zwesty
Write-ups / Day 4 / Warmups
Day 4 · Sun, Oct 4 · Warmups

Two of a Kind

Prey slaughtered

Reading binary · planning decoders ahead from the next days' prompts · scoring decodes that contain no ordinary words · handling a server 503 safely

STTMClaude Homebase Both

Flags are shortened to their first 8 and last 4 characters because they're unique per team.

Challenge ID
warmups-day-04 (+ /time_trial, /mastery)
Solved
2026-10-07, all three modes, in 6 min 33 s from the first start (15:27:54 → 15:34:27 UTC); Mastery on its third attempt
Player
Zwesty (solo), with Claude Code (Opus 5.5)

The challenge

There are only two sides to this story.

The question, word for word Days 1–3:

Decode the assigned blob completely. What exact answer slug does its final non-empty decoded line instruct you to submit?

Answer format: word-word-word-NN, trimmed. Mastery: 18 blobs (Days 1–3 had 3, 8, and 13).

Reading the prompt: what it said we'd need

Clue What it pointed to What I did about it
"Only two sides" Base 2, binary: every digit is one of two values Add a binary decoder
"Two of a Kind" (the title) A pair: 0 and 1 —
The question is identical to Days 1–3 A compounding day: Base64, ROT13, and hex will be back in Mastery Build on Day 3's solver
Mastery has gained a line each day (2, then 3) Day 4's Mastery would have 4 lines, the last in binary Already handled by the per-line decoder, or so I thought (see Mastery)
The next three days' prompts were already posted Day 5: "reduced to numbers" (decimal). Day 6: "eight fingers" (octal). Day 7: "my address bar" (URL percent-encoding) Add all four number decoders now, so Days 5–7 start ready

What was in the files

Every blob decoded to the familiar sentence: "Nice work decoding this warmup! To solve, submit this exact answer to the Game Master: <slug>".

Mode Delivered as Raw format
Single Solve blob.txt, 998 B The whole sentence as space-separated 8-bit groups
Time Trial blob.txt, 980 B The same
Mastery 18 separate blob.txt files (not one zip, unlike Days 2–3) Four labelled lines per blob: 01 Base64, 02 ROT13, 03 hex, 04 binary

The Single Solve blob, raw (start only) and decoded:

01001110 01101001 01100011 01100101 00100000 01110111 01101111 …

Nice work decoding this warmup! To solve, submit this exact answer to the Game Master: witty-starfish-turtle-96

How to read binary by eye: groups of 8 bits are one character each. 010 starts lowercase letters (0x60–0x7f), 0100 uppercase, and 00100000 is a space. 01001110 = 64+8+4+2 = 78 = "N".

A Mastery blob, split across four encodings, one per day so far (the hex line is shortened here):

01<TAB>TmljZSB3b3JrIGRlY29kaW5nIHRoaXMgd2Fy
02<TAB>zhc! Gb fbyir, fhozvg guvf
03<TAB>657861637420616e…
04<TAB>01110011 01110100 01100101 01110010 00111010 00100000 01111010 …
Line Encoding Decodes to
01 Base64 (Day 1) "Nice work decoding this war"
02 ROT13 (Day 2) "mup! To solve, submit this "
03 Hex (Day 3) "exact answer to the Game Ma"
04 Binary (Day 4) "ster: zippy-basket-ripple-42"

Single Solve: CORRECT

Started at 15:27:54 UTC. The blob's SHA-256 matched. One binary layer gave witty-starfish-turtle-96. CORRECT at 15:29:27, flag 018069c0…8971.

The solver

Our Day 4 solver loads Day 3's solver by path (Days 1–3: the Base64 family, ROT13, per-line decoding, loose hex) and adds four number decoders:

Decoder For Accepts
binary Day 4 Spaced 8-bit groups, or one run of bits
decimal Day 5 (expected) 78 105 99, 78,105,99
octal Day 6 (expected) 116 151 143, \116\151, 0o116
percent Day 7 (expected) %4E%69, Nice%20work

Order matters, and a test caught a trap: - Binary before decimal, because 0/1 groups are also valid decimal numbers. - Decimal before octal. An 8 or a 9 rules octal out, and octal read as decimal gives bytes above 127, which fail the printable check. - All four before Day 1's line-label stripper. That stripper reads 78,105,99,… as "label 78, then a payload", and peeled one number per round until it hit the 64-layer safety limit. The comma-separated decimal test found it before anything was submitted.

8 tests at first (9 after Mastery): each format in its variants, octal not misread as decimal, mixing with Base64 and ROT13, a four-line per-line blob, and garbage refused.

Time Trial: 1.51 s of a 6-second clock

started_at 2026-10-07T15:29:28.817Z  deadline 2026-10-07T15:29:34.817Z
  artifact blob.txt 980 bytes sha256 ee99e57f491ac205… (checked)
  message: jaunty-daisy-pebble-47
  start         445 ms
  artifact      379 ms
  solve           0 ms
  submit        688 ms
  TOTAL        1513 ms
result CORRECT  flag 4214e96f…7371

Mastery: CORRECT on the third attempt

Attempt What happened Submitted?
1 (15:29:32, 7 s clock) The Game Master returned HTTP 503 temporarily_unavailable mid-run. Our timed script stopped No
2 (retry, 15:32:08) 18 separate files, all hashes checked. The solver stopped on 16 of 18 blobs (see below) No
3 (retry, 15:34:22) All 18 decoded. CORRECT Yes

Both failures stopped before submitting, so no wrong answer was ever sent. Attempt 1 also had a slip of mine: a second, hidden Mastery run chained into the same command. Its start got a 503 too and did nothing, but it shouldn't have been there.

Why attempt 2 failed: a line with no ordinary words

The per-line decoder (built on Day 2) picks each line's decoding by counting common English words: "the", "answer", "submit", and so on. Line 4 was ster: zippy-basket-ripple-42: the tail of "Master" plus three random slug words, none of them common. It scored 0, the same as the raw binary digits, and the tie rule ("fewer layers wins") kept the raw digits. With no instruction to be found, the solver refused to answer. Blobs 06 and 08 passed only because their lines split at different points.

The fix, in the shared per-line decoder: 1. A second score, "naturalness": the share of letters and spaces, halved when the chunk has no space or hyphen at all (Base64 and hex never do). Readable text now beats digit runs and encoded strings. 2. Combinations: keep each line's top 4 candidates, and try them together, best first, until the joined text reads as the instruction with exactly one slug. Even if one line's best guess is wrong, the right combination is found, in about 0.5 ms per blob.

Checked before the retry: all 18 failed blobs decoded, the 21 real Mastery blobs from Days 2 and 3 still gave their accepted answers, and all three days' tests passed, plus a new test built from the real failing blob.

started_at 2026-10-07T15:34:22.720Z  deadline 2026-10-07T15:34:29.720Z
  18 artifacts blob.txt, 374–386 bytes each (all checked)
  set1.message: zippy-basket-ripple-42 … set18.message: proud-chimney-nugget-67
  retry        1855 ms
  start         379 ms
  solve           9 ms
  submit        719 ms
  TOTAL        4050 ms
result CORRECT  flag 89314f7a…480a

The retry call itself took 1.86 s, like every Mastery start today. With 18 downloads in parallel, the whole run still finished 3 seconds inside the clock.

Time to solve

All three modes were solved on 2026-10-07 by 15:34:27 UTC, 6 min 33 s after the first start. The Single Solve took 93 s and the Time Trial went through first time in 1.51 s; the Mastery passed on its third attempt in 4.05 s, after a server 503 and a solver stop, neither of which sent anything.

Takeaways

  • Read ahead. The later days' prompts were already posted, so the Day 4 solver was built for Days 5–7 too.
  • A scorer that counts words fails on text without words. Slugs, IDs, and fragments carry no common English. Use a second signal (letters and spaces versus digits and encoded strings) and test combinations rather than trusting each piece's best guess alone.
  • Decoder order is a design decision. Binary is valid decimal, decimal can look like a labelled line, and octal can look like decimal. Each conflict needs a rule, and a test.
  • Stopping is a feature. Both failed Mastery attempts stopped before submitting, one on a server error and one on its own doubt. Neither cost anything but a retry (254 of 255 attempts remained).
  • Check what a command will actually run. A second Mastery run was chained in by mistake. It was harmless this time, but timed runs deserve one deliberate command each.