I was building Unlist — a tool that surfaces hidden faults in used car listings on Spinny and Cars24. Spinny was easy: their web app makes API calls I could intercept straight from Chrome DevTools. Cars24 was a different story. Click "View Inspection Report" on their website and you get a popup: Download the app to access this.
So I needed to get inside the app.
What is SSL Pinning?
Before getting into the journey, a quick explainer. When an app makes a network request, it goes over HTTPS — encrypted. Tools like Charles Proxy act as a man-in-the-middle: your traffic goes through the proxy, gets decrypted, logged, then re-encrypted and sent on. Apps can block this by pinning their SSL certificate — meaning they only trust one specific certificate (their own), not any CA cert you install on your device. If the cert doesn't match, the app refuses to connect.
Cars24 uses SSL pinning. My job was to get around it without rooting my phone.
Attempt 1: Just Try Charles Proxy
First thing I did was set up Charles Proxy on my laptop, configured my phone to route traffic through it, and installed the Charles CA certificate on my phone. Opened Cars24. Nothing. SSL handshake failures everywhere. SSL pinning confirmed.
Attempt 2: Android Studio Virtual Device
My thinking: use an Android emulator where I have full control. Set up an Android Virtual Device in Android Studio, tried to install the Cars24 APK I'd downloaded from a browser inside the emulator.
Spent 2-3 hours here. The APKs weren't installing. Eventually figured out the emulator was running an x86 image but Cars24's APK was ARM-only. Android Studio doesn't offer ARM emulator images easily. Dead end.
Attempt 3: Pull the APK from My Phone
Changed approach. Connected my phone via USB, used ADB to pull the actual Cars24 APK installed on my device:
adb shell pm path com.cars24.customer
adb pull /data/app/com.cars24.customer-.../base.apk
Except it turned out Cars24 uses a split APK — not one file, but several: base.apk, split_config.arm64_v8a.apk, split_config.en.apk etc. Had to pull all of them. New territory.
The Network Security Config Approach
The standard non-root bypass for SSL pinning is patching the app's network security config. Android apps can declare which certificates they trust in res/xml/network_security_config.xml. If you add a user-trusted CA to this config, the app will accept your proxy's certificate.
The process:
- Decode the APK with apktool:
apktool d base.apk - Modify
network_security_config.xmlto trust user CAs - Repackage:
apktool b base.apk - Zipalign:
zipalign -v 4 base.apk base-aligned.apk - Sign with a debug keystore:
apksigner sign --ks debug.keystore base-aligned.apk - Install all split APKs together:
adb install-multiple base.apk split_config.*.apk
Did this. App installed. Launched. Crashed immediately — a graphic rendering error, something about NineAlpha patch files.
The NineAlpha Problem (and a Costly Mistake)
Someone online suggested replacing the patched APK's res folder with the original's res folder to fix the rendering crash. I did this. App launched successfully.
I thought I was done. Opened Charles Proxy. Saw Cars24 traffic flowing through.
Except I hadn't actually bypassed anything. By replacing the entire res folder with the original, I'd also restored the original network_security_config.xml — undoing the only change that mattered. I was just running the original app through a proxy it was successfully blocking. I didn't realise this for hours.
This was the lowest point.
Attempt 4: Frida
Someone suggested using Frida — a dynamic instrumentation toolkit that can hook into running processes and override functions at runtime. The pitch: hook the SSL verification function and make it always return true, bypassing pinning without touching the APK.
Tried it. Frida requires root access to inject into system processes on a non-rooted device. Dead end.
Back to Network Security Config (Done Right)
Came back to the patched APK approach with fresh eyes. This time: patch the network security config, then replace only the graphic resources that were causing the crash — not the entire res folder. Keep the modified network_security_config.xml intact.
<!-- res/xml/network_security_config.xml -->
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" /> <!-- this is the key line -->
</trust-anchors>
</base-config>
</network-security-config>
Zipalign, sign, install. App launched. No crash.
The Proxy Chain Problem
One more issue: my laptop was connected to the internet via my phone's mobile hotspot. Charles Proxy was running on the laptop. I needed the phone's traffic to route through the laptop's proxy — but the phone was the one providing the laptop's internet. Circular dependency.
Fix: SuperProxy. Installed it on the phone, configured it to forward traffic to Charles on the laptop's IP, which then forwarded to the actual internet. Proxy chaining.
Set this up. Opened the Cars24 app. Navigated to an inspection report.
Charles lit up with API calls. One of them: a POST returning a full JSON inspection report — every fault, every part, tyre life percentages, the works.
20 hours. Done.
What the API Returns
{
"detail": {
"carCondition": {
"categories": [...],
"checkpoints": [...],
"repainted": false
},
"year": 2023,
"make": "Mahindra",
"listingPrice": 1260300
}
}
No auth beyond standard headers mimicking the app. Works without any login. I wrote a Python scraper around it and moved on.
What I Learned
- SSL pinning and how apps implement it via certificate pinning vs network security config
- Split APKs — modern Android apps aren't single files
- apktool for decoding and repackaging APKs
- zipalign and apksigner — Android requires APKs to be aligned and signed before installation
- Frida — and why it requires root for system-level hooking
- Proxy chaining — routing traffic through multiple proxies when your network topology is awkward
- CA certificates — what they are, how Android's trust store works, user vs system CAs
The whole thing took 20 hours across two days. I came in not knowing what SSL pinning was. I left having bypassed it.
Top comments (0)