zwesty
Write-ups / Day 23 / Binary
Day 23 · Fri, Oct 23 · Binary

Trust Issues

Prey slaughtered

Static PE/CLI triage (managed .NET assembly), machine-field labels, CLR metadata root (BSJB), HCFG config record, cumulative question sets

STTMClaude Homebase Both

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

Challenge ID
binary-reverse-engineering-day-23-anti-analysis-recognition (+ /time_trial, /mastery)
Solved
2026-10-23: all three modes CORRECT. The solver's first Single Solve batch came back incorrect (09:01:13 ET); Claude fixed one answer form and two uncovered fields, then finished the Single Solve (09:05:09), the ranked Time Trial (09:05:34), and the ranked Mastery (09:05:50). 4 min 41 s from the first start request (09:01:09 ET) to the Mastery CORRECT
Player
Zwesty (solo), with Claude Code (Opus 5.5): our automated morning solver (a scheduled script on our Kali VM) started the Single Solve and sent the first batch; Claude found the cause, built the fix, and sent every later request on Binary

The challenge

"This binary doesn't trust you. It checks the clock, sniffs the environment, and takes different branches when it thinks it's being watched. Spot every predicate and force the truth out."

Binary is cumulative: 276 questions, 12 per day for Days 1–23, all on one evidence.zip. The 12 Day 23 fields:

answer_id Question (short) Format
d23_artifact_sha256_1, _2 SHA-256 of d23-- members 1 and 2, in ZIP central-directory order 64 lowercase hex
d23_analysis_format Classify the primary managed .dll by magic and container enum: elf, pe, pe_cli, jar, wasm, neko_bytecode
d23_analysis_machine Processor architecture from the executable-header machine field "architecture label or its equivalent decimal or hexadecimal code"
d23_analysis_metadata_version CLR metadata-root version string at BSJB + 16, trailing NULs removed exact text
d23_analysis_config_campaign, _domain, _mutex, _url Fields of the CRC32-valid HCFG record's decoded JSON exact text
d23_analysis_config_crc32_hex HCFG header bytes 8..11 0x + 8 lowercase hex
d23_analysis_hcfg_version HCFG header byte 4 base-10 integer
d23_analysis_xor_key_hex HCFG header byte 5 0x + 2 lowercase hex

Time Trial asked the same 276; Mastery asked them once per set (7 sets, 1,932 answers).

Reading the prompt: what it said we'd need

Clue What it pointed to What I did about it
"checks the clock, sniffs the environment" Anti-analysis checks (time and environment predicates) in the sample Nothing to run or bypass: none of the 12 Day 23 questions asked about the predicates. The answers come from headers and the embedded config, read statically
"takes different branches when it thinks it's being watched" Behaviour that changes under a debugger or sandbox Another reason not to execute it. Static reads give the same bytes every time
"force the truth out" Recover the real config, not a decoy The HCFG rule in the question: take the first record whose bounds, CRC32, and JSON all validate
"Use the unique d23-- primary managed assembly … ends .dll" (question text) A .NET (PE/CLI) DLL again, like Day 22 The Day 22 managed-.dll rules should apply. They didn't, because one was hard-coded to Day 22 (below)

Safety

Static analysis only. Nothing was executed. The DLLs were parsed as bytes (PE and CLI headers, the BSJB metadata root, an HCFG scan); no .NET runtime was started. The archives stayed on our Kali VM.

What was in the files

  • Single Solve: evidence.zip, 35,675,756 bytes, 30 encrypted members covering Days 1–23. Today's members are d23--sample.dll (8,060 bytes) and d23--sample.runtimeconfig.json (98 bytes). The Day 22 members include d22--FSharp.Core.dll (5.7 MB), which is most of the archive's size.
  • The second Day 23 hash looked wrong but wasn't. d23_artifact_sha256_2 (d6109426…6cf3) is the same digest as Day 3's member, because d23--sample.runtimeconfig.json is byte-identical to d03--sample.runtimeconfig.json.
  • The HCFG record decoded to a synthetic config (defanged): campaign BR23-000, domain node-000[.]day23[.]example[.]invalid, mutex Global\HuntressBR23_000, URL hxxps://node-000[.]day23[.]example[.]invalid/api/BR23-000, CRC32 0xeb13668a, version 1, XOR key 0x81.
  • Time Trial: one evidence.zip of 35,810,311 bytes. Mastery: seven, 35.68 to 35.81 MB each. Same template with different values; the whole solve ran unchanged on all of them once the fix was in.

