black electronics

Android

Android Application Penetration Testing

Android Application Penetration Testing

Android applications are distributed as APK packages that can be decompiled, inspected and modified. This section covers setting up an Android testing environment, reverse engineering and static analysis, runtime instrumentation with Frida, backend and cloud storage checks, and a practical methodology for the most common Android application vulnerabilities.

Setup and Preparation

Before testing an Android application you need an environment to run it in and a way to intercept its traffic. The tooling below covers emulators, physical/cloud devices, certificate installation and static analysis frameworks.

Genymotion

Genymotion is an Android emulator that runs on VirtualBox and is convenient for installing and interacting with APKs.

Terminal window
# Install Genymotion
https://www.genymotion.com/
# Install VirtualBox
https://www.virtualbox.org/wiki/Downloads

Genymotion SaaS

Genymotion also offers cloud-hosted devices driven from the gmsaas command-line tool.

Terminal window
# Install gmsaas
pip install gmsaas
# Android SDK setup
https://developer.android.com/tools/releases/platform-tools
# Copy and extract the platform-tools zip, then point gmsaas at the SDK
gmsaas config set android-sdk-path C:\Users\user\AndroidPlatformTools\platform-tools
# In Windows Terminal add adb to your PATH (temporary - make it permanent if you want)
$env:PATH += ";C:\Users\user\AndroidPlatformTools"
# Login to gmsaas
gmsaas auth login [email protected] # Enter password at prompt
# Start a virtual device from the Genymotion GUI
https://cloud.geny.io/launchpad
# Start a virtual device from the Genymotion CLI
gmsaas recipes list
gmsaas instances start <RECIPE-UUID> 'Example Test Phone Android 13' --no-wait --max-run-duration 30
# Connect to the virtual device using ADB
gmsaas instances list
gmsaas instances adbconnect <INSTANCE-UUID>

Configure the Burp certificate on the cloud device:

Terminal window
# Export the Burp certificate
openssl x509 -inform DER -in Burp_cert.cer -out Burp_cert.pem
openssl x509 -inform PEM -subject_hash_old -in Burp_cert.pem | head -1
mv Burp_cert.pem 9a5ba575.0
# Remount the system partition
adb remount
# Upload the certificate
adb push C:\Users\user\Downloads\9a5ba575.0 /system/etc/security/cacerts/
# If you get a "system is read-only" error use:
adb shell
mount -o rw,remount /system
# If still not working, use the below first
mount -o rw,remount /
# Once done
mount -o ro,remount /
# Change the certificate rights
adb shell chmod 664 /system/etc/security/cacerts/9a5ba575.0
adb reboot

Install the APK and proxy traffic to Burp:

Terminal window
# Install APK
adb install 'C:\path\to\example.apk'
# Proxy to Burp
adb shell settings put global http_proxy localhost:3333
adb reverse tcp:3333 tcp:8080
adb shell settings put global http_proxy :0 # Disable proxy
# Proxy multiple instances to Burp
gmsaas instances list
gmsaas instances adbconnect <INSTANCE-UUID-1>
adb -s localhost:33819 shell settings put global http_proxy localhost:3333
adb -s localhost:33819 reverse tcp:3333 tcp:8080
gmsaas instances adbconnect <INSTANCE-UUID-2>
adb -s localhost:41549 shell settings put global http_proxy localhost:4444
adb -s localhost:41549 reverse tcp:4444 tcp:8080
# If not root on the emulator
adb shell
setprop persist.sys.root_access 3
gmsaas instances adbconnect <INSTANCE-UUID>
adb shell
su

ARM Translation for Genymotion

Some apps ship only ARM native libraries and will not run on an x86 Genymotion image without an ARM translation layer.

