โ† Back to posts

Android SSL Pinning Bypass โ€” Complete Troubleshooting Guide

4mr
Amr En-Niari
@4mrr ยท 12 min read
Table of Contents

During mobile penetration testing engagements, one of the most common challenges is bypassing SSL pinning to intercept HTTPS traffic. This guide documents the common issues, errors, and solutions I've encountered across multiple Android mobile assessments.

This guide is intended for authorized penetration testing only. Always ensure you have proper written authorization before testing any application.

1. Android Emulator Setup Issues

1.1 ADB Root Access Denied

Error:

adbd cannot run as root in production builds

This happens when using a Google Play system image instead of a Google APIs image. Google Play images are production builds and do not allow root access.

Solution:

  1. Open Android Studio โ†’ SDK Manager โ†’ SDK Platforms โ†’ Show Package Details
  2. Download an image labeled "Google APIs" (NOT "Google Play System Image")
  3. Create a new AVD using this image

Command line alternative:

sdkmanager "system-images;android-30;google_apis;x86_64"
avdmanager create avd -n pentest -k "system-images;android-30;google_apis;x86_64"

2. Frida Server Setup

2.1 Uploading Frida Server to Emulator

First, check the emulator architecture:

adb shell getprop ro.product.cpu.abi

Download the matching frida-server from GitHub releases. Make sure the server version matches your local Frida version:

# Check your frida version
frida --version

# Download matching server (example for x86_64)
wget https://github.com/frida/frida/releases/download/16.7.19/frida-server-16.7.19-android-x86_64.xz
xz -d frida-server-16.7.19-android-x86_64.xz

Push to the device and set permissions:

adb root
adb push frida-server-16.7.19-android-x86_64 /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &

Verify it's running:

frida-ps -U

2.2 SELinux Policy Error

Error:

Unable to load SELinux policy from the kernel: Failed to open file
"/sys/fs/selinux/policy": Permission denied

SELinux is blocking Frida server execution. Disable enforcement before running frida-server:

adb root
adb shell setenforce 0
adb shell /data/local/tmp/frida-server &
Sometimes this warning is non-fatal and frida-server runs anyway. Test with: frida-ps -U

3. APK Patching Issues

3.1 Extracting APK from Emulator

# Find APK path
adb shell pm path com.target.app

# Pull the APK
adb pull /data/app/com.target.app-xxxx/base.apk ./target.apk

For split APKs (multiple paths):

adb shell pm path com.target.app | while read -r line; do
  adb pull $(echo $line | cut -d: -f2)
done

3.2 Invalid Filename Characters ($)

Error:

W: res/drawable/$avd_hide_password__0.xml: Invalid file name:
must contain only [a-z0-9_.]

Apktool cannot handle filenames containing the $ character.

Solution:

# Decompile
apktool d merged.apk -o source

# Rename files with $ to _
cd source
find . -name '*\$*' -exec bash -c 'mv "$0" "${0//\$/_}"' {} \;

# Fix references in XML files
grep -rl '\$' res/ | xargs sed -i 's/\$/_/g'

3.3 Corrupted PNG Files

Error:

W: libpng error: IDAT: invalid bit length repeat
W: ERROR: Failure processing PNG image /path/to/image.png
W: libpng error: bad adaptive filter value
W: libpng error: IDAT: CRC error

PNG files became corrupted during decompilation or were optimized in a way apktool cannot process. Skip apktool entirely and use apk-mitm which modifies the APK directly:

npm install -g apk-mitm
apk-mitm merged.apk

3.4 String Formatting Errors

Error:

W: /path/strings.xml:371: error: Multiple substitutions specified
in non-positional format; did you mean to add the formatted="false" attribute?

Add formatted="false" to the problematic string, or use apk-mitm to bypass this issue entirely.

3.5 Merging Split APKs

# Using APKEditor
java -jar APKEditor.jar m -i ./split_apks/ -o merged.apk

4. SSL Pinning Bypass Methods

Method 1: Frida + Objection (Fastest)

The quickest approach when Frida is already running on the device:

objection -g com.target.app explore

# Then run inside objection:
android sslpinning disable

Method 2: Universal Frida Script

Use the community-maintained unpinning script from Frida Codeshare:

