Intercepting traffic on Android with Mainline and Conscrypt
这篇文章介绍了Android系统中证书管理的变化,特别是从Android 14开始通过Mainline模块Conscrypt管理和更新根证书的方式。作者详细讲解了AlwaysTrustUserCerts模块如何支持从Android 7到16 Beta的版本,并通过复制用户证书到系统目录并挂载到Conscrypt的apex目录来解决HTTPS流量拦截问题。 2025-6-5 07:0:0 Author: blog.nviso.eu(查看原文) 阅读量:12 收藏

TL;DR: The AlwaysTrustUserCerts module now supports Android 7 until Android 16 Beta. If you want to learn more about Mainline, Conscrypt and how everything works together, keep reading!

Intro

To properly test the backend of any mobile application, we need to intercept (and modify) the API traffic. We could use Swagger or Postman files if they are available, but it’s a lot easier to intercept real traffic so we don’t have to worry about providing correct values, sequencing, etc.

Sometimes intercepting traffic is very straightforward: You configure a device proxy, install your proxy certificate on the device and you’re good to go. This was even the default behavior until Android stopped trusting user certificates by default. On recent versions of Android, this will only work if the network security config has been modified to include user certificates, or if the user certificate has been moved into the system certificate repository.

Android 14 (A14) made interception a bit more difficult by moving all root certificates to a Mainline module, as I’ll explain below. Recently though, one of our devices was showing the same behavior, even on A13. While I was surprised initially, it actually makes a lot of sense. Let’s dive in!

Android’s Conscrypt module and Mainline

The Conscrypt module, which was introduced in Android 9, is used by the Android OS to verify the TLS certificates of HTTPS connections. It contains Conscrypt itself in the form of a Java security provider, and the BoringSSL library, Google’s Fork of OpenSSL. Conscrypt is still the default security provider on Android 15 (A15).

In Android 10, Google introduced Mainline, which is a way for Google to update certain parts of the Android OS without requiring an over-the-air (OTA) update. These updates are installed via the Google Play Services app and require an onboarded Google Play app. Since these Mainline updates are completely separated from system updates, even devices that no longer receive official OS updates can still receive security updates for selected components. Since the introduction in Android 10, many modules have been merged into Mainline, currently bringing the total to 33 modules for A15.

As a result, devices typically have two update levels:

  • Android Security Update (ASU): Delivered as OTA updates by the OEM
  • Google Play System Update (GPSU): Delivered by Google via Google Play
An Android 13 (A13) device with two patch levels: The Android Security Update (ASU) level and the Google Play System Update (GPSU) level

Internally, Mainline modules are located in the /apex/ folder and can be viewed with root permissions. On a fresh Android 13 (A13) installation (UP1A.231005.007), the /apex/ folder might look as follows:

$ ls -lh /apex
total 256K
-rw-r--r--  1 root   system  11K 2025-05-12 17:20 apex-info-list.xml
drwxr-xr-x  7 system system 4.0K 1970-01-01 01:00 com.android.adbd
drwxr-xr-x  7 system system 4.0K 1970-01-01 01:00 com.android.adbd@331314022
drwxr-xr-x  8 system system 4.0K 1970-01-01 01:00 com.android.adservices
drwxr-xr-x  8 system system 4.0K 1970-01-01 01:00 com.android.adservices@331418080
drwxr-xr-x  6 system system 4.0K 1970-01-01 01:00 com.android.apex.cts.shim
drwxr-xr-x  6 system system 4.0K 1970-01-01 01:00 com.android.apex.cts.shim@1
drwxr-xr-x  6 system system 4.0K 1970-01-01 01:00 com.android.appsearch
drwxr-xr-x  6 system system 4.0K 1970-01-01 01:00 com.android.appsearch@331311000
drwxr-xr-x  8 system system 4.0K 1970-01-01 01:00 com.android.art
drwxr-xr-x  8 system system 4.0K 1970-01-01 01:00 com.android.art@331413030
drwxr-xr-x  7 system system 4.0K 1970-01-01 01:00 com.android.btservices
drwxr-xr-x  7 system system 4.0K 1970-01-01 01:00 com.android.btservices@331716000
drwxr-xr-x  5 system system 4.0K 1970-01-01 01:00 com.android.cellbroadcast
drwxr-xr-x  5 system system 4.0K 1970-01-01 01:00 com.android.cellbroadcast@331411000
drwxr-xr-x  8 system system 4.0K 1970-01-01 01:00 com.android.compos
drwxr-xr-x  8 system system 4.0K 1970-01-01 01:00 com.android.compos@1
drwxr-xr-x  8 system system 4.0K 1970-01-01 01:00 com.android.conscrypt
drwxr-xr-x  8 system system 4.0K 1970-01-01 01:00 com.android.conscrypt@331411000

