zwesty
Write-ups / Day 11 / Android
Day 11 · Sun, Oct 11 · Android

Local Secrets

Prey slaughtered

Static APK inspection, reading a packaged asset, XOR decoding

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-11-local-secrets (+ /time_trial, /mastery)
Solved
2026-10-11, all three modes; 7 min 8 s from first start to last CORRECT (09:00:12–09:07:20 ET)
Player
Zwesty (solo), with Claude Code (Opus 5.5); all three modes by our automated morning solver (a scheduled script on our Kali VM), the timed modes on a manual rerun after an HTTP 429

The challenge

Separate active credentials from decoys across generated local stores.

One question, answer: "For case MOB-11-… in package com.huntress.mobile.d11.…: Separate active credentials from decoys across generated local stores. Submit only the exact backend answer code returned for this case." Format: ANS- + 16 uppercase hex characters.

Reading the prompt: what it said we'd need

Clue What it pointed to What I did about it
"active credentials … decoys … local stores" an app's on-device storage (shared preferences, databases) Not needed: as on Days 1–10, the answer is in the APK's assets/huntress_puzzle.json
"backend answer code" a runtime service The same packaged puzzle; the app is never run

The full method is in the Network Config Split write-up.

Safety

Static only: each APK was opened as a zip and one JSON asset read. Nothing installed or run.

What was in the files

One 12.7 KB APK per set with assets/huntress_puzzle.json, codec xor (as on Day 4): data is Base64, and each decoded byte is XORed with key. Single Solve, Time Trial, and all three Mastery APKs used xor with different keys.

Runs (all by the solver, using our shared Android solver)

Single Solve   start 320  artifact 251  solve 0  submit 1249  TOTAL 1820 ms   CORRECT 0bc1a2d3…d136
               vs started_at: start +81, artifact +331, ready +332, submit +1581 ms
Time Trial     7 s clock, ranked; vs started_at: start +67, artifact +339, ready +340, submit +959 ms
               CORRECT e2a5b0a0…1b9e
Mastery        8 s clock, 3 APKs (delivery N: …_mastery_0N.apk); vs started_at: start +66, artifact +395, ready +396,
               submit +1053 ms   CORRECT c640671b…08e4

The timed modes ran at 09:07, not 09:00: the solver hit HTTP 429 right after the Single Solve and stopped. After pacing was added (5 s between runs, 1 s between status checks) and the limit cleared at 09:06:55, a manual rerun finished them with no further 429s.

Time to solve

The Single Solve started at 13:00:12 UTC and went CORRECT 2 s later; an HTTP 429 then stopped the solver. On the paced rerun the ranked Time Trial and the Mastery each went CORRECT on the first submit, the Mastery at 13:07:20, 7 min 8 s after the first start.

Takeaways

  • The puzzle-asset solver carried straight over: a known codec, no change, all modes unattended.
  • The rate limit counts every request, not just submits; the 7-minute gap was the limit, not the solver.