Search code examples
androidsslproxyreverse-engineeringfrida

How to execute MITM attack on an android phone when there are some unknown protection?


I've got some difficulties trying to execute "Man in the Middle" attack on my experimental subject: https://tiktok.en.uptodown.com/android

I have setup proxy on my PC which I pass my phone's traffic through. Of course I've had installed certificate of this proxy on my rooted phone as system one, and I have ssl traffic decrypted, but not from my app.

I thought that there was SSL-pinning, or there was just a specific certificate built-in that this app uses. I tried using frida and run the app with these scripts that are supposed to disable ssl-pinning and root checking (unsuccessfully):

https://codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida/ https://codeshare.frida.re/@akabe1/frida-multiple-unpinning/ https://codeshare.frida.re/@dzonerzy/fridantiroot/

and some others that I can't find now.

I don't see anything that I need in this app's internet security configuration (see below). This, as I think, should pass traffic using system certificates, when not in debuggable mode (on production)

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates overridePins="true" src="system" />
        </trust-anchors>
    </base-config>
    <debug-overrides>
        <trust-anchors>
            <certificates src="user" />
        </trust-anchors>
    </debug-overrides>
</network-security-config>

I also tried using apktool to decompile the app and just add my certificate to this config but could not build it back (it fails compiling even if there was no changes, maybe apktool bug).

The most interesting thing is that I can see SSL traffic decrypted when running the app on emulator. But this solution doesn't work for me since this app works differently (for example, I don't have "Content Preferences" button in the settings).

My question is that I just want to know anything that I can also dig into, maybe, some cases from people (reverse engineers or android developers) who had experience doing similar thing. Or they just have something on their minds that probably could help me to find a solution. Maybe there are some other methods of protecting from MITM attacks that I don't know and haven't found on the internet. Thanks.


Solution

  • Since I've found a solution, I'm answering my own question and summing up everything I have found out.

    In order to successfully get API calls of an application which has Certificate Pinning, you need firstly check if it really has Certificate Pinning:

    1. Search for Pin Digest in the network security config: https://developer.android.com/training/articles/security-config#CertificatePinning You can also grep all files decompiled and search for <pin digest=""> tags. If you find something, you can just remove these settings and recompile your application. In my case, I didn't find anything.

    2. You can also check logcat logs (adb logcat) to find something that says "Certificate verification failed" or "Certificate pinning failure" or something like that, that were just examples.

    3. If you see that your application's requests are not decoded but other ones are decoded, it means that your environment is OK and the application really have some validation which makes it not to trust your proxy certificate.

    What about methods to bypass this protection:

    1. Sometimes, lower versions of an application does not support SSL pinning, so you can try to find an older version. Not my case. I needed the latest one

    2. Modify the network security config file if it has pin digests. You can try to remove all of them and recompile the app using apktool. Not my case either.

    3. Using frida. There are some scripts I pinned in my question. They can help you to bypass SSL pinning. As Robert said under my question, You can also try to look for methods that are responsible for sending requests and getting responses. You can write a script to listen for functions and print arguments or return values. That's not too hard. It helped me, but I only managed to get requests, not responses. I think, If I find a way to get responses, this is the best method in my case

    4. If your app has native functions, try to look for libraries. You may notice something strange. In my case, there was a custom cronet library which has its own implementation of SSL verifying. You can use radare2 (or IDA Pro, but it's not free) to patch .so libraries. It's very simple and useful tool. That's my case. I spent several days changing return values of strange functions I found, and it did its work, but I still can't view contents of some requests, but there are few of them so it's not a big problem for me.