Docs / Mobile & Frida / Extract mTLS certs

Guide Mobile & Frida

Extract mTLS client certs

~10 min · Android/iOS · Frida · Hunter Pro

The short version. Some apps authenticate with a client certificate, not just a token — so even with pinning bypassed, your replayed requests get rejected at the TLS layer. Crusader catches this: a failed mTLS handshake raises the mTLS REQUIRED toast. Run Capture mTLS client cert (Android) from the Mobile tab against a rooted device (jailbroken iOS for the iOS variant), Import as identity, then replay the failing request from Repeater with that identity set. The honest caveat: hardware-backed keys are non-exportable — if the private key lives in AndroidKeyStore/StrongBox or the Secure Enclave, Crusader tells you so and you cannot proceed.

01When you hit it

You've routed the app through Crusader and bypassed cert pinning, but a specific endpoint still won't talk to you. The handshake dies before any HTTP is exchanged: the server is doing mutual TLS, demanding a client certificate the app holds and you don't. At the TLS layer this shows up as a bad_certificate or certificate_required alert.

Crusader recognizes that failure instead of leaving you to decode an opaque handshake error. The moment a client-cert handshake fails, it raises a toast:

mTLS REQUIRED — "{host} wants a client certificate." Helper text: "Run the mobile app on a rooted device, then use Mobile > Capture mTLS to pull its cert. Crusader auto-imports it as an identity you can use here." Buttons: Open Mobile tab / Dismiss.

That toast is your signal that this is an mTLS problem, not a pinning or scope problem. Click Open Mobile tab to start the capture, or read on for what has to be true first.

Authorized testing only. Pulling an app's client certificate and replaying its authenticated requests is intrusive — do it only against apps and backends you are explicitly authorized to test.

02The hardware-key limit (read this first)

The whole technique depends on one thing: the private key has to be extractable. Modern platforms increasingly make sure it isn't. Crusader is honest about this rather than faking a result.

When the key is generated in and bound to secure hardware, it physically never leaves that hardware — there is no API, rooted or not, that exports it. Crusader detects this and reports it instead of writing a bogus PEM:

  • Android — keys in AndroidKeyStore, StrongBox, or otherwise hardware-backed are non-exportable. Capture reports the key as hardware-backed and stops; there is nothing to pull.
  • iOS — keys in the Secure Enclave or guarded by an access-control policy are non-exportable for the same reason.

