Complete Android app penetration testing environment setup with Android Studio, rooted emulator, Magisk, and reverse engineering tools
---
name: android-pentest-environment-setup
description: Complete Android app penetration testing environment setup with Android Studio, rooted emulator, Magisk, and reverse engineering tools
triggers:
- how do I set up an Android pentesting environment
- configure Android emulator for app security testing
- root Android Studio emulator with Magisk
- install frida on rooted Android emulator
- setup Android app reverse engineering environment
- configure proxy for Android app traffic interception
- bypass Android SSL pinning with Magisk modules
- setup ADB for Android security testing
---
# Android Penetration Testing Environment Setup
> Skill by [ara.so](https://ara.so) — Security Skills collection.
This skill covers setting up a complete Android application penetration testing environment using Android Studio emulators, including rooting with Magisk, installing security testing frameworks (Frida, LSPosed), and configuring traffic interception tools.
## What This Project Provides
A comprehensive guide to building a modern (2026) Android app penetration testing lab environment on Android Studio, including:
- Android Studio AVD (Android Virtual Device) configuration optimized for security testing
- Root access via Magisk framework
- Frida dynamic instrumentation framework
- LSPosed/Xposed module framework for runtime hooking
- SSL/TLS certificate pinning bypass capabilities
- Traffic interception setup with Burp Suite/mitmproxy
- Anti-emulator detection bypass techniques
**Key Advantages:**
- Reproducible environment using snapshots
- No need for physical devices
- Full system access for deep analysis
- Support for Android 16 (API 36)
**Limitations:**
- Some apps detect emulators and refuse to run
- Performance may be slower than physical devices
## Prerequisites
- macOS, Linux, or Windows
- 16GB+ RAM recommended
- Android Studio installed
- Proxy tool (Burp Suite, mitmproxy, Charles) for traffic analysis
## Installation
### 1. Install Android Studio and SDK
```bash
# macOS/Linux - Download from official site
# https://developer.android.google.cn/studio
# After installation, configure SDK path (default recommended)
# macOS: ~/Library/Android/sdk
# Linux: ~/Android/Sdk
# Windows: %LOCALAPPDATA%\Android\Sdk
# Set environment variables (macOS/Linux bash)
cat >> ~/.bash_profile << 'EOF'
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/emulator
EOF
source ~/.bash_profile
# For zsh users
cat >> ~/.zshrc << 'EOF'
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/emulator
EOF
source ~/.zshrc
# Verify ADB is accessible
adb version
```
**Windows PowerShell:**
```powershell
# Add to System Environment Variables
[Environment]::SetEnvironmentVariable("ANDROID_HOME", "$env:LOCALAPPDATA\Android\Sdk", "User")
$path = [Environment]::GetEnvironmentVariable("Path", "User")
[Environment]::SetEnvironmentVariable("Path", "$path;$env:ANDROID_HOME\platform-tools;$env:ANDROID_HOME\tools", "User")
```
### 2. Create Android Virtual Device (AVD)
```bash
# List available system images
sdkmanager --list | grep system-images
# Install Android 16 (API 36) Google APIs ARM64
sdkmanager "system-images;android-36;google_apis;arm64-v8a"
# Create AVD via command line (alternative to GUI)
avdmanager create avd \
-n pentest_pixel9 \
-k "system-images;android-36;google_apis;arm64-v8a" \
-d "pixel_9_pro"
# Or use Android Studio GUI:
# More Actions → Virtual Device Manager → Create Device
# - Device: Pixel 9 Pro
# - System Image: API 36 (Android 16), Google APIs, arm64-v8a
# - Configuration:
# * RAM: 4096 MB
# * Internal Storage: 16384 MB
# * VM heap: 512 MB
# * Boot option: Cold Boot
```
**Important:** Choose **Google APIs** (NOT Google Play) to allow root access.
### 3. Root with Magisk (Method A: rootAVD - Recommended)
```bash
# Clone rootAVD tool
git clone https://gitlab.com/newbit/rootAVD.git
cd rootAVD
# Download latest Magisk APK and rename to Magisk.zip
# https://github.com/topjohnwu/Magisk/releases
curl -L -o Magisk.zip https://github.com/topjohnwu/Magisk/releases/download/v28.1/Magisk-v28.1.apk
# List available AVDs
./rootAVD.sh ListAllAVDs
# Root the specific system image
./rootAVD.sh system-images/android-36/google_apis/arm64-v8a/ramdisk.img
# Start emulator (will auto-install Magisk)
emulator -avd pentest_pixel9 -writable-system
# Verify root
adb shell su -c "id"
# Expected output: uid=0(root) gid=0(root)
```
### 4. Root with Magisk (Method B: Manual Patch - If rootAVD Fails)
```bash
# Start emulator with writable system
emulator -avd pentest_pixel9 -writable-system &
sleep 30
adb root
adb remount
# Install Magisk APK
adb install Magisk-v28.1.apk
# Push ramdisk to device
RAMDISK="$ANDROID_HOME/system-images/android-36/google_apis/arm64-v8a/ramdisk.img"
adb push "$RAMDISK" /sdcard/Download/ramdisk.img
# In Magisk app: Install → Select and Patch a File → Choose ramdisk.img
# Wait for patching to complete
# Pull patched ramdisk
adb pull /sdcard/Download/magisk_patched_*.img ./
# Replace original ramdisk
cp magisk_patched_*.img "$ANDROID_HOME/system-images/android-36/google_apis/arm64-v8a/ramdisk.img"
# Restart emulator
adb reboot
```
## Key Commands
### ADB (Android Debug Bridge)
```bash
# List connected devices
adb devices
# Connect to specific emulator
adb -s emulator-5554 shell
# Install APK
adb install app.apk
adb install -r app.apk # Reinstall keeping data
# Pull/Push files
adb pull /data/data/com.example.app/databases/app.db ./
adb push burp-cert.der /sdcard/
# Forward ports
adb forward tcp:8080 tcp:8080
# Get root shell
adb root
adb shell
# Remount system as writable
adb remount
# Log viewing
adb logcat | grep -i "com.example.app"
adb logcat -c # Clear logs
# Screen capture
adb shell screencap /sdcard/screen.png
adb pull /sdcard/screen.png
# Start/Stop app
adb shell am start -n com.example.app/.MainActivity
adb shell am force-stop com.example.app
```
### Magisk Module Management
```bash
# Install module via ADB
adb push module.zip /sdcard/Download/
adb shell su -c "magisk --install-module /sdcard/Download/module.zip"
# List installed modules
adb shell su -c "ls /data/adb/modules"
# Enable Zygisk (required for LSPosed)
adb shell su -c "magisk --sqlite 'UPDATE settings SET value=1 WHERE key=\"zygisk\"'"
adb reboot
# Check Magisk status
adb shell su -c "magisk -v"
```
## Installing Security Testing Frameworks
### 1. Install Frida
```bash
# Get Android architecture
adb shell getprop ro.product.cpu.abi
# Output: arm64-v8a
# Download Frida server (match version with frida-tools)
FRIDA_VERSION=$(pip3 show frida | grep Version | cut -d' ' -f2)
wget "https://github.com/frida/frida/releases/download/${FRIDA_VERSION}/frida-server-${FRIDA_VERSION}-android-arm64.xz"
unxz frida-server-*-android-arm64.xz
# Push to device
adb root
adb push frida-server-*-android-arm64 /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server
# Start Frida server
adb shell "/data/local/tmp/frida-server &"
# Verify on host
pip3 install frida-tools
frida-ps -U
# Should list running processes
```
**Persistent Frida with Magisk Module:**
```bash
# Create Magisk module structure
mkdir -p frida-module/system/bin
cp frida-server-*-android-arm64 frida-module/system/bin/frida-server
# Create module.prop
cat > frida-module/module.prop << 'EOF'
id=frida_server
name=Frida Server
version=16.5.0
versionCode=16050
author=Frida
description=Frida dynamic instrumentation toolkit
EOF
# Create service script
cat > frida-module/service.sh << 'EOF'
#!/system/bin/sh
/system/bin/frida-server &
EOF
# Package and install
cd frida-module
zip -r ../frida-module.zip .
adb push ../frida-module.zip /sdcard/
adb shell su -c "magisk --install-module /sdcard/frida-module.zip"
adb reboot
```
### 2. Install LSPosed (Xposed Framework)
```bash
# Download LSPosed Zygisk version
# https://github.com/LSPosed/LSPosed/releases
wget https://github.com/LSPosed/LSPosed/releases/download/v1.9.2/LSPosed-v1.9.2-7024-zygisk-release.zip
# Install via Magisk
adb push LSPosed-v1.9.2-7024-zygisk-release.zip /sdcard/
adb shell su -c "magisk --install-module /sdcard/LSPosed-v1.9.2-7024-zygisk-release.zip"
adb reboot
# Access LSPosed Manager (after reboot)
# Notification will appear, or run:
adb shell am start -n org.lsposed.manager/.ui.activity.MainActivity
```
**Common LSPosed Modules for Pentesting:**
```bash
# TrustMeAlready - Bypass SSL pinning
# https://github.com/ViRb3/TrustMeAlready/releases
# JustTrustMe - Alternative SSL bypass
# Install via LSPosed Manager → Repository
# XPrivacyLua - Privacy/permission control
# Useful for testing permission bypasses
```
### 3. Install ZygiskNext (Improved Zygisk)
```bash
# Download ZygiskNext
wget https://github.com/Dr-TSNG/ZygiskNext/releases/download/v4.0.1/Zygisk-Next-4.0.1-release.zip
# Disable built-in Zygisk first
adb shell su -c "magisk --sqlite 'UPDATE settings SET value=0 WHERE key=\"zygisk\"'"
# Install ZygiskNext
adb push Zygisk-Next-4.0.1-release.zip /sdcard/
adb shell su -c "magisk --install-module /sdcard/Zygisk-Next-4.0.1-release.zip"
adb reboot
```
## SSL/TLS Certificate Pinning Bypass
### Method 1: System Certificate Installation
```bash
# Convert PEM cert to Android format
openssl x509 -inform PEM -subject_hash_old -in burp-cert.pem | head -1
# Output: 9a5ba575
# Rename cert
cp burp-cert.pem 9a5ba575.0
# Push to system store
adb root
adb remount
adb push 9a5ba575.0 /system/etc/security/cacerts/
adb shell chmod 644 /system/etc/security/cacerts/9a5ba575.0
adb reboot
```
### Method 2: Using Magisk Modules
**Install TrustMeAlready:**
```bash
# Download from LSPosed Manager or:
adb push TrustMeAlready.apk /sdcard/
adb install /sdcard/TrustMeAlready.apk
# Enable in LSPosed:
# 1. Open LSPosed Manager
# 2. Modules → TrustMeAlready → Enable
# 3. Select target apps
# 4. Reboot
```
**Install Shamiko (Hide root from apps):**
```bash
wget https://github.com/LSPosed/LSPosed.github.io/releases/download/shamiko-354/Shamiko-v0.7.4-354-release.zip
adb push Shamiko-v0.7.4-354-release.zip /sdcard/
adb shell su -c "magisk --install-module /sdcard/Shamiko-v0.7.4-354-release.zip"
adb reboot
```
## Traffic Interception Setup
### Configure Proxy on Emulator
```bash
# Method 1: Via ADB (requires root)
adb shell settings put global http_proxy <HOST_IP>:8080
# Method 2: Via emulator settings
# Settings → Network & Internet → Wi-Fi → AndroidWifi →
# Proxy → Manual → Hostname: <HOST_IP>, Port: 8080
# Disable proxy
adb shell settings put global http_proxy :0
# Verify proxy settings
adb shell settings get global http_proxy
```
### Burp Suite Configuration
```bash
# 1. Export Burp CA certificate (DER format)
# Proxy → Options → Import/Export CA Certificate → Export DER
# 2. Push to emulator
adb push burp-cert.der /sdcard/
# 3. Install via Settings
# Settings → Security → Install from SD card → Select burp-cert.der
# 4. For system-level trust (Android 7+)
openssl x509 -inform DER -in burp-cert.der -out burp-cert.pem
openssl x509 -inform PEM -subject_hash_old -in burp-cert.pem | head -1
# e.g., output: 9a5ba575
cp burp-cert.pem 9a5ba575.0
adb root
adb remount
adb push 9a5ba575.0 /system/etc/security/cacerts/
adb shell chmod 644 /system/etc/security/cacerts/9a5ba575.0
adb reboot
```
## Frida Scripts for Common Tasks
### Bypass SSL Pinning (Universal Script)
```javascript
// ssl-pinning-bypass.js
Java.perform(function() {
console.log("[*] Bypassing SSL Pinning...");
// OkHttp3
try {
var CertificatePinner = Java.use('okhttp3.CertificatePinner');
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {
console.log('[+] OkHttp3 pinning bypassed');
return;
};
} catch(err) {
console.log('[-] OkHttp3 not found');
}
// TrustManager
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
var SSLContext = Java.use('javax.net.ssl.SSLContext');
var TrustManager = Java.registerClass({
name: 'dev.asd.test.TrustManager',
implements: [X509TrustManager],
methods: {
checkClientTrusted: function(chain, authType) {},
checkServerTrusted: function(chain, authType) {},
getAcceptedIssuers: function() { return []; }
}
});
var TrustManagers = [TrustManager.$new()];
var SSLContext_init = SSLContext.init.overload(
'[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom'
);
SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) {
console.log('[+] TrustManager bypassed');
SSLContext_init.call(this, keyManager, TrustManagers, secureRandom);
};
});
```
**Run the script:**
```bash
frida -U -f com.example.app -l ssl-pinning-bypass.js --no-pause
```
### Extract Shared Preferences
```javascript
// extract-prefs.js
Java.perform(function() {
var context = Java.use('android.app.ActivityThread')
.currentApplication()
.getApplicationContext();
var prefsDir = context.getFilesDir().getParent() + '/shared_prefs';
console.log('[*] Shared Preferences location:', prefsDir);
var File = Java.use('java.io.File');
var dir = File.$new(prefsDir);
var files = dir.listFiles();
for (var i = 0; i < files.length; i++) {
console.log('[+] Found:', files[i].getName());
}
});
```
### Hook Crypto Functions
```javascript
// crypto-hook.js
Java.perform(function() {
var Cipher = Java.use('javax.crypto.Cipher');
Cipher.doFinal.overload('[B').implementation = function(byteArr) {
console.log('[*] Cipher.doFinal called');
console.log('[*] Algorithm:', this.getAlgorithm());
console.log('[*] Input:', Java.use('android.util.Base64')
.encodeToString(byteArr, 0));
var result = this.doFinal(byteArr);
console.log('[*] Output:', Java.use('android.util.Base64')
.encodeToString(result, 0));
return result;
};
});
```
## Troubleshooting
### Emulator Won't Start
```bash
# Check available resources
emulator -list-avds
emulator -avd pentest_pixel9 -verbose
# Try cold boot
emulator -avd pentest_pixel9 -no-snapshot-load
# Wipe data if corrupted
emulator -avd pentest_pixel9 -wipe-data
```
### ADB Can't Connect
```bash
# Kill and restart ADB server
adb kill-server
adb start-server
# Check emulator port
adb devices
# emulator-5554 device
# Manually connect
adb connect localhost:5554
```
### Magisk Not Working After Reboot
```bash
# Re-run rootAVD
cd rootAVD
./rootAVD.sh system-images/android-36/google_apis/arm64-v8a/ramdisk.img
# Or restore from snapshot before rooting
```
### Frida Connection Issues
```bash
# Ensure frida-server is running
adb shell "ps | grep frida-server"
# Kill and restart
adb shell "pkill frida-server"
adb shell "/data/local/tmp/frida-server &"
# Check port forwarding
adb forward tcp:27042 tcp:27042
# Verify version match
frida --version
adb shell /data/local/tmp/frida-server --version
```
### LSPosed Not Appearing
```bash
# Verify Zygisk is enabled
adb shell su -c "magisk --sqlite 'SELECT * FROM settings WHERE key=\"zygisk\"'"
# Should show value=1
# Check module status
adb shell su -c "ls -la /data/adb/modules/zygisk_lsposed"
# View logs
adb logcat | grep -i lsposed
```
### App Detects Emulator
**Use Shamiko + DenyList:**
```bash
# Enable Shamiko (if not already)
# Configure DenyList in Magisk
adb shell su -c "magisk --denylist add com.example.app"
adb shell su -c "magisk --denylist enable"
# Hide Magisk app itself
# Magisk → Settings → Hide Magisk App → Random package name
```
**Modify build.prop:**
```bash
adb root
adb remount
adb pull /system/build.prop
# Edit locally, change:
# ro.product.manufacturer=Google
# ro.product.model=Pixel 9 Pro
# ro.build.fingerprint=google/...
adb push build.prop /system/build.prop
adb reboot
```
### SSL Pinning Still Active
```bash
# Try multiple bypass methods simultaneously
frida -U -f com.example.app \
-l ssl-pinning-bypass.js \
-l universal-ssl-bypass.js \
--no-pause
# Enable TrustMeAlready in LSPosed for target app
# Reboot and test again
```
## Advanced Configuration
### Create Snapshot After Setup
```bash
# Via Android Studio GUI
# Virtual Device Manager → AVD → Dropdown → Snapshots → Take Snapshot
# Via command line (emulator must be running)
adb shell "sync; echo 3 > /proc/sys/vm/drop_caches"
# Then use GUI to snapshot
```
### Automated Environment Setup Script
```bash
#!/bin/bash
# setup-pentest-env.sh
AVD_NAME="pentest_pixel9"
ANDROID_API="android-36"
ARCH="arm64-v8a"
echo "[*] Setting up Android Pentest Environment..."
# Install system image
sdkmanager "system-images;${ANDROID_API};google_apis;${ARCH}"
# Create AVD
avdmanager create avd -n ${AVD_NAME} \
-k "system-images;${ANDROID_API};google_apis;${ARCH}" \
-d "pixel_9_pro" --force
# Root with rootAVD
cd rootAVD
./rootAVD.sh system-images/${ANDROID_API}/google_apis/${ARCH}/ramdisk.img
# Start emulator
emulator -avd ${AVD_NAME} -writable-system &
sleep 60
# Install Frida
FRIDA_VERSION=$(pip3 show frida | grep Version | awk '{print $2}')
wget -q "https://github.com/frida/frida/releases/download/${FRIDA_VERSION}/frida-server-${FRIDA_VERSION}-android-${ARCH}.xz"
unxz frida-server-*.xz
adb root
adb push frida-server-* /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server
adb shell "/data/local/tmp/frida-server &"
echo "[+] Setup complete. Connect via: adb -s emulator-5554 shell"
```
## References
- Original project: https://github.com/d0ctorsec/AndroidStudioAppPentestEnvironmentSetup
- rootAVD: https://gitlab.com/newbit/rootAVD
- Magisk: https://github.com/topjohnwu/Magisk
- Frida: https://frida.re
- LSPosed: https://github.com/LSPosed/LSPosed
Creator's repository · aradotso/security-skills