📱 Android APK Analysis
🧠 Description
Android APK reverse engineering is the process of analyzing compiled Android applications to understand their functionality, find vulnerabilities, and extract sensitive information.
- Extract hardcoded API keys, passwords, and credentials
- Discover insecure data storage practices
- Identify SSL pinning implementations for traffic interception
- Find business logic vulnerabilities
- Analyze third-party SDK security
- Detect counterfeit or malicious apps
APK Structure:
classes.dex- Dalvik bytecode (compiled Java/Kotlin)AndroidManifest.xml- App permissions and componentsres/- Resources (layouts, strings, images)lib/- Native libraries (.so files)assets/- Additional bundled filesMETA-INF/- Signature and certificate info
📦 APK Extraction
From Device (via ADB):
# List installed packages adb shell pm list packages # Get APK path for specific app adb shell pm path com.example.app # Pull APK to local machine adb pull /data/app/com.example.app/base.apk ./app.apk
From Play Store:
# Using gplaycli (Linux/macOS) gplaycli -d com.example.app # Using Rastic (Windows) rastic download com.example.app # APK Downloader websites apkcombo.com apkpure.com
From Emulator:
# Enable USB debugging on emulator adb emu kill adb shell "su -c 'cp /data/app/com.example.app/base.apk /sdcard/'" adb pull /sdcard/base.apk
🔍 Static Analysis
Decompile APK:
# Using apktool (extracts resources + decompiles DEX) apktool d app.apk -o output_folder # Using jadx (Java decompiler) jadx -d output_folder app.apk # Using MobSF (automated analysis) docker run -it -p 8000:8000 opensecurity/mobsf:latest
Analysis Steps:
- Check
AndroidManifest.xmlfor excessive permissions - Search for hardcoded credentials in source code
- Analyze network traffic encryption implementation
- Review data storage mechanisms
- Identify crypto implementation
- Find exported components
Common Findings:
- Hardcoded API keys:
BuildConfig.API_KEY - Hardcoded passwords:
"admin", "password123" - Weak crypto: MD5, SHA1 for passwords
- Insecure storage: SharedPreferences without encryption
- Debug enabled:
android:debuggable="true"
🔐 Permissions Analysis
Dangerous Permissions:
# Runtime permissions that require user consent android.permission.CAMERA android.permission.RECORD_AUDIO android.permission.ACCESS_FINE_LOCATION android.permission.ACCESS_COARSE_LOCATION android.permission.READ_CONTACTS android.permission.WRITE_CONTACTS android.permission.READ_SMS android.permission.RECEIVE_SMS android.permission.READ_CALL_LOG android.permission.WRITE_CALL_LOG android.permission.READ_PHONE_STATE android.permission.CALL_PHONE android.permission.READ_EXTERNAL_STORAGE android.permission.WRITE_EXTERNAL_STORAGE
Permission Misuse Examples:
| Permission | Potential Abuse | Legitimate Use |
|---|---|---|
| READ_SMS | Steal OTPs, 2FA codes | OTP auto-fill |
| READ_CONTACTS | Harvest contact list | Payment apps |
| RECORD_AUDIO | Surveillance | Voice notes |
| READ_EXTERNAL_STORAGE | Exfiltrate files | Photo editing |
⚡ Dynamic Analysis
Setting Up Proxy:
# Install Burp CA certificate as system trusted CA openssl x509 -in burp_cert.crt -out burp_cert.cer -outform DER adb push burp_cert.cer /sdcard/ adb shell "su -c 'mv /sdcard/burp_cert.cer /system/etc/security/cacerts/'" adb shell "su -c 'chmod 644 /system/etc/security/cacerts/burp_cert.cer'"
Frida Setup:
# Install frida-server on Android device adb push frida-server /data/local/tmp/ adb shell "su -c 'chmod 755 /data/local/tmp/frida-server'" adb shell "su -c '/data/local/tmp/frida-server &'" # Attach to app on PC frida -U -f com.example.app -l script.js --no-pause
Common Frida Scripts:
// Bypass SSL pinning
Java.perform(function() {
var TrustManagerImpl = Java.use('com.android.trustpoint.' +
'tls.TrustManagerImpl');
TrustManagerImpl.verifyChain.implementation = function(chain, authType) {
return chain;
};
});
// Hook crypto calls
Java.perform(function() {
var Cipher = Java.use('javax.crypto.Cipher');
Cipher.doFinal.implementation = function(input) {
console.log('Cipher input: ' + bytesToString(input));
return this.doFinal(input);
};
});
// Find stored credentials
Java.perform(function() {
var SharedPreferences = Java.use('android.content.SharedPreferences');
var editor = SharedPreferences.edit();
// Hook putString to capture writes
});
💾 Secure Storage Analysis
Common Insecure Storage Locations:
# SharedPreferences (often unencrypted) /data/data/com.example.app/shared_prefs/ /data/data/com.example.app/shared_prefs/*.xml # SQLite Databases /data/data/com.example.app/databases/ /data/data/com.example.app/databases/*.db # External Storage /mnt/sdcard/Android/data/com.example.app/files/ /mnt/sdcard/Download/ # Log files /data/data/com.example.app/logs/ /data/data/com.example.app/cache/
SQLite Analysis:
# Pull database from device adb pull /data/data/com.example.app/databases/app.db # View with sqlite3 CLI sqlite3 app.db sqlite> .tables sqlite> .schema table_name sqlite> SELECT * FROM table_name; # Using SQLite Viewer (GUI) DB Browser for SQLite SQLiteStudio
- SQLite with plaintext passwords or tokens
- SharedPreferences with username/password stored in cleartext
- Session tokens in world-readable files
- Logging sensitive data to files in external storage
🔒 Cryptography Analysis
Weak Crypto Indicators:
- Usage of
CryptoProvideror custom encryption - AES with ECB mode (predictable output)
- Hardcoded encryption keys in source code
- MD5 or SHA1 for password hashing
- ECB mode encryption for sensitive data
Safe Crypto Patterns (Search for):
# Good patterns to find
javax.crypto.Cipher.getInstance("AES/GCM/NoPadding")
javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding")
javax.crypto.spec.SecretKeySpec (with random key)
java.security.SecureRandom
# Bad patterns to find
Cipher.getInstance("AES/ECB") // Never use ECB
new SecretKeySpec(key.getBytes(), "AES") // Hardcoded key?
MessageDigest.getInstance("MD5") // Broken hash
URLEncoder.encode(password) // Not encryption
🛠️ Tools & Commands
Jadx-gui
Java decompiler with GUI. View decompiled source code.
apktool
APK decompilation. Extract resources and decompile DEX.
MobSF
Automated mobile app security analysis.
Frida
Dynamic instrumentation toolkit.
Objection
Runtime mobile exploration without root.
Drozer
Android security assessment framework.
Useful Commands:
# Extract strings from APK strings app.apk | grep -i "api_key\|password\|secret" # Extract URLs strings app.apk | grep "http" # Check signature apksigner verify --print-certs app.apk # Extract certificates keytool -printcert -file META-INF/CERT.RSA # Objection runtime analysis objection explore -gobjection -g memory search "password" --string # Drozer module dz> run app.package.list dz> run app.package.info -a com.example.app dz> run app.activity.info -a com.example.app
⚠️ Common Vulnerabilities
| Vulnerability | Description | Risk |
|---|---|---|
| Hardcoded Credentials | API keys, passwords in source code | Critical |
| Insecure Storage | Sensitive data in plaintext files | High |
| No SSL Pinning | Traffic interception possible | High |
| Root Detection Bypass | Malware can run on rooted devices | Medium |
| Exported Components | Other apps can access functionality | Medium |
| Debug Enabled | Runtime inspection possible | Medium |
| Excessive Permissions | More access than needed | Medium |
🛡️ Mitigation
- Use Android Keystore for cryptographic keys
- Implement SSL/TLS pinning properly
- Encrypt SharedPreferences with EncryptedSharedPreferences
- Use SQLCipher for database encryption
- Implement root/tamper detection (but don't rely solely on it)
- Enable ProGuard/R8 for code obfuscation
- Use secure random number generators
- Never log sensitive data
Best Practices:
- Store tokens in KeyStore, not SharedPreferences
- Use biometric authentication for sensitive operations
- Implement certificate validation properly
- Use Android's built-in encryption (EncryptedFile, EncryptedSharedPreferences)
- Follow principle of least privilege for permissions