zwesty
Write-ups / Day 21 / Android
Day 21 · Wed, Oct 21 · Android

Debug Me If You Can

Prey slaughtered

APK asset analysis, puzzle codec routing, anti-debug concepts (read, not run)

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-21-debug-me-if-you-can (+ /time_trial, /mastery)
Solved
2026-10-21: all three modes CORRECT on the first submit, by 09:02:52 ET, 14 s after the solver's first start request (09:02:38 ET). Both timed modes were ranked runs. Late start: the scheduled 08:58 run didn't start because a leftover session on our Kali VM was still blocking it, and a catch-up run began at 09:01:40, about 3 min 39 s late. So the 2 min 52 s from the 9 AM release to the Mastery CORRECT includes that delay
Player
Zwesty (solo); solved by our automated morning solver (a scheduled script on our Kali VM), built with Claude Code (Opus 5.5) and started here by the catch-up run, with no manual work needed

The challenge

"Neutralize a clean-room anti-debug state machine while retaining the intended app flow."

answer_id Question Format
answer "For case MOB-21-… in package com.huntress.mobile.d21.…: Neutralize a clean-room anti-debug state machine while retaining the intended app flow. 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

Mastery asked the same question for five APKs (set1.answer … set5.answer), each with its own case and package.

Reading the prompt: what it said we'd need

Clue What it pointed to What I did about it
"anti-debug state machine" Checks in the app that change its behaviour when a debugger is attached Nothing to defeat: the answer sits in the puzzle asset, so the app never had to run
"Neutralize … while retaining the intended app flow" In a real app: patch or hook the checks and let the normal flow reach its result Read the flow's end point statically instead (the challenge activity and its loopback evidence URL) and didn't contact it
"Debug Me If You Can" (title) Anti-debugging; the class is literally DebugMeIfYouCan with CONTROL="anti_debug" Confirmed the day's mechanic from the DEX strings
"backend answer code" An ANS- token, as on every Android day The chain requires exactly one ANS- plus 16 hex reading

Safety

APKs are hostile: static analysis only, on our Kali VM. No APK was installed or run, and nothing was patched or debugged. The solver reads zip members and the puzzle JSON as bytes. ChallengeActivity builds a loopback "evidence" URL (127.0.0.1:19090) from the answer and case ID; it was not contacted (not needed, and not in scope). The DEX also carries a fixture client-secret string; it wasn't used and isn't quoted here.

What was in the files

  • Single Solve: debug_me_if_you_can.apk, 12,704 bytes:
  • assets/huntress_puzzle.json (95 bytes): schema huntress.mobile.puzzle.v1, day 21, codec reverse, and a data string that is the answer written backwards (it ends …-SNA).
  • classes.dex (2,576 bytes): MainActivity, ChallengeActivity, and DebugMeIfYouCan, which has CODEC, CONTROL="anti_debug", and a describe() string DAY-21:anti_debug:anti-debug state checks.
  • a binary AndroidManifest.xml (3,496 bytes): meta-data huntress.mechanic = "anti-debug state checks", a launcher activity, and a browsable deep link huntress21://debug-me-if-you-can/unlock into ChallengeActivity.
  • v1 signing files (META-INF/MANIFEST.MF, FIXTURE-.SF, FIXTURE-.RSA).
  • Time Trial: debug_me_if_you_can_time_trial.apk, 12,704 bytes, the same template (day 21, reverse) with its own case and answer.
  • Mastery: five APKs (12,704 to 12,772 bytes), one per earlier mechanic: day 2 (reverse), day 6 (hex), day 15 (native, with lib/x86_64/libarena.so), day 18 (xor with a key field), and day 21 (reverse).

So the timed variants used the same template with different values, and the Mastery mixed today's APK with older ones.

Single Solve

The solver solved it with no stop, and the codec was known. It used our Android solver from Day 20, which builds on the Day 19 and Day 17 versions and the Day 15 base. The Day 17 layer found reverse in its known-codec table and handed the APK to the Days 1-16 decoder, which has read reverse since Day 2 (Deep Link Drift). The solver's report has no fallback or unknown-codec line (Day 20's had "unknown puzzle codec 'dynamic'"). No new solver, tests, or rehearsal were written today.

started_at  2026-10-21T13:02:38.385Z
deadline    none (Single Solve)
answers     1   ANS-B40F…F25A
start        333 ms
artifact     339 ms
solve          1 ms
submit       605 ms
TOTAL       1277 ms   (submit +1.03 s after started_at)
result      CORRECT   flag d3bfeaf8…19c8

Time Trial

CORRECT on the first attempt, ranked. The start reply showed unique_attempts_remaining: 31.

started_at  2026-10-21T13:02:44.637Z
deadline    2026-10-21T13:03:34.637Z   (50 s)
answers     1   ANS-C986…530E
start        264 ms
artifact     223 ms
solve          1 ms
submit       996 ms
TOTAL       1484 ms   (submit +1.32 s after started_at)
result      CORRECT   flag beabc0ac…f604

Mastery

CORRECT on the first attempt, ranked (5 APKs, 170 s clock).

started_at  2026-10-21T13:02:51.417Z
deadline    2026-10-21T13:05:41.417Z   (170 s)
answers     5   (codecs reverse, hex, native, xor, reverse)
start        525 ms
artifact     622 ms
solve          2 ms
submit       729 ms
TOTAL       1878 ms   (submit +1.47 s after started_at)
result      CORRECT   flag 65110a58…ee77

Time to solve

All three modes were solved by 09:02:52 ET, 14 s after the solver's first start request at 09:02:38 ET, and each went through on the first submit; both timed modes were ranked. The finish, 2 min 52 s after release, was set by the late start: the catch-up run began at 09:01:40 instead of 08:58 and handled the Metadata and Warmups lanes first.

Takeaways

  • A new mechanic doesn't mean a new codec. The prompt was about anti-debugging, but the puzzle asset used Day 2's reverse, so the known-codec table took it with no fallback.
  • Read the theme from the DEX, then decide whether it matters. The anti-debug class and deep link explain the story; the answer path didn't touch them.
  • Mastery mixes old mechanics. Today's five APKs spanned days 2 to 21, including a native library; the chain answered all five in 2 ms.