Bash

The apex-info-list.xml contains an overview of the installed modules. For example, for com.android.conscrypt we have the following element:

<?xml version="1.0" encoding="utf-8"?>
<apex-info-list>
...
<apex-info
   moduleName="com.android.conscrypt"
   modulePath="/data/apex/decompressed/[email protected]"
   preinstalledModulePath="/system/apex/com.google.android.conscrypt.apex"
   versionCode="331411000"
   versionName=""
   isFactory="true"
   isActive="true"
   lastUpdateMillis="1747063014"
   provideSharedApexLibs="false"
/>
...
</apex-info-list>

XML

The Conscript module itself contains some metadata, the BoringSSL library, and the Conscrypt security provider:

$ ls -lah /apex/com.android.conscrypt
total 48K
drwxr-xr-x  8 system system 4.0K 1970-01-01 01:00 .
drwxr-xr-x 64 root   root   1.3K 2025-05-12 11:37 ..
-rw-r--r--  1 system system   61 1970-01-01 01:00 apex_manifest.json
-rw-r--r--  1 system system  103 1970-01-01 01:00 apex_manifest.pb
drwxr-xr-x  2 root   shell  4.0K 1970-01-01 01:00 bin
drwxr-xr-x  3 root   shell  4.0K 1970-01-01 01:00 etc
drwxr-xr-x  2 root   shell  4.0K 1970-01-01 01:00 javalib
drwxr-xr-x  2 root   shell  4.0K 1970-01-01 01:00 lib
drwxr-xr-x  2 root   shell  4.0K 1970-01-01 01:00 lib64
drwx------  2 root   root    16K 1970-01-01 01:00 lost+found  

Bash

Android 14 (A14): Updatable root certificate authorities

When Android validates a TLS certificate chain, it does so using a collection of root certificate authorities. All versions of Android have the /system/etc/security/cacerts folder:

$ ls /system/etc/security/cacerts
00673b5b.0  35105088.0  5e4e69e7.0  88950faa.0  b0f3e76e.0  d16a5865.0
04f60c28.0  399e7759.0  5f47b495.0  89c02a45.0  b3fb433b.0  d18e9066.0
0d69c7e1.0  3a3b02ce.0  60afe812.0  8d6437c3.0  b74d2bd5.0  d41b5e2a.0
10531352.0  3ad48a91.0  6187b673.0  91739615.0  b7db1890.0  d4c339cb.0
111e6273.0  3c58f906.0  63a2c897.0  9282e51c.0  b872f2b4.0  d59297b8.0
12d55845.0  3c6676aa.0  67495436.0  9339512a.0  b936d1c6.0  d7746a63.0
1dcd6f4c.0  3c860d51.0  69105f4f.0  9479c8c3.0  bc3f2570.0  da7377f6.0
1df5a75f.0  3c899c73.0  6b03dec0.0  9576d26b.0  bd43e1dd.0  dbc54cab.0
1e1eab7c.0  3c9a4d3b.0  75680d2e.0  95aff9e3.0  bdacca6f.0  dbff3a01.0
1e8e7201.0  3d441de8.0  76579174.0  9685a493.0  bf64f35b.0  dc99f41e.0
1eb37bdf.0  3e7271e8.0  7892ad52.0  9772ca32.0  c2c1704e.0  dfc0fe80.0
1f58a078.0  40dc992e.0  7999be0d.0  985c1f52.0  c491639e.0  e442e424.0
219d9499.0  455f1b52.0  7a7c655d.0  9d6523ce.0  c51c224c.0  e48193cf.0
23f4c490.0  48a195d8.0  7a819ef2.0  9f533518.0  c559d742.0  e775ed2d.0
27af790d.0  4be590e0.0  7c302982.0  a2c66da8.0  c7e2a638.0  e8651083.0
2add47b6.0  5046c355.0  7d453d8f.0  a3896b44.0  c907e29b.0  ed39abd0.0
2d9dafe4.0  524d9b43.0  81b9768f.0  a7605362.0  c90bc37d.0  f013ecaf.0
2fa87019.0  52b525c7.0  82223c44.0  a7d2cf64.0  cb156124.0  f0cd152c.0
302904dd.0  583d0756.0  85cde254.0  a81e292b.0  cb1c3204.0  f459871d.0
304d27c3.0  5a250ea7.0  86212b19.0  ab5346f4.0  ccc52f49.0  facacbc6.0
31188b5e.0  5a3f0ff8.0  869fbf79.0  ab59055e.0  cf701eeb.0  fb5fa911.0
33ee480d.0  5acf816d.0  87753b0d.0  aeb67534.0  d06393bb.0  fd08c599.0
343eb6cb.0  5cf9d536.0  882de061.0  b0ed035a.0  d0cddf45.0  fde84897.0