Single Solve

The solver's batch: incorrect

The solver reported coverage 274 of 276: d23_analysis_format and d23_analysis_metadata_version had no answer. It sent the core batch (199 answers) and got a bare incorrect, with no hint which field. It stopped there, before the add-on batches, and left Binary for Claude.

started_at  2026-10-23T13:01:09.540Z   (solver)
deadline    none (Single Solve)
answers     199 (core batch)
result      incorrect, no field named; solver stopped Binary; timed modes not started

The cause and the fix (Claude)

d23_analysis_machine was sent as 332 (the decimal of 0x14c). The question says a decimal code is accepted, but on Day 22 332 had been rejected and i386 accepted for the same field on a managed DLL. The solver's label rule was written for Day 22 only, so Day 23 fell back to the number.

The fix was built in a separate copy, without touching the solver while it was running: - The managed-PE machine label rule now applies to days ≥ 22. - The Day 22 managed-DLL add-on now answers dNN_analysis_format and dNN_analysis_metadata_version for every day ≥ 22 from that day's own dNN--sample.dll. This closed the two uncovered fields. - Coverage 276 of 276. The only change from the solver's batch was machine 332 → i386.

The first choices were machine i386 (with x86 and 0x14c as fallbacks), format pe_cli, and metadata version v4.0.30319. All three were accepted, so no other value was sent.

started_at  2026-10-23T13:01:09.540Z   (same attempt, resumed by Claude at 13:05:01)
deadline    none (Single Solve)
answers     199 core (accepted, remaining 77), then 77 add-on answers
start       1416 ms
artifact    3340 ms   (35.7 MB)
solve       1090 ms
submit      2185 ms   (core 348, add-ons 1835)
TOTAL       8031 ms
result      CORRECT   flag 4f0eee93…195b   (server stamp 13:05:08.712Z)

Accepted Day 23 values: pe_cli, i386, v4.0.30319, plus the HCFG fields listed above.

Time Trial

CORRECT on the first attempt, ranked (80 s clock), from the fixed copy.

started_at  2026-10-23T13:05:29.770Z
deadline    2026-10-23T13:06:49.770Z   (80 s)
answers     276
start        259 ms after started_at
artifact    2119 ms   (35.8 MB)
solve        762 ms
submit      1621 ms
TOTAL       4501 ms from the start reply   (submit +4.76 s after started_at)
result      CORRECT   flag 1cd3bdaf…ce48

Mastery

CORRECT on the first attempt, ranked (465 s clock). The seven archives were streamed with 3 workers; all were in by +4,266 ms.

started_at  2026-10-23T13:05:44.069Z
deadline    2026-10-23T13:13:29.069Z   (465 s)
answers     1,932 (7 sets × 276)
start        464 ms after started_at
artifact    3802 ms   (7 × ~35.7 MB, streamed, last one at +4266 ms)
solve        642 ms
submit      1804 ms
TOTAL       6251 ms from the start reply   (submit +6.72 s after started_at)
result      CORRECT   flag 6f2ae425…f040

Afterwards the fix went into the solver for the following days. Before that it was checked: re-solving 114 saved Binary sets changed only d23_analysis_machine, a replay of 46 saved Masteries was clean, and the Day 23 accepted answers matched.

Time to solve

All three modes were solved by 09:05:50 ET, 5 min 50 s after release (4 min 41 s from the first start request). The first Single Solve batch was incorrect and the attempt was resumed after the fix; the Time Trial and Mastery were both ranked and went through on the first submit.

Takeaways

  • Write day rules as day >= N, not day == N. Binary is cumulative and the managed-.dll fields came back the next day. The Day 22 rule stopped working after one day.
  • "Decimal is accepted" in the format text wasn't true for this field. The Game Master took i386 and rejected 332 on both days. Prefer the tool label that was accepted before.
  • A repeated digest isn't always a bug. Identical support files across days give identical hashes; check the bytes before "fixing" one.
  • The solver stopping on a bare incorrect cost nothing. No timed attempt was started, so both ranked runs were still first attempts once the fix was in.
  • The prompt's theme didn't change the questions. "Anti-analysis" sounded like new work, but the 12 fields were the usual header and config set. Read the question list before planning around the prompt.