Terminal window
# The virtual device you add in Genymotion must be Android 8.0 (e.g. the Pixel 2, Android 8.0)
# Step 1: Download v8.0 from https://github.com/m9rco/Genymotion_ARM_Translation
# Step 2: Open an administrative CMD and cd to C:\Program Files\Genymobile\Genymotion\tools
# Step 3: Push the zip to the device
adb push C:\Users\user\Downloads\Genymotion-ARM-Translation_for_8.0.zip /sdcard/Download
# Step 4: Open an adb shell
adb shell
# Step 5: Flash the archive
sh /system/bin/flash-archive.sh /sdcard/Download/Genymotion-ARM-Translation_for_8.0.zip
# Step 6: Exit the adb shell and reboot (also close Genymotion and re-open)
adb reboot
# Step 7: Install GApps

Android Studio

Android Studio’s emulator is a rooted-capable alternative that supports installing the Burp certificate into the system store.

Terminal window
# Install Android Studio
https://developer.android.com/studio
# Create a virtual device
# 1. Open Android Studio
# 2. Click More Actions --> Virtual Device Manager
# 3. Choose a device (a Pixel 3XL without Google Play keeps the device rooted)
# 4. Choose a system image (e.g. API 29 x86 Android 10 with Google APIs - needed if the app talks to Firebase etc.)
# Make the system partition mountable
cd C:\Users\user\AppData\Local\Android\Sdk\emulator
.\emulator.exe -writable-system -no-snapshot-load -avd Example -gpu host
# In another terminal while the above is running:
cd C:\Users\user\AppData\Local\Android\Sdk\platform-tools
.\adb.exe root
.\adb.exe shell avbctl disable-verification
.\adb.exe reboot #Wait for this to complete - the emulator will look frozen
.\adb.exe root
.\adb.exe remount

Push the Burp certificate to the device and install it as a system certificate (a user certificate will not be trusted by most apps):

Terminal window
# First on the machine running Burp
# 1. Proxy tab --> Options --> Import/export CA certificate --> Certificate in DER format --> save as burp.der
openssl x509 -inform DER -in burp.der -out burp.pem
openssl x509 -inform PEM -subject_hash_old -in burp.pem | head -1
mv burp.pem 9a5ba575.0
# Copy 9a5ba575.0 to the machine running the emulator
# On the emulator machine
.\adb.exe push C:\Users\user\Downloads\9a5ba575.0 /sdcard/
.\adb.exe shell
mv /sdcard/9a5ba575.0 /system/etc/security/cacerts/
chmod 644 /system/etc/security/cacerts/9a5ba575.0
# Run the AVD with the internal laptop webcam enabled
cd C:\Users\user\AppData\Local\Android\Sdk\emulator
.\emulator.exe -writable-system -no-snapshot-load -camera-front webcam0 -avd Example -gpu host

Check Connected Devices

Confirm the correct device is attached before running any tooling.

Terminal window
adb devices

Install an APK via ADB

Terminal window
adb install
adb install 'C:\path\to\example.apk'

If the app is distributed as a split APK, install all the parts together:

Terminal window
adb install-multiple 'C:\path\to\com.example.app-base.apk' 'C:\path\to\com.example.app-split_config.en.apk' 'C:\path\to\com.example.app-split_config.x86.apk' 'C:\path\to\com.example.app-split_config.xxhdpi.apk'

Android Device Architecture

You need the device architecture to download the matching Frida server build.

Terminal window
adb shell
getprop ro.product.cpu.abi

Install the Burp Certificate

The steps below install the Burp CA into the Genymotion system trust store.

Terminal window
# In Burp
# Proxy tab --> Options --> Import/export CA certificate --> Certificate in DER format --> save as burp.der
# On the machine with Burp
openssl x509 -inform DER -in burp.der -out burp.pem
openssl x509 -inform PEM -subject_hash_old -in burp.pem | head -1
# 9a5ba575
mv burp.pem 9a5ba575.0
# On Windows
adb push 9a5ba575.0 /sdcard/
adb shell
mv /sdcard/9a5ba575.0 /system/etc/security/cacerts/
chmod 644 /system/etc/security/cacerts/9a5ba575.0
# If you get a "system is read-only" error use:
adb shell
mount -o rw,remount /system
# If still not working, use the below first
mount -o rw,remount /
# Once done
mount -o ro,remount /

Alternatively, install from the device UI:

