<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sudhanshu Sharma</title>
    <description>The latest articles on DEV Community by Sudhanshu Sharma (@sudhanshu_sharma_1ca7ff62).</description>
    <link>https://dev.to/sudhanshu_sharma_1ca7ff62</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3975065%2Fc5c33c88-3d11-4c1f-9b53-116d1c7713da.png</url>
      <title>DEV Community: Sudhanshu Sharma</title>
      <link>https://dev.to/sudhanshu_sharma_1ca7ff62</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sudhanshu_sharma_1ca7ff62"/>
    <language>en</language>
    <item>
      <title>How I Bypassed SSL Pinning on the Cars24 Android App (Without Rooting My Phone)</title>
      <dc:creator>Sudhanshu Sharma</dc:creator>
      <pubDate>Tue, 09 Jun 2026 02:33:44 +0000</pubDate>
      <link>https://dev.to/sudhanshu_sharma_1ca7ff62/how-i-bypassed-ssl-pinning-on-the-cars24-android-app-without-rooting-my-phone-3hno</link>
      <guid>https://dev.to/sudhanshu_sharma_1ca7ff62/how-i-bypassed-ssl-pinning-on-the-cars24-android-app-without-rooting-my-phone-3hno</guid>
      <description>&lt;p&gt;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: &lt;em&gt;Download the app to access this.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I needed to get inside the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SSL Pinning?
&lt;/h2&gt;

&lt;p&gt;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 &lt;em&gt;pinning&lt;/em&gt; 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.&lt;/p&gt;

&lt;p&gt;Cars24 uses SSL pinning. My job was to get around it without rooting my phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt 1: Just Try Charles Proxy
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt 2: Android Studio Virtual Device
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt 3: Pull the APK from My Phone
&lt;/h2&gt;

&lt;p&gt;Changed approach. Connected my phone via USB, used ADB to pull the actual Cars24 APK installed on my device:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell pm path com.cars24.customer
adb pull /data/app/com.cars24.customer-.../base.apk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Except it turned out Cars24 uses a &lt;em&gt;split APK&lt;/em&gt; — not one file, but several: &lt;code&gt;base.apk&lt;/code&gt;, &lt;code&gt;split_config.arm64_v8a.apk&lt;/code&gt;, &lt;code&gt;split_config.en.apk&lt;/code&gt; etc. Had to pull all of them. New territory.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Network Security Config Approach
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;res/xml/network_security_config.xml&lt;/code&gt;. If you add a user-trusted CA to this config, the app will accept your proxy's certificate.&lt;/p&gt;

&lt;p&gt;The process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Decode the APK with apktool: &lt;code&gt;apktool d base.apk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Modify &lt;code&gt;network_security_config.xml&lt;/code&gt; to trust user CAs&lt;/li&gt;
&lt;li&gt;Repackage: &lt;code&gt;apktool b base.apk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Zipalign: &lt;code&gt;zipalign -v 4 base.apk base-aligned.apk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Sign with a debug keystore: &lt;code&gt;apksigner sign --ks debug.keystore base-aligned.apk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Install all split APKs together: &lt;code&gt;adb install-multiple base.apk split_config.*.apk&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Did this. App installed. Launched. Crashed immediately — a graphic rendering error, something about NineAlpha patch files.&lt;/p&gt;

&lt;h2&gt;
  
  
  The NineAlpha Problem (and a Costly Mistake)
&lt;/h2&gt;

&lt;p&gt;Someone online suggested replacing the patched APK's &lt;code&gt;res&lt;/code&gt; folder with the original's &lt;code&gt;res&lt;/code&gt; folder to fix the rendering crash. I did this. App launched successfully.&lt;/p&gt;

&lt;p&gt;I thought I was done. Opened Charles Proxy. Saw Cars24 traffic flowing through. &lt;/p&gt;

&lt;p&gt;Except I hadn't actually bypassed anything. By replacing the entire &lt;code&gt;res&lt;/code&gt; folder with the original, I'd also restored the original &lt;code&gt;network_security_config.xml&lt;/code&gt; — 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.&lt;/p&gt;

&lt;p&gt;This was the lowest point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt 4: Frida
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Tried it. Frida requires root access to inject into system processes on a non-rooted device. Dead end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to Network Security Config (Done Right)
&lt;/h2&gt;

&lt;p&gt;Came back to the patched APK approach with fresh eyes. This time: patch the network security config, then replace only the &lt;em&gt;graphic resources&lt;/em&gt; that were causing the crash — not the entire &lt;code&gt;res&lt;/code&gt; folder. Keep the modified &lt;code&gt;network_security_config.xml&lt;/code&gt; intact.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- res/xml/network_security_config.xml --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;network-security-config&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;base-config&lt;/span&gt; &lt;span class="na"&gt;cleartextTrafficPermitted=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;trust-anchors&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;certificates&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"system"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;certificates&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- this is the key line --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/trust-anchors&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/base-config&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/network-security-config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zipalign, sign, install. App launched. No crash.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Proxy Chain Problem
&lt;/h2&gt;

&lt;p&gt;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 &lt;em&gt;through&lt;/em&gt; the laptop's proxy — but the phone was the one providing the laptop's internet. Circular dependency.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Set this up. Opened the Cars24 app. Navigated to an inspection report.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;20 hours. Done.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the API Returns
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"carCondition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"checkpoints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"repainted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"year"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"make"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mahindra"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"listingPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1260300&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No auth beyond standard headers mimicking the app. Works without any login. I wrote a Python scraper around it and moved on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSL pinning&lt;/strong&gt; and how apps implement it via certificate pinning vs network security config&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split APKs&lt;/strong&gt; — modern Android apps aren't single files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;apktool&lt;/strong&gt; for decoding and repackaging APKs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;zipalign and apksigner&lt;/strong&gt; — Android requires APKs to be aligned and signed before installation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frida&lt;/strong&gt; — and why it requires root for system-level hooking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proxy chaining&lt;/strong&gt; — routing traffic through multiple proxies when your network topology is awkward&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CA certificates&lt;/strong&gt; — what they are, how Android's trust store works, user vs system CAs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole thing took 20 hours across two days. I came in not knowing what SSL pinning was. I left having bypassed it.&lt;/p&gt;

</description>
      <category>software</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
