├── module
├── .gitignore
├── system
│ └── etc
│ │ └── security
│ │ └── cacerts
│ │ └── .gitkeep
├── module.prop
└── post-fs-data.sh
├── zygisk_module
├── .gitignore
├── src
│ └── main
│ │ └── AndroidManifest.xml
├── jni
│ ├── Application.mk
│ ├── Android.mk
│ ├── common.cpp
│ ├── common.h
│ ├── module.cpp
│ ├── companion.cpp
│ └── zygisk.hpp
└── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitmodules
├── .gitignore
├── settings.gradle
├── ndk_path.py
├── gradle.properties
├── dist.sh
├── gradlew.bat
├── README.md
└── gradlew
/module/.gitignore:
--------------------------------------------------------------------------------
1 | /zygisk
2 | /META-INF
3 |
--------------------------------------------------------------------------------
/module/system/etc/security/cacerts/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/zygisk_module/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /libs
3 | /obj
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ngorskikh/adguardcert/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/zygisk_module/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "zygisk_module/jni/libcxx"]
2 | path = zygisk_module/jni/libcxx
3 | url = https://github.com/topjohnwu/libcxx.git
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 | .cxx
10 | local.properties
11 | *.zip
12 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | dependencyResolutionManagement {
2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | include ':zygisk_module'
9 |
--------------------------------------------------------------------------------
/zygisk_module/jni/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
2 | APP_CPPFLAGS := -std=c++17 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden
3 | APP_STL := none
4 | APP_PLATFORM := android-21
5 |
--------------------------------------------------------------------------------
/module/module.prop:
--------------------------------------------------------------------------------
1 | id=adguardcert
2 | name=AdGuard Certificate
3 | version=v1.0
4 | versionCode=1
5 | author=AdGuard
6 | description=Copies AdGuard's CA certificate from the user certificate store to the system store and forces Zygisk unmount procedures for Chrome.
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Sep 26 02:13:18 PDT 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/zygisk_module/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | }
4 |
5 | android {
6 | compileSdkVersion 31
7 | ndkVersion "23.1.7779620"
8 |
9 | externalNativeBuild {
10 | ndkBuild {
11 | path("jni/Android.mk")
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/zygisk_module/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 | LOCAL_MODULE := copycert
5 | LOCAL_SRC_FILES := module.cpp companion.cpp common.cpp
6 | LOCAL_STATIC_LIBRARIES := libcxx
7 | LOCAL_LDLIBS := -llog
8 | include $(BUILD_SHARED_LIBRARY)
9 |
10 | include jni/libcxx/Android.mk
11 |
12 | # If you do not want to use libc++, link to system stdc++
13 | # so that you can at least call the new operator in your code
14 |
15 | # include $(CLEAR_VARS)
16 | # LOCAL_MODULE := example
17 | # LOCAL_SRC_FILES := example.cpp
18 | # LOCAL_LDLIBS := -llog -lstdc++
19 | # include $(BUILD_SHARED_LIBRARY)
20 |
--------------------------------------------------------------------------------
/ndk_path.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 |
5 | def get_ndk_path():
6 | sdk_path = os.environ.get('ANDROID_HOME')
7 | if os.path.isdir(sdk_path):
8 | path = os.path.join(sdk_path, 'ndk')
9 | if os.path.isdir(path):
10 | # Android Studio can install multiple ndk versions in 'ndk'.
11 | # Find the newest one.
12 | ndk_version = None
13 | for name in os.listdir(path):
14 | if not ndk_version or ndk_version < name:
15 | ndk_version = name
16 | if ndk_version:
17 | return os.path.join(path, ndk_version)
18 | ndk_path = os.path.join(sdk_path, 'ndk-bundle')
19 | if os.path.isdir(ndk_path):
20 | return ndk_path
21 | return None
22 |
23 | print(get_ndk_path())
24 |
--------------------------------------------------------------------------------
/zygisk_module/jni/common.cpp:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 | #include
3 |
4 | int ag::read_int(int fd) {
5 | int i;
6 | if (read(fd, &i, sizeof(i)) != sizeof(i)) {
7 | return INT_MIN;
8 | }
9 | return i;
10 | }
11 |
12 | std::string ag::read_string(int fd) {
13 | size_t size = 0;
14 | if (read(fd, &size, sizeof(size)) != sizeof(size)) {
15 | return "";
16 | }
17 | std::string s;
18 | s.resize(size);
19 | if (read(fd, s.data(), s.size()) != s.size()) {
20 | return "";
21 | }
22 | return s;
23 | }
24 |
25 | void ag::write_int(int fd, int v) {
26 | write(fd, &v, sizeof(v));
27 | }
28 |
29 | void ag::write_string(int fd, std::string_view s) {
30 | size_t size = s.size();
31 | write(fd, &size, sizeof(size));
32 | write(fd, s.data(), size);
33 | }
34 |
--------------------------------------------------------------------------------
/module/post-fs-data.sh:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 | MODDIR=${0%/*}
3 |
4 | # Android hashes the subject to get the filename, field order is significant
5 | # AdGuard certificate is /C=EN/O=AdGuard/CN=AdGuard Personal CA
6 | # The filename is then . where is an integer
7 | AG_CERT_HASH=0f4ed297
8 | cp -f /data/misc/user/*/cacerts-added/${AG_CERT_HASH}.* $MODDIR/system/etc/security/cacerts
9 | chown -R 0:0 $MODDIR/system/etc/security/cacerts
10 |
11 | [ "$(getenforce)" = "Enforcing" ] || exit 0
12 |
13 | default_selinux_context=u:object_r:system_file:s0
14 | selinux_context=$(ls -Zd /system/etc/security/cacerts | awk '{print $1}')
15 |
16 | if [ -n "$selinux_context" ] && [ "$selinux_context" != "?" ]; then
17 | chcon -R $selinux_context $MODDIR/system/etc/security/cacerts
18 | else
19 | chcon -R $default_selinux_context $MODDIR/system/etc/security/cacerts
20 | fi
21 |
--------------------------------------------------------------------------------
/zygisk_module/jni/common.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include
7 |
8 | #include
9 |
10 | #define LOG_TAG "CopyCertificates"
11 |
12 | #ifndef NDEBUG
13 | #define dbglog(fmt_, ...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "%s(): " fmt_, __func__, ##__VA_ARGS__)
14 | #else
15 | #define dbglog(fmt_, ...) ((void) fmt_)
16 | #endif
17 |
18 | #define warnlog(fmt_, ...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "%s(): " fmt_, __func__, ##__VA_ARGS__)
19 |
20 | namespace ag {
21 |
22 | template
23 | using Ftor = std::integral_constant;
24 | using Dir = std::unique_ptr>;
25 |
26 | int read_int(int fd);
27 | std::string read_string(int fd);
28 |
29 | void write_int(int fd, int v);
30 | void write_string(int fd, std::string_view s);
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 |
--------------------------------------------------------------------------------
/dist.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ -z "${ANDROID_HOME}" ]; then
4 | echo "Specify the Android SDK directory through the ANDROID_HOME environment variable"
5 | exit 1
6 | fi
7 |
8 | NDK_PATH=$(./ndk_path.py)
9 |
10 | if [ ! -d "${NDK_PATH}" ]; then
11 | echo "NDK version ${NDK_VERSION} is required and was not found at ${NDK_PATH}"
12 | exit 1
13 | fi
14 |
15 | NDK_BUILD="${NDK_PATH}/ndk-build"
16 |
17 | (cd ./zygisk_module && ${NDK_BUILD} -j8) || exit 1
18 |
19 | mkdir ./module/zygisk
20 |
21 | for i in $(ls ./zygisk_module/libs); do
22 | cp -f ./zygisk_module/libs/$i/*.so ./module/zygisk/$i.so
23 | done
24 |
25 | UPDATE_BINARY_URL="https://raw.githubusercontent.com/topjohnwu/Magisk/master/scripts/module_installer.sh"
26 |
27 | mkdir -p ./module/META-INF/com/google/android
28 | curl "${UPDATE_BINARY_URL}" > ./module/META-INF/com/google/android/update-binary
29 | echo "#MAGISK" > ./module/META-INF/com/google/android/updater-script
30 |
31 | VERSION=$(sed -ne "s/version=\(.*\)/\1/gp" ./module/module.prop)
32 | NAME=$(sed -ne "s/id=\(.*\)/\1/gp" ./module/module.prop)
33 |
34 | rm -f ${NAME}-${VERSION}.zip
35 | (
36 | cd ./module
37 | zip ../${NAME}-${VERSION}.zip -r * -x ".*" "*/.*"
38 | )
39 |
--------------------------------------------------------------------------------
/zygisk_module/jni/module.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 |
6 | #include "common.h"
7 | #include "zygisk.hpp"
8 |
9 | static const std::string PACKAGES_TO_UNMOUNT[] = {
10 | "com.android.chrome",
11 | "com.chrome.canary",
12 | "com.chrome.beta",
13 | "com.chrome.dev",
14 | };
15 |
16 | class MyModule : public zygisk::ModuleBase {
17 | public:
18 | void onLoad(zygisk::Api *api, JNIEnv *env) override {
19 | this->api = api;
20 | this->env = env;
21 | }
22 |
23 | void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
24 | int fd = api->connectCompanion();
25 | if (fd < 0) {
26 | warnlog("Failed to connect companion");
27 | return;
28 | }
29 | ag::write_int(fd, args->uid);
30 | std::string package = ag::read_string(fd);
31 | if (std::any_of(std::begin(PACKAGES_TO_UNMOUNT), std::end(PACKAGES_TO_UNMOUNT),
32 | [&](const std::string &pkg) { return pkg == package; })) {
33 | dbglog("Forcing denylist unmount routines for package: %s", package.c_str());
34 | api->setOption(zygisk::Option::FORCE_DENYLIST_UNMOUNT);
35 | }
36 | api->setOption(zygisk::Option::DLCLOSE_MODULE_LIBRARY);
37 | close(fd);
38 | }
39 |
40 | private:
41 | zygisk::Api *api;
42 | JNIEnv *env;
43 | };
44 |
45 | REGISTER_ZYGISK_MODULE(MyModule)
46 |
--------------------------------------------------------------------------------
/zygisk_module/jni/companion.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include "common.h"
11 | #include "zygisk.hpp"
12 |
13 | #define APP_ID(uid) (uid % 100000)
14 |
15 | using Map = std::unordered_map;
16 | static std::shared_ptr