From 3121eb0f9ad55a3b0d08337f13d07be7e452cf1f Mon Sep 17 00:00:00 2001 From: Rifat Azad Date: Wed, 15 Jan 2025 14:26:42 +0600 Subject: [PATCH] manager: add susfs status and sus_su toggle userspace: add susfsd ci: build susfsd ksud_overlayfs: update aarch64 bin BusyBox v1.36.1.1 topjohnwu (2024-10-06 01:38:43 PDT) Co-authored-by: rifsxd --- .github/workflows/ksud_magic.yml | 62 +++++ .github/workflows/ksud_overlayfs.yml | 62 +++++ .github/workflows/susfsd.yml | 34 +++ manager/app/src/main/res/drawable/ic_sus.xml | 9 + .../app/src/main/res/values-in/strings.xml | 2 + userspace/ksud/bin/.gitignore | 3 +- userspace/ksud/src/assets.rs | 1 + userspace/ksud_overlayfs/bin/.gitignore | 2 + userspace/ksud_overlayfs/src/assets.rs | 52 ++++ userspace/susfsd/.gitignore | 2 + userspace/susfsd/jni/Android.mk | 6 + userspace/susfsd/jni/Application.mk | 3 + userspace/susfsd/jni/susfsd.c | 239 ++++++++++++++++++ 13 files changed, 476 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ksud_magic.yml create mode 100644 .github/workflows/ksud_overlayfs.yml create mode 100644 .github/workflows/susfsd.yml create mode 100644 manager/app/src/main/res/drawable/ic_sus.xml create mode 100644 userspace/ksud_overlayfs/bin/.gitignore create mode 100644 userspace/ksud_overlayfs/src/assets.rs create mode 100644 userspace/susfsd/.gitignore create mode 100644 userspace/susfsd/jni/Android.mk create mode 100644 userspace/susfsd/jni/Application.mk create mode 100644 userspace/susfsd/jni/susfsd.c diff --git a/.github/workflows/ksud_magic.yml b/.github/workflows/ksud_magic.yml new file mode 100644 index 00000000..d5786386 --- /dev/null +++ b/.github/workflows/ksud_magic.yml @@ -0,0 +1,62 @@ +name: Build ksud_magic +on: + workflow_call: + inputs: + target: + required: true + type: string + os: + required: false + type: string + default: ubuntu-latest + pack_lkm: + required: false + type: boolean + default: true + use_cache: + required: false + type: boolean + default: true +jobs: + build: + runs-on: ${{ inputs.os }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download artifacts + uses: actions/download-artifact@v4 + + - name: Prepare LKM fies + if: ${{ inputs.pack_lkm }} + run: | + cp android*-lkm/*_kernelsu.ko ./userspace/ksud_magic/bin/aarch64/ + + - name: Import susfsd lib + run: | + cp susfsd-aarch64-linux-android/arm64-v8a/susfsd ./userspace/ksud_magic/bin/aarch64/ + + - name: Setup rustup + run: | + rustup update stable + rustup target add x86_64-apple-darwin + rustup target add aarch64-apple-darwin + - uses: Swatinem/rust-cache@v2 + with: + workspaces: userspace/ksud_magic + cache-targets: false + + - name: Install cross + run: | + cargo install cross --git https://github.com/cross-rs/cross --rev 66845c1 --force + + - name: Build ksud_magic + run: CROSS_NO_WARNINGS=0 cross build --target ${{ inputs.target }} --release --manifest-path ./userspace/ksud_magic/Cargo.toml + + - name: Upload ksud_magic artifact + uses: actions/upload-artifact@v4 + with: + name: ksud_magic-${{ inputs.target }} + path: userspace/ksud_magic/target/**/release/ksud* + diff --git a/.github/workflows/ksud_overlayfs.yml b/.github/workflows/ksud_overlayfs.yml new file mode 100644 index 00000000..db3f6528 --- /dev/null +++ b/.github/workflows/ksud_overlayfs.yml @@ -0,0 +1,62 @@ +name: Build ksud_overlayfs +on: + workflow_call: + inputs: + target: + required: true + type: string + os: + required: false + type: string + default: ubuntu-latest + pack_lkm: + required: false + type: boolean + default: true + use_cache: + required: false + type: boolean + default: true +jobs: + build: + runs-on: ${{ inputs.os }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download artifacts + uses: actions/download-artifact@v4 + + - name: Prepare LKM fies + if: ${{ inputs.pack_lkm }} + run: | + cp android*-lkm/*_kernelsu.ko ./userspace/ksud_overlayfs/bin/aarch64/ + + - name: Import susfsd lib + run: | + cp susfsd-aarch64-linux-android/arm64-v8a/susfsd ./userspace/ksud_overlayfs/bin/aarch64/ + + - name: Setup rustup + run: | + rustup update stable + rustup target add x86_64-apple-darwin + rustup target add aarch64-apple-darwin + - uses: Swatinem/rust-cache@v2 + with: + workspaces: userspace/ksud_overlayfs + cache-targets: false + + - name: Install cross + run: | + cargo install cross --git https://github.com/cross-rs/cross --rev 66845c1 --force + + - name: Build ksud_overlayfs + run: CROSS_NO_WARNINGS=0 cross build --target ${{ inputs.target }} --release --manifest-path ./userspace/ksud_overlayfs/Cargo.toml + + - name: Upload ksud_overlayfs artifact + uses: actions/upload-artifact@v4 + with: + name: ksud_overlayfs-${{ inputs.target }} + path: userspace/ksud_overlayfs/target/**/release/ksud* + diff --git a/.github/workflows/susfsd.yml b/.github/workflows/susfsd.yml new file mode 100644 index 00000000..d63699a9 --- /dev/null +++ b/.github/workflows/susfsd.yml @@ -0,0 +1,34 @@ +name: Build susfsd +on: + push: + branches: [ "next" ] + paths: + - '.github/workflows/susfsd.yml' + - 'userspace/susfsd/**' + workflow_dispatch: + workflow_call: + inputs: + target: + required: true + type: string + os: + required: false + type: string + default: ubuntu-latest +jobs: + build-susfs: + name: Build userspace susfsd + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Build susfsd + working-directory: ./userspace/susfsd + run: $ANDROID_NDK/ndk-build + - name: Upload a Build Artifact + uses: actions/upload-artifact@v4 + with: + name: susfsd-aarch64-linux-android + path: ./userspace/susfsd/libs + diff --git a/manager/app/src/main/res/drawable/ic_sus.xml b/manager/app/src/main/res/drawable/ic_sus.xml new file mode 100644 index 00000000..ea794670 --- /dev/null +++ b/manager/app/src/main/res/drawable/ic_sus.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/manager/app/src/main/res/values-in/strings.xml b/manager/app/src/main/res/values-in/strings.xml index afe50176..6c4eba14 100644 --- a/manager/app/src/main/res/values-in/strings.xml +++ b/manager/app/src/main/res/values-in/strings.xml @@ -66,6 +66,8 @@ Gagal membarui Profil pada %s Melepas Modul secara bawaan Menggunakan \"Umount Modul\" secara universal pada Profil Aplikasi. Jika diaktifkan, akan menghapus semua modifikasi sistem untuk aplikasi yang tidak memiliki set profil. + Sembunyikan hook kprobe + Ini menonaktifkan hook kprobe yang dibuat oleh ksu, dan sebagai gantinya, hook inline non-kprobe akan diaktifkan, sama seperti implementasi untuk kernel non-gki yang tidak mendukung kprobe. Aktifkan opsi ini agar KernelSU dapat memulihkan kembali berkas termodifikasi oleh modul pada aplikasi ini. Domain Aturan diff --git a/userspace/ksud/bin/.gitignore b/userspace/ksud/bin/.gitignore index 1464b7ed..c8b95e0e 100644 --- a/userspace/ksud/bin/.gitignore +++ b/userspace/ksud/bin/.gitignore @@ -1 +1,2 @@ -**/*.ko \ No newline at end of file +**/*.ko +susfsd \ No newline at end of file diff --git a/userspace/ksud/src/assets.rs b/userspace/ksud/src/assets.rs index e8255c82..f7623bbe 100644 --- a/userspace/ksud/src/assets.rs +++ b/userspace/ksud/src/assets.rs @@ -8,6 +8,7 @@ use crate::{defs::BINARY_DIR, utils}; pub const RESETPROP_PATH: &str = concatcp!(BINARY_DIR, "resetprop"); pub const BUSYBOX_PATH: &str = concatcp!(BINARY_DIR, "busybox"); pub const BOOTCTL_PATH: &str = concatcp!(BINARY_DIR, "bootctl"); +pub const SUSFSD_PATH: &str = concatcp!(BINARY_DIR, "susfsd"); #[cfg(all(target_arch = "x86_64", target_os = "android"))] #[derive(RustEmbed)] diff --git a/userspace/ksud_overlayfs/bin/.gitignore b/userspace/ksud_overlayfs/bin/.gitignore new file mode 100644 index 00000000..879d7ba9 --- /dev/null +++ b/userspace/ksud_overlayfs/bin/.gitignore @@ -0,0 +1,2 @@ +**/*.ko +susfsd diff --git a/userspace/ksud_overlayfs/src/assets.rs b/userspace/ksud_overlayfs/src/assets.rs new file mode 100644 index 00000000..250fc63c --- /dev/null +++ b/userspace/ksud_overlayfs/src/assets.rs @@ -0,0 +1,52 @@ +use anyhow::Result; +use const_format::concatcp; +use rust_embed::RustEmbed; +use std::path::Path; + +use crate::{defs::BINARY_DIR, utils}; + +pub const RESETPROP_PATH: &str = concatcp!(BINARY_DIR, "resetprop"); +pub const BUSYBOX_PATH: &str = concatcp!(BINARY_DIR, "busybox"); +pub const BOOTCTL_PATH: &str = concatcp!(BINARY_DIR, "bootctl"); +pub const SUSFSD_PATH: &str = concatcp!(BINARY_DIR, "susfsd"); + +#[cfg(all(target_arch = "x86_64", target_os = "android"))] +#[derive(RustEmbed)] +#[folder = "bin/x86_64"] +struct Asset; + +// IF NOT x86_64 ANDROID, ie. macos, linux, windows, always use aarch64 +#[cfg(not(all(target_arch = "x86_64", target_os = "android")))] +#[derive(RustEmbed)] +#[folder = "bin/aarch64"] +struct Asset; + +pub fn ensure_binaries(ignore_if_exist: bool) -> Result<()> { + for file in Asset::iter() { + if file == "ksuinit" || file.ends_with(".ko") { + // don't extract ksuinit and kernel modules + continue; + } + let asset = Asset::get(&file).ok_or(anyhow::anyhow!("asset not found: {}", file))?; + utils::ensure_binary(format!("{BINARY_DIR}{file}"), &asset.data, ignore_if_exist)? + } + Ok(()) +} + +pub fn copy_assets_to_file(name: &str, dst: impl AsRef) -> Result<()> { + let asset = Asset::get(name).ok_or(anyhow::anyhow!("asset not found: {}", name))?; + std::fs::write(dst, asset.data)?; + Ok(()) +} + +pub fn list_supported_kmi() -> Result> { + let mut list = Vec::new(); + for file in Asset::iter() { + // kmi_name = "xxx_kernelsu.ko" + if let Some(kmi) = file.strip_suffix("_kernelsu.ko") { + list.push(kmi.to_string()); + } + } + Ok(list) +} + diff --git a/userspace/susfsd/.gitignore b/userspace/susfsd/.gitignore new file mode 100644 index 00000000..720289cc --- /dev/null +++ b/userspace/susfsd/.gitignore @@ -0,0 +1,2 @@ +/obj +/libs diff --git a/userspace/susfsd/jni/Android.mk b/userspace/susfsd/jni/Android.mk new file mode 100644 index 00000000..e805f0b4 --- /dev/null +++ b/userspace/susfsd/jni/Android.mk @@ -0,0 +1,6 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := susfsd +LOCAL_SRC_FILES := susfsd.c +include $(BUILD_EXECUTABLE) diff --git a/userspace/susfsd/jni/Application.mk b/userspace/susfsd/jni/Application.mk new file mode 100644 index 00000000..61d31236 --- /dev/null +++ b/userspace/susfsd/jni/Application.mk @@ -0,0 +1,3 @@ +APP_ABI := arm64-v8a +APP_PLATFORM := android-24 +APP_STL := none diff --git a/userspace/susfsd/jni/susfsd.c b/userspace/susfsd/jni/susfsd.c new file mode 100644 index 00000000..61111f46 --- /dev/null +++ b/userspace/susfsd/jni/susfsd.c @@ -0,0 +1,239 @@ +#include +#include +#include +#include +#include +#include +#include + +#define KERNEL_SU_OPTION 0xDEADBEEF + +#define CMD_SUSFS_SHOW_VERSION 0x555e1 +#define CMD_SUSFS_SHOW_ENABLED_FEATURES 0x555e2 +#define CMD_SUSFS_SHOW_VARIANT 0x555e3 +#define CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE 0x555e4 +#define CMD_SUSFS_IS_SUS_SU_READY 0x555f0 +#define CMD_SUSFS_SUS_SU 0x60000 + +#define SUS_SU_DISABLED 0 +#define SUS_SU_WITH_HOOKS 2 + +struct st_sus_su { + int mode; +}; + +int enable_sus_su(int last_working_mode, int target_working_mode) { + struct st_sus_su info; + int error = -1; + + if (target_working_mode == SUS_SU_WITH_HOOKS) { + info.mode = SUS_SU_WITH_HOOKS; + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SUS_SU, &info, NULL, &error); + if (error) { + if (error == 1) { + } else if (error == 2) { + } + return error; + } + printf("[+] sus_su mode 2 is enabled\n"); + } else if (target_working_mode == SUS_SU_DISABLED) { + info.mode = SUS_SU_DISABLED; + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SUS_SU, &info, NULL, &error); + if (error) { + if (error == 1) { + } + return error; + } + printf("[+] sus_su mode 0 is enabled\n"); + } else { + return 1; + } + return 0; +} + +int main(int argc, char *argv[]) { + int error = -1; + char support[16]; + char version[16]; + char variant[16]; + + + + // Check for arguments + if (argc < 2) { + fprintf(stderr, "Usage: %s |>\n", argv[0]); + return 1; + } + + if (strcmp(argv[1], "version") == 0) { + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_VERSION, version, NULL, &error); + if (!error) { + printf("%s\n", version); + } else { + printf("Invalid\n"); + } + } else if (strcmp(argv[1], "variant") == 0) { + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_VARIANT, variant, NULL, &error); + if (!error) { + printf("%s\n", variant); + } else { + printf("Invalid\n"); + } + } else if (strcmp(argv[1], "features") == 0) { + char *enabled_features_buf = malloc(getpagesize() * 2); + char *ptr_buf; + unsigned long enabled_features; + int str_len; + + if (!enabled_features_buf) { + perror("malloc"); + return -ENOMEM; + } + ptr_buf = enabled_features_buf; + + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_ENABLED_FEATURES, &enabled_features, NULL, &error); + if (!error) { + if (enabled_features & (1 << 0)) { + str_len = strlen("CONFIG_KSU_SUSFS_SUS_PATH\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_PATH\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 1)) { + str_len = strlen("CONFIG_KSU_SUSFS_SUS_MOUNT\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_MOUNT\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 2)) { + str_len = strlen("CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 3)) { + str_len = strlen("CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 4)) { + str_len = strlen("CONFIG_KSU_SUSFS_SUS_KSTAT\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_KSTAT\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 5)) { + str_len = strlen("CONFIG_KSU_SUSFS_SUS_OVERLAYFS\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_OVERLAYFS\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 6)) { + str_len = strlen("CONFIG_KSU_SUSFS_TRY_UMOUNT\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_TRY_UMOUNT\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 7)) { + str_len = strlen("CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 8)) { + str_len = strlen("CONFIG_KSU_SUSFS_SPOOF_UNAME\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SPOOF_UNAME\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 9)) { + str_len = strlen("CONFIG_KSU_SUSFS_ENABLE_LOG\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_ENABLE_LOG\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 10)) { + str_len = strlen("CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 11)) { + str_len = strlen("CONFIG_KSU_SUSFS_SPOOF_BOOTCONFIG\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SPOOF_BOOTCONFIG\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 12)) { + str_len = strlen("CONFIG_KSU_SUSFS_OPEN_REDIRECT\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_OPEN_REDIRECT\n", str_len); + ptr_buf += str_len; + } + if (enabled_features & (1 << 13)) { + str_len = strlen("CONFIG_KSU_SUSFS_SUS_SU\n"); + strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_SU\n", str_len); + ptr_buf += str_len; + } + printf("%s", enabled_features_buf); + free(enabled_features_buf); + } else { + printf("Invalid\n"); + } + } else if (strcmp(argv[1], "support") == 0) { + unsigned long enabled_features; + int any_feature_enabled = 0; + + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_ENABLED_FEATURES, &enabled_features, NULL, &error); + if (!error) { + if (enabled_features & ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | + (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | + (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | + (1 << 12) | (1 << 13))) { + any_feature_enabled = 1; + } + if (any_feature_enabled) { + printf("Supported\n"); + } else { + printf("Unsupported\n"); + } + } else { + printf("Unsupported\n"); + } + } else if (argc == 3 && !strcmp(argv[1], "sus_su")) { + int last_working_mode = 0; + int target_working_mode; + char* endptr; + + prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE, &last_working_mode, NULL, &error); + if (error) + return error; + if (!strcmp(argv[2], "mode")) { + printf("%d\n", last_working_mode); + return 0; + } + target_working_mode = strtol(argv[2], &endptr, 10); + if (*endptr != '\0') { + return 1; + } + if (target_working_mode == SUS_SU_WITH_HOOKS) { + bool is_sus_su_ready; + prctl(KERNEL_SU_OPTION, CMD_SUSFS_IS_SUS_SU_READY, &is_sus_su_ready, NULL, &error); + if (error) + return error; + if (!is_sus_su_ready) { + printf("[-] sus_su mode %d has to be run during or after service stage\n", SUS_SU_WITH_HOOKS); + return 1; + } + if (last_working_mode == SUS_SU_DISABLED) { + error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS); + } else if (last_working_mode == SUS_SU_WITH_HOOKS) { + printf("[-] sus_su is already in mode %d\n", last_working_mode); + return 1; + } else { + error = enable_sus_su(last_working_mode, SUS_SU_DISABLED); + if (!error) + error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS); + } + } else if (target_working_mode == SUS_SU_DISABLED) { + if (last_working_mode == SUS_SU_DISABLED) { + printf("[-] sus_su is already in mode %d\n", last_working_mode); + return 1; + } + error = enable_sus_su(last_working_mode, SUS_SU_DISABLED); + } + } else { + fprintf(stderr, "Invalid argument: %s\n", argv[1]); + return 1; + } + + return 0; +}