This is not a Crusader limitation you can configure around — you cannot proceed without the key. The technique works when the certificate and key are stored in software (a bundled PKCS#12 the app unlocks, a file in app storage, an in-memory KeyManager holding the raw key). The capture script preserves KeyManagers so a software-resident key can be read out of a live process.

Two more things stay out of reach regardless of root: Cloudflare device attestation and native-only Cronet mTLS paths. If the app uses those, capture won't help.

03What you'll need

  • Crusader with the Mobile / Frida tooling — part of Hunter Pro (feature MobileFrida). The capture, and especially Export PKCS#12, are gated to Pro.
  • Android: a rooted device (Magisk or a userdebug build). Root is required to attach Frida to the target app and read process memory. The Mobile tab is where the script-driven workflow lives.
  • iOS: a jailbroken device. There is no iOS device manager — the iOS capture is a Frida script you run manually against the app.
  • Frida on the host (frida-tools) plus the Android SDK platform-tools (adb) for the Android path. Crusader can one-click install these via your package manager; frida-server is downloaded on demand.
  • A captured request to the mTLS-protected endpoint already in History — the one that triggered the toast — so you have something to replay.

04Step 1 — Capture the cert from the device

Get the app running on your rooted device with Frida attached (the Easy Mode "Set up the sandbox" pipeline, or your own frida-server on the device, gets you there). Then open the Mobile tab and, from the script picker, run:

  • Capture mTLS client cert (Android) — for the Android path, against the rooted device.
  • The iOS variant of the same capture — run manually against a jailbroken device.

The capture is orchestrated by Crusader's mTLS extractor. It hooks the app's TLS stack while the app performs the protected request, finds the client certificate and its private key, and — if the key is software-resident — reads both out. If the key is hardware-backed, this is where Crusader stops and tells you (see section 02).

On a successful pull, Crusader raises a second toast:

mTLS CLIENT CERT CAPTURED — with an Import as identity action.

The aggressive pinning-bypass script preserves KeyManagers precisely so mTLS keeps working during instrumentation. If you bypass pinning first, the client-cert flow still completes — pinning and mTLS are separate layers. See Bypass certificate pinning.

05Step 2 — Import as identity

Click Import as identity on the capture toast. Crusader creates an Identity that carries the actual auth material:

FieldValue
Name<CN> - mTLS — taken from the certificate's common name.
KindmTLS client cert.
MaterialThe PEM cert + key read from the app.
ExpiresAtThe certificate's NotAfter — the identity is only good until the cert expires.
HostPatternInferred from the cert CN if it looks like a hostname; otherwise * (all hosts).

The identity now shows up on the Identities screen with an mTLS - {expiry} chip, ready to attach to any request. Because the host pattern can fall back to *, glance at it — if the CN wasn't a hostname, the identity is scoped to every host until you narrow it.

06Step 3 — Replay the failing request from Repeater

Now reuse the cert. Find the request that triggered the mTLS REQUIRED toast in History and open it in Repeater. Set that tab's per-tab identity to the captured mTLS identity, then Send.

Crusader presents the client certificate during the TLS handshake on your behalf, so the server completes mTLS and answers the request — the same wall the app got past, now under your control. From here you can edit, refuzz, and iterate on the authenticated endpoint like any other request.

The identity is scope-aware. With Identity Shadow Replay (Hunter Pro) you can also compare how the mTLS-authenticated actor and a different actor see the same endpoints — useful for authorization-drift testing behind a client-cert wall. See Identities & shadow replay.

07Step 4 — Re-extract and export

The identity card carries two mTLS-specific buttons:

  • Re-extract cert — pull a fresh cert + key from the device. Use this when the captured cert has expired (the mTLS - {expiry} chip tells you), or when the app rotates its certificate.
  • Export PKCS#12 — bundle the cert + key as a .p12 to hand to another tool. This action is gated by MobileFrida (Hunter Pro).

Export opens a Export mTLS bundle (PKCS#12) save dialog defaulting to crusader-mtls-<id>.p12. Crusader generates a random 16-hex passphrase and copies it to your clipboard — paste it where you import the bundle.

Treat the .p12 file as a secret. It is live authentication material: anyone holding the bundle and its passphrase can impersonate the app's identity to the backend until the certificate expires. Store it like a credential, scope it to the engagement, and delete it when you're done.

08Troubleshooting

Capture reports the key as hardware-backed

This is the expected, honest result for AndroidKeyStore / StrongBox / hardware-backed (Android) and Secure Enclave / access-control (iOS) keys — the private key never leaves secure hardware, so there is nothing to export. There is no workaround; this technique only applies to software-resident keys. See section 02.

No "mTLS REQUIRED" toast, just a generic handshake error

Confirm the failure is actually mTLS and not pinning. The mTLS toast fires on a bad_certificate / certificate_required alert specifically. If the app is still pinning, bypass that first — run Kill SSL pinning from the Mobile script picker (see Bypass certificate pinning) so the request reaches the handshake where mTLS is negotiated.

Capture or Export PKCS#12 is locked

The Mobile / Frida tooling, and Export PKCS#12 specifically, require Hunter Pro (MobileFrida). Check License & billing; the 14-day Pro trial unlocks it with just an email.

Replay still fails after setting the identity

Make sure the identity's HostPattern actually covers the target host — if the cert CN wasn't a hostname it defaulted to *, but if you narrowed it, confirm it matches. Also check the mTLS - {expiry} chip: an expired cert won't authenticate. If the cert rotated, hit Re-extract cert.

Frida can't attach / no device

Android capture needs a rooted device with frida-server running and reachable over adb; iOS needs a jailbroken device with the Frida runtime. Without root/jailbreak there is no way to read the app's process memory, and capture can't run.

Want a guide that isn't here yet? Email hello@crusaderproxy.com.