The challenge
"Zig promises one binary for every platform. Compare the ELF and PE service descriptors side by side and prove they're the same program wearing different uniforms."
100 questions: 10 binaries × 10. One evidence.zip holds every binary from Days 1–10 (SHA-256 9c31fb3a…1fc4). The d01–d09 fields are the same ones as in Nimble (Day 9); d10 is new: a Zig build. Exact-text answers carry the usual rule: "use the literal none only when the requested field is absent."
The d10 questions:
answer_id |
Question (short) | Format |
|---|---|---|
d10_ |
SHA-256 of the d10 file | Exact text |
d10_ |
Architecture | Exact text |
d10_ |
Container format | Exact text |
d10_ |
Machine | Base-10 integer |
d10_ / _ / _ / _ |
The four config values | Exact text |
d10_ |
The config's CRC32 | Lowercase hex with 0x |
d10_ |
New: does the file have an hcfg section? |
Enum true / false |
The other 90, carried over from earlier days:
| Binary | Fields |
|---|---|
| d01 (C ELF) | SHA-256, ELF class, machine, section names (JSON), symbols (JSON), disassembly (JSON), ELF type, endianness, entry point, has_ |
| d02 (C++ ELF) | SHA-256, format, config campaign / domain / mutex / URL / CRC32, XOR key, has_, has_ |
| d03 (.NET DLL) | Two SHA-256s, format, machine, metadata version, config ×5 |
| d04 (Go), d05 (Rust) | SHA-256, architecture, format, config ×5, hcfg_, XOR key |
| d06 (Java), d07 (Kotlin) | SHA-256, format, config ×5, hcfg_, XOR key, compression methods (JSON) |
| d08 (Swift) | SHA-256, architecture, ELF class (integer), format, machine (integer), config ×5 |
| d09 (Nim) | SHA-256, architecture, format, machine (integer), config ×5, hcfg_ |
Reading the prompt: what it said we'd need
| Clue | What it pointed to | What I did about it |
|---|---|---|
| "one binary for every platform" | Zig cross-compiles, so the same program may arrive as an ELF or a PE | Expected the timed sets to mix builds. Mastery set 2 was the PE |
| "Compare the ELF and PE service descriptors side by side" | The config record (the "service descriptor") should look the same in both containers; only the wrapper differs | Reused the existing HCFG finder unchanged; it read the config from both builds |
| "the same program wearing different uniforms" | Header fields that do differ (container format, machine number) need a rule for each container | Wrote the PE machine rule to mirror ELF's (raw header number) before sending it |
The new field has_ (enum) |
A question about where the record lives: in its own named section, or inside a general data section | Read the section table and checked that a section named . held exactly the record before answering true |
| 100 questions, 90 of them from earlier days | A compounding challenge: the Days 1–9 solver should answer most of it | The morning solver sent everything the solver and add-ons already covered; only the new field was worked by hand |
Safety
Static analysis only. No binary was ever executed. The evidence stayed on our Kali VM. The solver reads the AES zip's members straight into memory, so no binary member is ever written to disk. Every answer came from reading bytes: ELF and PE headers, the section tables, and the config record. The config values weren't recorded and aren't given here.
What was in the files
evidence.zip held one file per day, the same d01–d09 files as before, plus the new d10--variant-000.elf: a Zig x86-64 ELF (machine 62, architecture x86-64, format elf, all answered by the existing rules and accepted).
The config record is the same HCFG layout as the earlier days: a 12-byte header (HCFG magic, version, XOR key, length, CRC32) followed by the XOR'd JSON config. What was new is where Zig puts it: in its own section.
| What | Where | Size |
|---|---|---|
ELF section named . |
File offset 132160 | 380 bytes |
The HCFG record |
Starts at the same offset | 12-byte header + 368 bytes = 380 bytes, filling the section exactly |
The timed variants: the Time Trial delivered one 100-question set; the solver answered all 100 from the new bytes. Mastery delivered three sets (300 answers). Set 2's d10 was d10--variant-001.exe: a native PE build, x86-64, with its own .hcfg section. That is the "different uniform" from the prompt. Each set's values weren't recorded, only that the solver re-derived them from each set's own download.
Single Solve: CORRECT (99 from the morning solver, the last one by Claude)
The morning solver (our Kali VM, 13:00:05–13:00:08 UTC): 99 of 100 accepted, no wrong submits. The scheduled solver found the challenge list at 9:00 ET, started Zig Zag, and sent three batches:
| Pass | Sent | Result |
|---|---|---|
| Core Binary solver | 84 | accepted, 16 left |
| d01 ELF add-on | 9 | accepted, 7 left |
| d02 config add-on | 6 | accepted, 1 left |
Time Trial and Mastery were not started: the solver only starts them after a Single Solve CORRECT.
The one left: d10_analysis_has_hcfg_section. No rule existed; the field was new.
- Claude read the d10 ELF's section table statically. It has a section named
.hcfgat file offset 132160, size 380. - The section is the config record and nothing else. The
HCFGrecord starts at the section's offset, and its 12-byte header plus 368-byte body add up to exactly 380. So the name isn't a coincidence or a decoy. - It was sent alone:
true→ CORRECT (14:14:58). Single Solve flag:e28a4e79…b2e1.
single_solve started_at 2026-10-10T13:00:05.667Z deadline None
13:00:08 core 84 → accepted (16 left) · d01 ELF add-on 9 → accepted (7 left) · d02 config add-on 6 → accepted (1 left)
14:14:58 d10_analysis_has_hcfg_section = true (sent alone) → CORRECT
result CORRECT flag e28a4e79…b2e1
The solver: our shared Binary solver answers every confirmed field from the bytes. Three rules were added today:
- Section names: returns the section names of an ELF or a PE (by walking the COFF section table after the optional header), and nothing for any other file.
has_hcfg_section:trueif a section is named.hcfg,falseif the file has a section table without one, and no answer for files that are neither ELF nor PE.- PE
machine(added after the Mastery stop below): the raw COFFMachinenumber, mirroring ELF's rawe_machine.
The changes were tested before going live: the updated solver was re-run against all 44 saved earlier sets and had to give byte-identical answers on 44/44. There's still no dedicated unit test file for the binary solver; that snapshot run is the regression check.
Time Trial: CORRECT in 3.6 s (first attempt)
Run from our Kali VM right after the Single Solve. The new has_hcfg_section rule answered the d10 field on the fresh set.
time_trial started_at 2026-10-10T14:16:35.089Z deadline not recorded
100 answer_ids, coverage 100/100
start 579 · artifact 1474 · solve 637 · submit 906 · TOTAL 3,600 ms
result CORRECT flag 91f7df60…60cd
Mastery: CORRECT on the retry
1. Attempt 1, 14:16:42: stopped before submitting. The run downloaded three sets. Set 2's d10 was a native PE (d10--variant-001.exe, x86-64, also with an .hcfg section), and machine had no PE rule: the Day 3 rule only covers the .NET DLL, and the Day 8 rule only covers ELF. Every other PE field already had a confirmed rule from Day 9. The solver left the field unanswered, and the run stopped safely. Nothing was sent.
2. The PE rule: ELF's accepted machine is the raw e_machine number (62), not a name. The PE mirror is the raw COFF Machine field: 0x8664 = 34404. Because a Mastery is all or nothing, a wrong value would fail the whole attempt; everything else in it was already confirmed.
3. Retry, 14:19:09: one 300-answer submit → CORRECT.
mastery attempt 1 started_at 2026-10-10T14:16:42.482Z 3 sets · set 2's d10 is a PE · stopped before submit, nothing sent
mastery retry started_at 2026-10-10T14:19:09.775Z
300 answer_ids · set2.d10_analysis_machine = 34404
retry 1615 · artifact 2141 · solve 1945 · submit 1027 · TOTAL 6,730 ms
result CORRECT flag 54190b17…7ef6
This one submit confirmed the PE machine rule. It is now part of the solver.
The HTTP 429 that morning didn't touch this challenge. The same morning run also started the Script challenge Bind Over Matter, whose add-ons sent about 22 single-answer submits in 11 s; the Game Master answered 429 rate_limited and the solver stopped as designed. Zig Zag's three batches had already been accepted. Our Game Master client now spaces consecutive submits 1 s apart.
Time to solve
The morning solver started the Single Solve at 13:00:05 UTC and had 99 of 100 accepted three seconds later; the last field went in by hand at 14:14:58 for the CORRECT, 1 h 14 min 53 s after the start. The Time Trial went CORRECT on its first attempt in 3.6 s, and the Mastery went CORRECT on the retry at 14:19:15 after the first attempt stopped without sending, 1 h 19 min 10 s after the first start.
Takeaways
- A compounding challenge runs itself now. The scheduled solver sent 99 of 100 before anyone sat down; the real work was one new field.
- A section name is evidence, but check what's in it.
.hcfgwas trusted only after the record was found filling the section exactly. - Zig keeps the config in its own section, so the section table is the first place to look. Earlier days hid it in
.rodataor a string literal. - "One binary for every platform" means the timed sets can switch containers. Every header-level field needs a rule per container, ELF and PE.
- Mirror a confirmed rule instead of guessing a new style. ELF
machinewas the raw number, so PEmachinewas too (34404), and it went in first time. - Leaving a field blank is a safe stop. Attempt 1 sent nothing; the retry came with the rule worked out.
- Test solver changes against every earlier set. 44/44 identical before going live meant the new rules broke nothing.
- Fast single-answer loops trip rate limits. The 429 hit another challenge's add-ons the same morning; submits are now spaced 1 s apart.