If you’ve ever tried to pentest an Android app, you know the frustration: you set up a Wi-Fi proxy, install a user certificate, and… nothing. The app either ignores your proxy entirely or refuses to connect because of certificate pinning and Android’s strict “User vs. System” CA store policies.
Most guides online are outdated or only cover half the story. After much trial and error, I’ve perfected a “Forensic Setup” that forces the Android Emulator to trust OWASP ZAP as a System Root CA and routes all traffic—even from system-level apps—through your proxy.
Here is how to build your own forensic mobile lab.
Prerequisites Link to heading
Before we dive in, ensure you have the following ready:
- OWASP ZAP (Installed and running)
- Android SDK Platform-Tools (
adb) (Configured in your system PATH) - A specific Android Emulator (AVD): You must use a “Google APIs” image. Avoid “Google Play” images; they are production-signed and make writing to the system partition nearly impossible.
- API Version Note: Newer versions (API 34 and above) sandbox network traffic more aggresively, which can interfere with this method. I recommend using API version 33 for the best results.
Step 1: Crafting the System-Compliant Certificate Link to heading
Android doesn’t just want a .cer file. It requires the certificate to be in PEM format and named after its subject hash.
- Export from ZAP: Go to
Tools > Options > Network > Server Certificatesand save your root CA aszap_root_ca.cer. - The Terminal Magic: Run these commands to identify the hash and rename the file correctly:
# Get the subject hash
HASH=$(openssl x509 -inform PEM -subject_hash_old -in zap_root_ca.cer | head -1)
# Copy/Rename to the format Android expects (<hash>.0)
cp zap_root_ca.cer $HASH.0
Step 2: Breaking into the System Store Link to heading
To intercept HTTPS from modern apps, our certificate must live in /system/etc/security/cacerts/. This requires a writable system partition.
- Launch with Writable Access: Open your terminal and start the emulator manually:
emulator -avd <YOUR_AVD_NAME> -writable-system -no-snapshot-load
- Disable Verity: This is the crucial step that “unlocks” the system partition by disabling integrity checks.
adb root
adb disable-verity
adb reboot
- Injecting the CA: Once the device reboots, remount the file system and push your certificate:
adb root
adb remount
adb push <YOUR_HASH>.0 /system/etc/security/cacerts/
adb shell chmod 644 /system/etc/security/cacerts/<YOUR_HASH>.0
adb reboot
Step 3: Routing the “Unroutable” Traffic Link to heading
Some apps ignore standard Wi-Fi proxy settings. We bypass this by setting a global HTTP proxy at the Android settings database level.
adb shell settings put global http_proxy 10.0.2.2:8080
Note: 10.0.2.2 is the special Android alias for your host machine’s localhost.
Step 4: Freeze the Configuration (Critical) Link to heading
Now that the certificate is injected and the proxy is set, we need to ensure this state is “frozen” so thse changes remain permanent. To do this, we need to save a snapshot by closing the emulator using the GUI (the X button). This triggers a “Quickboot” save, capturing the system store and proxy settings into a permanent snapshot.
From now on you MUST launch the emulator from the terminal (as described in the next step), and you should NEVER close it via the GUI again. Instead, kill the process via the terminal (using the it’s PID).
Killing the process prevents the emulator from saving session changes (like app data, temp files, or accidental setting changes), ensuring you always boot into the clean, forensic-ready state you just created.
Step 5: Automate with a Launch Script Link to heading
To simplify the workflow and enforce the “no-save” rule, use this Bash function in your ~/.bashrc:
launchemulator() {
if [ -z "$1" ]; then
echo "Usage: launchemulator <AVD_NAME>"
emulator -list-avds
return 1
fi
echo "Starting forensic emulator: $1"
# -writable-system: REQUIRED to keep the custom cert active
# -http-proxy: Forces the network gateway through ZAP
# -dns-server: Prevents DNS loop issues
emulator -avd "$1" \
-writable-system \
-http-proxy http://10.0.2.2:8080 \
-dns-server 8.8.8.8 \
-netdelay none -netspeed full >/dev/null 2>&1 &
export EMULATOR_PID=$!
adb wait-for-device root
echo "Lab is ready. PID: $EMULATOR_PID"
echo "To exit WITHOUT saving changes: kill -9 $EMULATOR_PID"
}
Step 6: The “Trust But Verify” Checklist Link to heading
Before starting your analysis, perform these checks:
System Tab: Go to
Settings > Security > Trusted credentials. Scroll through the System tab. You must see “OWASP Root CA” here.Global Proxy: Run
adb shell settings get global http_proxy. It must return10.0.2.2:8080.ZAP Connectivity: Open Chrome in the emulator and browse to any HTTPS site. The requests should immediately appear in ZAP’s History tab.
Conclusion Link to heading
Setting up a mobile lab is often the most tedious part of a pentest. By moving the ZAP certificate into the System store and freezing the state with a Quickboot snapshot, you create a robust, persistent environment for modern Android security research.
Happy hunting!