Docs / Mobile & Frida / Kill cert pinning
Kill cert pinning & intercept mobile
The short version. A hardened Android app pins its server's certificate, so even a trusted proxy CA gets rejected and your History stays empty. Crusader's Easy Mode stands up an emulator sandbox, routes it through your proxy, installs the Crusader CA into the device's system trust store, and attaches Frida — then you run the Kill SSL pinning (Android and iOS, aggressive) script to hook out the app's pinning checks at runtime. Decrypted HTTPS lands in your proxy. Mobile is Hunter Pro, the automated flow is Android-only, and the aggressive script is detectable — so run it after passive recon confirms the app actually pins.
01Why pinning blocks your proxy
Pointing a phone or emulator at Crusader's proxy and trusting the Crusader CA is enough for most apps. A hardened app does more: it pins the expected server certificate (or its public key) inside the app, then refuses any TLS handshake that doesn't present exactly that leaf — even one your device trusts. The connection dies inside the app before a single request reaches your proxy, and History stays empty.
To intercept it you attack on two fronts at once. First, make the device trust Crusader: route its traffic through the proxy and install the Crusader root into the system store so the OS itself accepts the per-host leaf certs Crusader mints. Second, defeat the in-app check: attach Frida and hook the pinning logic at runtime so the app accepts your cert as if it matched. Crusader's Easy Mode does the first part as a pipeline; one Frida script does the second.
Authorized testing only. Decrypting and instrumenting a mobile app's traffic is intrusive — run this only against apps and back ends you own or are explicitly authorized to test.
02The two surfaces
Crusader gives you two ways into mobile, depending on whether you want a clean sandbox or you already have a device under control:
- Easy Mode — a guided emulator wizard behind the Easy Mode button. It walks you from "no environment" to a booted, proxied, Frida-armed emulator with the test app installed, narrating what the app is doing as traffic flows. This is the path this guide follows.
- Mobile tab — the Pro surface: a Frida script picker plus rooted-server and gadget workflows. You point it at a device or emulator you've already prepared and run scripts directly. Use it when you've outgrown the wizard or you're working a real rooted device.
The automated end-to-end flow — Easy Mode, the sandbox pipeline, ADB, frida-server, system-CA install, APK install — is Android only. iOS is supported as two Frida scripts you run manually against a jailbroken device; there is no iOS device manager and no guided iOS wizard.
Mobile and Frida are Hunter Pro (the MobileFrida feature), enforced at sandbox launch/configure, APK install, and mTLS export. The traffic-narration in Easy Mode Step 3 is Free; standing up the sandbox and running Frida are Pro.
03What you'll need
Pick the emulator path (the Easy Mode default) or a real device:
- Emulator (recommended) — Android Studio and an AVD running API level 28 or higher. Crusader launches the emulator with
-writable-system, which is what lets it write the Crusader CA into the system trust store. - Real device — must be rooted (Magisk or a userdebug build) for frida-server and the system-CA install. Without root you're limited to objection gadget repackaging, which is less reliable on hardened or anti-tamper apps.
- Transport — USB / ADB.
- Host tools — Android SDK platform-tools (
adb) and thefridaCLI (frida-tools). The gadget path additionally needsobjection,apktool,java, andapksigner.
You don't have to install those by hand. Crusader can one-click install the host tools through your platform's package manager (winget / choco / scoop / brew / apt / pip / pipx) — it doesn't bundle them. frida-server and APKEditor.jar are downloaded on demand from their official GitHub releases.
| Tool | Used for | Source |
|---|---|---|
adb | Device transport, install, proxy + CA setup | Crusader one-click (platform-tools) |
frida | Running the pinning hook script | Crusader one-click (frida-tools) |
frida-server | On-device agent the script attaches to | Downloaded on demand (GitHub) |
objection, apktool, java, apksigner | Non-root gadget repackaging | Crusader one-click |
04Step 1 — Set up the sandbox
Open Easy Mode. The hero reads "Let's see what your app is doing." Step 1 is "Phone sandbox", with a status badge that moves through NEEDS SETUP → ALMOST READY → READY → RUNNING as you go.
If you don't have an environment yet, the wizard hands you the buttons to fix that: Get Android Studio, I already installed it, Open AVD Manager, and Re-check. Once an API ≥ 28 AVD exists, use Launch sandbox to boot it, then run the pipeline with Set up the sandbox.
Set up the sandbox is the heart of it. Behind one button it runs the full pipeline:
- Wait for the emulator to finish booting.
- Set the emulator's global HTTP proxy to
10.0.2.2:<port>—10.0.2.2is the emulator's alias for your host loopback, and<port>is your Crusader proxy port. - Install the Crusader CA into the device's system trust store.
- Install and start
frida-serveron the device. - Run a health check across all of the above.
While it works, the status line reads "Setting up frida-server, trusting CA, routing through proxy…". When it settles on READY / RUNNING, the device is proxied through Crusader, trusts your CA at the system level, and has Frida running — everything the bypass needs.
The system-CA install needs root. On the emulator that's the -writable-system boot; on a real device it's Magisk/userdebug. Crusader writes the pre-Android-14 store at /system/etc/security/cacerts/<hash>.0; if a direct write isn't possible it falls back to a Magisk module, which requires a reboot to take effect.
05Step 2 — Load the test app
Step 2 of Easy Mode is "Pick a test app". Drop your own build into the zone marked "Or pick your own APK/XAPK/APKS", or start with one of the linked sample targets — OWASP Juice Shop, Damn Vulnerable Bank, InsecureBankv2, DIVA (linked for download, not bundled).
Crusader accepts .apk, .xapk, and .apks. The split-bundle formats (.xapk / .apks) are unzipped and cached, then installed with adb install or install-multiple as appropriate.
Before it installs, an ABI preflight checks the app's native libraries against the device. An app built only for armeabi-v7a won't run on an x86_64 / arm64 emulator, so Crusader stops with DEVICE MISMATCH instead of a cryptic adb failure. It also classifies the common install errors directly — NO_MATCHING_ABIS, INSTALL_FAILED_MISSING_SPLIT, VERSION_DOWNGRADE, TEST_ONLY, and more.
If you hit DEVICE MISMATCH, create an AVD whose ABI matches the app (commonly an arm64-v8a image for arm-only builds) and re-run the install. The preflight is telling you the binary can't execute on this device — no bypass will fix that.
06Step 3 — Run the pinning bypass
With the sandbox ready and the app installed, defeat the in-app pinning check. There is no single literal "one click" button for this — the one-click experience is Set up the sandbox (proxy + CA + frida) followed by running the pinning script from the picker.
Open the Mobile script picker and run "Kill SSL pinning (Android and iOS, aggressive)" (id android-pinning-killer). It's a Frida hook script — run via frida … -l <script> against the running app, not a gadget. It neutralizes pinning across the stack:
- Android (Java) — OkHttp, Conscrypt, the platform
TrustManager, WebView, andNetworkSecurityConfig. - Native — BoringSSL / OpenSSL, and Cronet.
- iOS —
SecTrust, AFNetworking, Alamofire, and TrustKit.
Crucially, it preserves KeyManagers, so client-certificate authentication (mTLS) still works while pinning is disabled — you don't break a mutual-TLS app by bypassing its server pinning.
Once the script reports its hooks are in place, drive the app — log in, pull a screen, trigger a network call. The previously pinned HTTPS now negotiates against Crusader's leaf cert, and the requests land in your History. From there it's ordinary Crusader: scope it, send interesting requests to Repeater, run the scanner over the captured traffic.
All traffic is captured to History regardless of interception mode — intercept only decides whether requests pause. So you don't need Hold on to see the app's calls; turn it on only when you want to edit a request in flight.
07Detectability & limits
The aggressive script is powerful but loud. Know its edges before you lean on it:
- It's detectable (High). The script's detectability rating is High, and apps with anti-tamper or runtime-integrity checks will notice the hooks and may crash, log you out, or silently degrade. Run it after passive recon has confirmed the app actually pins — don't reach for the most invasive tool first.
- System-CA install needs root, and Crusader writes the pre-Android-14 trust store location. The Magisk-module fallback needs a reboot. The Android 14 APEX Conscrypt trust store isn't specifically handled — flag this on new real devices on recent Android.
- iOS is manual. On iOS there's no device manager and no guided pipeline: you run the two Frida scripts yourself on a jailbroken device.
- Non-root Android is weaker. Without root you fall back to objection gadget repackaging, which hardened and anti-tamper apps catch more readily than a clean frida-server attach.
- Some paths are out of reach. Crusader does not handle Cloudflare device attestation or native-only Cronet mTLS paths — treat those as unsupported.
Sequence matters: passive recon to confirm pinning, then Set up the sandbox, then the bypass script. Leading with the aggressive hook on an anti-tamper app usually just tips your hand.
08Troubleshooting
No traffic in History after the bypass
Confirm the sandbox pipeline actually finished — the badge should be RUNNING and the status should have cleared "Setting up frida-server, trusting CA, routing through proxy…". If the proxy route or system CA didn't stick, even a perfect Frida hook produces nothing. Re-run Set up the sandbox and watch the health check.
App still rejects the connection
The pinning hook may not be covering this app's mechanism, or an anti-tamper check disabled it. Re-confirm pinning with passive recon, make sure the system CA is trusted (not just a user CA), and remember the script is detectable (High) — an integrity-checked app can defeat it.
System CA "installed" but not trusted
The CA went into the pre-Android-14 store at /system/etc/security/cacerts/. If Crusader used the Magisk-module fallback, reboot the device for it to take effect. On Android 14+ real devices the APEX Conscrypt store isn't specifically handled.
Install fails with DEVICE MISMATCH
The ABI preflight blocked an app whose native code doesn't match the device — e.g. an armeabi-v7a-only split against an x86_64/arm64 emulator. Use an AVD with a matching ABI image. Other install errors are classified too (NO_MATCHING_ABIS, INSTALL_FAILED_MISSING_SPLIT, VERSION_DOWNGRADE, TEST_ONLY).
The app needs a client certificate
If the app does mutual TLS, the pinning script preserves KeyManagers so mTLS keeps working — but to replay those requests yourself you need the client cert. That's a separate flow; see Extract mTLS client certs.
Want a guide that isn't here yet? Email hello@crusaderproxy.com.