The challenge
The extensions claim one story; the first sixteen bytes tell another. Identify what each artifact actually is and isolate the deliberate disguise.
One question per file: "What are the first sixteen bytes as lowercase hexadecimal?" The answer is 32 hex characters, with no 0x and no spaces. (In this write-up the hex answers are shown with a space between bytes, for reading.)
| Mode | File asked about |
|---|---|
| Single Solve | metadata- |
| Time Trial | metadata- |
| Mastery | set 1 …- · set 2 …- |
Reading the prompt: what it said we'd need
| Clue | What it pointed to | What I did about it |
|---|---|---|
| "The extensions claim one story" | Extensions are labels, and labels can lie (the theme of Day 1's Hash to Ride) | Never decide a file's type from its name |
| "the first sixteen bytes tell another" | Magic bytes: the signature at the start of a file that says what it really is | Read the member's first 16 bytes, straight from inside the zip |
| "Identify what each artifact actually is" | Compare the signature with the extension | Record each file's true type, even though only the hex is submitted |
| "isolate the deliberate disguise" | At least one file's extension is a lie | Expect it in a later mode (the Mastery file is literally named disguised-) |
| The same zips and member names as Hash to Ride | A compounding day | Reuse Day 1's solver, with all its checks |
What magic bytes look like: many formats start with a fixed signature. %PDF- (255044462d) is a PDF. PK\x03\x04 (504b0304) is a zip, and also a .docx, .xlsx, .jar, or .apk, since those are zips inside. \x89PNG is a PNG, and MZ is a Windows executable. Plain text has no signature; its first bytes are just its first characters.
What was in the files
| Mode | File | Extension says | The first 16 bytes say | Disguised? |
|---|---|---|---|---|
| Single Solve | evidence- (126 B) |
text | Huntress Metadat: text |
No |
| Time Trial | roster. |
CSV | analyst_: CSV text |
No |
| Mastery set 1 | evidence- (126 B) |
text | Huntress Metadat: text |
No |
| Mastery set 2 | disguised- (95 B) |
"binary" | %PDF-: a PDF |
Yes: a PDF with a . extension |
Every other file told the truth. The only disguise was the PDF, which is "the deliberate disguise" the prompt promised. The Mastery delivery was itself a zip of two zips, and those inner zips correctly start with the zip signature 504b0304.
The Single Solve note, for context: the same kind of case note as Day 1 ("Huntress Metadata Forensics evidence note / Case marker / Endpoint / Collected sequence …"), 126 bytes. Its first 16 bytes are the start of its own first line.
Single Solve: CORRECT in 20 seconds
- Played entirely through the new pairing token, which needs no Homebase or VPN (it was announced on Discord on 2026-10-03). In token mode, the start reply's download link takes the outside form
/?op=download&capability=…, and the client handled it unchanged. - The zip: 287 B, its SHA-256 matching the start reply. It holds one member,
evidence-note.txt. - It was read in memory with the Day 1 inventory, which also checks that the zip's two name records agree.
- Answer
48 75 6e 74 72 65 73 73 20 4d 65 74 61 64 61 74(Huntress Metadat) → CORRECT at 13:33:59, 20 s after the start. Flag2791a342…3b36.
The solver: Day 1's, plus one field
Our Day 2 solver loads Hash to Ride's solver and adds a single new field, …-magic-prefix-hex-16 = the target member's first 16 bytes as lowercase hex. Everything else is inherited: finding the member from the question's zip -> member label, the name-record check, nested and stored zips, and keeping each Mastery set to its own zip.
Two snags: - A trap in the old code: Day 1's field matcher treats the word "bytes" as a size question, so "first sixteen bytes" would have been answered with the file size. The new field is matched first. - Both days' solver files have the same module name, so Day 1's is loaded by its path. Its dataclasses also need the module registered first.
5 tests: the real Single Solve; not-a-size-question; a PDF disguised as .bin and a PNG as .txt; Mastery's real question shape as separate and nested (stored) zips; and a file shorter than 16 bytes, which stops.
Time Trial: 2.62 s locally (1.167 s on the leaderboard), against a 5 s clock
started_at 2026-10-07T13:35:28.928Z deadline 2026-10-07T13:35:33.928Z
artifact metadata-day-02-evidence.zip 233 bytes sha256 cb06ac9e8c8a7319… (checked)
roster-magic-prefix-hex-16: 61 6e 61 6c 79 73 74 5f 69 64 2c 63 61 73 65 5f
start 918 ms
artifact 660 ms
solve 1 ms
submit 1046 ms
TOTAL 2624 ms
result CORRECT flag 775cbf17…73c6
Mastery: 3.35 s locally (1.080 s on the leaderboard), first attempt
started_at 2026-10-07T13:43:00.842Z deadline 2026-10-07T13:43:05.842Z
artifact metadata-forensics-day-02-looks-can-be-deceiving-mastery.zip 864 bytes sha256 286fe65f5037df6f… (checked)
set1.evidence-note-copy-magic-prefix-hex-16: 48 75 6e 74 72 65 73 73 20 4d 65 74 61 64 61 74
set2.disguised-report-magic-prefix-hex-16: 25 50 44 46 2d 31 2e 37 0a 25 20 48 75 6e 74 72
start 1750 ms
artifact 622 ms
solve 1 ms
submit 981 ms
TOTAL 3354 ms
result CORRECT flag 516ed5a4…f240
Why the local times are slower than the leaderboard's
The leaderboard seems to time from when the server receives the start to when it receives the submit. Our local total also counts the start reply travelling back and the submit reply travelling home. The solving itself took 1 ms. Almost all the time was network, and most of that was connection setup: each request starts a fresh curl with a new HTTPS handshake. A reused connection would cut that a lot. The leaders were at about 0.18 s.
Time to solve
All three modes were solved on 2026-10-07 by 13:43:02 UTC, 9 min 23 s after the first start. The Single Solve took 20 s, and the Time Trial and Mastery each went through on the first submit and were ranked (1.167 s and 1.080 s on the leaderboard).
Takeaways
- A file's first bytes say what it is; its extension says what someone wants you to think it is. Here,
disguised-report.binwas a PDF. - Read signatures from inside the archive. No extraction and no execution are needed to identify a file.
- Reusing earlier days' code is the point of compounding days, but check the old code's assumptions. "Bytes" meant size to Day 1's solver.
- In timed modes, the network dominates. Solving took 1 ms; connection setup took most of the 1–3 s.