🧠 Description

Android APK reverse engineering is the process of analyzing compiled Android applications to understand their functionality, find vulnerabilities, and extract sensitive information.

Why APK Analysis Matters:
  • 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 components
  • res/ - Resources (layouts, strings, images)
  • lib/ - Native libraries (.so files)
  • assets/ - Additional bundled files
  • META-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:

  1. Check AndroidManifest.xml for excessive permissions
  2. Search for hardcoded credentials in source code
  3. Analyze network traffic encryption implementation
  4. Review data storage mechanisms
  5. Identify crypto implementation
  6. 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:

PermissionPotential AbuseLegitimate Use
READ_SMSSteal OTPs, 2FA codesOTP auto-fill
READ_CONTACTSHarvest contact listPayment apps
RECORD_AUDIOSurveillanceVoice notes
READ_EXTERNAL_STORAGEExfiltrate filesPhoto 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
Insecure Storage Findings:
  • 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 CryptoProvider or 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 -g 
objection -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

VulnerabilityDescriptionRisk
Hardcoded CredentialsAPI keys, passwords in source codeCritical
Insecure StorageSensitive data in plaintext filesHigh
No SSL PinningTraffic interception possibleHigh
Root Detection BypassMalware can run on rooted devicesMedium
Exported ComponentsOther apps can access functionalityMedium
Debug EnabledRuntime inspection possibleMedium
Excessive PermissionsMore access than neededMedium

🛡️ Mitigation

✅ Secure Development Practices:
  • 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
Back to Mobile Security