frida -U --codeshare akabe1/frida-multiple-unpinning -f com.target.app

Method 3: Custom Bypass Script

Save this as bypass.js for apps with custom pinning implementations:

Java.perform(function() {
    // Custom TrustManager that accepts all certificates
    var TrustManager = Java.registerClass({
        name: 'dev.asd.test.TrustManager',
        implements: [Java.use('javax.net.ssl.X509TrustManager')],
        methods: {
            checkClientTrusted: function(chain, authType) {},
            checkServerTrusted: function(chain, authType) {},
            getAcceptedIssuers: function() { return []; }
        }
    });

    var TrustManagers = [TrustManager.$new()];
    var SSLContext = Java.use('javax.net.ssl.SSLContext');
    var SSLContext_init = SSLContext.init.overload(
        '[Ljavax.net.ssl.KeyManager;',
        '[Ljavax.net.ssl.TrustManager;',
        'java.security.SecureRandom'
    );

    SSLContext_init.implementation = function(km, tm, sr) {
        SSLContext_init.call(this, km, TrustManagers, sr);
    };

    // OkHttp CertificatePinner bypass
    try {
        var CertificatePinner = Java.use('okhttp3.CertificatePinner');
        CertificatePinner.check.overload(
            'java.lang.String', 'java.util.List'
        ).implementation = function() {};
        CertificatePinner.check.overload(
            'java.lang.String', 'java.security.cert.Certificate'
        ).implementation = function() {};
    } catch(e) {
        console.log("[*] OkHttp CertificatePinner not found");
    }
});

Run with:

frida -U -f com.target.app -l bypass.js

Method 4: APK Patching with apk-mitm

When Frida is not an option (e.g. Frida detection), patch the APK directly:

npm install -g apk-mitm
apk-mitm merged.apk

# Uninstall original and install patched
adb uninstall com.target.app
adb install merged-patched.apk

Method 5: Manual network_security_config.xml Patch

After decompiling with apktool d merged.apk -o source/, edit res/xml/network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system"/>
            <certificates src="user"/>
        </trust-anchors>
    </base-config>
</network-security-config>

Then rebuild and sign:

# Rebuild
apktool b source -o patched.apk

# Create keystore
keytool -genkey -v -keystore test.keystore -alias test \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -storepass password -keypass password -dname "CN=test"

# Sign
apksigner sign --ks test.keystore --ks-pass pass:password patched.apk

# Install
adb uninstall com.target.app
adb install patched.apk

5. Quick Reference: Error โ†’ Solution

Error Solution
adbd cannot run as root Use Google APIs image, not Google Play
SELinux policy permission denied adb shell setenforce 0
Invalid filename ($) Rename $ to _ in filenames
libpng errors / corrupted PNG Use apk-mitm instead of apktool
Multiple substitutions error Add formatted="false" or use apk-mitm
APK on emulator, not local adb shell pm path <pkg> then adb pull
aapt: Could not extract resource Install aapt: apt install aapt

6. Required Tools

Tool Installation
Frida pip install frida-tools
Objection pip install objection
apk-mitm npm install -g apk-mitm
apktool apt install apktool
apksigner Part of Android SDK build-tools
Android SDK With Google APIs images
Burp Suite For traffic interception

7. Workflow Summary

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ SSL Pinning Bypass Flow โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ 1. Setup Emulator (Google APIs image) โ”‚ โ†“ โ”‚ 2. Install Frida Server โ”‚ โ†“ โ”‚ 3. Try: objection โ†’ android sslpinning disable โ”‚ โ†“ โ”‚ 4. If fails โ†’ Try Frida scripts (codeshare/custom) โ”‚ โ†“ โ”‚ 5. If fails โ†’ Patch APK with apk-mitm โ”‚ โ†“ โ”‚ 6. Configure Burp proxy and intercept traffic โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The key takeaway is to start simple โ€” Objection and Frida scripts handle most apps. Only fall back to APK patching when runtime approaches fail, typically due to Frida detection or root detection mechanisms.

Always document your bypass methodology. It helps the client understand the risk and shows that their pinning implementation needs improvement.
โ† All posts Next: AD Trust Exploitation โ†’