Bash

However, with A14, Google started including a cacerts folder inside of the /apex/com.android.conscrypt/ package, too:

$ ls -l /apex/com.android.conscrypt/
-rw-r--r-- 1 system system   103 1970-01-01 01:00 apex_manifest.pb
drwxr-xr-x 2 root   shell   4096 1970-01-01 01:00 bin
drwxr-xr-x 2 root   shell   4096 1970-01-01 01:00 cacerts
drwxr-xr-x 3 root   shell   4096 1970-01-01 01:00 etc
drwxr-xr-x 2 root   shell   4096 1970-01-01 01:00 javalib
drwxr-xr-x 2 root   shell   4096 1970-01-01 01:00 lib64
drwx------ 2 root   root   16384 1970-01-01 01:00 lost+found

Bash

The original certificates on /system are still available, but they are only used as a fallback; if the cacerts folder is available via conscrypt, it will get priority over the ones stored at /system/etc/security/cacerts. The code below, taken from /apex/com.android.conscrypt/javalib/conscrypt.jar, shows this behavior. Note that this snippet also hints at a potential alternative way to disable apex certificate management via the system.certs.enabled property:

static {
    String ANDROID_ROOT = System.getenv("ANDROID_ROOT");
    String ANDROID_DATA = System.getenv("ANDROID_DATA");
    File updatableDir = new File("/apex/com.android.conscrypt/cacerts");
    if (System.getProperty("system.certs.enabled") != null && System.getProperty("system.certs.enabled").equals("true")) {
        defaultCaCertsSystemDir = new File(ANDROID_ROOT + "/etc/security/cacerts");
    } else if (updatableDir.exists() && updatableDir.list().length != 0) {
        defaultCaCertsSystemDir = updatableDir;
    } else {
        defaultCaCertsSystemDir = new File(ANDROID_ROOT + "/etc/security/cacerts");
    }
    TrustedCertificateStore.setDefaultUserDirectory(new File(ANDROID_DATA + "/misc/keychain"));
}

Java

So we could enable this system property and be done with it, but there are actually a few issues:

  • Setting this property with setprop/resetprop won’t work; The properties managed by these tools are a different set of properties than the one you get from System.getProperty
  • Google may modify this behavior in the future, so it’s not very future-proof
  • Injecting the property into the Dalvik VM may be detected by RASP

The AlwaysTrustUserCerts module currently only copies user certificates into the /system/ directory, which was enough until now. By adding the certificates before Zygote is initialized, the certificates automatically propagate to all apps when they are forked from Zygote. To make the module work with A14, we want to still copy the user certs into /system/, but also make sure that they are added to the /apex/ directory.

Unfortunately, adding certificates to the /apex/ folder is more complicated, as documented by Tim Perry on the httptoolkit blog: Any changes we make here will not automatically propagate to new applications, due to the way each app’s /apex folder is mounted.

As suggested in the httptoolkit blogpost, there are a few potential solutions, some of which require iteratively going into every process and updating the mounts to pick up our changes. To make sure the update covers both /system and /apex certificates, the module now does the following:

  1. Collect all user and /system certs and copy them into $MODULE/system/etc/security/cacerts
  2. Magisk/KernelSU will automatically overlay this onto the original /system/etc/security/cacerts folder
  3. Wait for zygote to become available and mount /system/etc/security/cacerts onto /apex/com.android.conscrypt/cacerts in zygote and all its children
  4. Monitor zygote to make sure the mount is still there. When zygote crashes, the mount disappears and we need to inject it again

Step 3 is required because even though zygote will see the newly mounted certificates, the mount will not propagate to its children since the /apex/ is specifically mounted with PRIVATE propagation.

It took a bit of work, but AlwaysTrustUserCerts now allows you to fully intercept HTTPS traffic on A14 🥳.

What about older versions?

