zwesty
Write-ups / Day 21 / Metadata
Day 21 · Wed, Oct 21 · Metadata

Package Deal

Prey slaughtered

APK structure, Android binary XML (AXML) manifests, pre-building parsers for likely fields

STTMClaude Homebase Both

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

Challenge ID
metadata-forensics-day-21-package-deal (+ /time_trial, /mastery)
Solved
2026-10-21: all three modes CORRECT on the first submit, by 09:02:11 ET, 28 s after the solver's first start request (09:01:43 ET). Both timed modes were ranked runs. Late start: the scheduled 08:58 run didn't start because a leftover session on our Kali VM was still blocking it, and a catch-up run began at 09:01:40, about 3 min 39 s late. So the 2 min 11 s from the 9 AM release to the Mastery CORRECT includes that delay (on Day 20 the solver's first request went at 09:00:22)
Player
Zwesty (solo); solved by our automated morning solver (a scheduled script on our Kali VM), built with Claude Code (Opus 5.5) and started here by the catch-up run, with no manual work needed

The challenge

"Mobile packages have been mirrored under friendly filenames. Recover Android package identities, distinguish rebuilds from clones, and expose the borrowed product name."

answer_id Question Format
d21-apk-001-apk-package-name "Determine apk.package_name for mobile-001.apk." exact text: "exact artifact-derived value only, without quotes or explanatory text unless quotes are part of the value; use the literal none only when the requested field is absent"; trimmed

The Time Trial asked 26 questions: every earlier day's field (roster, evidence note, JPEG, PNG, PDF, ZIP, PE, .NET, MSI, LNK, OOXML, email, audio, video, ELF, Mach-O), today's package name, and the SHA-256 ordering synthesis. The Mastery asked the same family across 5 sets (130 questions).

Reading the prompt: what it said we'd need

Clue What it pointed to What I did about it
"mirrored under friendly filenames" The APK sits in the evidence zip under a generic name (mobile-001.apk), so the name says nothing about the app Read the identity from inside the APK, not from the filename
"Recover Android package identities" The package attribute of <manifest> in the binary AndroidManifest.xml The pre-built parser's AXML reader returns it verbatim; that answered the one new field
"distinguish rebuilds from clones" Signing (META-INF signature files) and version fields Not asked today. The pre-built parser already has signed / signature-file / version fields if a later day asks
"expose the borrowed product name" Probably the app's android:label (Huntress Evidence 08281778 here) Not asked today; noted for later

What was in the files

  • Single Solve: metadata-day-21-evidence.zip, 4,436 bytes, one member: mobile-001.apk, 8,535 bytes. Inside: a binary AndroidManifest.xml (1,840 bytes), a 912-byte classes.dex, and v1 signing files (META-INF/MANIFEST.MF, FIXTURE-.SF, FIXTURE-.RSA, certificate subject "Huntress Artifact Assembly Line", Huntress Labs). The manifest gives package com.huntress.arena.p08281778, version name 1.0, label Huntress Evidence 08281778, and one launcher activity .MainActivity.
  • Time Trial: evidence.zip, 632,986 bytes, 17 members: one sample per earlier day's file type (from camera-001.jpg to macos-001.bin) plus the same 8,535-byte mobile-001.apk.
  • Mastery: one 3,166,036-byte zip of 5 evidence sets (evidence-01.zip …), 130 questions. The per-set questions rotate which file is renamed (for example "the renamed evidence-note copy").

Every APK in every mode gave the same package name, so the timed variants reused the template with the same APK value. The Mach-O sample was still thin arm64 in every set (["0x0100000c"]), so Day 20's fat / ar ordering rule is still unconfirmed.

Single Solve

The solver solved it with no stop. Its preparation step started the Single Solve untimed and checked the one question. The field apk-package-name was new, but a parser we had built ahead of time already covered it:

  • A pre-built media and package parser (built 2026-10-15, before the day). It has its own reader for Android binary XML and maps package-name (also package, package-id, app-package, application-id) to <manifest package>, verbatim. Its tests compare it with aapt's output on an aapt-built APK and on saved Android-lane APKs.
  • The solver was our Day 20 Metadata solver, which loads that parser through its chain. No code was written today and no candidate guessing was needed.

Because the one question was already covered, the solver sent the Single Solve on its own. It logged a harmless note twice: one module skipped two field names (pe-signed, pe-is-signed) that another module already registers.

started_at  2026-10-21T13:01:43.849Z
deadline    none (Single Solve)
answers     1   com.huntress.arena.p08281778
start        175 ms   (the send step's start, resuming the attempt the preparation step opened)
artifact     347 ms
solve          1 ms
submit       565 ms
TOTAL       1087 ms   (submit +6.86 s after started_at; the preparation step ran in between)
result      CORRECT   flag 99dcb231…c0cc

Before the timed runs, a regression rehearsal replayed 93 saved attempts: slowest 0.08 s, identical on every Mastery set; it passed.

Time Trial

CORRECT on the first attempt, ranked. The start reply showed unique_attempts_remaining: 31.

started_at  2026-10-21T13:02:03.783Z
deadline    2026-10-21T13:02:53.783Z   (50 s)
answers     26
start        417 ms
artifact     274 ms
solve         12 ms
submit       586 ms
TOTAL       1289 ms   (submit +1.07 s after started_at)
result      CORRECT   flag af3380c4…7c63

Mastery

CORRECT on the first attempt, ranked (5 sets, 170 s clock).

started_at  2026-10-21T13:02:10.276Z
deadline    2026-10-21T13:05:00.276Z   (170 s)
answers     130 across 5 sets
start        289 ms
artifact     394 ms
solve         87 ms
submit       799 ms
TOTAL       1570 ms   (submit +1.39 s after started_at)
result      CORRECT   flag 1d74d30f…912c

Time to solve

All three modes were solved by 09:02:11 ET, 28 s after the solver's first start request at 09:01:43 ET, and each went through on the first submit; both timed modes were ranked. The finish, 2 min 11 s after release, was set by the late start: the catch-up run began at 09:01:40 instead of 08:58.

Takeaways

  • Pre-building paid off again. The APK manifest reader was written six days early as a guess; today it answered the new field first time, so the lane needed no candidate guessing.
  • The prompt promises more than the questions ask. "Rebuilds from clones" and "the borrowed product name" weren't asked today. They may come back as fields on later days, and the parser already covers signing and versions.
  • The late start cost more than the solve. The whole lane took 28 s; the late start cost about 3 min 39 s against the schedule.