| name | android-studio-pentest-environment |
| description | Set up a complete Android app penetration testing environment using Android Studio emulators with Magisk root, Frida, HTTP Toolkit, and LSPosed modules |
| triggers | ["how do I set up an Android pentest lab","configure Android emulator for security testing","install Magisk and Frida on Android Studio AVD","set up rootAVD for app testing","create Android pentest environment","configure HTTP proxy for Android app analysis","install LSPosed modules for bypassing SSL pinning","troubleshoot Android emulator root access"] |
Android Studio Pentest Environment Setup
Skill by ara.so — Security Skills collection.
This skill provides expertise in setting up a complete Android application penetration testing environment using Android Studio Virtual Device Manager (AVD) with root access via Magisk, Frida dynamic instrumentation, HTTP Toolkit for traffic interception, and LSPosed modules for runtime manipulation.
What This Project Does
This project guides you through building a 2026-ready Android app penetration testing lab that includes:
- Android Studio AVD with Google APIs (API 36/Android 16)
- Magisk (root) via rootAVD automation
- Frida for dynamic instrumentation
- HTTP Toolkit for HTTPS traffic interception
- LSPosed with TrustMeAlready and JustTrustMe modules for SSL pinning bypass
- Shamiko for root hiding
- ZygiskNext as modern Zygisk replacement
Prerequisites
Install Android Studio and SDK
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"
export ANDROID_HOME="$HOME/Android/Sdk"
export PATH="$PATH:$ANDROID_HOME/platform-tools"
$env:ANDROID_HOME = "$env:LOCALAPPDATA\Android\Sdk"
$env:Path += ";$env:ANDROID_HOME\platform-tools"
Apply the configuration:
source ~/.bash_profile
adb version
Create Android Virtual Device
sdkmanager --list | grep system-images
sdkmanager "system-images;android-36;google_apis;arm64-v8a"
Root the Emulator with Magisk
Method A: rootAVD (Recommended)
git clone https://gitlab.com/newbit/rootAVD.git
cd rootAVD
curl -L -o Magisk.zip https://github.com/topjohnwu/Magisk/releases/download/v28.1/Magisk-v28.1.apk
./rootAVD.sh ListAllAVDs
./rootAVD.sh system-images/android-36.1/google_apis/arm64-v8a/ramdisk.img
Method B: Manual Magisk Patch (Fallback)
emulator -avd Pixel_9_Pro_API_36 -writable-system &
adb root
adb remount
adb install Magisk-v28.1.apk
adb push "$ANDROID_HOME/system-images/android-36/google_apis/arm64-v8a/ramdisk.img" /sdcard/Download/
adb pull /sdcard/Download/magisk_patched_*.img ./
cp magisk_patched_*.img "$ANDROID_HOME/system-images/android-36/google_apis/arm64-v8a/ramdisk.img"
adb reboot
Configure Magisk
adb shell su -c "id"
Install Frida
Frida Server on Device
FRIDA_VERSION="16.5.9"
curl -L -o frida-server.xz "https://github.com/frida/frida/releases/download/${FRIDA_VERSION}/frida-server-${FRIDA_VERSION}-android-arm64.xz"
unxz frida-server.xz
adb push frida-server /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "su -c '/data/local/tmp/frida-server &'"
frida-ps -U
Frida Tools on Host
pip install frida-tools==16.5.9
frida-ps -U
Frida Usage Examples
import frida
import sys
def on_message(message, data):
print(f"[*] {message}")
package = "com.example.app"
device = frida.get_usb_device()
session = device.attach(package)
script_code = """
Java.perform(function() {
var MainActivity = Java.use('com.example.app.MainActivity');
MainActivity.checkRoot.implementation = function() {
console.log('[*] checkRoot() bypassed');
return false;
};
});
"""
script = session.create_script(script_code)
script.on('message', on_message)
script.load()
sys.stdin.read()
frida -U -f com.example.app -l ssl-pinning-bypass.js --no-pause
Install LSPosed and Modules
Install LSPosed (Zygisk version)
curl -L -o LSPosed.zip https://github.com/LSPosed/LSPosed/releases/download/v1.9.2/LSPosed-v1.9.2-7024-zygisk-release.zip
adb push LSPosed.zip /sdcard/Download/
adb reboot
Upgrade to ZygiskNext
curl -L -o ZygiskNext.zip https://github.com/Dr-TSNG/ZygiskNext/releases/download/v4.0.2/Zygisk-Next-4.0.2-291-release.zip
adb push ZygiskNext.zip /sdcard/Download/
adb reboot
Install TrustMeAlready (SSL Pinning Bypass)
curl -L -o TrustMeAlready.apk https://github.com/ViRb3/TrustMeAlready/releases/download/v1.11/TrustMeAlready-v1.11.apk
adb install TrustMeAlready.apk
Install JustTrustMe (Alternative)
curl -L -o JustTrustMe.apk https://github.com/Fuzion24/JustTrustMe/releases/download/v.2/JustTrustMe.apk
adb install JustTrustMe.apk
HTTP Traffic Interception
Method A: HTTP Toolkit
brew install --cask http-toolkit
adb shell settings get global http_proxy
Method B: Manual Proxy Setup
adb shell settings put global http_proxy 127.0.0.1:8080
openssl x509 -inform DER -in burp.cer -out burp.pem
HASH=$(openssl x509 -inform PEM -subject_hash_old -in burp.pem | head -1)
adb root
adb remount
adb push burp.pem "/system/etc/security/cacerts/${HASH}.0"
adb shell chmod 644 "/system/etc/security/cacerts/${HASH}.0"
adb reboot
Install Shamiko (Root Hiding)
curl -L -o Shamiko.zip https://github.com/LSPosed/LSPosed.github.io/releases/download/shamiko-281/Shamiko-v0.7.4-281-release.zip
adb push Shamiko.zip /sdcard/Download/
adb reboot
Testing and Verification
Verify Root Status
adb shell su -c "whoami"
adb shell pm list packages | grep -i magisk
Verify Frida
frida-ps -U
frida -U -f com.android.settings -l test.js
Verify SSL Pinning Bypass
Common Patterns
Install APK and Analyze
adb install target.apk
adb shell pm list packages -f | grep target
adb shell dumpsys package com.example.target | grep version
adb shell pm path com.example.target
adb pull /data/app/com.example.target-xxx/base.apk
Hook Function with Frida
Java.perform(() => {
const LoginActivity = Java.use('com.example.app.LoginActivity');
LoginActivity.validateCredentials.implementation = function(username, password) {
console.log(`[*] Username: ${username}`);
console.log(`[*] Password: ${password}`);
return this.validateCredentials(username, password);
};
});
frida -U -f com.example.app -l hook_login.js --no-pause
Bypass Root Detection
Java.perform(() => {
const RootBeer = Java.use('com.scottyab.rootbeer.RootBeer');
RootBeer.isRooted.implementation = () => false;
const File = Java.use('java.io.File');
File.exists.implementation = function() {
const path = this.getAbsolutePath();
if (path.includes('su') || path.includes('magisk')) {
return false;
}
return this.exists();
};
});
Extract Secrets from Memory
import frida
import sys
package = "com.example.app"
device = frida.get_usb_device()
pid = device.spawn([package])
session = device.attach(pid)
script = session.create_script("""
Java.perform(() => {
const String = Java.use('java.lang.String');
String.$init.overload('java.lang.String').implementation = function(str) {
if (str.includes('api_key') || str.includes('secret')) {
console.log('[*] Found secret: ' + str);
}
return this.$init(str);
};
});
""")
script.load()
device.resume(pid)
sys.stdin.read()
Troubleshooting
Magisk Not Showing Root
adb shell ls -la /data/adb/magisk/
adb shell su -c "magisk --version"
cd rootAVD
./rootAVD.sh system-images/android-36.1/google_apis/arm64-v8a/ramdisk.img restore
./rootAVD.sh system-images/android-36.1/google_apis/arm64-v8a/ramdisk.img
Frida Server Crashes
adb shell getprop ro.product.cpu.abi
adb shell "su -c 'killall frida-server'"
adb shell "su -c '/data/local/tmp/frida-server -D'"
LSPosed Not Working
adb shell su -c "magisk --sqlite 'SELECT * FROM settings WHERE key=\"zygisk\"'"
adb shell ls -la /data/adb/lspd/
adb shell su -c "rm -rf /data/adb/lspd/cache"
adb reboot
SSL Pinning Bypass Not Working
frida -U -f com.example.app --codeshare akabe1/frida-multiple-unpinning
adb shell "su -c 'ls -la /system/etc/security/cacerts/'"
Emulator Boot Loop After Root
cd rootAVD
./rootAVD.sh system-images/android-36.1/google_apis/arm64-v8a/ramdisk.img restore
emulator -avd Pixel_9_Pro_API_36 -no-snapshot-load
ADB Not Finding Device
adb kill-server
adb start-server
emulator -list-avds
adb devices
adb connect 127.0.0.1:5555
Environment Variables
Always use environment variables for sensitive configuration:
const API_KEY = Java.use('java.lang.System').getenv('TARGET_API_KEY');
export TARGET_API_KEY="your-key-here"
frida -U -f com.example.app -l frida_config.js
References