zwesty
Write-ups / Day 16 / Android
Day 16 · Fri, Oct 16 · Android

JNI Boundary

Prey slaughtered

APK structure, JNI native libraries, static string extraction

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-16-jni-boundary (+ /time_trial, /mastery)
Solved
2026-10-16, all three modes, 24 s from the first start (13:01:11 → 13:01:35 UTC)
Player
Zwesty (solo), with Claude Code (Opus 5.5): solved by our automated morning solver (a scheduled script on our Kali VM)

The challenge

Identify a Java-to-native type or length assumption that changes backend authorization.

One question per APK: the backend answer code for a named case and package, as ANS- followed by 16 uppercase hex characters.

Reading the prompt: what it said we'd need

Clue What it pointed to What I did about it
"Java-to-native" A JNI library (lib/<abi>/*.so) the Java code calls The solver reads the library's strings statically
"type or length assumption" The bug class the app models (a truncated or mistyped value crossing JNI) Context only: the answer is the code the native side returns
"backend answer code" ANS- + 16 hex Cross-checked the library's value against the puzzle asset

Safety

Static only: the APK is unzipped and read; nothing is installed or run. Artifacts stayed on our Kali VM.

What was in the files

A 12.8 KB APK: classes.dex, lib/x86_64/libarena.so, and assets/huntress_puzzle.json, whose codec is native, the same as Day 15. The answer is the string the native library returns, and the asset carries the same value. The Mastery's five APKs mixed in earlier days' builds (delivery 1 was a Day 1 plain codec APK with no native library).

Single Solve, Time Trial, and Mastery

All three came from the morning solver with our existing Android solver (the Day 10 puzzle-asset solver plus Day 15's native codec). Nothing new was needed.

Single Solve: solve 1 ms · submit 1538 ms · TOTAL 2322 ms
result CORRECT  flag 659ace73…fae3

Time Trial (ranked): solve 1 ms · submit 1108 ms · TOTAL 1872 ms
result CORRECT  flag 45d41c9e…b303

Mastery (5 APKs): solve 2 ms · submit 8571 ms · TOTAL 9607 ms
result CORRECT  flag 46f93b72…e9b1  status pending

The Mastery reply said status: pending, which has meant "correct, points not recorded yet" before. The 8.6 s submit was the server's time, not ours.

Time to solve

All three modes were solved by 13:01:35 UTC (09:01:35 ET), 24 s after the first start, each on the first submit; the Time Trial was ranked. The Mastery's 9 s was mostly a slow submit reply from the server.

Takeaways

  • A codec added for one day carried the next. Day 15's native decoder covered Day 16 unchanged.
  • Server-side time dominates small routes: our solve was 1–2 ms; the Mastery submit took 8.6 s on the server.