Terminal window
# On the emulated device
# Drag and drop the .cer file to the SD card
# Go to Settings --> Security & Location --> Encryption & credentials --> Install from SD card --> /sdcard/Download

MobSF

The Mobile Security Framework (MobSF) performs automated static and dynamic analysis of APKs.

Terminal window
https://github.com/MobSF/Mobile-Security-Framework-MobSF
# Install MobSF
cd C:\path\to\Mobile-Security-Framework-MobSF
.\setup.bat
# Run MobSF
cd C:\path\to\Mobile-Security-Framework-MobSF
.\run.bat 127.0.0.1:8000

Troubleshooting

Terminal window
# If you get a "system is read-only" error use:
adb shell
mount -o rw,remount /system
# If still not working, use the below first
mount -o rw,remount /
# Once done
mount -o ro,remount /
Terminal window
# If you get connection issues, restore internet access with:
adb shell
settings put global http_proxy :0
Terminal window
# Upload files to the SD card
adb push C:\path\to\example_resigned.apk /sdcard

Reverse Engineering and Static Analysis

Reverse engineering an APK exposes the application’s source, resources and manifest, which is where hardcoded secrets, API keys and insecure configuration are usually found.

Reverse Engineering Tools

Terminal window
# Tools
# APKTool
# Dex2Jar (built into Kali) # d2j-dex2jar app-release.apk
# JD-GUI
# SQLite DB Browser
# Keytool (comes with Java)

APKTool unpacks resources and decodes the manifest:

Terminal window
# https://ibotpeaches.github.io/Apktool/install/
apktool d C:\path\to\example.apk
.\apktool.bat -r d .\example\app.apk -o .\example\temp
# Searching for strings in the decompiled app
findstr /SIN "firebase" 'C:\path\to\example\*' # Apply the same logic for keys and passwords
findstr /SIN "API_KEY" *
findstr /SIN "secret" *
findstr /SIN firebase secret api_key password *

Dex2Jar converts .dex/.apk to a .jar you can browse in JD-GUI:

Terminal window
# Dex2Jar (built into Kali, or Windows https://github.com/pxb1988/dex2jar)
d2j-dex2jar example.apk
.\d2j-dex2jar.bat C:\path\to\example.apk
# Open the resulting .jar with JD-GUI - http://java-decompiler.github.io/

Keytool shows the details of the signing certificate found in the original folder after using APKTool:

Terminal window
keytool -printcert -file "C:\path\to\example\original\META-INF\CERT.RSA"

Static Code Analysis (StaCoAn)

StaCoAn scans decompiled code for interesting lines such as hardcoded credentials, API keys, API URLs, decryption keys and major coding mistakes.

Terminal window
https://github.com/vincentcox/StaCoAn
# StaCoAn looks for interesting lines in the code which can contain:
# - Hardcoded credentials
# - API keys
# - URLs of APIs
# - Decryption keys
# - Major coding mistakes
# Requires 64-bit Java.

The AndroidManifest.xml File

The manifest contains detailed information about the application, including its declared permissions, exported components and security-relevant flags such as android:debuggable and android:allowBackup. On a device you can inspect it with an app such as ManifestViewer, or extract it during static analysis with APKTool.

Modifying Smali

Decompiling to Smali lets you modify application behaviour (for example to disable a client-side control) and recompile and re-sign the APK.

Terminal window
# Decompile, modify Smali, recompile and sign an APK
https://www.hebunilhanli.com/wonderland/mobile-security/decompile-modify-smali-recompile-and-sign-apk/
https://book.hacktricks.xyz/mobile-apps-pentesting/android-app-pentesting/smali-changes
https://github.com/skylot/jadx

React Native Apps

If you see an index.android.bundle file in /assets after unpacking with APKTool, the app is a React Native app.