A14 comes with Mainline-updatable root-CAs out of the box. But …the whole idea of Mainline is to bring important security updates to devices without requiring a full OTA update. Managing root certificate authorities definitely is a security-critical service, and since Conscrypt is part of Mainline, these updates can be made available to pre-A14 devices, too!

A commit from December 2022 mentions the inclusion of CA certificates in apex:

Add conscrypt updatable certificates.

This cl adds the new blueprint files required for certificate loading, and an additional ca_certificates_apex build rule used to create the prebuild modules for loading certificates. While we are currently have to out all certificates within Conscrypt's apex build rules, we intend to later avoid that step.

But which devices will get this specific update? This question is answered a few commits later, when the minSDK is set to 30 (A11):

Merge "Add minSdkVersion="30" to Conscrypt APEX" into main

It’s currently still at this value, so let’s do a quick test and flash A11.0.0 (RP1A.200720.009, Sep 2020) to my Pixel 3a device. After the initial installation, we have version 300900703 which does not have a cacerts folder yet:

$ ls -lh com.android.conscrypt@300900703/
total 22K
-rw-r--r-- 1 system system   62 1970-01-01 01:00 apex_manifest.json
-rw-r--r-- 1 system system   85 1970-01-01 01:00 apex_manifest.pb
drwxr-xr-x 2 root   shell  4.0K 1970-01-01 01:00 bin
drwxr-xr-x 2 root   shell  4.0K 1970-01-01 01:00 etc
drwxr-xr-x 2 root   shell  4.0K 1970-01-01 01:00 javalib
drwxr-xr-x 2 root   shell  4.0K 1970-01-01 01:00 lib
drwxr-xr-x 2 root   shell  4.0K 1970-01-01 01:00 lib64
drwx------ 2 root   root    16K 1970-01-01 01:00 lost+found

Bash

Unfortunately, try as a I might, I couldn’t trigger a GPSU. After doing some research, it seems that multiple users have this issue, and the suggested fix is to update to A12. So let’s give that a try and install SP1A.210812.015, the first available A12 version for Pixel 3a:

# SP1A.210812.015 - pre update
sargo:/apex/com.android.conscrypt@310727000 # ls -l
total 44
-rw-r--r-- 1 system system    62 1970-01-01 01:00 apex_manifest.json
-rw-r--r-- 1 system system   103 1970-01-01 01:00 apex_manifest.pb
drwxr-xr-x 2 root   shell   4096 1970-01-01 01:00 bin
drwxr-xr-x 3 root   shell   4096 1970-01-01 01:00 etc
drwxr-xr-x 2 root   shell   4096 1970-01-01 01:00 javalib
drwxr-xr-x 2 root   shell   4096 1970-01-01 01:00 lib
drwxr-xr-x 2 root   shell   4096 1970-01-01 01:00 lib64
drwx------ 2 root   root   16384 1970-01-01 01:00 lost+found

Bash

Luckily this time we do get an update after refreshing the update window a few times (April 1st 2025) and the cacerts folder is now available:

# SP1A.210812.015 - post update (April 1st 2025 update)
sargo:/apex/com.android.conscrypt@351412000 # ls -lah
total 48K
drwxr-xr-x  9 system system 4.0K 1970-01-01 01:00 .
drwxr-xr-x 55 root   root   1.1K 2025-05-13 09:59 ..
-rw-r--r--  1 system system  103 1970-01-01 01:00 apex_manifest.pb
drwxr-xr-x  2 root   shell  4.0K 1970-01-01 01:00 bin
drwxr-xr-x  2 root   shell  4.0K 1970-01-01 01:00 cacerts
drwxr-xr-x  3 root   shell  4.0K 1970-01-01 01:00 etc
drwxr-xr-x  2 root   shell  4.0K 1970-01-01 01:00 javalib
drwxr-xr-x  2 root   shell  4.0K 1970-01-01 01:00 lib
drwxr-xr-x  2 root   shell  4.0K 1970-01-01 01:00 lib64
drwx------  2 root   root    16K 1970-01-01 01:00 lost+found

Bash

This means that, depending on your GPSU level, your device may or may not use apex-based certificates starting as early as A12. Other devices may still get GPSUs on A11 though, so let’s dig a bit deeper. (Note: At the time of writing, only A14+ devices will use the apex certificates, as explained down below)

Backporting to Android 11 (A11)

My Pixel 3a doesn’t get a GPSU on A11, but it does already have a conscrypt APEX folder installed. Since the conscrypt module supports A11, we should be able to install the newer conscrypt version on our A11 installation, as long as we can find the correct apex file. Apex files shouldn’t be device-specific (that would defeat the entire point) so why don’t we just pull it from the A12 version and install it on A11?

