← Back to list

Bypassing librust.so SSL Pinning on Android

I was working on analyzing a traffic of an Android app. Most of the time, adding the Frida gadget in the app and executing the command…

0x1r1s · 2024-10-17 11:02 · 5 claps · 3.3 min read
#android #reverse-engineering #ssl-pinning #pentesting #rust
Open on Medium ↗
Wiki topics: 🔒 · Cybersecurity 📟 · Gadgets & IoT 🥊 · Combat Sports

Bypassing librust.so SSL Pinning on Android

I was working on analyzing a traffic of an Android app. Most of the time, adding the Frida gadget in the app and executing the command below is enough to bypass 90% of the SSL Pinning process on Android.

objection explore --startup-command 'android sslpinning disable'

However, this doesn’t work in some specific cases. One is when the SSL Pinning implementation is done within some native libraries. The most common example is flutter Apps, as it requires you to patch the libflutter.so library manually, which can be a painful process (see https://blog.nviso.eu/2022/08/18/intercept-flutter-traffic-on-ios-and-android-http-https-dio-pinning/)

As I had encountered this situation before, I opened the app in JADX to see which native libraries the app uses.

I was surprised to see the app uses a Rust native library. I first tried to patch the libflutter.so library and inspect the traffic of the app, but I was only getting errors in Burp:

After inspecting the logcat output of the app, something tickled me:

Apparently the Rust API was called in order to make some requests. So the main culprit in this story is the librust.so library. First, I tried to find out which exact function was annoying me. After some time of RE, I stumbled upon this class: https://paritytech.github.io/try-runtime-cli/rustls/client/danger/trait.ServerCertVerifier.html

I was pretty sure that the verify_server_cert was the function rejecting my Burp self-signed certificate.

So the next step is to patch it. From here things can get messy really fast. Fortunately, in my case, the app source code is public so I could build the app locally without stripping native libraries. This is crucial because it allows us to see the function names and symbols, which makes it way easier to find the method’s address.

The argument you should add is “ — no-strip” when you execute the cargo command.

Next, we can simply search for all the occurences of the “verify_server_cert” in the librust.so file:

We found three of them. Let’s first look at the first one in Ghidra:

This seems to be a kind of null implementation of the verify_server_cert. We’re lucky here, because we know how to patch the “real” implementation of this method now.

Here is the second occurence. It looks like the method we saw in the Rust documentation.

We have now everything to patch the verify_server_cert method: its address, the patched assembly code, and the name of the native library.

Final step is to create a Frida script with all this information:

We can now launch Objection in order to effectively apply the patch. Depending on your application, the librust.so loading is hazardous, so you might explore your app in order to trigger the loading.

Finally, we have access to the App traffic in Burp.

The next step would be to create some patterns based on your phone architecture and librust.so version, so that even if the librust.so library is stripped, you can still defeat SSL Pinning. This was done with the libflutter.so library (see: https://github.com/NVISOsecurity/disable-flutter-tls-verification).

For the time being, I think stumbling upon the librust.so library is still quite rare in the Android ecosystem.


메타데이터
post_id
6fcd96362fcc
slug
bypassing-librust-so-ssl-pinning-6fcd96362fcc
url
https://medium.com/@0x1r1s/bypassing-librust-so-ssl-pinning-6fcd96362fcc
canonical_url
https://medium.com/@0x1r1s/bypassing-librust-so-ssl-pinning-6fcd96362fcc
author_url
https://medium.com/@0x1r1s
status
ok
fetched_at
2026-06-10 09:45:17