Terminal window
# Decompile the APK
# https://ibotpeaches.github.io/Apktool/install/
.\apktool.bat -r d '.\example.apk' -o .\example
# Extract the index.android.bundle file from the /assets folder
# Decompile index.android.bundle (may not work if built with webpack v5 etc.)
https://github.com/numandev1/react-native-decompiler
sudo apt install npm
npm install -g react-native-decompiler
npx react-native-decompiler -i ~/clients/example/index.android.bundle -o ~/clients/example/output
# Decompile index.android.bundle if based on the Hermes engine
https://github.com/bongtrop/hbctool
git clone https://github.com/bongtrop/hbctool.git
cd hbctool
poetry build
pip install --force-reinstall dist/hbctool-0.1.5-py3-none-any.whl
hbctool disasm index.android.bundle example_hasm
# Decompile index.android.bundle if based on the Hermes engine (option 2)
https://github.com/P1sec/hermes-dec
git clone https://github.com/P1sec/hermes-dec.git
cd hermes-dec
hbc-disassembler ~/clients/example/index.android.bundle ~/clients/example/example_hermes.hasm
hbc-decompiler ~/clients/example/index.android.bundle ~/clients/example/example_hermes.js

Xamarin Apps

Xamarin apps store their .NET assemblies (DLLs) in /unknown/assemblies. Decompile these to review source for database credentials, encryption keys and other secrets.

Terminal window
# Find security vulnerabilities in Xamarin.Android apps
https://github.com/wesleydekraker/xamarin-security-scanner
https://dotnet.microsoft.com/download/dotnet-core/thank-you/sdk-3.1.401-windows-x64-installer
"C:\path\to\xamarin-security-scanner" dotnet run --project ./XamarinSecurityScanner\XamarinSecurityScanner.App --path C:\path\to\example\
# The tool reports issues such as:
# - Certificate validation overwritten
# - Permissions may not be enforced
# - Unsafe cipher mode used
# - External storage is used
# - Hardcoded HTTP URL found
# - JavaScript enabled in WebView
# - JavascriptInterface added to a WebView
# - Logging was found
# - Access to phone number
# - WorldReadable file found
# - Backups are enabled
# - App has debugging enabled
# - App supports an outdated Android version
# - App contains a private key
# Xamarin apps store DLLs in /unknown/assemblies
# Use https://www.jetbrains.com/decompiler/ to view the DLL source for DB credentials, encryption keys etc.

Runtime Analysis with Objection and Frida

Frida instruments a running application and Objection builds on it to provide a runtime mobile exploration toolkit, useful for tasks such as bypassing SSL pinning or root detection.

Installing Frida and Objection

Terminal window
# Install Frida (Windows)
pip install frida-tools
# Install Objection (Windows)
pip install objection
# Add the above tools to the Windows PATH
pip show frida-tools # Note the location
pip show objection # Note the location
# The above shows ...\site-packages. Add the directory one level up, e.g.
# ...\AppData\Local\Programs\Python\Python311\Scripts, to the PATH
# Test
frida ps
objection

Running Frida Server

Terminal window
# Get the device architecture
adb shell
getprop ro.product.cpu.abi # For example x86_64
# Download the matching Frida server version
https://github.com/frida/frida/releases
# Usually https://github.com/frida/frida/releases/download/16.1.4/frida-server-16.1.4-android-x86_64.xz
# Extract and push the server to /data/local/tmp
adb push .\Downloads\frida\frida-server-16.1.4-android-x86_64 /data/local/tmp
adb shell
cd /data/local/tmp
chmod 777 frida-server-16.1.4-android-x86_64
./frida-server-16.1.4-android-x86_64
# List apps installed, using Frida
frida-ps -Uai

Runtime Changes with Objection

Terminal window
# Perform runtime changes using Objection on one of the apps listed above
https://book.hacktricks.xyz/mobile-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial
objection -g com.example.app explore

Backend and Cloud Storage

Mobile apps frequently talk to cloud backends. Misconfigured Firebase databases and storage buckets are a common source of high-impact findings.

Firebase

Methodology to search for and exploit poorly configured Firebase databases:

