Set up an Android 14+ phone to snoop on App's HTTPS communications.

Intro

Problem: there is a website somewhere that hates robots and stuff. But you are a good robot or script that still wants to access, say, your own data. Solution: Pretend to be an Android App! These also are kind of human controlled robots/scripts, that will call whatever API and get resuts.

So you want to figure out how the app works on a phone, what kind of credentials it’s using, and understand how the remote API is being called.

TL;DR

  • Find a phone supported by Lineage4MicroG
  • Follow the Installation process.
    • At some point you have the option to sideload Add-Ons, so download Magisk APK, rename it to magisk.zip and adb sideload that
  • Finish Android installation
  • Finish Magisk Installation (will require multiple reboots)
  • Install https://github.com/pwnlogs/cert-fixer Magisk module
  • Reboot
  • adb push mitmproxy_certificate.der /sdcard/Download (make sure the file has .der extension)
  • In Android Settings Go to Security & Privacy → Encryption & credentials → Trusted Credentials
  • Add mitmproxy_certificate.der
  • Reboot
  • Redirect your phone’s traffic to your instance of mitmproxy
    • nftables example :
      • ip saddr $android_phone_ip tcp dport 80 dnat to $machine_running_mitmproxy:8080
      • ip saddr $android_phone_ip tcp dport 443 dnat to $machine_running_mitmproxy:8080
  • start mitmproxy
  • Install the app you want to install. Some helpful commands:
    • adb install app.apk
    • If you have an .apkx:
      • unzip app.apkx
      • adb install-multiple *.apk, or, if in Windows PowerShell adb.exe install-multiple @(Resolve-Path *.apk)
  • Start your app, requests should show up on mitmproxy
  • Save your current mitmproxy session as HAR with : save.har @all output.har
  • Start hacking

Why is this so complicated?

Problem 1: apps don’t work well on x86_64 emulators

Back in the days people would write Java. But that was annoying because companies want to write one line of code and have it work everywhere… Which was the whole point of Java…. But the Java of today is HTML+JS or something like that.

So people who want Apps write them on top of Flutter. Which takes Dart as input, and machine code as output. And since every machine out there is a phone running ARM64, if you download an APK, it’ll most certainly be only containing code for arm64 platforms.

Android tells us that it’s fine because the OS provides magical translation of arm into x86, so you can run your arm64 native code on x86_64.

But also everytime I try my x86_64 android emulator crashes so here’s that.

Also, since the offician Android emulator is based on Qemu, you should be able to run a arm64 qemu virtual machine on x86_64, at a performance cost, but this is not supported anymore.

So use a physical phone.

Problem 2: Can’t mess up with Android 14+ system certificate store easily anymore.

One obviously can’t just sniff the network connection, because SSL, so you want to use mitmproxy. But for this to work, you’ll need to make the App you want to analyze accept the certificate used by the proxy.

But since Android 14, the certificates stored in the /system partition are ignored, and favored by these stored in the Conscrypt module APEX, and you can’t just drop files in there because security.

Solution: Use Magisk & the CertFixer module.

This will do magic (lol) stuff during boot, and copy the user certificates in the proper place.

Problem 3: What if the App does pinning and doesn’t trust Android’s store? Or refuses to run if the device is rooted? Or has some other kind of protection against all this?

That sucks.

Automated patching with Medusa

You can try to use Medusa that builds on top of Frida. It maintains a list of modules that are scripts that will tell Frida to do the appropriate hooks and in-memory code modification to try and defeat code in the App that does any of this stuff we don’t want. For example:

But the couple times I’ve tried these, the app would crash.

More manual approach with Frida

Decompile the apk

I recommend using Bytecode Viewer. Just drop a .apk file and you can start exploring and maybe figure out what method to patch.

Here for example, I figured out that in the app “AppBaseActivity”, they were loading a class called x8 where a static value a was could be set to True, which enables ‘debug mode’, and then none of the Root checks would run.

I easily found it by using Bytecode Viewer to search for the strings displayed in the warning when the app detects your rooted phone and complains about it.

setTimeout(function() { // avoid java.lang.ClassNotFoundException

	Java.perform(function() {

		// Root detection bypass example

		var BaseActivity = Java.use("com.app.android.views.core.AppBaseActivity");
		console.log("info: hooking activity class");

        const onCreate = BaseActivity.onCreate;
        onCreate.implementation = function(v) {

            var params = Java.use("x8.a");
            console.log("Is_debug_build value is ",params.a.value.booleanValue());
            params.a.value = Java.use("java.lang.Boolean").$new(true);
            console.log("Is_debug_build value is ",params.a.value.booleanValue());

            onCreate.call(this, v);
        }

	});

}, 0);

Install Frida server on the phone.

Saved as script.js and run frida -U -f com.app.android -l .\script.js. It should start your app, patch the x8.a value, and the app starts.

Still need to look into

References