Android APK Analysis
Android APK Analysis คือการแกะและวิเคราะห์แอป Android ครบวงจร: โครงสร้าง APK, static analysis (jadx/apktool หา secret/endpoint/logic), การอ่าน smali, exported component abuse, dynamic analysis ด้วย Frida/objection (bypass SSL pinning, root detection, hook ฟังก์ชัน), การ patch+repackage APK และ native lib reverse บทนี้มี setup ครบ + lab walkthrough + troubleshooting (เนื้อหาเพื่อฝึกใน lab/CTF/ระบบที่ได้รับอนุญาตเท่านั้น)
1. โครงสร้าง APK
APK เป็นไฟล์ ZIP ที่มี: AndroidManifest.xml (binary XML — permission, component, exported flag), classes.dex (โค้ด Dalvik bytecode), resources.arsc + res/ (resource compiled), assets/ (ไฟล์ดิบ), lib/ (native .so แยกตาม ABI), META-INF/ (signature)
unzip -l app.apk # ดูไฟล์ทั้งหมด
unzip app.apk -d app_raw # แตกออกมา
file app_raw/lib/*/*.so # ดู ABI ของ native lib2. ตั้งค่าเครื่องมือ
# jadx (decompile เป็น Java)
wget https://github.com/skylot/jadx/releases/latest/download/jadx.zip && unzip jadx.zip
# apktool (แกะ smali + resource + manifest)
wget https://github.com/iBotPeaches/Apktool/releases/latest/download/apktool.jar
# Frida (dynamic) — ฝั่ง PC
pip install frida-tools objection
# ฝั่งอุปกรณ์ (rooted/emulator): ดาวน์โหลด frida-server ให้ตรง arch
# adb push frida-server /data/local/tmp/ && adb shell "/data/local/tmp/frida-server &"
# adb (คุยกับอุปกรณ์)
adb devices3. Static Analysis
# decompile เป็น Java (อ่านง่ายสุด)
jadx -d out app.apk
jadx-gui app.apk # GUI: ค้น string, ตาม xref
# แกะ smali + manifest (อ่าน manifest ได้, แก้+repack ได้)
apktool d app.apk -o app_apktool
# ค้น secret/flag/endpoint
grep -rnE 'flag|secret|api[_-]?key|password|token|Bearer|https?://[a-z]' out/
grep -rnE 'AKIA|firebaseio|amazonaws|\.herokuapp' out/ # cloud/3rd-party| ที่ซ่อน | ทำไมต้องดู |
|---|---|
| res/values/strings.xml | flag/API key/URL มัก hardcode |
| BuildConfig.java (ใน out/) | constant ฝังตอน build (secret, base URL, DEBUG flag) |
| AndroidManifest.xml | exported component, permission, deep link, debuggable |
| assets/ | ไฟล์ config/db/JS ดิบ (บางทีมี key) |
| smali (ใน apktool) | logic ที่ jadx decompile ไม่สมบูรณ์ |
| lib/*/*.so | logic สำคัญย้ายไป native (JNI) |
MobSF (docker) อัปโหลด APK → ได้รายงาน static เต็ม (permission, secret, cert, ช่องโหว่) ในคลิกเดียว4. Manifest & Exported Component Abuse
component (Activity/Service/Receiver/Provider) ที่ android:exported="true" เรียกได้จากแอปอื่นหรือ adb — เป็นช่องโจมตี เช่น bypass login โดยเรียก Activity ภายในตรงๆ, หรือ ContentProvider ที่ leak data
# ดู manifest (decode แล้ว)
cat app_apktool/AndroidManifest.xml | grep -A3 'exported="true"'
# เรียก exported Activity ตรงๆ (อาจ bypass หน้า login)
adb shell am start -n com.app/.SecretActivity
# ส่ง intent + extra
adb shell am start -n com.app/.Activity --es key value
# query ContentProvider ที่ exported (leak data)
adb shell content query --uri content://com.app.provider/users
# เช็ค debuggable (ถ้า true = debug ได้ = run-as อ่านไฟล์ได้)
grep 'debuggable' app_apktool/AndroidManifest.xml5. Dynamic Analysis — Frida & objection
เมื่อ logic ซับซ้อน หรือมี SSL pinning/root detection → hook runtime งานหลัก: bypass pinning เพื่อดู traffic (แล้วทดสอบ API เหมือน web) + hook ฟังก์ชันเช็ค
# inject เข้า app ที่รันอยู่
objection -g com.app explore
# ใน objection prompt:
android sslpinning disable # ปิด SSL pinning
android root disable # ปิด root detection
android hooking list activities # ดู activity ทั้งหมด
android hooking watch class_method com.app.Crypto.decrypt --dump-args --dump-return
android heap search instances com.app.User # หา object ใน memory// hook.js — hook ฟังก์ชันเช็ค license/flag
Java.perform(function() {
var C = Java.use('com.app.LicenseChecker');
C.isValid.implementation = function() {
console.log('[+] isValid() bypassed -> true');
return true;
};
// dump ค่าที่ decrypt
var Crypto = Java.use('com.app.Crypto');
Crypto.decrypt.implementation = function(s) {
var r = this.decrypt(s);
console.log('[+] decrypt(' + s + ') = ' + r);
return r;
};
});
// รัน: frida -U -f com.app -l hook.js- bypass pinning → ตั้ง proxy (Burp) → ทดสอบ API (IDOR/JWT/auth) เหมือน web
- hook ฟังก์ชัน root/jailbreak/license → return ค่าที่ต้องการ
- dump runtime value: key ที่ decrypt, token, response ก่อน encrypt
6. Patch & Repackage
ถ้าต้องการแก้ logic ถาวร (เช่นลบ check, เปิด debug) → แก้ smali แล้ว repack + sign
# 1. แกะ
apktool d app.apk -o app_mod
# 2. แก้ smali (เช่น เปลี่ยน check ให้ return true เสมอ)
# หา method ใน app_mod/smali/.../X.smali แล้วแก้:
# const/4 v0, 0x1 (return 1 = true)
# return v0
# 3. rebuild
apktool b app_mod -o app_patched.apk
# 4. sign (ต้อง sign ถึงติดตั้งได้)
keytool -genkey -v -keystore my.keystore -alias a -keyalg RSA -keysize 2048 -validity 10000
apksigner sign --ks my.keystore --ks-key-alias a app_patched.apk
# 5. ติดตั้ง
adb install -r app_patched.apk7. Native Library Reverse
แอปที่ป้องกันดีมักย้าย logic สำคัญ (crypto, flag check) ไป native .so ผ่าน JNI ต้อง reverse ด้วย Ghidra (ARM/ARM64)
# extract
unzip app.apk 'lib/*' -d native
file native/lib/arm64-v8a/libnative.so
# ใน Ghidra: หา JNI function (ชื่อขึ้นต้น Java_com_app_Class_method)
# หรือ JNI_OnLoad ที่ RegisterNatives (dynamic registration)
strings native/lib/arm64-v8a/libnative.so | grep -iE 'flag|key'
# Frida hook native function
# Interceptor.attach(Module.findExportByName('libnative.so','Java_com_app_X_check'), {...})8. Lab Walkthrough (crackme APK)
- 1
jadx-gui app.apk→ ดู MainActivity เจอcheckFlag(input)เรียก native หรือ Java - 2ถ้าเป็น Java: อ่าน logic — เช่น XOR input กับ key คงที่แล้วเทียบ → คำนวณ flag ย้อนกลับ
- 3ถ้าเป็น native:
grep flagใน .so หรือ Frida hookcheckFlagdump argument - 4ถ้ามี SSL pinning + flag อยู่ server:
objection -g com.app explore→android sslpinning disable→ proxy → เห็น API → ทดสอบ - 5ถ้า flag หลัง login: hook ฟังก์ชัน auth ให้ return true หรือเรียก exported Activity ตรงๆ
- 6เก็บ flag — มักได้จาก: strings, decrypt runtime (Frida dump), API response, หรือ logic ที่ reverse
9. Troubleshooting
| อาการ | สาเหตุ / แก้ |
|---|---|
| jadx decompile ไม่ครบ (// failed) | ใช้ apktool ดู smali แทน ส่วนนั้น |
| Frida: unable to connect | frida-server ไม่รัน/ผิด arch — เช็ค adb shell ps | grep frida |
| objection: pinning ปิดแล้วยังไม่เห็น traffic | proxy ผิด หรือ pinning custom — เขียน Frida hook เฉพาะ |
| ติดตั้ง patched APK ไม่ได้ (signature) | ยังไม่ sign / sign ผิด — ใช้ apksigner sign |
| app crash หลัง patch | smali ผิด syntax/register — ตรวจ .locals + register count |
| root detection ไม่ผ่านแม้ hook | มีหลายชั้น — hook ทุก method ที่เกี่ยว, หรือ patch smali |
| string ถูก obfuscate | decrypt ตอน runtime — Frida hook ฟังก์ชัน decrypt ดู output |
10. Indicators & Quick Reference
- flow: jadx static → หา secret/logic → ถ้าตัน ใช้ Frida dynamic
- MobSF = scan อัตโนมัติ (เริ่มเร็ว), jadx = อ่าน code ลึก
- endpoint ที่เจอ → ทดสอบเหมือน web API (ดู Mentor หมวด web)
- flag มักอยู่: strings.xml, assets/, decompiled logic, decrypt runtime, API response, native .so
- iOS (IPA) คล้ายกัน: ใช้ class-dump/Hopper + Frida/objection (objection รองรับทั้งคู่)
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติเพิ่งเจอโจทย์ CTF/mobile pentest แล้วได้ไฟล์ .apk มาก้อนเดียว มีแค่เครื่อง Kali เปล่าๆ ไม่รู้จะเริ่มตรงไหน — ทำตามขั้นตอนนี้ทีละสเต็ป ถ้าไปต่อไม่ได้ให้ดู decision tree ด้านล่างว่าควรหักเลี้ยวไปทางไหน
- 1ติดตั้งเครื่องมือก่อน:
sudo apt install apktoolแล้วโหลดjadxจาก GitHub release (wget <jadx-release-url> && unzip jadx.zip -d jadx) ถ้ายังไม่มี - 2แตก static ชั้นแรก: พิมพ์
apktool d app.apk -o app_apktoolควรเห็น folder ใหม่ที่มีsmali/,res/,AndroidManifest.xmlฉบับอ่านออก - 3decompile เป็น Java อ่านง่าย: พิมพ์
jadx app.apk -d app_jadxหรือเปิดjadx-gui app.apkแล้วดู source ใน MainActivity - 4หา secret แบบเร็ว: พิมพ์
grep -rnE 'flag|secret|api[_-]?key|password|token|Bearer' app_jadx/ app_apktool/res/ถ้าเจอ string ที่หน้าตาเป็น flag/key ให้เก็บไว้ก่อน - 5ตรวจ AndroidManifest.xml หา exported component: พิมพ์
grep -B2 -A3 'exported="true"' app_apktool/AndroidManifest.xmlถ้าเจอ Activity/Provider ที่ exported แปลว่ามีช่องเรียกตรงได้ - 6เช็คว่าโจทย์มี logic client-side check ไหม (root detection, license check, ปุ่ม premium): เปิด
jadx-guiค้นคำว่าisRoot,checkLicense,isPremium - 7ถ้าเจอ logic ที่ต้อง bypass runtime: เตรียม emulator/rooted device แล้ว push frida-server:
adb push frida-server /data/local/tmp/ && adb shell chmod 755 /data/local/tmp/frida-server && adb shell '/data/local/tmp/frida-server &' - 8เช็คว่า frida คุยกับ device ได้: พิมพ์
frida-ps -Uควรเห็น process list บนเครื่อง/emulator - 9hook แบบเร็วด้วย objection ก่อน (ไม่ต้องเขียน script): พิมพ์
objection -g com.app exploreแล้วลองandroid root disableหรือandroid sslpinning disable - 10ถ้า objection ไม่พอ เขียน frida script เฉพาะจุด แล้วรัน
frida -U -f com.app -l hook.js --no-pauseดู log ว่า hook ติดไหม - 11ถ้าทุกทางตัน ลองอัปโหลดเข้า MobSF (self-hosted) ให้สแกนอัตโนมัติ อาจเจอจุดที่พลาดดู
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| แตก APK / อ่าน smali+manifest | unzip, apktool | apktool เวอร์ชันล่าสุดจาก GitHub ถ้า apt เก่า | - |
| decompile เป็น Java อ่านง่าย | jadx-gui / jadx | โหลด jadx.zip จาก GitHub release แล้ว unzip | jadx online decompiler (จำกัดขนาดไฟล์) |
| dynamic instrumentation / hook | frida-tools, objection | frida-server ฝั่งอุปกรณ์ (โหลดให้ตรง arch แล้ว adb push) | - |
| scan อัตโนมัติ | - | MobSF (docker run มาตรฐาน) | MobSF cloud demo (ถ้าเปิดให้ใช้) |
| คุยกับอุปกรณ์/emulator | adb (android-tools-adb) | Android Studio emulator ถ้าไม่มีเครื่องจริง | - |
| sign APK ที่ patch แล้ว | apksigner, keytool | มาพร้อม Android SDK build-tools | - |
| ตรวจ native .so | file, strings, Ghidra | ติดตั้ง Ghidra (โหลดจาก GitHub release) | - |
| เช็ค hash/reputation เบื้องต้น | - | - | VirusTotal |
aws-iam-privesc หรือ aws-s3-attacks ทดสอบสิทธิ์จริงของ key นั้น | bypass pinning แล้วเจอ backend API → ทดสอบแบบ web ปกติที่ idor หรือ jwt-attacks (ตรวจ token/session) | logic ซ่อนใน native lib หรือ Frida hook ปกติไม่ติด → อ่านเทคนิคเจาะลึก dynamic instrumentation เพิ่มที่ frida | โจทย์มีทั้ง Android และ iOS build คู่กัน → เทียบ logic กับ ios-ipa-analysis อาจมี hint ฝั่งที่ป้องกันอ่อนกว่าหัวข้อที่เชื่อมโยง
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้