Terminal window
# https://book.hacktricks.xyz/pentesting/pentesting-web/buckets/firebase-database
# 1. Get the APK of the app (any method to pull the APK from the device works)
# 2. Decompile the APK with apktool
.\apktool.bat d C:\path\to\example.apk
# 3. In res/values/strings.xml search for the "firebase" keyword. You may find a URL
# such as https://xyz.firebaseio.com/
Get-ChildItem -Path .\example\ -Recurse | Select-String -Pattern "firebase"
findstr.exe /SIN "firebaseio" .\app-release\*
# 4. Navigate to the found URL with .json appended: https://xyz.firebaseio.com/.json
# 5. Two responses can appear:
# "Permission Denied" -> it is well configured
# "null" or a block of JSON -> the database is public and you have at least read access
# 6. If readable, check for write privileges using:
# https://github.com/MuhammadKhizerJaved/Insecure-Firebase-Exploit

Google Storage Buckets

Terminal window
https://github.com/RhinoSecurityLabs/GCPBucketBrute
# Brute forcing bucket names
cd ~/tools/GCPBucketBrute
sudo python3 gcpbucketbrute.py -k example -u
# URL format for buckets
# www.googleapis.com/storage/v1/b/<BUCKET NAME>/o
# error 404 -> does not exist
# error 401 -> exists but configured properly
# a list of files -> the bucket is vulnerable and misconfigured
# Get the bucket policy
https://www.googleapis.com/storage/v1/b/<BUCKET NAME>/iam
https://www.googleapis.com/storage/v1/b/example-app-production.appspot.com/iam
# Check strings in the decompiled APK for a storage bucket reference
Get-ChildItem -Path .\app\ -Recurse | Select-String -Pattern "google_storage_bucket"
# "google_storage_bucket" : "example-app-production.appspot.com"
Terminal window
# gsutil
https://cloud.google.com/storage/docs/gsutil_install
# List the contents of a bucket (needs auth, but use it to check if anonymous access is allowed)
gsutil ls gs://example-app-production.appspot.com

Pulling Databases

App data is stored under /data/data/<package>; apps can also store data in external storage under /mnt/sdcard.

Terminal window
# Enter an ADB shell
adb shell
cd /data/data
cd com.android.providers.telephony
cd databases
# In a new terminal, pull the databases
.\adb.exe pull /data/data/com.android.providers.telephony/databases
# Open the .db files with DB Browser for SQLite
# https://sqlitebrowser.org/dl/
# App-specific data is stored in:
# /data/data/****
# Apps can also store data in external storage:
# /mnt/sdcard

SSL Pinning

Apps that implement certificate pinning will reject Burp’s certificate. The references below cover testing and bypassing pinning (often via Frida/Objection).

Terminal window
# Testing SSL pinning
https://medium.com/globant/testing-ssl-pinning-in-a-mobile-application-44e0175f9244
https://medium.com/@evilprince007/ssl-pinning-bypass-simplified-48c0d5294a6c

Mobile Application Methodology

The checklist below walks through the most common Android application weaknesses.

1. Insecure Data Storage

Check for sensitive user data stored insecurely in shared preferences, databases and temporary files.

Terminal window
# Insecure data storage
adb shell
cd /data/data
cd mnt
cd /mnt/sdcard
# Check for insecure user data storage in:
# 1. Shared Preferences
/data/data/com.example.app/shared_prefs/UserInfo.xml
# 2. Databases
# 3. Temporary files

2. Hardcoding Issues

Terminal window
# Use JD-GUI to view .jar source code for hardcoded API keys etc.

3. Insecure Logging

Terminal window
# Use logcat to view logs of app activity
adb logcat
.\adb.exe -s 192.168.1.100:5555 logcat | Select-String -Pattern com.example.app
# Look for cleartext logging of sensitive data, for example:
# - Credit card details
# - Login credentials

4. Input Validation Issues

Terminal window
# Classic SQL injection
' OR '1'='1'--
# Check WebViews for possible input validation flaws
# Web addresses e.g. http://www.example.com
# Files e.g. file:///data/data/com.example.app/shared_prefs/UserInfo.xml
# Enter these in places like search fields

5. Re-signing the Application

An attacker may inject malicious code into an app and re-sign it so a device will install it.

