The challenge
Rust leaves its own fingerprints: mangled symbols with a distinct accent, panic strings that confess, trait objects hiding in plain sight. Learn the accent.
One evidence.zip (AES, password infected) holding every binary from Days 1–5, and 40 questions: Go Fish's 32 plus 8 for the new Rust file. Every question uses the same template: "What is the exact <field> value for field <answer_id> in the delivered evidence set?" All are checked with exact normalisation.
answer_id |
What it asks for | Format |
|---|---|---|
d01_, d01_ / machine / elf_ / endianness |
Day 1's C ELF: hash and header fields | Exact text |
d01_, d01_ |
Day 1's section and symbol lists | Compact JSON array, exact order |
d01_ |
recover_'s instructions |
JSON array; empty if recover_ is absent |
d02_, d02_ |
Day 2's C++ ELF | Exact text |
d02_ / domain / mutex / url |
Day 2's config | Exact text |
d02_, d02_ |
Day 2's config checksum and key | Lowercase hex with 0x |
d03_ / _, d03_ / metadata_, config campaign / domain / mutex |
Day 3's .NET DLL and its runtimeconfig | Exact text |
d03_ |
Day 3's container | "one container_runtime token; CLI, CLR, or .NET may name the managed part" |
d04_, d04_ / format, config campaign / domain / mutex / url |
Day 4's Go ELF | Exact text |
d04_ |
Day 4's config checksum | Lowercase hex with 0x |
d05_ |
The Rust ELF's SHA-256 | Exact text |
d05_, d05_ |
Its machine and its format | Exact text |
d05_ / domain / mutex / url |
Its config | Exact text |
d05_ |
Its config checksum | Lowercase hex with 0x |
The exact-text format adds: "use the literal none only when the requested field is absent." d05_analysis_format is the field this write-up is mostly about. The question gives no hint about its vocabulary. Only Day 3's version of the field does.
Reading the prompt: what it said we'd need
| Clue | What it pointed to | What I did about it |
|---|---|---|
| "Rust leaves its own fingerprints" | The new file is a Rust binary, and it can be recognised as one | Confirmed it from the toolchain string in . (rustc 1.) and Rust standard-library source paths |
| "mangled symbols with a distinct accent" | Rust's own symbol mangling, different from C++'s | The file is not stripped, so the symbols are there. No question asked about them, so none are recorded here |
| "panic strings that confess" | Rust's panic messages carry source paths | The Homebase agent saw paths into Rust core and the standard library. Again, no question needed them |
| "trait objects hiding in plain sight" | Rust's vtables for dyn Trait |
Not needed for any answer |
| The 8 d05 questions are the same fields as Day 4's | Same config layout as the Go binary, so the same extractor should work | Ran our HCFG config extractor on the Rust file: one CRC-checked hit |
d05_, "exact artifact-derived value" |
A label for the file's format, in a vocabulary nobody had confirmed yet | Day 3's hint (a "container_runtime token") suggested ELF_. That hint was for Day 3 only (see below) |
In short, the prompt teaches how to recognise Rust, but the questions only asked what Day 4 asked. Recognising the language mattered for triage, and it was misleading for the format field.
Safety
Static analysis only. No binary was ever executed. The evidence was unpacked and read on our Kali VM (Claude, Single Solve) or in the Huntress AI Homebase (the agent, timed runs), and the artifacts stayed there. Our binary solver only reads bytes: it hashes files, parses headers, and scans for the config record. It never runs anything from the evidence.
What was in the files
The Single Solve's evidence.zip: 1,916,070 bytes, SHA-256 6049e2c8…e117 (matched the start reply), AES-encrypted with infected.
- d01–d04 were byte-identical to Go Fish's (SHA-256 checked): the C ELF, the C++ ELF with its config record, the .NET DLL with its
runtimeconfig.json, and the Go ELF. See the Day 1–4 write-ups for those. - d05, the new file:
d05--variant-000.elf, SHA-2564ac8f95b…c247.
file on d05 (the Homebase agent's saved output):
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, with debug_info, not stripped
What identifies it as Rust:
- .comment names the compiler: rustc 1.90.0 (1159e78c4 2025-09-14).
- It's not stripped and keeps its DWARF debug info, so Rust symbol names and source paths stay in the file.
- Embedded source paths point into Rust's core and standard library (the Homebase agent's reading).
- Like the Go binary, it also carries the lab's huntress.binary.dynamic_trace.v1 string next to HUNTRESS_HOST_MODE / HUNTRESS_HOST_MODEL (found by the agent's byte-string scan).
Where its config sits: in the same HCFG record the C++, .NET, and Go binaries carry: a magic, a version, a one-byte XOR key, a length, a CRC32 of the plaintext, then the XOR'd JSON. The Rust compiler didn't change the record at all. Our extractor scans the whole file for the magic and only accepts a hit whose CRC32 matches, so it didn't need to know which language built the file. (Which section or offset it sat at wasn't recorded.)
| Field | d05 value |
|---|---|
| XOR key / length / CRC32 | 0x61 / 368 bytes / 0x8f37c323 (CRC verified) |
| campaign | BR05- |
| domain | node- |
| url | https:/ |
| mutex | Global\HuntressBR05_ |
| ipv4 (not asked) | 198. |
The timed variants used the same template. The Time Trial's 40 answer IDs matched the Single Solve's. Mastery had two sets of 40 (80 answers), and set 2 swapped two of the files' type: d02 (MinGW C++) and d04 (Go) came as native Windows PE .exe files instead of ELFs. The d05 Rust file stayed an ELF in both sets. (The variants' own values aren't recorded here; the solver reads them fresh each run.)
Single Solve: CORRECT (on 2026-10-09, after a long wait on format)
The certain answers went in first, as one batch. Go Fish's 24 accepted answers were rebuilt from its request log, and the 7 new d05 answers added: the SHA-256, architecture x86-64 (Go Fish had already shown that the ELF machine spelling wins over amd64), and the 5 config fields. 31 sent → accepted, 9 left. The whole new day took one submit, because the config extractor was language-independent.
What was left (9): the 7 d02 fields and the format answers for d04 and d05.
The d02 config fields came from the Homebase agent. Claude's safety filter had stopped one step of the analysis during the d02 config work on Mangled, and we didn't work around it, so Claude didn't attempt them here. The agent's Day 2 config analyser answered all six; sent as their own batch on 2026-10-07 at 17:13: accepted, 3 left (d02_analysis_format, d04_analysis_format, d05_analysis_format).
The long-open format field
Every ELF and JAR day had the same open field, and every guess followed Day 3's hint. Day 3's .NET answer was PE_CLI (container + runtime), so a Rust ELF "should" be something like ELF_Rust. It wasn't.
| When (UTC) | Who | Where | Value sent for the Rust ELF's format | Result |
|---|---|---|---|---|
| 2026-10-07 16:13:23 | Claude (our Kali VM) | Rust Belt | ELF_ |
incorrect. Stopped: the d02 and d04 formats were open too, so one pattern was likely |
| 2026-10-08 | Homebase agent | Routine Check (same d05 file) | ELF64_, then Rust_ |
both incorrect |
| 2026-10-09 13:27:16 – 15:25:23 | Homebase agent | Rust Belt | ELF/, ELF64_, ELF_, ELF64/, Rust, RUSTC, ELF64_, RUST_ (8 single-value submits) |
all incorrect |
On 2026-10-09 the agent kept probing across all the open format fields. It worked through container + language spellings, file and MIME output, ABI names and header combinations on the other challenges. The answer was the simplest one: lowercase elf, the family name objdump -f prints (elf64-x86-64). Uppercase ELF had been rejected on Day 2, and the lowercase form hadn't been tried until then.
Once Mangled accepted elf, it unlocked every ELF format field at once, and jar did the same for the JARs. On Rust Belt:
| Time (UTC) | Field | Value | Result |
|---|---|---|---|
| 15:31:29 | d02_ |
elf |
accepted, 2 left |
| 15:34:33 | d05_ |
elf |
accepted, 1 left |
| 15:35:23 | d04_ |
elf |
CORRECT |
Single Solve: 40 of 40. Flag c0446667…fa85.
The confirmed d05 answers: SHA-256 4ac8f95b…c247 · architecture x86-64 · format elf · the five config values above.
The solver: our core binary solver answers every SHA-256, architecture, format, and config field from the evidence bytes, using the HCFG extractor for the config and an archive reader to open the AES zip. format returns elf for anything with the ELF magic, jar for a JAR, and PE_CLI for Day 3's managed DLL. In the timed runs the d01 ELF fields came from the Homebase agent's Day 1 ELF reader and the d02 config from its config analyser (the Single Solve carried d01 over from Go Fish). A small helper on our Kali VM sent the Single Solve's explicit answers.
Time Trial: CORRECT in 2.5 s (first attempt)
Run by the Homebase agent, as part of its timed batch for Days 3–9. Our solvers covered all 40 answers, so it was one submit.
started_at 2026-10-09T16:58:58.970Z deadline 2026-10-09T16:59:05.970Z (40 answer_ids)
(Homebase agent, coverage 40/40)
start 449 ms · artifact 502 ms · solve 868 ms · submit 716 ms · TOTAL 2534 ms
result CORRECT flag c1923710…4ca9
A 7-second window, finished in 2.5 s. Claude later re-ran the fixed solvers offline against the saved delivery: same 40 answers as the agent submitted.
Mastery: CORRECT in practice mode (from our Kali VM)
Attempt 1 (Homebase agent, 16:59:06): stopped before submitting. Nothing was sent.
started_at 2026-10-09T16:59:06.275Z deadline 2026-10-09T16:59:13.275Z (2 sets x 40 answer_ids)
(Homebase agent)
missing: set1.d02_config x6 · set2.d02_analysis_format · set2.d02_config x6
set2.d04_analysis_architecture · set2.d04_analysis_format
result stopped before submit (coverage check)
Two things were missing:
- The Day 2 config analyser ignored setN.-prefixed answer IDs and .exe files, so set 1's and set 2's d02 config went unanswered.
- Set 2's d02 and d04 were native Windows PE files. There was no confirmed format or architecture value for a native PE.
The fixes (Claude, 2026-10-09): the config analyser handles set IDs and .exe; a new native-PE add-on holds the PE answers, off until confirmed. Both PE values were confirmed in one submit on Nimble's Mastery at 17:27 UTC: format pe and architecture x86-64 (machine 0x8664).
Attempt 2 (Claude, from our Kali VM). The retry was refused: Rust Belt had no fresh variants left. Practice mode continues on the last delivery with no timer and no Hall of Fame time, and still completes the mode.
17:28:36 retry -> HTTP 409 rotation_exhausted (unique_attempts_remaining 0)
17:28:37 practice -> started_at 2026-10-09T17:28:37.327Z, deadline None (practice)
80 answers (2 sets x 40), set 2 with the PE answers pe / x86-64
TOTAL 2742 ms
result CORRECT flag 6ebbef89…1f55
(Only the total was recorded for this run, not the per-phase timings.) Correct on the first submit, because every field had a confirmed rule by then.
Time to solve
The Single Solve was completed on 2026-10-09 at 15:35:23 UTC: 31 of 40 answers were accepted 10 s after the start on 2026-10-07, and the three format fields stayed open for two days. The Time Trial went through first time in 2.53 s; the first Mastery attempt stopped before submitting, and the Mastery was finished at 17:28:39 UTC as untimed practice, so it is unranked, 2 days 1 h 16 min after the first start.
Takeaways
- One language-independent extractor turned a new language into one submit. Our
HCFGextractor finds the config by its magic and checks it by its CRC, so Rust, Go, C++, and .NET all looked the same to it. - A hint for one field isn't the rule for its neighbours. Day 3's "container_runtime token" hint shaped every guess for the ELF and JAR formats (
ELF_Rust,ELF64_Rust, …). The real answer was just the container:elf. - Under exact normalisation, case is a separate guess.
ELFwas rejected on Day 2, and that hidelffor days. - One confirmed answer can unlock a whole lane.
elfon Mangled closed the ELF format fields on seven challenges. - Recognising the language is triage, not the answer. The prompt taught Rust's fingerprints. The questions only wanted the hash, machine, container, and config.
- Mastery can change the file type under you. Set 2 swapped two ELFs for PE files, so a coverage check before submitting is what kept the first attempt from sending guesses.
- An exhausted Mastery still finishes in practice mode: no timer, no Hall of Fame, but the mode completes.