The challenge
"Filenames have been randomized, but Windows version resources remember what the binaries called themselves. Recover the original identities and expose the impersonator."
One question about telemetry-agent-001.exe inside metadata-day-11-evidence.zip.
| answer_id | Question | Format |
|---|---|---|
d09- |
"Determine pe.version_original_filename for telemetry-agent-001.exe." | exact_: the artifact's own text, punctuation kept, no explanation; trimmed |
Reading the prompt: what it said we'd need
| Clue | What it pointed to | What I did about it |
|---|---|---|
| "Filenames have been randomized" | The name in the zip is worthless as an answer | Checked what the existing solver would send: the zip name. Day 1's matcher reads any question ID ending in - as "the member's name". So the new field had to be matched exactly and checked first |
| "Windows version resources" | The PE's RT_ resource (VS_), whose string table holds OriginalFilename |
Walked the resource directory to it, rather than searching the file for the text |
| "what the binaries called themselves" | The OriginalFilename string, exactly as stored |
Answered it with no changes |
| "expose the impersonator" | A file whose name on disk doesn't match its recorded identity | Every file here was one: telemetry- on disk, pe- inside. No separate question asked about it |
Safety
- The artifacts are Windows executables (the Single Solve file is a Go build). Everything was static: the solver reads bytes with
structand never runs or loads a challenge file. pefile was used once as a read-only cross-check. - The artifacts stayed on our Kali VM; none were copied to a Windows machine.
What was in the files
- Single Solve:
telemetry-agent-001.exe, a 1.26 MB PE32 (Intel i386) Go binary. Its one version string table (language040904b0, US English, Unicode) holds CompanyNameHuntress Labs, FileVersion1.0.0.0, OriginalFilenamepe-base-386.exe, ProductNameHuntress Metadata Forensics, and ProductVersion2026.10.1.0. - Time Trial: the same template with
telemetry-agent-002.exe(1.33 MB), whose OriginalFilename waspe-base-amd64.exe. - Mastery: an outer zip holding
metadata-day-11-evidence-01.zipand-02.zip, one executable each. Their OriginalFilenames werepe-base-arm64.exeandpe-base-386.exe.
The original names follow Go's architecture names (386, amd64, arm64), so this looks like one program built for several targets and then renamed.
Single Solve
The morning solver's prep was wrong. It started the Single Solve, downloaded it, and reported that the latest Metadata solver "answers 1/1 questions". Running that solver on the material showed it would have sent telemetry-agent-001.exe, the randomized name. That's a trap we first met on Day 2: an older day's loose field matcher answers a new question with confidence.
Our solver wraps Day 10's, which wraps Days 1–9. It adds:
- a resource-directory walk: data directory 2 → the RT_VERSION (type 16) entry → every name and language → each leaf's data, mapped from RVA to file offset through the section table;
- a generic reader for VS_VERSIONINFO nodes (length, value length, type, UTF-16 key, 32-bit alignment, children), which returns one dictionary per string table;
- an exact check for question IDs ending in pe-version-original-filename, placed before the older days' matchers. No version resource gives none, the same convention as Days 9–10 for non-PEs (not tested on this field). Two string tables that disagree stop the run instead of guessing;
- handling for Mastery questions labelled delivery N: <zip> -> <member>, which this lane hasn't used yet.
The first send of pe-base-386.exe hit HTTP 429. The morning solver had made about 25 requests in 10 seconds and the limit counts every request. One more try two minutes later also got 429. After the limit cleared: CORRECT (a7df8224…b3dd).
Its tests (7, all pass):
- a PE with no resources gives no answer, and so does a fake OriginalFilename UTF-16 string outside the resource section (in a PE and in a script);
- the real Single Solve answers exactly pe-base-386.exe, and the whole string table reads correctly;
- a plain -filename question still means the member's name (Day 1 isn't broken);
- a delivery 1: label finds its download, and a mismatched delivery stops;
- Day 10's real question still answers 0x00065bd0.
Time Trial
CORRECT on the first attempt. The first start asked for a ranked clock and got 409 timed_intent_not_available: this route doesn't take the opt-in, and nothing started. A plain start was already timed (deadline 7 s after started_at, ranked, 1 unique attempt remaining).
started_at 2026-10-11T13:14:14.761Z
deadline 2026-10-11T13:14:21.761Z (7 s)
answers 1 pe-base-amd64.exe
start 483 ms
artifact 397 ms
solve 6 ms
submit 645 ms
TOTAL 1.53 s
result CORRECT flag 2e64aa5a…88ec
Mastery
CORRECT on the first attempt (2 sets, deadline 7 s, 1 unique attempt remaining).
started_at 2026-10-11T13:14:22.545Z
deadline 2026-10-11T13:14:29.545Z (7 s)
answers 2 pe-base-arm64.exe, pe-base-386.exe
start 459 ms
artifact 304 ms
solve 11 ms
submit 875 ms
TOTAL 1.65 s
result CORRECT flag 8eb3f79c…28fb
Time to solve
The morning solver started and downloaded the Single Solve at 13:00:05 UTC; two manual sends hit HTTP 429, and once the limit cleared the Single Solve went CORRECT at 13:13:49. The ranked Time Trial (1.53 s) and the Mastery (1.65 s) each went CORRECT on the first submit, the Mastery at 13:14:23, 14 min 18 s after the first start.
Takeaways
- A version resource keeps the name the developer gave the file. Renaming the file on disk doesn't change
OriginalFilename, so comparing the two exposes the disguise. - Parse the structure; don't search for the string. Walking the resource directory means a decoy
OriginalFilenameelsewhere in the file can't answer. A test pins this. - "The solver already knows this" needs checking. The prep's count was based on a loose match that would have sent a wrong answer with confidence. The new field's check now goes first and matches exactly.
- The rate limit counts every request. A burst from the morning solver blocked our manual sends for about 7 minutes, the biggest part of today's finish time.