Terminal window
# Tools: jarsigner (comes with the JDK)
jarsigner -verify -verbose C:\path\to\example.apk
Terminal window
# Remove the existing certificate and signature
# 1. Unpack the apk with APKTool
# 2. Remove the META-INF folder
# Now you can re-sign the application
# Set up a keystore to hold the private key used to sign the application
keytool -genkey -v -keystore [name of keystore] -alias [your key alias] -keyalg RSA -keysize 2048 -validity [number of days]
keytool -genkey -v -keystore example-keystore -alias example -keyalg RSA -keysize 2048 -validity 10000
Terminal window
# Sign the application with jarsigner (admin cmd)
jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore [name of your keystore] [your .apk file] [your key alias]
jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore example-keystore C:\path\to\example_resigned.apk example

6. Access Control Issues

Exported activities can sometimes be launched directly, bypassing intended access controls.

Terminal window
https://tools.androidtamer.com/Training/DIVA/10_Access_Control_Issues_P2/
# Activity manager
adb shell am start [action from intent filter]
adb shell am start -W -a android.intent.action.MAIN

7. Backup Vulnerabilities

If the manifest sets allowBackup="true", application data can be extracted through the backup mechanism.

Terminal window
https://resources.infosecinstitute.com/topic/android-hacking-security-part-15-hacking-android-apps-using-backup-techniques/
# Look for: allowBackup="true"
Terminal window
https://vishwarajbhattrai.wordpress.com/2017/07/17/finding-backup-vulnerabilities-in-android-apps/
adb backup -f C:\path\to\example.ab com.example.app
# Convert the .ab file into .tar using Android Backup Extractor
# https://github.com/nelenkov/android-backup-extractor/
# Get abe-all.jar from releases, rename it to abe and copy it to your working folder
cd C:\path\to\android-backup-extractor
abe.jar unpack example.ab example.tar
# Copy the tar file to Kali and extract it
tar xvf example.tar
# Explore the extracted files, including assets like .db and sharedprefs.xml, for sensitive
# information - developers sometimes leave secrets, passwords, or API auth tokens here.
# Use sqlite to view .db files.

8. Permissions

List all requested permissions and look for dangerous ones.

Terminal window
https://aaptdownload.com/
# List all permissions for the APK
aapt d permissions 'C:\path\to\example.apk'

9. Free Security Features are Activated

Check the native libraries for PIE and stack-smashing protections (canary and pic must both be true).

Terminal window
https://github.com/radareorg/radare2/
# Test a single native library
.\rabin2.exe -I 'C:\path\to\example\lib\x86_64\libexample.so' | Select-String "canary|pic"
# Repeat for all .so files in the \lib\x86_64\ folder
# In PowerShell ISE, run rabin2 across every file in the \lib\x86_64\ folder
$PrevErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = 'silentlycontinue'
Get-ChildItem -Path 'C:\path\to\example\lib\x86_64\' -Recurse | ForEach-Object {$_.FullName
C:\path\to\radare2\bin\rabin2.exe -I $_.Fullname | Select-String 'canary|pic'}
$ErrorActionPreference = $PrevErrorActionPreference

10. Testing if the App is Debuggable

Terminal window
# Manual
# Check AndroidManifest.xml for the android:debuggable attribute and its value
# Using adb
adb shell dumpsys package com.example.app | Select-String "DEBUGGABLE"
# Using aapt (if the result is 1, the directive is present)
aapt d xmltree 'example.apk' AndroidManifest.xml | Select-String -Pattern 'android:debuggable\(0x[0-9a-f]+\)=\(type\s0x[0-9a-f]+\)0xffffffff'

Additional Tools to Test

Terminal window
# QARK - https://github.com/linkedin/qark (Quick Android Review Kit)
# Drozer - https://labs.f-secure.com/tools/drozer
# PentDroid - https://github.com/vishwaraj101/PentDroid
# Mobile Nuclei templates - https://github.com/optiv/mobile-nuclei-templates
# Using the Android USB driver to extract data as a USB mass storage device
# https://seclists.org/fulldisclosure/2021/Jun/50
# General
# https://github.com/sensepost/objection
Useful LinksPentest PayloadsCheat Sheets