The challenge
"Complete a mass-generated multi-app campaign that composes every released mobile primitive under one aggregate clock."
| answer_id | Question | Format |
|---|---|---|
answer |
"For case MOB-31-3480CA08CF in package com.huntress.mobile.d31.v3480ca08cf24:" then the prompt, then "Submit only the exact backend answer code returned for this case." | pattern: "ANS- followed by exactly 16 uppercase hexadecimal characters; no spaces or explanatory text"; exact |
The Time Trial asked the same for its own case; the Mastery asked it once per delivery (15 deliveries, 15 answers).
Reading the prompt: what it said we'd need
Nobody read the prompt on the day; the solver answered from the files. This table is written afterwards.
| Clue | What it pointed to | How the solver met it |
|---|---|---|
| "mass-generated multi-app campaign" | Many APKs at once | The Mastery's 15 APKs, each one control from an earlier day |
| "composes every released mobile primitive" | The controls of Days 1–31: native code, a later-loaded DEX, reflection, and so on | Mastery sets from Days 2 to 31, including two JNI sets (Days 15, 16) and a secondary-DEX set (Day 20). The interpreter already modelled each of them |
| "under one aggregate clock" | One timer for the whole Mastery | 7 min 50 s for 15 APKs; done in 1.3 s on the server's stamps |
| "the exact backend answer code returned" | The ANS- value the app's own code builds |
The v2 analysis path: find the one static method that builds ANS- and evaluate it statically |
| "Mobile Arena Gauntlet" (title) | The lane's finale, mixing earlier days | Confirmed by the Mastery's spread of days |
Safety
Static analysis only. Nothing was installed or executed. The solver opens APKs as ZIP files, reads the puzzle asset as JSON, checks classes.dex against MANIFEST.MF, and evaluates the answer method with an interpreter written in Python. Native JNI functions are evaluated by an instruction-level model, not run. Nothing went near an emulator or a device. For this write-up the solver's report, the saved Game Master replies, and the solver source were read, plus each saved APK's puzzle-asset fields schema, day, and codec, read as ZIP entries (no code was run). The APKs stayed on our Kali VM.
What was in the files
- Single Solve:
mobile_arena_gauntlet.apk, 12,704 bytes. The puzzle asset is v2 (huntress.mobile.puzzle.v2) withday: 31andcodec: "analysis". The solver evaluatedLcom/huntress/mobile/d31/v3480ca08cf24/Release;->codein 58,940 interpreter steps:ANS-2711…746E. - Time Trial:
mobile_arena_gauntlet_time_trial.apk, 12,704 bytes, also v2analysiswithday: 31;Release->codein 63,157 steps:ANS-D069…3AE5. - Mastery: 15 APKs, all v2
analysis, each an earlier day's control (from each asset'sday):
| Set | Day | Size (bytes) | Extra entry | Interpreter steps (solver output) |
|---|---|---|---|---|
| 1 | 2 | 12,704 | not itemised | |
| 2 | 4 | 12,704 | not itemised | |
| 3 | 5 | 12,704 | not itemised | |
| 4 | 7 | 12,704 | 76,799 | |
| 5 | 9 | 12,704 | 57,048 | |
| 6 | 11 | 12,704 | 724 | |
| 7 | 15 (JNI) | 12,772 | lib/ |
236 |
| 8 | 16 (JNI) | 12,772 | lib/ |
37,754 |
| 9 | 18 | 12,704 | 518 | |
| 10 | 20 (loaded later) | 12,768 | assets/ |
330 |
| 11 | 22 | 12,704 | 92,572 | |
| 12 | 25 | 12,704 | 22,543 | |
| 13 | 27 | 12,704 | 56,358 | |
| 14 | 29 | 12,704 | 696 | |
| 15 | 31 | 12,704 | 85,135 |
The solver's output lists an interpreter line for 12 of the 15 sets; why the Day 2, 4, and 5 sets have none isn't recorded. All 15 answers were sent in one submit and the Mastery was CORRECT.
The break in the pattern. On Days 24–30 the Single carried a new v1 codec while the timed modes were v2 code-reading puzzles, and on Day 30 the new layered codec stopped the solver. Day 31's Single was v2 analysis itself, so there was no unknown codec to stop on.
Single Solve: the automated solver
The solver used our Android solver as it stood after Day 30; nothing was changed for Day 31.
What answered it. The Day 30 solver builds on Day 29's, which builds on the earlier days in turn. A v2 puzzle with codec analysis goes to the Day 25 interpreter: it checks classes.dex against the manifest digest, finds the static String methods that use ANS-, and requires exactly one (otherwise it stops). It then evaluates that method with opaque arguments and accepts only a result that matches ANS- + 16 uppercase hex. The earlier days' controls live in the same chain: Day 20's secondary DEX (added on Day 24), Day 19's Class.forName dispatch (Day 25), split bundles (Day 26), and Day 24's x86-64 evaluator for JNI functions. Day 30's solver swaps that evaluator for a branch-aware one, built for an earlier Mastery, that follows cmp/jcc guards. Whether Day 31's Day 16 set needed the branch support isn't recorded.
Single Solve
started_at 09:03:26.900 ET deadline none
answers 1 ANS-2711…746E
start 324 ms
artifact 275 ms (12,704 bytes)
solve 34 ms (58,940 interpreter steps)
submit 617 ms
TOTAL 1249 ms (submit +1,011 ms after started_at)
result CORRECT flag 30e24a94…d1cc (09:03:27.5 ET)
Time Trial
CORRECT on the first attempt, ranked, on a fresh variant.
Time Trial (ranked)
started_at 09:03:33.223 ET deadline 09:04:23.223 (50 s clock)
answers 1 ANS-D069…3AE5
start 329 ms
artifact 317 ms (12,704 bytes)
solve 40 ms (63,157 interpreter steps)
submit 619 ms
TOTAL 1306 ms (submit +1,059 ms after started_at)
result CORRECT flag 8cb6a404…0ff9 (09:03:33.8 ET; 0.611 s on the server's stamps)
Mastery
CORRECT on the first attempt, ranked, on a fresh variant. The solver's report has no timing block for this run; the marks below are from its saved timings.
Mastery (ranked)
started_at 09:03:39.901 ET deadline 09:11:29.901 (7 min 50 s clock)
answers 15 (one per delivery)
start +127 ms after started_at
artifact +735 ms (15 APKs)
solve +1195 ms
submit +1864 ms
result CORRECT flag 8406706c…2c26 (09:03:41.2 ET; 1.313 s on the server's stamps)
Why no change was needed
- No new codec. The Single and Time Trial were v2
analysispuzzles, the shape the v2 interpreter has read since Day 23 (Day 25's version is the one in use). - No new control. Fourteen Mastery sets were earlier days' controls the chain already modelled, and the Day 31 set had the same shape as the Single. All 15 were answered in one submit.
- The Day 16 native guard was already covered. If this Day 16 set had the guard that stopped Day 30's Mastery (not recorded), the branch-aware evaluator added on Day 30 handles it.
- The fail-closed rules held: exactly one
ANS-method per APK and a result in the exact format, so nothing was guessed.
Time to solve
All three modes were solved by 09:03:41.2 ET, 3 min 41.2 s after release and 14.3 s after the Single started. Each mode went through on its first submit, and both timed modes were ranked.
Takeaways
- The finale was a review, and the chain had every chapter. Fifteen APKs from fifteen different days went through one interpreter in about a second.
- Fixes kept in a chain add up. Each day's solver builds on the one before, so Day 30's solver still carried Day 20's secondary DEX, Day 25's reflection, and Day 24's native evaluator.
- A staged fix earned its keep twice. The branch-aware native evaluator, written for an earlier Mastery and first used live on Day 30, was in place for the Day 16 set.
- The solve is not where the time goes. On the VM the Single spent 34 ms solving, but 275 ms downloading and 617 ms submitting.