zwesty
Write-ups / Day 5 / Android
Day 5 · Mon, Oct 5 · Android

Backup Spill

Prey slaughtered

Static APK inspection (an APK is a zip), reading packaged assets, simple decoding (split)

STTMClaude Homebase Both

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

Challenge ID
mobile-android-day-05-backup-spill (+ /time_trial, /mastery)
Solved
2026-10-10, all three modes, 4 min 59 s from first start to last CORRECT
Player
Zwesty (solo), with Claude Code (Opus 5.5)

The challenge

Extract synthetic application state admitted by a flawed backup boundary.

One question, answer: “For case MOB-05-9E90479049 in package com.huntress.mobile.d05.v9e904790496a: Extract synthetic application state admitted by a flawed backup boundary. Submit only the exact backend answer code returned for this case.” Artifact: backup_spill.apk. Format: ANS- followed by exactly 16 uppercase hexadecimal characters; no spaces or explanatory text, normalization exact.

How this lane was solved is explained once, in the Network Config Split write-up (Day 10, the first Android solve). Short version: every assigned APK carries assets/huntress_puzzle.json, and decoding it gives the answer. The app never has to run.

Reading the prompt: what it said we'd need

Clue What it pointed to What I did about it
flawed backup boundary allowBackup-style app data exposure Static route
synthetic application state made-up data, safe to extract The puzzle used the split codec: three pieces and an order

Honest note: the prompts describe real Android attack surface, which would mean installing and driving the app. In this event the answer sat in a packaged JSON file that the app's own code never reads, so none of that was needed.

Safety

Static only. The APKs were opened as zip files on our Kali VM and one JSON asset was read; nothing was installed or run.

What was in the files

backup_spill.apk, about 12.7 KB: one classes.dex, the manifest, a few resources, and assets/huntress_puzzle.json:

{"schema":"huntress.mobile.puzzle.v1","day":5,"codec":"split","data":"","parts":["0A353BE7B","ANS-5","709E18"],"order":[2,0,1]}

Codec split: the answer cut into parts; part i goes in slot order[i] (part 1 ANS-… goes first). The other reading, parts[order[i]], puts ANS- last and can't match the format.

The Time Trial and Mastery APKs use the same template with different values.

Single Solve

Started untimed to download the APK, decoded by our shared Android solver, and sent once (Day 10 had already confirmed how split reads): ANS-5709E180A353BE7B → CORRECT in 1,664 ms (start to submit), flag 5572c33f…00a4.

Solver: our Android solver from Day 10, shared by Days 1–10. It reads the asset from the zip, checks the schema, decodes the codec, and returns the answer only if it is exactly ANS- + 16 uppercase hex; anything unknown stops the run before sending. Its tests: 10/10.

Time Trial

A 6-second clock. Same puzzle schema and codec as the Single Solve.

started_at 2026-10-10T15:56:38.419Z  deadline 2026-10-10T15:56:44.419Z  answer_ids ['answer']
  artifact backup_spill_time_trial.apk 12704 bytes sha256 a8c24ec33f7d8d37… (checked)
  answer: ANS-B39DB6B0EF32F0C7
  start         596 ms
  artifact      330 ms
  solve           1 ms
  submit        847 ms
  TOTAL        1774 ms
result CORRECT  flag 7eae66fa…ff0d

Mastery

A 7-second clock. 3 APKs, one per set; the questions name them delivery N: …_mastery_0N.apk. Same puzzle schema and codec as the Single Solve.

started_at 2026-10-10T15:56:41.330Z  deadline 2026-10-10T15:56:48.330Z  answer_ids ['set1.answer', 'set2.answer', 'set3.answer']
  artifact 01-backup_spill_mastery_01.apk 12704 bytes sha256 f753e9cba23a02b1… (checked)
  artifact 02-backup_spill_mastery_02.apk 12704 bytes sha256 93d510784a744062… (checked)
  artifact 03-backup_spill_mastery_03.apk 12704 bytes sha256 b40bb7a28d1fb865… (checked)
  set1.answer: ANS-5C0FFD4E9D125126
  set2.answer: ANS-47041998B0057DDC
  set3.answer: ANS-D5567D49A864EB0E
  start         679 ms
  artifact      346 ms
  solve           1 ms
  submit        618 ms
  TOTAL        1644 ms
result CORRECT  flag 4bb1f770…9854

Time to solve

All three modes were solved on 2026-10-10 by 15:56:42 UTC, 4 min 59 s after the first start; each mode went through on its first submit, and both timed runs were ranked.

Takeaways

  • Read every packaged file before assuming the app must run. The answer sat in assets/, unread by the app's code.
  • The answer format is a strong check. ANS- + 16 uppercase hex rules out wrong decodings (Day 10's other split reading, a wrong Caesar direction) before anything is sent.