The challenge
The configuration is encoded, but the decoder ships with the binary — a ring waiting for its secret. Recover the reversible decoder and read what it was hiding.
Single Solve asked 204 artifact-derived questions. Time Trial used the same question set against variant files. Mastery repeated the field families across five sets, for 1,020 questions total. Answers were submitted under the exact answer IDs.
| Answer IDs | Question | Format |
|---|---|---|
d17_, dNN_ |
Report the HCFG record's file offset. | Base-10 integer, no units or explanation. |
d17_, dNN_ |
Report the HCFG version byte. | Base-10 integer. |
d17_, dNN_ |
Report the one-byte XOR key. | Lowercase hexadecimal with 0x prefix. |
d17_, dNN_ |
Report the CRC32 stored for the decoded payload. | Lowercase hexadecimal with 0x prefix. |
dNN_, _, _, _ |
Recover the named JSON configuration values. | Exact artifact text, without quotes or explanation. |
d12_, d14_ |
Classify where the raw HCFG record is stored. | After the question fix: one exact, case-sensitive token from raw, base64, raw_, raw_, wasm_. |
d15_, d16_ |
Give the SHA-256 for each delivered file. | Exact 64-character digest; numbered by ZIP central-directory order. |
Other dNN_ fields |
Report the requested file format, architecture, symbols, section names, runtime markers, or language metadata. | Field-specific exact text, integer, JSON array, boolean enum, or pattern stated in each question. |
The D12 and D14 storage questions were later updated with full placement rules. The original answer format did not define a storage vocabulary; the consequence is described below.
Reading the prompt: what it said we'd need
| Clue | What it pointed to | What I did about it |
|---|---|---|
| “The decoder ships with the binary” | The file contains both the encoded record and the logic that reverses it. | Read headers, sections, references, and decoder instructions statically. |
| “Recover the reversible decoder” | Find the transform and its parameters instead of guessing strings from a binary scan. | Located HCFG records, XORed the payload with its one-byte key, and checked the CRC32. |
| “Read what it was hiding” | A successful decode should produce structured configuration data. | Parsed the CRC-verified plaintext as JSON and answered from those fields. |
| Repeated artifact-derived questions | The same analysis has to work across different formats and variants. | Used static parsers for ELF, PE/COFF, Java, and WebAssembly artifacts and kept each answer tied to its exact answer ID. |
| Two HCFG storage questions | The physical carrier matters as well as the decoded contents. | Recorded the containing section or data segment separately from the HCFG encoding. The required label vocabulary was added later. |
| Multiple files for Days 15 and 16 | The numbered digests depend on how the archive orders its members. | Preserved central-directory order when hashing; alphabetical filename order was wrong for the timed evidence. |
Safety
This was static analysis only. No challenge binary or class was executed. The encrypted evidence archive and extracted samples stayed in the analysis VM.
What was in the files
Each mode delivered an evidence.zip with day-numbered samples and per-day questions. Day 3 also included a runtime configuration file. Days 15 and 16 each had multiple artifacts, which is why their questions included two SHA-256 answer IDs.
The builds followed the same broad template, but the files and configuration values changed between variants. The first Time Trial used the same Day 1 build as Single Solve. The second used a stripped Day 1 variant. In both runs, D02 and D08 matched the Single Solve, D16 was unchanged, and the other days used different variants. The HCFG storage layouts for D08–D14 and D17 stayed the same in the timed evidence, while configuration values varied. In Mastery, sets 1, 3, and 5 carried Windows PE builds for two days: D02 as a MinGW C++ .exe and D04 as a Go .exe. Sets 2 and 4 were ELF throughout.
HCFG record and decoded configuration
The record format is:
| Bytes | Meaning |
|---|---|
0. |
ASCII magic HCFG |
4 |
Version |
5 |
One-byte XOR key |
6. |
Payload length, little-endian u16 |
8. |
CRC32 of the plaintext, little-endian u32 |
12. |
JSON payload, each byte XORed with the key |
I searched the binary bytes and candidate Base64 carriers for HCFG, then accepted a hit only when the declared payload length was present, XOR decoding produced the stored CRC32, and the plaintext parsed as JSON. This avoids treating an incidental HCFG string as a real record.
In the Day 17 ELF, the raw HCFG starts at file offset 207432 (0x32a48) in .rodata. Its version is 1, key is 0x73, payload length is 367, and CRC32 is 0x265cc435. XORing the payload bytes with 0x73 produced this JSON:
{
"campaign": "BR17-000",
"domain": "node-000.day17.example.invalid",
"ipv4": "198.51.100.70",
"url": "https://node-000.day17.example.invalid/api/BR17-000",
"mutex": "Global\\HuntressBR17_000",
"windows_path": "C:\\ProgramData\\HuntressLab\\day17\\BR17-000.dat",
"linux_path": "/var/tmp/huntress-lab/day17/BR17-000.dat",
"service": "HuntressLab-Day17-000",
"host_model": "workstation"
}
The D12 and D14 files exposed the storage-label issue:
| File | HCFG location | Key / length | Observed layout |
|---|---|---|---|
| D12 | File offset 82928 (0x143f0) in ELF . |
0x81 / 368 bytes |
Raw record, addressed directly by the decoder at a fixed image address. |
| D14 | File offset 4000 (0xfa0) in ELF . |
0xa1 / 367 bytes |
Raw record begins in the dedicated . section. |
The bytes established those physical facts, but the original D12 question gave no rule mapping a .data byte array to a canonical answer string. It also did not say that raw_const_array described the observed layout without requiring proof of a source-level const declaration. A stripped binary had no symbol naming the D12 object, and its Free Pascal metadata did not supply a storage annotation. The accepted token therefore could not be derived from the bytes alone.
John Hammond's question fix added five exact labels and mutually exclusive placement rules. Under those rules, D12 is raw_const_array: literal HCFG in a native data section other than .hcfg, directly addressed as an in-image byte array. D14 is raw_hcfg_section: literal HCFG begins in a section named .hcfg. The rules also distinguish Base64 carriers, WebAssembly data segments, and other raw carriers.
About 1,370 D12 storage values were sent by the Homebase agent before the fix, and none was accepted. The closest was raw_hcfg_const_array.
Single Solve
Our automated morning solver (a scheduled script on our Kali VM) sent what our shared binary solver already knew at release: its core plus the Day 1 ELF and Day 2 config plug-ins, 186 of 204 answers. The Homebase agent covered the other 18 with a new plug-in. It handles the Day 1 marker and recover code, the C++ and Rust symbols, Go and Rust section names, the Java class fields, and the storage classifier. It also added section flags to the symbol-table reader. Coverage offline was then 204/204.
One 38-answer batch (13:15:42Z) came back incorrect because of its D12 and D14 storage values. Its other 36 answers were resent later and accepted. D14's raw_hcfg_section was accepted before D12 was resolved.
After the question text gained the enum and placement rules, the first enum token sent for D12, raw_const_array, was accepted and completed the mode.
started_at: 2026-10-17 13:00:29.192Z
deadline: none (Single Solve)
answers: 204 / 204
artifact / analysis / submit timings: not recorded
completed: 2026-10-17 16:19:51Z
total: 3:19:21.808
result: CORRECT — bd42487e…11e3
Time Trial
The first two 204-answer submissions were incorrect:
| Run | Started | Deadline | Result |
|---|---|---|---|
| 1 | 16:22:08.588Z | 16:23:28.588Z (80 seconds) | Incorrect at 16:22:14Z. |
| 2, untimed retry | 16:24:24Z | None | Incorrect at 16:24:30Z. |
The Homebase agent's own timings put the two failed runs at about 6.7 seconds and 9.3 seconds from its start; the request timestamps put each submit roughly six seconds after its attempt start. Both are approximate, because they measure from different points.
Both failed runs came from the Homebase agent's solver. Claude then took over from our Kali VM. Offline, the VM's own solver disagreed with the Homebase plug-in on exactly four fields, the D15/D16 hashes. But the Single Solve had passed with the Homebase's values, so that wasn't proof. The open untimed attempt was then diagnosed in day-by-day batches. Fifteen day batches were accepted; D15 and D16 were incorrect. Splitting those days showed their non-hash fields were accepted. The four digest answers were reversed because the Homebase plug-in sorted the two members by filename. The answer IDs follow ZIP central-directory order, so the fix was to hash the members in that order. The corrected D15/D16 hash pairs were accepted and completed the mode.
The Single Solve had completed even though the Homebase solver used alphabetical order for these hashes. Our records can't confirm whether the Single Solve accepted either order or whether ZIP-order answers had already been accepted in an earlier batch.
failed run 1:
started_at: 2026-10-17 16:22:08.588Z
deadline: 2026-10-17 16:23:28.588Z
answers: 204
result: incorrect at 16:22:14Z
failed run 2:
started_at: 2026-10-17 16:24:24Z
deadline: none (untimed retry)
answers: 204
result: incorrect at 16:24:30Z
successful diagnostic run (the same untimed attempt):
started_at: 2026-10-17 16:24:24Z
deadline: none; unranked
answers: 17 day batches, then 4 split batches (21 submits)
result: CORRECT at 16:41:02.792Z — 7ad69c3d…f290
elapsed from attempt start: 16:38.792
artifact / per-batch processing timings: not recorded
ranked: no; the attempt was untimed
Mastery
Mastery contained five sets and 1,020 questions. Claude ran it from our Kali VM. A plain start created an untimed attempt. The solver was a copy of our solver with the Homebase plug-in and the zip-order fix. It was checked offline first: 204/204 equal to the accepted Time Trial answers, and 408/408 on a two-set mock Mastery built from the saved Time Trial sets. The static solver produced 1,011 answers in 6.1 seconds after five artifact downloads that took 4.3 seconds. Each of the five set batches was accepted. Nine PE-specific fields remained, so the remaining answers were split into three field batches.
The three PE-only field types were:
- MinGW C++
mangled_score_symbol: the first COFF entry holding the name, which is the section symbol.text$_ZNK15DiscoveryEngine5scoreEPKc. - MinGW C++
typeinfo_symbol: the same section-symbol rule, yielding.rdata$_ZTI15DiscoveryEngine. - Go PE
section_names: section-header names in order, with no leading empty string:[".text",".rdata",".data",".pdata",".xdata",".idata",".reloc",".symtab",".rsrc"].
All nine instances of those fields across sets 1, 3, and 5 were accepted on the first try. The eight submissions (five set batches and three PE-field batches) completed Mastery.
started_at: 2026-10-17 16:44:52.009Z
deadline: none; plain start, unranked
questions: 1,020
first pass: 1,011 answers; five set batches accepted
remaining: 9 PE-only fields, accepted in three field batches
downloads: 5 artifacts in 4.3s
solver: 1,011 answers in 6.1s
result: CORRECT at 16:46:02.040Z — 31e512d8…5719
total: 1:10.031
ranked: no; the attempt was untimed
Time to solve
All three modes were solved by 16:46:02 UTC (12:46:02 ET), 3 h 45 min 33 s after the first start. The Single Solve took 3 h 19 min because the D12 storage question had no defined vocabulary until it was fixed; the Time Trial failed twice on reversed hashes before an untimed, batched diagnosis went through at 16:41:02, and the untimed Mastery took 1 min 10 s. None of the timed modes was ranked.
Takeaways
- Validate the transform. A plausible plaintext is not enough; require the record length, CRC32, and JSON parse to agree.
- Separate bytes from vocabulary. D12's physical placement was visible, but its canonical category needed explicit question rules.
- Keep archive order. Answer numbering can refer to ZIP order even when alphabetical order looks stable.
- Use partial feedback. Untimed day batches reduced a 204-field failure to D15 and D16; splitting those batches exposed the hash-only defect.
- Plan for format variants. The PE symbol and section-name questions needed COFF-specific handling alongside the ELF and WebAssembly paths.