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

Pending Intent Relay

Prey slaughtered

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

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-04-pending-intent-relay (+ /time_trial, /mastery)
Solved
2026-10-10, all three modes, 4 min 55 s from first start to last CORRECT
Player
Zwesty (solo), with Claude Code (Opus 5.5)

The challenge

Recover and redirect a mutable PendingIntent while preserving every earlier component check.

One question, answer: “For case MOB-04-0C53CC9C9F in package com.huntress.mobile.d04.v0c53cc9c9f40: Recover and redirect a mutable PendingIntent while preserving every earlier component check. Submit only the exact backend answer code returned for this case.” Artifact: pending_intent_relay.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
mutable PendingIntent a PendingIntent another app can fill in Static route
preserving every earlier component check the lane compounds: Days 1–3 still apply The puzzle asset added a key: Base64 then XOR

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

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

{"schema":"huntress.mobile.puzzle.v1","day":4,"codec":"xor","data":"XFNOMCstXCxeXCVYJSQkKiUpKy8=","key":29}

Codec xor: data is Base64; XOR each decoded byte with key to get the answer.

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

Single Solve

Started untimed to download the APK, decoded by our shared Android solver, and sent once: ANS-60A1CA8E89978462 → CORRECT in 1,173 ms (start to submit), flag 1140fdba…687a.

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, with different keys (103).

started_at 2026-10-10T15:56:32.634Z  deadline 2026-10-10T15:56:38.634Z  answer_ids ['answer']
  artifact pending_intent_relay_time_trial.apk 12704 bytes sha256 01d87994b7a6e941… (checked)
  answer: ANS-FC8EF157E3911AE7
  start         683 ms
  artifact      317 ms
  solve           1 ms
  submit       1199 ms
  TOTAL        2200 ms
result CORRECT  flag e6eb857b…733a

Mastery

A 6-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, with different keys (189, 31, 81).

started_at 2026-10-10T15:56:35.885Z  deadline 2026-10-10T15:56:41.885Z  answer_ids ['set1.answer', 'set2.answer', 'set3.answer']
  artifact 01-pending_intent_relay_mastery_01.apk 12704 bytes sha256 30d8c7dd24084479… (checked)
  artifact 02-pending_intent_relay_mastery_02.apk 12704 bytes sha256 306ab99782329e99… (checked)
  artifact 03-pending_intent_relay_mastery_03.apk 12704 bytes sha256 6575bd65136f0d80… (checked)
  set1.answer: ANS-42090FEBC4F2A58E
  set2.answer: ANS-A4DE09BF726165E9
  set3.answer: ANS-D501A4C9F4B42C26
  start         693 ms
  artifact      301 ms
  solve           1 ms
  submit        613 ms
  TOTAL        1607 ms
result CORRECT  flag a69b4c6a…f09f

Time to solve

All three modes were solved on 2026-10-10 by 15:56:36 UTC, 4 min 55 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.