| name | mobile-ctf |
| description | Lab/CTF: mobile challenges; APK/AAB/IPA, Android backups, DEX/smali, SQLite/XML/keystore, Unity/IL2CPP, mobile forensics. |
| license | MIT |
| compatibility | Linux/macOS; APK/IPA/AB artifacts; jadx, apktool, Python 3, optional frida/objection for dynamic tasks. |
| metadata | {"author":"AeonDave","version":"1.0","category":"ctf-solving"} |
Mobile CTF
Solve mobile CTF challenges by classifying the artifact type first, then choosing the narrowest extraction path before escalating to dynamic or native analysis.
When this skill applies
- Artifact is an APK, AAB, IPA,
.ab (Android backup), DEX file, or mobile game binary.
- Challenge asks to find a flag, key, secret, PIN, or hidden data from a mobile app or device backup.
- Artifact contains images, SQLite databases, or SharedPreferences with embedded or encoded flag content.
Operating model
1. Classify artifact: APK | Android backup (.ab) | IPA | Unity game
2. Quick-win attempt: strings + grep flag{ on raw artifact
3. Static analysis path per artifact type
4. If flag not found: dynamic analysis (Frida/objection) or native reversing
5. Validate and submit
Always try strings <file> | grep -i "flag{" first. Saves time on ~30% of challenges.
Technique integration
reversing-technique for obfuscated native .so libraries, IL2CPP dumps, or complex custom crypto.
mobile-technique for dynamic instrumentation details, SSL pinning bypass, and runtime hooking.
forensic-technique if the artifact is a full device image or PCAP from a mobile session.
Artifact type 1 — APK / AAB static analysis
Quick triage
strings target.apk | grep -i "flag{"
unzip -o target.apk -d apk_out/
find apk_out/ -type f | grep -v META-INF | sort
jadx decompilation
jadx -d jadx_out/ target.apk
grep -r "flag{" jadx_out/
grep -r "SecretKeySpec\|AES\|cipher\|encrypt\|decrypt\|base64\|sha\|md5" jadx_out/ | grep -v "^Binary"
cat jadx_out/resources/AndroidManifest.xml | grep -i "MAIN\|LAUNCHER" -B2
Hardcoded crypto (most common easy/medium pattern)
When strings or jadx shows SecretKeySpec, Cipher.getInstance, or a suspicious short string near crypto imports:
Trace the byte-exact dataflow from source/charset through decode, concat/repeat,
slice/pad/truncate, key/IV construction, transformation, ciphertext decode, and
doFinal. Mirror only operations proven in code and validate by re-encryption or a
known ciphertext. Load references/apk-crypto-patterns.md for canonical recipes,
including provider-sensitive CFB feedback width.
Asset and resource analysis
ls -lh apk_out/assets/
find apk_out/assets/ -type f | xargs file
zsteg apk_out/assets/suspicious.png
steghide info apk_out/assets/suspicious.jpg
strings apk_out/assets/suspicious.png | grep -iE 'flag\{|ctf\{'
python3 -c "
data=open('apk_out/assets/suspicious.png','rb').read()
eof=data.rfind(b'\\x89PNG')
print(repr(data[-200:])) # check tail for appended data
"
cat jadx_out/resources/res/values/strings.xml | grep -i "key\|secret\|flag\|token\|pass"
Firebase and remote config leaks
cat apk_out/google-services.json 2>/dev/null
curl "https://<project-id-from-config>.firebaseio.com/.json"
Artifact type 2 — Android backup (.ab)
Android backups contain app data, shared storage, and sometimes sensitive files.
Extraction
python3 -c "
with open('backup.ab','rb') as f: print(repr(f.read(60)))
"
python3 - <<'PY'
import zlib, pathlib
raw = pathlib.Path('backup.ab').read_bytes()
p = 0
for _ in range(4):
p = raw.index(b'\n', p) + 1
pathlib.Path('backup.tar').write_bytes(zlib.decompress(raw[p:]))
PY
tar xf backup.tar -C extracted/
find extracted/ -type f | grep -v "_manifest" | sort
Triage after extraction
grep -r "flag{" extracted/ 2>/dev/null
python3 -c "
import os, re
for root, _, files in os.walk('extracted/'):
for f in files:
p = os.path.join(root, f)
try:
d = open(p,'rb').read()
m = re.findall(rb'(?:flag|ctf|HTB|THM)\{[^}]{1,60}\}', d)
if m: print(p, m)
except: pass
"
find extracted/ -name "*.jpg" -o -name "*.png" | sort
for db in $(find extracted/ -name "*.db" | grep -v shm | grep -v wal); do
python3 -c "
import sqlite3, sys
c = sqlite3.connect(sys.argv[1])
for t in c.execute(\"SELECT name FROM sqlite_master WHERE type='table'\").fetchall():
rows = c.execute(f'SELECT * FROM \"{t[0]}\" LIMIT 5').fetchall()
if rows: print(sys.argv[1], t[0], rows[:3])
" "$db" 2>/dev/null
done
find extracted/ -name "*.xml" | xargs grep -l "." | xargs cat 2>/dev/null
Key backup paths to check
| Path | Content |
|---|
extracted/apps/<package>/sp/*.xml | SharedPreferences — app settings, tokens |
extracted/apps/<package>/db/*.db | App databases |
extracted/shared/0/Pictures/ | Device camera roll — may show documents |
extracted/shared/0/DCIM/ | Camera photos |
extracted/shared/0/Download/ | Downloaded files |
Artifact type 3 — Unity / IL2CPP APK
Arno-style: Unity game with libil2cpp.so. The game logic (C# code) is compiled into native ARM binary — jadx shows only Unity wrapper stubs.
ls apk_out/lib/arm64-v8a/
find apk_out/assets/ -name "*.dat" -o -name "global-metadata*"
git clone https://github.com/Perfare/Il2CppDumper
grep -i "flag\|key\|secret\|password\|htb\|cheat\|unlock" output/dump.cs -i | head -20
strings apk_out/lib/arm64-v8a/libil2cpp.so | grep -i "flag{\|flag\|key"
Artifact type 4 — iOS IPA
unzip -o target.ipa -d ipa_out/
find ipa_out/Payload/ -type f | sort
file ipa_out/Payload/AppName.app/AppName
strings ipa_out/Payload/AppName.app/AppName | grep -i "flag{"
grep -r "flag{" ipa_out/ 2>/dev/null
Dynamic analysis (when static fails)
Use when: flag is constructed at runtime, key is derived (not hardcoded), or logic is obfuscated.
frida -U -f <package_name> -l hook_crypto.js
objection -g <package_name> explore
Quick pivots by symptom
| Symptom | Action |
|---|
strings finds flag{ in APK | Done — submit |
SecretKeySpec + short string in dex | AES hardcoded key → decrypt with Python |
Large image in assets/ | Stego → zsteg / visual inspection |
.ab file, photos in extracted backup | View ALL photos — flag may be on photographed document |
libil2cpp.so + global-metadata.dat | Unity/IL2CPP → Il2CppDumper |
Firebase config in APK | Check Realtime DB public endpoint |
| Multi-dex, no obvious strings | jadx + grep → Frida if static fails |
Native .so with JNI_ exports | reversing-technique for binary analysis |
Resources
- references/android-backup-forensics.md — Full .ab extraction workflow, header format variants, SQLite triage, photo inspection patterns.
- references/apk-crypto-patterns.md — byte-exact key/IV derivation, provider-sensitive AES modes, hardcoded-key patterns, and Python validation templates.
- references/ios-ipa-triage.md — Load for IPA/
.app/Mach-O artifacts: bundle structure, plist/keychain/SQLite extraction, Mach-O static analysis, FairPlay decryption, and Frida/objection dynamic recovery.