Extracting the apex is actually straightforward, as it’s stored on-disk in /data/apex/active/:

Next, let’s flash RQ3A.211001.001 (A11) and install the apex file. Installation should be as easy as installing an APK:

$ adb install [email protected]
Failure [INSTALL_FAILED_DUPLICATE_PACKAGE: Scanning Failed.: com.google.android.conscrypt is an APEX package and can't be installed as an APK.]

Bash

Weird. A different documentation page suggests using –staged while installing, which does work:

$ adb install --staged [email protected]
Performing Streamed Install
Success. Reboot device to apply staged session

Bash

Finally, after rebooting, we do see our newly installed conscrypt version:

$ ls /apex/com.android.conscrypt@351412000
apex_manifest.pb  bin  cacerts  etc  javalib  lib  lib64  lost+found

Bash

Success! Since the signature is valid, the APEX module is loaded and the device now has apex-based CAs! However, after some testing, it turns out that even though the folder is available, the system still falls back to the old /system location. At some point, Google updated the initialization logic to also check the current SDK version. This logic is currently also included in the latest installable Conscrypt version via Mainline:

static {
    String ANDROID_ROOT = System.getenv("ANDROID_ROOT");
    String ANDROID_DATA = System.getenv("ANDROID_DATA");
    File updatableDir = new File("/apex/com.android.conscrypt/cacerts");
    if (shouldUseApex(updatableDir)) {
        defaultCaCertsSystemDir = updatableDir;
    } else {
        defaultCaCertsSystemDir = new File(ANDROID_ROOT + "/etc/security/cacerts");
    }
    TrustedCertificateStore.setDefaultUserDirectory(new File(ANDROID_DATA + "/misc/keychain"));
}

static boolean shouldUseApex(File updatableDir) {
    Object sdkVersion = getSdkVersion();
    if (sdkVersion == null || ((Integer) sdkVersion).intValue() < 34) {
        return false;
    }
    if ((System.getProperty("system.certs.enabled") != null && System.getProperty("system.certs.enabled").equals("true")) || !updatableDir.exists() || ArrayUtils.isEmpty(updatableDir.list())) {
        return false;
    }
    return true;
}

Java

So even though the cacerts folder exists via APEX, it won’t be used on anything below A14. That being said, it’s not unthinkable that this logic could be changed in the future. If a root certificate is ever compromised (e.g. like the DigiNotar hack), Google could actually remove the compromised certificate from all Mainline-enabled devices!

In the intro, I mentioned that we did see this behavior on A13. Unfortunately, I could not confirm this, since the device had since received the latest mainline update and it’s not straightforward to collect previous versions of a specific Mainline module. Traffic interception did work after manually mounting the certificate into /apex/ though.

As a final step, let’s clean up and remove the APEX module again. Even though the module is called com.android.conscrypt, it’s not the correct package name to uninstall it:

$ adb uninstall com.android.conscrypt
Failure [DELETE_FAILED_INTERNAL_ERROR]

Bash

The correct package name is actually contained within the APEX file we installed earlier, which is com.google.android.conscrypt. Why a different package name? 🤷‍♂️

$ adb -d uninstall com.google.android.conscrypt
Success
$ ls /apex/com.android.conscrypt/
apex_manifest.json  apex_manifest.pb  bin  etc  javalib  lib  lib64  lost+found

Bash

But wait, there’s more (Android 15+)

On A15, something weird happens. After installing the AlwaysTrustUser certs module, all of the certificates have disappeared:

Normal list of certificates on the left, an empty list on the right.

It took me a while to figure this out, but luckily the fix is really simple. The problem is two-fold:

  1. I was mounting /system/etc/security/cacert onto /apex/com.android.conscrypt/cacerts
  2. With A15, each certificate in /system/etc/security/cacerts is actually a mount itself:
 $ mount | grep cert
/dev/block/dm-7 on /system/etc/security/otacerts.zip type ext4 (ro,seclabel,noatime)
/dev/block/dm-7 on /system/etc/security/cacerts/bf64f35b.0 type ext4 (ro,seclabel,noatime)
/dev/block/dm-7 on /system/etc/security/cacerts/5acf816d.0 type ext4 (ro,seclabel,noatime)
/dev/block/dm-7 on /system/etc/security/cacerts/d41b5e2a.0 type ext4 (ro,seclabel,noatime)
/dev/block/dm-7 on /system/etc/security/cacerts/33ee480d.0 type ext4 (ro,seclabel,noatime)
...

Bash

So why have the certificates disappeared? Well, the module collects all the certificates into $MODDIR/system/etc/security/cacerts which is then automatically overlayed onto the real /system/etc/security/cacerts location.

Then, the /system/etc/security/cacerts folder is bind-mounted into each process which should make the contents of the folder available. Since every file inside of /system/etc/security/cacerts is now also a mount, these mounts are not automatically propagated. The fix? Use --rbind instead of --bind when entering the process:

# Wrong
/system/bin/nsenter --mount=/proc/$zp/ns/mnt -- /bin/mount --bind $SYS_CERT_DIR $APEX_CERT_DIR

# Correct
/system/bin/nsenter --mount=/proc/$zp/ns/mnt -- /bin/mount --rbind $SYS_CERT_DIR $APEX_CERT_DIR

Bash

With all of these complex mounts, I was surprised to see that disabling root CAs from the settings still worked without any issues. Digging a bit deeper into the implementation, it turns out that root certificates are not removed, but rather copied to the /data/misc/user/0/cacerts-removed directory when they are disabled in the settings application:

// conscrypt.jar - com.android.org.conscrypt.TrustedCertificateStore
public void deleteCertificateEntry(String alias) throws IOException, CertificateException {
        File file;
        if (alias == null || (file = fileForAlias(alias)) == null) {
            return;
        }
        if (isSystem(alias)) {
            X509Certificate cert = readCertificate(file);
            if (cert == null) {
                return;
            }
            // deleteDir = /data/misc/user/0/cacerts-removed/
            File deleted = getCertificateFile(this.deletedDir, cert);
            if (deleted.exists()) {
                return;
            }
            writeCertificate(deleted, cert);
            return;
        }
        if (isUser(alias)) {
            new FileOutputStream(file).close();
            removeUnnecessaryTombstones(alias);
        }
    }

Java

When the TrustedCertificateStore later looks for the correct root CA, it checks if the identified root CA is available in the cacerts-removed directory and ignores it if it is:

// conscrypt.jar - com.android.org.conscrypt.TrustedCertificateStore
@Override public X509Certificate getTrustAnchor(final X509Certificate c) {
    CertSelector selector = new CertSelector(this) { // from class: com.android.org.conscrypt.TrustedCertificateStore.2
        @Override // com.android.org.conscrypt.TrustedCertificateStore.CertSelector
        public boolean match(X509Certificate ca) {
            return ca.getPublicKey().equals(c.getPublicKey());
        }
    };
    X509Certificate user = (X509Certificate) findCert(this.addedDir, c.getSubjectX500Principal(), selector, X509Certificate.class);
    if (user != null) {
        return user;
    }
    X509Certificate system = (X509Certificate) findCert(this.systemDir, c.getSubjectX500Principal(), selector, X509Certificate.class);
    if (system != null && !isDeletedSystemCertificate(system)) {
        return system;
    }
    return null;
}
public boolean isDeletedSystemCertificate(X509Certificate x) {
    return getCertificateFile(this.deletedDir, x).exists();
}

Java

Final solution

It took quite some troubleshooting and testing, but my Magisk module has now been updated to cover all (🤞) situations, ranging from Android 7 until Android 16 Beta. Some of the features:

  • Should work on Magisk, KernelSU, KernelSU Next, APatch
  • Copies all certificates from the user store to the /system store
  • Supports multiple users (e.g. work profiles)
  • Mounts the updated /system store to /apex, if it’s available
  • Injects the updated mount into zygote and all children
  • When zygote crashes, it reinjects all mounts
  • Disabling root CAs is supported

Enjoy, and open a PR if there are any issues! https://github.com/NVISOsecurity/AlwaysTrustUserCerts

Jeroen Beckers

Jeroen Beckers is a mobile security expert working in the NVISO Software Security Assessment team. He travels around the world teaching SANS SEC575: iOS and Android Application Security Analysis and Penetration Testing and is a co-author of OWASP Mobile Application Security (MAS) project, which includes:

  • OWASP Mobile Application Security Testing Guide (MASTG)
  • OWASP Mobile Application Security Verification Standard (MASVS)
  • OWASP Mobile Application Security Weakness Enumeration (MASWE)

文章来源: https://blog.nviso.eu/2025/06/05/intercepting-traffic-on-android-with-mainline-and-conscrypt/
如有侵权请联系:admin#unsafe.sh