├── gradle.properties ├── module ├── .gitignore └── src │ ├── META-INF │ └── com │ │ └── google │ │ └── android │ │ ├── updater-script │ │ └── update-binary │ ├── uninstall.sh │ ├── module.prop │ ├── post-mount.sh │ ├── sepolicy.rule │ ├── verify.sh │ ├── service.sh │ └── post-fs-data.sh ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── pull_request.yml │ └── issue_template.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ci.yml │ └── trusted_ci.yml ├── loader ├── src │ ├── ptracer │ │ ├── mount.h │ │ ├── init.h │ │ ├── plt.cpp │ │ ├── monitor.h │ │ ├── breakpoint.h │ │ ├── main.c │ │ └── utils.h │ ├── injector │ │ ├── zygisk.hpp │ │ ├── entry.cpp │ │ ├── solist.h │ │ ├── art_method.hpp │ │ ├── init.c │ │ └── clear.c │ ├── common │ │ ├── misc.c │ │ ├── utils.cpp │ │ └── socket_utils.c │ ├── include │ │ ├── misc.h │ │ ├── rules.hpp │ │ ├── umount.hpp │ │ ├── socket_utils.h │ │ ├── logging.h │ │ ├── utils.hpp │ │ ├── daemon.h │ │ └── elf_util.h │ ├── external │ │ └── CMakeLists.txt │ └── CMakeLists.txt └── build.gradle.kts ├── .gitignore ├── webroot ├── fonts │ ├── poppins.ttf │ └── header.css ├── assets │ ├── back.svg │ ├── close.svg │ ├── home.svg │ ├── module.svg │ ├── delete.svg │ ├── content.svg │ ├── expand.svg │ ├── mark.svg │ ├── tick.svg │ ├── error.svg │ ├── warn.svg │ ├── ec-icon.svg │ ├── settings.svg │ └── action.svg ├── js │ ├── errorScreen.js │ ├── themes │ │ ├── lightNavbar.js │ │ ├── darkNavbar.js │ │ ├── amoled.js │ │ ├── monochrome.js │ │ ├── lightIcon.js │ │ ├── dark.js │ │ └── light.js │ ├── restoreError.js │ ├── translate │ │ ├── modules.js │ │ ├── settings.js │ │ ├── actions.js │ │ └── home.js │ ├── browserRedirect.js │ ├── errorCatcher.js │ ├── switcher │ │ └── fontChanger.js │ ├── smallPageDesabler.js │ ├── monitorActions.js │ ├── navbar.js │ ├── smallPage │ │ ├── language.js │ │ ├── errorHistory.js │ │ └── theme.js │ ├── language.js │ └── kernelsu.js ├── assets_light │ ├── home.svg │ ├── module.svg │ ├── settings.svg │ └── action.svg ├── css │ ├── error.css │ └── icons.css └── lang │ ├── zh_CN.json │ ├── ja_JP.json │ ├── ar_EG.json │ ├── en_US.json │ ├── tr_TR.json │ ├── ms_MS.json │ ├── uk_UA.json │ ├── id_ID.json │ ├── ru_RU.json │ ├── de_DE.json │ ├── nl_NL.json │ ├── vi_VN.json │ ├── it_IT.json │ ├── es_AR.json │ ├── es_ES.json │ ├── es_MX.json │ ├── pt_BR.json │ └── fr_FR.json ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── libs.versions.toml ├── zygiskd └── src │ ├── companion.h │ ├── zygiskd.h │ ├── root_impl │ ├── apatch.h │ ├── magisk.h │ ├── kernelsu.h │ ├── common.h │ ├── common.c │ └── apatch.c │ ├── constants.h │ ├── main.c │ ├── utils.cpp │ └── companion.c ├── .gitmodules ├── settings.gradle.kts ├── TRANSLATOR.md ├── gradlew.bat └── READMEs ├── README_ja-JP.md ├── README_pt-BR.md ├── README_id-ID.md └── README_vi-VN.md /gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=false 2 | -------------------------------------------------------------------------------- /module/.gitignore: -------------------------------------------------------------------------------- 1 | public_key 2 | private_key 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /module/src/META-INF/com/google/android/updater-script: -------------------------------------------------------------------------------- 1 | #MAGISK 2 | -------------------------------------------------------------------------------- /loader/src/ptracer/mount.h: -------------------------------------------------------------------------------- 1 | 2 | void mount_ns_main(char **argv); 3 | void mount_ns_private(); 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | .cxx 4 | .vscode 5 | build 6 | local.properties 7 | Cargo.lock 8 | -------------------------------------------------------------------------------- /webroot/fonts/poppins.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nampud/ReZygisk/HEAD/webroot/fonts/poppins.ttf -------------------------------------------------------------------------------- /webroot/fonts/header.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Poppins"; 3 | src: url("./poppins.ttf"); 4 | } -------------------------------------------------------------------------------- /module/src/uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | export TMP_PATH=/data/adb/nrezygisk 4 | 5 | # rm -rf $TMP_PATH -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nampud/ReZygisk/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /zygiskd/src/companion.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPANION_H 2 | #define COMPANION_H 3 | 4 | void companion_entry(int fd); 5 | 6 | #endif /* COMPANION_H */ 7 | -------------------------------------------------------------------------------- /zygiskd/src/zygiskd.h: -------------------------------------------------------------------------------- 1 | #ifndef ZYGISKD_H 2 | #define ZYGISKD_H 3 | 4 | void zygiskd_start(char *restrict argv[]); 5 | 6 | #endif /* ZYGISKD_H */ 7 | -------------------------------------------------------------------------------- /webroot/assets/back.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /module/src/module.prop: -------------------------------------------------------------------------------- 1 | id=${moduleId} 2 | name=${moduleName} 3 | version=${versionName} 4 | versionCode=${versionCode} 5 | author=Unofficial fork, upstream by PerformanC Org 6 | description=Standalone implementation of Zygisk. 7 | -------------------------------------------------------------------------------- /webroot/js/errorScreen.js: -------------------------------------------------------------------------------- 1 | const button = document.getElementById('esc-copy-button') 2 | const log = document.getElementById('esc-log') 3 | 4 | button.addEventListener('click', () => { 5 | navigator.clipboard.writeText(log.innerHTML) 6 | }) -------------------------------------------------------------------------------- /webroot/assets/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webroot/assets/home.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "LSPlt"] 2 | path = loader/src/external/lsplt 3 | url = https://github.com/PerformanC/LSPlt 4 | [submodule "loader/src/external/xz-embedded"] 5 | path = loader/src/external/xz-embedded 6 | url = https://github.com/tukaani-project/xz-embedded.git 7 | -------------------------------------------------------------------------------- /loader/src/injector/zygisk.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | extern void *start_addr; 6 | extern size_t block_size; 7 | 8 | void clean_mounts(char **argv, char **envp); 9 | 10 | void hook_functions(); 11 | 12 | extern "C" void send_seccomp_event(); 13 | -------------------------------------------------------------------------------- /webroot/assets_light/home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /loader/src/common/misc.c: -------------------------------------------------------------------------------- 1 | int parse_int(const char *str) { 2 | int val = 0; 3 | 4 | char *c = (char *)str; 5 | while (*c) { 6 | if (*c > '9' || *c < '0') 7 | return -1; 8 | 9 | val = val * 10 + *c - '0'; 10 | c++; 11 | } 12 | 13 | return val; 14 | } 15 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /loader/src/ptracer/init.h: -------------------------------------------------------------------------------- 1 | #ifndef INIT_H 2 | #define INIT_H 3 | 4 | #include 5 | 6 | extern bool init_injected; 7 | extern bool init_hooked; 8 | extern int init_sock; 9 | void init_inject(); 10 | void init_suspend_hooks(); 11 | bool init_resume_hooks(); 12 | void init_went_well(); 13 | 14 | 15 | #endif /* INIT_H */ -------------------------------------------------------------------------------- /webroot/js/themes/lightNavbar.js: -------------------------------------------------------------------------------- 1 | export function setLightNav() { 2 | document.getElementById('ni_home').classList.add('light') 3 | document.getElementById('ni_modules').classList.add('light') 4 | document.getElementById('ni_actions').classList.add('light') 5 | document.getElementById('ni_settings').classList.add('light') 6 | } 7 | -------------------------------------------------------------------------------- /webroot/js/themes/darkNavbar.js: -------------------------------------------------------------------------------- 1 | export function setDarkNav() { 2 | document.getElementById('ni_home').classList.remove('light') 3 | document.getElementById('ni_modules').classList.remove('light') 4 | document.getElementById('ni_actions').classList.remove('light') 5 | document.getElementById('ni_settings').classList.remove('light') 6 | } -------------------------------------------------------------------------------- /zygiskd/src/root_impl/apatch.h: -------------------------------------------------------------------------------- 1 | #ifndef APATCH_H 2 | #define APATCH_H 3 | 4 | #include "../constants.h" 5 | 6 | void apatch_get_existence(struct root_impl_state *state); 7 | 8 | bool apatch_uid_granted_root(uid_t uid); 9 | 10 | bool apatch_uid_should_umount(uid_t uid); 11 | 12 | bool apatch_uid_is_manager(uid_t uid); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /webroot/js/restoreError.js: -------------------------------------------------------------------------------- 1 | const errorh_panel = document.getElementById('errorh_panel') 2 | let sys_error = localStorage.getItem('/system/error') 3 | 4 | if (!sys_error) { 5 | localStorage.setItem('/system/error', '') 6 | 7 | sys_error = localStorage.getItem('/system/error') 8 | } 9 | 10 | if (sys_error.length !== 0) errorh_panel.innerHTML = sys_error -------------------------------------------------------------------------------- /loader/src/include/misc.h: -------------------------------------------------------------------------------- 1 | #ifndef MISC_H 2 | #define MISC_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif /* __cplusplus */ 7 | 8 | /* 9 | * Bionic's atoi runs through strtol(). 10 | * Use our own implementation for faster conversion. 11 | */ 12 | int parse_int(const char *str); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif /* __cplusplus */ 17 | 18 | #endif /* MISC_H */ -------------------------------------------------------------------------------- /webroot/assets/module.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | agp = "8.2.0" 3 | kotlin = "1.9.22" 4 | 5 | [plugins] 6 | agp-lib = { id = "com.android.library", version.ref = "agp" } 7 | kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } 8 | lsplugin-jgit = { id = "org.lsposed.lsplugin.jgit", version = "1.1" } 9 | rust-android = { id = "org.mozilla.rust-android-gradle.rust-android", version = "0.9.3" } 10 | -------------------------------------------------------------------------------- /loader/src/include/rules.hpp: -------------------------------------------------------------------------------- 1 | #ifndef REZYGISK_RULES_HPP 2 | #define REZYGISK_RULES_HPP 3 | 4 | #include 5 | 6 | bool rules_reload(); 7 | void rules_unload(); 8 | 9 | bool rules_should_deny(uid_t uid, const std::string &process, const std::string &data_dir, 10 | bool on_denylist); 11 | 12 | bool rules_should_umount(std::string &mountpoint); 13 | 14 | #endif //REZYGISK_RULES_HPP 15 | -------------------------------------------------------------------------------- /webroot/assets/delete.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webroot/assets_light/module.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /zygiskd/src/root_impl/magisk.h: -------------------------------------------------------------------------------- 1 | #ifndef MAGISK_H 2 | #define MAGISK_H 3 | 4 | #include "../constants.h" 5 | 6 | enum magisk_variants { 7 | MOfficial, 8 | MKitsune 9 | }; 10 | 11 | void magisk_get_existence(struct root_impl_state *state); 12 | 13 | bool magisk_uid_granted_root(uid_t uid); 14 | 15 | bool magisk_uid_should_umount(const char *const process); 16 | 17 | bool magisk_uid_is_manager(uid_t uid); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /zygiskd/src/root_impl/kernelsu.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNELSU_H 2 | #define KERNELSU_H 3 | 4 | #include "../constants.h" 5 | 6 | enum kernelsu_variants { 7 | KOfficial, 8 | KNext 9 | }; 10 | 11 | void ksu_get_existence(struct root_impl_state *state); 12 | 13 | bool ksu_uid_granted_root(uid_t uid); 14 | 15 | bool ksu_uid_should_umount(uid_t uid); 16 | 17 | bool ksu_uid_is_manager(uid_t uid); 18 | 19 | void ksu_cleanup(void); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /module/src/post-mount.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | DEBUG=@DEBUG@ 4 | 5 | MODDIR=${0%/*} 6 | if [ "$ZYGISK_ENABLED" ]; then 7 | exit 0 8 | fi 9 | 10 | cd "$MODDIR" 11 | 12 | CPU_ABIS=$(getprop ro.product.cpu.abilist) 13 | 14 | if [[ "$CPU_ABIS" == *"arm64-v8a"* || "$CPU_ABIS" == *"x86_64"* ]]; then 15 | ./bin/zygisk-ptrace64 mount_ns_private 16 | else 17 | # INFO: Device is 32-bit only 18 | 19 | ./bin/zygisk-ptrace32 mount_ns_private 20 | fi -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Changes 2 | 3 | Write here about the changes you've made 4 | 5 | ## Why 6 | 7 | Write here why you think this should be merged 8 | 9 | ## Checkmarks 10 | 11 | - [ ] The modified functions have been tested. 12 | - [ ] Used the same indentation as the rest of the project. 13 | - [ ] Updated documentation (changelog). 14 | 15 | ## Additional information 16 | 17 | If you have any additional information, write it here 18 | -------------------------------------------------------------------------------- /webroot/assets/content.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webroot/assets/expand.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webroot/assets/mark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webroot/assets/tick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /webroot/js/translate/modules.js: -------------------------------------------------------------------------------- 1 | export function translateModulesPage(new_translations) { 2 | document.getElementById('panel_modules_header').innerHTML = new_translations.page.modules.header 3 | document.getElementById('modules_list_not_avaliable').innerHTML = new_translations.page.modules.notAvaliable 4 | 5 | /* INFO: arch type */ 6 | const module_element_arch = document.getElementsByClassName('arch_desc') 7 | for (const module of module_element_arch) { 8 | module.innerHTML = new_translations.page.modules.arch 9 | } 10 | } -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 2 | 3 | pluginManagement { 4 | repositories { 5 | google() 6 | mavenCentral() 7 | gradlePluginPortal() 8 | } 9 | } 10 | 11 | dependencyResolutionManagement { 12 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | } 18 | 19 | rootProject.name = "ReZygisk" 20 | include( 21 | ":loader", 22 | ":module", 23 | ":zygiskd", 24 | ) 25 | -------------------------------------------------------------------------------- /webroot/assets/error.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webroot/assets/warn.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webroot/js/browserRedirect.js: -------------------------------------------------------------------------------- 1 | import { exec } from './kernelsu.js' 2 | 3 | document.addEventListener('click', async (event) => { 4 | const getLink = event.target.getAttribute('credit-link') 5 | if (!getLink || typeof getLink !== 'string') return; 6 | 7 | const ptrace64Cmd = await exec(`am start -a android.intent.action.VIEW -d https://${getLink}`).catch(() => { 8 | return window.open(`https://${getLink}`, "_blank", 'toolbar=0,location=0,menubar=0') 9 | }) 10 | if (ptrace64Cmd.errno !== 0) return window.open(`https://${getLink}`, "_blank", 'toolbar=0,location=0,menubar=0') 11 | }, false) -------------------------------------------------------------------------------- /webroot/js/errorCatcher.js: -------------------------------------------------------------------------------- 1 | function setError(place, issue) { 2 | const fullErrorLog = setErrorData(`${place}: ${issue}`) 3 | document.getElementById('errorh_panel').innerHTML = fullErrorLog 4 | } 5 | 6 | function setErrorData(errorLog) { 7 | const getPrevious = localStorage.getItem('/system/error') 8 | const finalLog = getPrevious && getPrevious.length !== 0 ? getPrevious + `\n` + errorLog : errorLog 9 | 10 | localStorage.setItem('/system/error', finalLog) 11 | return finalLog 12 | } 13 | 14 | if (window.onerror) window.onerror = (err) => { 15 | setError('WebUI', err.stack ? err.stack : err.message) 16 | } -------------------------------------------------------------------------------- /webroot/assets/ec-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /loader/src/ptracer/plt.cpp: -------------------------------------------------------------------------------- 1 | #include "../external/lsplt/lsplt/src/main/jni/elf_util.hpp" 2 | #include "../external/lsplt/lsplt/src/main/jni/elf_util.cc" 3 | 4 | /* INFO: This file is an ugly hack */ 5 | 6 | extern "C" void* elfplt_init(uintptr_t base_addr) { 7 | auto *elf = new Elf(base_addr); 8 | if (!elf->Valid()) { 9 | delete elf; 10 | return nullptr; 11 | } 12 | return (void*) elf; 13 | } 14 | 15 | extern "C" void* elfplt_addr(void *v_elf, const char *name) { 16 | Elf *elf = (Elf*) v_elf; 17 | auto addrs = elf->FindPltAddr(name); 18 | if (!addrs.empty()) { 19 | return (void*) addrs[0]; 20 | } 21 | return nullptr; 22 | } -------------------------------------------------------------------------------- /loader/src/ptracer/monitor.h: -------------------------------------------------------------------------------- 1 | #ifndef MONITOR_H 2 | #define MONITOR_H 3 | 4 | #include 5 | 6 | void init_monitor(int ready_fd); 7 | 8 | bool trace_zygote(int pid); 9 | 10 | bool should_stop_inject32(); 11 | bool should_stop_inject64(); 12 | 13 | enum rezygiskd_command { 14 | START = 1, 15 | STOP = 2, 16 | EXIT = 3, 17 | 18 | /* sent from daemon */ 19 | ZYGOTE64_INJECTED = 4, 20 | ZYGOTE32_INJECTED = 5, 21 | DAEMON64_SET_INFO = 6, 22 | DAEMON32_SET_INFO = 7, 23 | DAEMON64_SET_ERROR_INFO = 8, 24 | DAEMON32_SET_ERROR_INFO = 9, 25 | SYSTEM_SERVER_STARTED = 10 26 | }; 27 | 28 | int send_control_command(enum rezygiskd_command cmd); 29 | 30 | #endif /* MONITOR_H */ -------------------------------------------------------------------------------- /loader/src/ptracer/breakpoint.h: -------------------------------------------------------------------------------- 1 | #ifndef BREAKPOINT_H 2 | #define BREAKPOINT_H 3 | 4 | #include "utils.h" 5 | 6 | struct init_fork { 7 | pid_t pid; 8 | void *next_breakpoint; 9 | long old_data; 10 | struct user_regs_struct *restore_regs; 11 | int stop; 12 | }; 13 | 14 | void attr_hook_fork_init(struct init_fork *proc); 15 | void attr_hook_fork_free(struct init_fork *proc); 16 | void attr_hook_fork_realloc(struct init_fork **procs, size_t old_len, size_t new_len); 17 | void attr_hook_prepare(void); 18 | void attr_hook_place_first_breakpoint(struct init_fork *proc); 19 | bool attr_hook_handle(struct init_fork *proc); 20 | void attr_hook_bad_status(); 21 | 22 | #endif /* BREAKPOINT_H */ 23 | -------------------------------------------------------------------------------- /loader/src/include/umount.hpp: -------------------------------------------------------------------------------- 1 | #ifndef REZYGISK_UMOUNT_HPP 2 | #define REZYGISK_UMOUNT_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "daemon.h" 9 | 10 | static struct sockaddr_un umountd_sock_addr = { 11 | .sun_family = AF_UNIX, 12 | .sun_path = TMP_PATH "/tmp/umountd.sock\0" 13 | }; 14 | 15 | struct ToUmount { 16 | std::string mountPoint; 17 | int mountId; 18 | std::string majorMinor; 19 | bool get_fd(int &mnt_fd, std::string &fd_path) const; 20 | }; 21 | 22 | enum umount_filter { 23 | UmountsGetAll, 24 | UmountsNoPrivate 25 | }; 26 | 27 | std::vector umount_list(umount_filter filter); 28 | 29 | #endif //REZYGISK_UMOUNT_HPP 30 | -------------------------------------------------------------------------------- /loader/src/external/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(external) 2 | 3 | OPTION(LSPLT_BUILD_SHARED OFF) 4 | add_subdirectory(lsplt/lsplt/src/main/jni) 5 | 6 | add_library(phmap INTERFACE) 7 | target_include_directories(phmap INTERFACE parallel-hashmap) 8 | target_compile_options(phmap INTERFACE -Wno-unused-value) 9 | 10 | add_library(xz-embedded STATIC 11 | xz-embedded/linux/lib/xz/xz_crc32.c 12 | xz-embedded/linux/lib/xz/xz_crc64.c 13 | xz-embedded/linux/lib/xz/xz_dec_lzma2.c 14 | xz-embedded/linux/lib/xz/xz_dec_stream.c 15 | ) 16 | target_include_directories(xz-embedded PUBLIC xz-embedded/linux/include/linux) 17 | target_include_directories(xz-embedded PRIVATE xz-embedded/userspace) 18 | target_compile_options(xz-embedded PUBLIC -DXZ_USE_CRC64) 19 | -------------------------------------------------------------------------------- /webroot/assets/settings.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webroot/assets_light/settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /zygiskd/src/root_impl/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #include 5 | 6 | #include "../constants.h" 7 | 8 | enum root_impls { 9 | None, 10 | Multiple, 11 | KernelSU, 12 | APatch, 13 | Magisk 14 | }; 15 | 16 | struct root_impl_state { 17 | enum RootImplState state; 18 | uint8_t variant; 19 | }; 20 | 21 | struct root_impl { 22 | enum root_impls impl; 23 | uint8_t variant; 24 | }; 25 | 26 | #define LONGEST_ROOT_IMPL_NAME sizeof("Magisk Official") 27 | 28 | void root_impls_setup(void); 29 | 30 | void get_impl(struct root_impl *uimpl); 31 | 32 | bool uid_granted_root(uid_t uid); 33 | 34 | bool uid_should_umount(uid_t uid, const char *const process); 35 | 36 | bool uid_is_manager(uid_t uid); 37 | 38 | void root_impl_cleanup(void); 39 | 40 | #endif /* COMMON_H */ 41 | -------------------------------------------------------------------------------- /loader/src/include/socket_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef SOCKET_UTILS_H 2 | #define SOCKET_UTILS_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | ssize_t read_n(int fd, void *buf, size_t n); 11 | 12 | ssize_t write_n(int fd, const void *buf, size_t n); 13 | 14 | int read_fd(int fd); 15 | 16 | ssize_t write_string(int fd, const char *str); 17 | 18 | char *read_string(int fd); 19 | 20 | #define write_func_def(type) \ 21 | ssize_t write_## type(int fd, type val) 22 | 23 | #define read_func_def(type) \ 24 | ssize_t read_## type(int fd, type *val) 25 | 26 | write_func_def(uint8_t); 27 | 28 | read_func_def(uint8_t); 29 | 30 | write_func_def(uint32_t); 31 | 32 | read_func_def(uint32_t); 33 | 34 | write_func_def(size_t); 35 | 36 | read_func_def(size_t); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | 42 | #endif /* SOCKET_UTILS_H */ -------------------------------------------------------------------------------- /loader/src/injector/entry.cpp: -------------------------------------------------------------------------------- 1 | #include "daemon.h" 2 | #include "logging.h" 3 | #include "solist.h" 4 | #include "zygisk.hpp" 5 | 6 | using namespace std; 7 | 8 | void *start_addr = nullptr; 9 | size_t block_size = 0; 10 | 11 | extern "C" [[gnu::visibility("default")]] 12 | void entry(void* addr, size_t size, char **argv, char **envp) { 13 | LOGD("Zygisk library injected, version %s", ZKSU_VERSION); 14 | 15 | start_addr = addr; 16 | block_size = size; 17 | 18 | if (argv && !rezygiskd_ping()) { 19 | LOGE("Zygisk daemon is not running"); 20 | 21 | return; 22 | } 23 | 24 | clean_mounts(argv, envp); 25 | 26 | LOGD("start plt hooking"); 27 | hook_functions(); 28 | 29 | solist_drop_so_path(addr, true); 30 | solist_reset_counters(1, 1); 31 | 32 | send_seccomp_event(); 33 | 34 | LOGD("Zygisk library execution done, addr: %p, size: %zu", addr, size); 35 | } 36 | -------------------------------------------------------------------------------- /loader/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.22.1) 2 | project("loader") 3 | 4 | find_package(cxx REQUIRED CONFIG) 5 | 6 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 7 | 8 | add_definitions(-DZKSU_VERSION=\"${ZKSU_VERSION}\") 9 | 10 | aux_source_directory(common COMMON_SRC_LIST) 11 | add_library(common STATIC ${COMMON_SRC_LIST}) 12 | target_include_directories(common PRIVATE include) 13 | target_link_libraries(common log xz-embedded cxx::cxx) 14 | 15 | aux_source_directory(injector INJECTOR_SRC_LIST) 16 | add_library(zygisk SHARED ${INJECTOR_SRC_LIST}) 17 | target_include_directories(zygisk PRIVATE include) 18 | target_link_libraries(zygisk cxx::cxx log common lsplt_static phmap) 19 | 20 | aux_source_directory(ptracer PTRACER_SRC_LIST) 21 | add_executable(libzygisk_ptrace.so ${PTRACER_SRC_LIST}) 22 | target_include_directories(libzygisk_ptrace.so PRIVATE include) 23 | target_link_libraries(libzygisk_ptrace.so log common cxx::cxx) 24 | add_subdirectory(external) 25 | -------------------------------------------------------------------------------- /webroot/css/error.css: -------------------------------------------------------------------------------- 1 | .e-container { 2 | background-color: black; 3 | z-index: 30; 4 | position: fixed; 5 | top: 0; 6 | bottom: 0; 7 | left: 0; 8 | right: 0; 9 | color: #fff; 10 | } 11 | 12 | .e-main { 13 | background-color: black; 14 | color: #fff; 15 | } 16 | 17 | .e-wrap { 18 | display: flex; 19 | align-items: center; 20 | overflow: auto; 21 | position: absolute; 22 | top: 0; 23 | left: 0; 24 | bottom: 0; 25 | right: 0; 26 | } 27 | 28 | .e-bg { 29 | background-color: black; 30 | color: #fff; 31 | } 32 | 33 | .e-card { 34 | margin: 30px; 35 | color: #fff; 36 | } 37 | 38 | .e-font { 39 | color: #ba1a1a; 40 | } 41 | 42 | .e-button { 43 | display: flex; 44 | align-items: center; 45 | justify-content: center; 46 | width: 120px; 47 | height: 40px; 48 | border-radius: 30px; 49 | background-color: #ba1a1a; 50 | color: black; 51 | transition: transform 0.1s ease-in-out; 52 | } 53 | 54 | .e-button:active { 55 | transform: scale(90%) 56 | } -------------------------------------------------------------------------------- /webroot/assets/action.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /loader/src/include/logging.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGGING_H 2 | #define LOGGING_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifndef LOG_TAG 9 | #ifdef __LP64__ 10 | #define LOG_TAG "zygisk-core64" 11 | #else 12 | #define LOG_TAG "zygisk-core32" 13 | #endif 14 | #endif 15 | 16 | #ifndef NDEBUG 17 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) 18 | #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) 19 | #else 20 | #define LOGD(...) 21 | #define LOGV(...) 22 | #endif 23 | 24 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 25 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) 26 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 27 | #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__) 28 | #define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno)) 29 | 30 | #endif /* LOGGING_H */ -------------------------------------------------------------------------------- /webroot/assets_light/action.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /webroot/js/switcher/fontChanger.js: -------------------------------------------------------------------------------- 1 | const switcher = document.getElementById('font_switcher') 2 | const rootCss = document.querySelector(':root') 3 | 4 | let sys_font = localStorage.getItem('/system/font') 5 | if (!sys_font) sys_font = setData('false') 6 | if (sys_font === 'true') { 7 | switcher.setAttribute('checked', '') 8 | 9 | setSystemFont() 10 | } 11 | 12 | switcher.addEventListener('click', () => { 13 | sys_font = setData(String(switcher.checked)) 14 | 15 | switcher.checked ? setSystemFont() : document.getElementById('font-tag').remove() 16 | }) 17 | 18 | function setSystemFont() { 19 | const headTag = document.getElementsByTagName('head')[0] 20 | const styleTag = document.createElement('style') 21 | 22 | styleTag.id = 'font-tag' 23 | headTag.appendChild(styleTag) 24 | styleTag.innerHTML = ` 25 | :root { 26 | --font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif 27 | }` 28 | } 29 | 30 | function setData(mode) { 31 | localStorage.setItem('/system/font', mode) 32 | 33 | return mode 34 | } -------------------------------------------------------------------------------- /webroot/js/smallPageDesabler.js: -------------------------------------------------------------------------------- 1 | export function smallPageDisabler(page_name, new_page, custom_page) { 2 | const navbar_data_tag = document.getElementById('cache-navbar-previous') 3 | const small_panel_data_tag = document.getElementById('cache-page-small-previous') 4 | 5 | document.getElementById(`small_panel_${page_name}`).classList.remove('show') 6 | small_panel_data_tag.removeAttribute('content') 7 | 8 | const previous = navbar_data_tag.getAttribute('content') 9 | 10 | /* INFO: Disable icon on old state */ 11 | const pre_input = document.getElementById(`n_${previous}`) 12 | const pre_background = document.getElementById(`nibg_${previous}`) 13 | 14 | pre_input.removeAttribute('checked') 15 | pre_background.classList.remove('show') 16 | 17 | /* INFO: Enable icon on new state */ 18 | const curr_input = document.getElementById(`n_${new_page}`) 19 | const i_background = document.getElementById(`nibg_${new_page}`) 20 | 21 | document.getElementById(`panel_${new_page}`).classList.toggle('show') 22 | curr_input.setAttribute('checked', '') 23 | i_background.classList.toggle('show') 24 | 25 | navbar_data_tag.setAttribute('content', custom_page ? custom_page : 'settings') 26 | } -------------------------------------------------------------------------------- /webroot/css/icons.css: -------------------------------------------------------------------------------- 1 | /* Dark */ 2 | #ni_home { 3 | background: url(../assets/home.svg); 4 | width: 24px; 5 | height: 24px; 6 | z-index: 10; 7 | } 8 | 9 | #ni_modules { 10 | background: url(../assets/module.svg); 11 | width: 24px; 12 | height: 24px; 13 | z-index: 10; 14 | } 15 | 16 | #ni_actions { 17 | background: url(../assets/action.svg); 18 | width: 24px; 19 | height: 24px; 20 | z-index: 10; 21 | } 22 | 23 | #ni_settings { 24 | background: url(../assets/settings.svg); 25 | width: 24px; 26 | height: 24px; 27 | z-index: 10; 28 | } 29 | 30 | #ec_icon { 31 | background: url(../assets/ec-icon.svg); 32 | z-index: 40; 33 | } 34 | 35 | /* Light */ 36 | #ni_home.light { 37 | background: url(../assets_light/home.svg); 38 | width: 24px; 39 | height: 24px; 40 | z-index: 10; 41 | } 42 | 43 | #ni_modules.light { 44 | background: url(../assets_light/module.svg); 45 | width: 24px; 46 | height: 24px; 47 | z-index: 10; 48 | } 49 | 50 | #ni_actions.light { 51 | background: url(../assets_light/action.svg); 52 | width: 24px; 53 | height: 24px; 54 | z-index: 10; 55 | } 56 | 57 | #ni_settings.light { 58 | background: url(../assets_light/settings.svg); 59 | width: 24px; 60 | height: 24px; 61 | z-index: 10; 62 | } 63 | -------------------------------------------------------------------------------- /loader/src/include/utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef REZYGISK_UTILS_HPP 2 | #define REZYGISK_UTILS_HPP 3 | 4 | #include 5 | 6 | struct MappedBuffer { 7 | char *data; 8 | size_t size; 9 | size_t capacity; 10 | 11 | MappedBuffer() : data(nullptr), size(0), capacity(0) {} 12 | 13 | MappedBuffer(MappedBuffer &&other) noexcept 14 | : data(other.data), size(other.size), capacity(other.capacity) { 15 | other.data = nullptr; 16 | other.size = 0; 17 | other.capacity = 0; 18 | } 19 | 20 | MappedBuffer &operator=(MappedBuffer &&other) noexcept { 21 | if (this != &other) { 22 | data = other.data; 23 | size = other.size; 24 | capacity = other.capacity; 25 | other.data = nullptr; 26 | other.size = 0; 27 | other.capacity = 0; 28 | } 29 | return *this; 30 | } 31 | 32 | bool grow(size_t target); 33 | 34 | void unmap(); 35 | 36 | bool file_read(const char *path, size_t expected_len); 37 | 38 | bool operator==(MappedBuffer const &rhs) const; 39 | 40 | MappedBuffer(const MappedBuffer &) = delete; 41 | 42 | MappedBuffer &operator=(const MappedBuffer &) = delete; 43 | }; 44 | 45 | #endif //REZYGISK_UTILS_HPP 46 | -------------------------------------------------------------------------------- /module/src/sepolicy.rule: -------------------------------------------------------------------------------- 1 | type zygisk_file file_type 2 | typeattribute zygisk_file mlstrustedobject 3 | allow zygote zygisk_file sock_file {read write} 4 | 5 | allow zygote magisk lnk_file read 6 | allow zygote unlabeled file {read open} 7 | allow zygote zygote capability sys_chroot 8 | allow zygote su dir search 9 | allow zygote su {lnk_file file} read 10 | 11 | allow zygote adb_data_file dir {search getattr} 12 | allow zygote adb_data_file file * 13 | allow zygote proc file {read open} 14 | allow zygote nsfs file {read open} 15 | allow zygote zygote process {execmem ptrace} 16 | allow system_server system_server process execmem 17 | allow zygote tmpfs file * 18 | allow zygote appdomain_tmpfs file * 19 | 20 | allow init zygote_exec file * 21 | allow init zygisk_file sock_file {read write} 22 | 23 | allow init magisk lnk_file read 24 | allow init unlabeled file {read open} 25 | allow init init capability sys_chroot 26 | allow init su dir search 27 | allow init su {lnk_file file} read 28 | 29 | allow init adb_data_file dir search 30 | allow init adb_data_file file * 31 | allow init proc file {read open} 32 | allow init nsfs file {read open} 33 | allow init init process execmem 34 | allow init tmpfs file * 35 | allow init appdomain_tmpfs file * 36 | allow init zygote unix_stream_socket * 37 | allow init zygote sock_file * 38 | allow init magisk unix_dgram_socket * 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/pull_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Ask for a new feature to be added 3 | title: "[FR]: " 4 | labels: ["enhancement", "not confirmed"] 5 | 6 | body: 7 | - type: textarea 8 | id: description 9 | attributes: 10 | label: Description 11 | description: A clear and concise description of what the feature is. 12 | validations: 13 | required: true 14 | 15 | - type: textarea 16 | id: reason 17 | attributes: 18 | label: Reason 19 | description: Why should this feature be added? 20 | validations: 21 | required: true 22 | 23 | - type: checkboxes 24 | id: terms 25 | attributes: 26 | label: Confirmations 27 | description: The following confirmations are required to open a feature request. 28 | options: 29 | - label: This feature is not already implemented. 30 | required: true 31 | - label: I have verified that this is not a duplicate feature request. 32 | required: true 33 | 34 | - type: checkboxes 35 | id: code_of_conduct 36 | attributes: 37 | label: Code of Conduct 38 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/PerformanC/contributing/blob/main/CODE_OF_CONDUCT.md) 39 | options: 40 | - label: I agree to follow this project's Code of Conduct 41 | required: true -------------------------------------------------------------------------------- /zygiskd/src/constants.h: -------------------------------------------------------------------------------- 1 | #ifndef CONSTANTS_H 2 | #define CONSTANTS_H 3 | 4 | #include 5 | 6 | #ifndef __cplusplus 7 | #define bool _Bool 8 | #define true 1 9 | #define false 0 10 | #endif 11 | 12 | #if (defined(__LP64__) || defined(_LP64)) 13 | #define lp_select(a, b) b 14 | #else 15 | #define lp_select(a, b) a 16 | #endif 17 | 18 | #define PROCESS_NAME_MAX_LEN 256 + 1 19 | 20 | #define ZYGOTE_INJECTED lp_select(5, 4) 21 | #define DAEMON_SET_INFO lp_select(7, 6) 22 | #define DAEMON_SET_ERROR_INFO lp_select(9, 8) 23 | #define SYSTEM_SERVER_STARTED 10 24 | 25 | enum DaemonSocketAction { 26 | PingHeartbeat = 0, 27 | GetProcessFlags = 1, 28 | GetInfo = 2, 29 | ReadModules = 3, 30 | RequestCompanionSocket = 4, 31 | GetModuleDir = 5, 32 | ZygoteRestart = 6, 33 | SystemServerStarted = 7, 34 | UpdateMountNamespace = 8 35 | }; 36 | 37 | enum ProcessFlags: uint32_t { 38 | PROCESS_GRANTED_ROOT = (1u << 0), 39 | PROCESS_ON_DENYLIST = (1u << 1), 40 | PROCESS_IS_MANAGER = (1u << 27), 41 | PROCESS_ROOT_IS_APATCH = (1u << 28), 42 | PROCESS_ROOT_IS_KSU = (1u << 29), 43 | PROCESS_ROOT_IS_MAGISK = (1u << 30), 44 | PROCESS_IS_FIRST_STARTED = (1u << 31) 45 | }; 46 | 47 | enum RootImplState { 48 | Supported, 49 | TooOld, 50 | Inexistent, 51 | Abnormal 52 | }; 53 | 54 | enum MountNamespaceState { 55 | Clean, 56 | Mounted 57 | }; 58 | 59 | #endif /* CONSTANTS_H */ 60 | -------------------------------------------------------------------------------- /TRANSLATOR.md: -------------------------------------------------------------------------------- 1 | # 🌎 Translators 2 | - **ar_EG** by [@ZG089](https://github.com/ZG089) 3 | - **de_DE** by [@Blazzycrafer](https://github.com/Blazzycrafter) 4 | - **en_US** by [@PerformanC (The PerformanC Organization)](https://github.com/PerformanC) 5 | - **es_AR** by [@Flopster101](https://github.com/Flopster101) 6 | - **es_ES** by [@LuchoModzzz](https://github.com/Lxchoooo) 7 | - **es_MX** by [@LuchoModzzz](https://github.com/Lxchoooo) 8 | - **fr_FR** by [@GhostFRR](https://github.com/GhostFRR) 9 | - **ja_JP** by [@Fyphen1223](https://github.com/Fyphen1223) & [@reindex-ot](https://github.com/reindex-ot) 10 | - **id_ID** by [@bpanca05](https://github.com/bpanca05) & [@LuckyKiddos](https://github.com/GuitarHeroStyles) 11 | - **it_IT** by [@thasave14](https://github.com/thasave14) 12 | - **pt_BR** by [@ThePedroo](https://github.com/ThePedroo) 13 | - **ro_RO** by [@ExtremeXT](https://github.com/ExtremeXT) 14 | - **ru_RU** by [@Emulond](https://github.com/Emulond) & [@AJleKcAHgP68](https://github.com/AJleKcAHgP68) 15 | - **tr_TR** by [@witchfuneral](https://github.com/witchfuneral) 16 | - **uk_UA** by [@Kittyskj](https://github.com/Kittyskj) 17 | - **vi_VN** by [@RainyXeon](https://github.com/RainyXeon) 18 | - **zh_CN** by [@Meltartica](https://github.com/Meltartica) & [@SheepChef](https://github.com/SheepChef) 19 | - **zh_TW** by [@Meltartica](https://github.com/Meltartica) 20 | 21 | > [!NOTE] 22 | > Want to add your translation? Go to [Crowdin](https://crowdin.com/project/rezygisk) and translate! 23 | -------------------------------------------------------------------------------- /webroot/js/themes/amoled.js: -------------------------------------------------------------------------------- 1 | import { setDarkNav } from './darkNavbar.js' 2 | 3 | const rootCss = document.querySelector(':root') 4 | 5 | /* INFO: Changes the icons to match the theme */ 6 | const close_icons = document.getElementsByClassName('close_icon') 7 | const expand_icons = document.getElementsByClassName('expander') 8 | const sp_lang_close = document.getElementById('sp_lang_close') 9 | const sp_theme_close = document.getElementById('sp_theme_close') 10 | 11 | export function setAmoled(chooseSet) { 12 | rootCss.style.setProperty('--background', '#000000') 13 | rootCss.style.setProperty('--font', '#d9d9d9') 14 | rootCss.style.setProperty('--desc', '#a9a9a9') 15 | rootCss.style.setProperty('--dim', '#0b0d0f') 16 | rootCss.style.setProperty('--icon', '#22292d') 17 | rootCss.style.setProperty('--icon-bc', '#171b1d') 18 | rootCss.style.setProperty('--desktop-navbar', '#111417') 19 | rootCss.style.setProperty('--desktop-navicon', '#1c2225') 20 | rootCss.style.setProperty('--button', 'var(--background)') 21 | 22 | if (chooseSet) setData('amoled') 23 | 24 | for (const close_icon of close_icons) { 25 | close_icon.innerHTML = '' 26 | } 27 | 28 | for (const expand_icon of expand_icons) { 29 | expand_icon.innerHTML = '' 30 | } 31 | 32 | sp_lang_close.innerHTML = '' 33 | sp_theme_close.innerHTML = '' 34 | setDarkNav() 35 | } 36 | 37 | function setData(mode) { 38 | localStorage.setItem('/system/theme', mode) 39 | 40 | return mode 41 | } -------------------------------------------------------------------------------- /webroot/js/themes/monochrome.js: -------------------------------------------------------------------------------- 1 | import { setDarkNav } from './darkNavbar.js' 2 | 3 | const rootCss = document.querySelector(':root') 4 | 5 | /* INFO: Changes the icons to match the theme */ 6 | const close_icons = document.getElementsByClassName('close_icon') 7 | const expand_icons = document.getElementsByClassName('expander') 8 | const sp_lang_close = document.getElementById('sp_lang_close') 9 | const sp_theme_close = document.getElementById('sp_theme_close') 10 | 11 | export function setMonochrome(chooseSet) { 12 | rootCss.style.setProperty('--background', '#141414') 13 | rootCss.style.setProperty('--font', '#ffffff') 14 | rootCss.style.setProperty('--desc', '#c9c9c9') 15 | rootCss.style.setProperty('--dim', '#1c1c1c') 16 | rootCss.style.setProperty('--icon', '#494949') 17 | rootCss.style.setProperty('--icon-bc', '#292929') 18 | rootCss.style.setProperty('--desktop-navbar', '#252525') 19 | rootCss.style.setProperty('--desktop-navicon', '#3a3a3a') 20 | rootCss.style.setProperty('--button', 'var(--background)') 21 | 22 | if (chooseSet) setData('monochrome') 23 | 24 | for (const close_icon of close_icons) { 25 | close_icon.innerHTML = '' 26 | } 27 | 28 | for (const expand_icon of expand_icons) { 29 | expand_icon.innerHTML = '' 30 | } 31 | 32 | sp_lang_close.innerHTML = '' 33 | sp_theme_close.innerHTML = '' 34 | setDarkNav() 35 | } 36 | 37 | function setData(mode) { 38 | localStorage.setItem('/system/theme', mode) 39 | 40 | return mode 41 | } -------------------------------------------------------------------------------- /webroot/js/monitorActions.js: -------------------------------------------------------------------------------- 1 | import { exec, toast } from './kernelsu.js' 2 | 3 | import { getTranslations } from './language.js' 4 | 5 | const monitor_start = document.getElementById('monitor_start_button') 6 | const monitor_stop = document.getElementById('monitor_stop_button') 7 | const monitor_pause = document.getElementById('monitor_pause_button') 8 | 9 | const monitor_status = document.getElementById('monitor_status'); 10 | 11 | (async () => { 12 | const sys_lang = localStorage.getItem('/system/language') 13 | const translations = await getTranslations(sys_lang || 'en_US') 14 | 15 | if (monitor_start) { 16 | monitor_start.addEventListener('click', () => { 17 | if (![ translations.page.actions.status.tracing, translations.page.actions.status.stopping, translations.page.actions.status.stopped ].includes(monitor_status.innerHTML)) return; 18 | 19 | monitor_status.innerHTML = translations.page.actions.status.tracing 20 | 21 | exec('/data/adb/modules/rezygisk/bin/zygisk-ptrace64 ctl start') 22 | }) 23 | 24 | monitor_stop.addEventListener('click', () => { 25 | monitor_status.innerHTML = translations.page.actions.status.exiting 26 | 27 | exec('/data/adb/modules/rezygisk/bin/zygisk-ptrace64 ctl exit') 28 | }) 29 | 30 | monitor_pause.addEventListener('click', () => { 31 | if (![ translations.page.actions.status.tracing, translations.page.actions.status.stopping, translations.page.actions.status.stopped ].includes(monitor_status.innerHTML)) return; 32 | 33 | monitor_status.innerHTML = translations.page.actions.status.stopped 34 | 35 | exec('/data/adb/modules/rezygisk/bin/zygisk-ptrace64 ctl stop') 36 | }) 37 | } 38 | })() -------------------------------------------------------------------------------- /webroot/js/themes/lightIcon.js: -------------------------------------------------------------------------------- 1 | export const light_expand_icon = ` 2 | 3 | 4 | 5 | ` 6 | export const light_close_icon = ` 7 | 8 | 9 | 10 | ` 11 | export const light_logs_icon = ` 12 | 13 | 14 | 15 | ` 16 | export const light_page_exit_icon = ` 17 | 18 | 19 | 20 | ` 21 | -------------------------------------------------------------------------------- /webroot/js/themes/dark.js: -------------------------------------------------------------------------------- 1 | import { setDarkNav } from './darkNavbar.js' 2 | 3 | const rootCss = document.querySelector(':root') 4 | 5 | /* INFO: Changes the icons to match the theme */ 6 | const close_icons = document.getElementsByClassName('close_icon') 7 | const expand_icons = document.getElementsByClassName('expander') 8 | const sp_lang_close = document.getElementById('sp_lang_close') 9 | const sp_theme_close = document.getElementById('sp_theme_close') 10 | const sp_errorh_close = document.getElementById('sp_errorh_close') 11 | 12 | export function setDark(chooseSet) { 13 | rootCss.style.setProperty('--background', '#181c20') 14 | rootCss.style.setProperty('--font', '#ffffff') 15 | rootCss.style.setProperty('--desc', '#c9c9c9') 16 | rootCss.style.setProperty('--dim', '#1d2327') 17 | rootCss.style.setProperty('--icon', '#48565e') 18 | rootCss.style.setProperty('--icon-bc', '#313a3f') 19 | rootCss.style.setProperty('--desktop-navbar', '#252b31') 20 | rootCss.style.setProperty('--desktop-navicon', '#333d42') 21 | rootCss.style.setProperty('--button', 'var(--background)') 22 | 23 | if (chooseSet) setData('dark') 24 | 25 | for (const close_icon of close_icons) { 26 | close_icon.innerHTML = '' 27 | } 28 | 29 | for (const expand_icon of expand_icons) { 30 | expand_icon.innerHTML = '' 31 | } 32 | 33 | sp_lang_close.innerHTML = '' 34 | sp_theme_close.innerHTML = '' 35 | sp_errorh_close.innerHTML = '' 36 | setDarkNav() 37 | } 38 | 39 | function setData(mode) { 40 | localStorage.setItem('/system/theme', mode) 41 | 42 | return mode 43 | } -------------------------------------------------------------------------------- /webroot/js/themes/light.js: -------------------------------------------------------------------------------- 1 | import { 2 | light_close_icon, 3 | light_expand_icon, 4 | light_page_exit_icon, 5 | } from './lightIcon.js' 6 | import { setLightNav } from './lightNavbar.js' 7 | 8 | const rootCss = document.querySelector(':root') 9 | 10 | /* INFO: Changes the icons to match the theme */ 11 | const close_icons = document.getElementsByClassName('close_icon') 12 | const expand_icons = document.getElementsByClassName('expander') 13 | const sp_lang_close = document.getElementById('sp_lang_close') 14 | const sp_theme_close = document.getElementById('sp_theme_close') 15 | const sp_errorh_close = document.getElementById('sp_errorh_close') 16 | 17 | export function setLight(chooseSet) { 18 | rootCss.style.setProperty('--background', '#f2f2f2') 19 | rootCss.style.setProperty('--font', '#181c20') 20 | rootCss.style.setProperty('--desc', '#484d53') 21 | rootCss.style.setProperty('--dim', '#e0e0e0') 22 | rootCss.style.setProperty('--icon', '#acacac') 23 | rootCss.style.setProperty('--desktop-navbar', '#fefefe') 24 | rootCss.style.setProperty('--desktop-navicon', '#eeeeee') 25 | rootCss.style.setProperty('--icon-bc', '#c9c9c9') 26 | rootCss.style.setProperty('--button', '#b3b3b3') 27 | 28 | if (chooseSet) setData('light') 29 | 30 | for (const close_icon of close_icons) { 31 | close_icon.innerHTML = light_close_icon 32 | } 33 | 34 | for (const expand_icon of expand_icons) { 35 | expand_icon.innerHTML = light_expand_icon 36 | } 37 | 38 | sp_lang_close.innerHTML = light_page_exit_icon 39 | sp_theme_close.innerHTML = light_page_exit_icon 40 | sp_errorh_close.innerHTML = light_page_exit_icon 41 | setLightNav() 42 | } 43 | 44 | function setData(mode) { 45 | localStorage.setItem('/system/theme', mode) 46 | 47 | return mode 48 | } 49 | -------------------------------------------------------------------------------- /zygiskd/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "root_impl/common.h" 9 | #include "companion.h" 10 | #include "zygiskd.h" 11 | 12 | #include "utils.h" 13 | 14 | char **g_argv = 0; 15 | 16 | int __android_log_print(int prio, const char *tag, const char *fmt, ...); 17 | 18 | int main(int argc, char *argv[]) { 19 | g_argv = argv; 20 | #ifdef __LP64__ 21 | LOGI("Welcome to ReZygisk %s Zygiskd64!\n", ZKSU_VERSION); 22 | #else 23 | LOGI("Welcome to ReZygisk %s Zygiskd32!\n", ZKSU_VERSION); 24 | #endif 25 | 26 | if (argc > 1) { 27 | if (strcmp(argv[1], "companion") == 0) { 28 | if (argc < 3) { 29 | LOGI("Usage: zygiskd companion \n"); 30 | 31 | return 1; 32 | } 33 | 34 | int fd = atoi(argv[2]); 35 | companion_entry(fd); 36 | 37 | return 0; 38 | } 39 | 40 | else if (strcmp(argv[1], "version") == 0) { 41 | LOGI("ReZygisk Daemon %s\n", ZKSU_VERSION); 42 | 43 | return 0; 44 | } 45 | 46 | else if (strcmp(argv[1], "root") == 0) { 47 | root_impls_setup(); 48 | 49 | struct root_impl impl; 50 | get_impl(&impl); 51 | 52 | char impl_name[LONGEST_ROOT_IMPL_NAME]; 53 | stringify_root_impl_name(impl, impl_name); 54 | 55 | LOGI("Root implementation: %s\n", impl_name); 56 | 57 | return 0; 58 | } 59 | 60 | else { 61 | LOGI("Usage: zygiskd [companion|version|root]\n"); 62 | 63 | return 0; 64 | } 65 | } 66 | 67 | if (switch_mount_namespace((pid_t)1) == false) { 68 | LOGE("Failed to switch mount namespace\n"); 69 | 70 | return 1; 71 | } 72 | root_impls_setup(); 73 | zygiskd_start(argv); 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /webroot/js/translate/settings.js: -------------------------------------------------------------------------------- 1 | export function translateSettingsPage(new_translations) { 2 | document.getElementById('panel_settings_header').innerHTML = new_translations.page.settings.header 3 | 4 | /* INFO: Change font option */ 5 | document.getElementById('sys_font_option_title').innerHTML = new_translations.page.settings.font.header 6 | document.getElementById('sys_font_option_desc').innerHTML = new_translations.page.settings.font.description 7 | 8 | /* INFO: Change font option */ 9 | document.getElementById('sys_theme_option_title').innerHTML = new_translations.page.settings.theme.header 10 | document.getElementById('sys_theme_option_desc').innerHTML = new_translations.page.settings.theme.description 11 | 12 | /* INFO: Change font option */ 13 | document.getElementById('sys_lang_option_title').innerHTML = new_translations.page.settings.language.header 14 | document.getElementById('sys_lang_option_desc').innerHTML = new_translations.page.settings.language.description 15 | 16 | /* INFO: Change font option */ 17 | document.getElementById('sys_errorh_title').innerHTML = new_translations.page.settings.logs.header 18 | document.getElementById('sys_errorh_desc').innerHTML = new_translations.page.settings.logs.description 19 | 20 | /* INFO: Credit card */ 21 | document.getElementById('mcre_title').innerHTML = new_translations.page.settings.credits.module 22 | document.getElementById('omcre_title').innerHTML = new_translations.page.settings.credits.original 23 | document.getElementById('webcre_title').innerHTML = new_translations.page.settings.credits.web 24 | /* INFO: License card */ 25 | document.getElementById('mlic_title').innerHTML = new_translations.page.settings.license.module 26 | document.getElementById('mweb_title').innerHTML = new_translations.page.settings.license.web 27 | } -------------------------------------------------------------------------------- /webroot/js/translate/actions.js: -------------------------------------------------------------------------------- 1 | export function translateActionsPage(old_translations, new_translations) { 2 | /* INFO: actions card */ 3 | document.getElementById('panel_actions_header').innerHTML = new_translations.page.actions.header 4 | 5 | /* INFO: monitor small card */ 6 | document.getElementById('monitor_title').innerHTML = new_translations.page.actions.monitor 7 | if (document.getElementById('monitor_stop_button')) { /* INFO: Not all devices have 32-bit support */ 8 | document.getElementById('monitor_stop_button').innerHTML = new_translations.page.actions.monitorButton.stop 9 | document.getElementById('monitor_start_button').innerHTML = new_translations.page.actions.monitorButton.start 10 | document.getElementById('monitor_pause_button').innerHTML = new_translations.page.actions.monitorButton.pause 11 | } 12 | 13 | /* INFO: monitor status card */ 14 | const monitor_status = document.getElementById('monitor_status') 15 | switch (monitor_status.innerHTML.replace(/(\r\n|\n|\r)/gm, '').trim()) { 16 | case old_translations.page.actions.status.tracing: { 17 | monitor_status.innerHTML = new_translations.page.actions.status.tracing 18 | 19 | break 20 | } 21 | case old_translations.page.actions.status.stopping: { 22 | monitor_status.innerHTML = new_translations.page.actions.status.stopping 23 | 24 | break 25 | } 26 | case old_translations.page.actions.status.stopped: { 27 | monitor_status.innerHTML = new_translations.page.actions.status.stopped 28 | 29 | break 30 | } 31 | case old_translations.page.actions.status.exiting: { 32 | monitor_status.innerHTML = new_translations.page.actions.status.exiting 33 | 34 | break 35 | } 36 | default: monitor_status.innerHTML = new_translations.page.actions.status.unknown 37 | } 38 | } -------------------------------------------------------------------------------- /module/src/verify.sh: -------------------------------------------------------------------------------- 1 | TMPDIR_FOR_VERIFY="$TMPDIR/.vunzip" 2 | mkdir "$TMPDIR_FOR_VERIFY" 3 | 4 | abort_verify() { 5 | ui_print "*********************************************************" 6 | ui_print "! $1" 7 | ui_print "! This zip may be corrupted, please try downloading again" 8 | abort "*********************************************************" 9 | } 10 | 11 | # extract 12 | extract() { 13 | zip=$1 14 | file=$2 15 | dir=$3 16 | junk_paths=$4 17 | [ -z "$junk_paths" ] && junk_paths=false 18 | opts="-o" 19 | [ $junk_paths = true ] && opts="-oj" 20 | 21 | file_path="" 22 | hash_path="" 23 | if [ $junk_paths = true ]; then 24 | file_path="$dir/$(basename "$file")" 25 | hash_path="$TMPDIR_FOR_VERIFY/$(basename "$file").sha256" 26 | else 27 | file_path="$dir/$file" 28 | hash_path="$TMPDIR_FOR_VERIFY/$file.sha256" 29 | fi 30 | 31 | unzip $opts "$zip" "$file" -d "$dir" >&2 32 | [ -f "$file_path" ] || abort_verify "$file not exists" 33 | 34 | unzip $opts "$zip" "$file.sha256" -d "$TMPDIR_FOR_VERIFY" >&2 35 | [ -f "$hash_path" ] || abort_verify "$file.sha256 not exists" 36 | 37 | (echo "$(cat "$hash_path") $file_path" | sha256sum -c -s -) || abort_verify "Failed to verify $file" 38 | ui_print "- Verified $file" >&1 39 | } 40 | 41 | file="META-INF/com/google/android/update-binary" 42 | file_path="$TMPDIR_FOR_VERIFY/$file" 43 | hash_path="$file_path.sha256" 44 | unzip -o "$ZIPFILE" "META-INF/com/google/android/*" -d "$TMPDIR_FOR_VERIFY" >&2 45 | [ -f "$file_path" ] || abort_verify "$file not exists" 46 | if [ -f "$hash_path" ]; then 47 | (echo "$(cat "$hash_path") $file_path" | sha256sum -c -s -) || abort_verify "Failed to verify $file" 48 | ui_print "- Verified $file" >&1 49 | else 50 | ui_print "- Download from Magisk app" 51 | fi 52 | -------------------------------------------------------------------------------- /webroot/js/navbar.js: -------------------------------------------------------------------------------- 1 | const navbar_data_tag = document.getElementById('cache-navbar-previous') 2 | const small_panel_data_tag = document.getElementById('cache-page-small-previous') 3 | 4 | setData('home', navbar_data_tag) 5 | 6 | document.getElementById('panel_home').classList.toggle('show') 7 | document.getElementById(`nibg_home`).classList.toggle('show') 8 | 9 | document.querySelectorAll('[name=navbutton]').forEach((element) => { 10 | element.addEventListener('click', (event) => { 11 | let smallPagePass = false 12 | 13 | const value = event.target.value 14 | const previous = !navbar_data_tag.getAttribute('content') 15 | ? setData('home', navbar_data_tag) 16 | : navbar_data_tag.getAttribute('content') 17 | 18 | const small_panel = small_panel_data_tag.getAttribute('content') 19 | 20 | if (small_panel && small_panel.length !== 0) { 21 | document.getElementById(`small_panel_${small_panel}`).classList.remove('show') 22 | small_panel_data_tag.removeAttribute('content') 23 | smallPagePass = true 24 | } 25 | 26 | if (previous === value && !smallPagePass) return; 27 | 28 | /* INFO: Disable icon on old state */ 29 | const pre_input = document.getElementById(`n_${previous}`) 30 | const pre_background = document.getElementById(`nibg_${previous}`) 31 | 32 | document.getElementById(`panel_${previous}`).classList.remove('show') 33 | pre_input.removeAttribute('checked') 34 | pre_background.classList.remove('show') 35 | 36 | /* INFO: Enable icon on new state */ 37 | const curr_input = document.getElementById(`n_${value}`) 38 | const i_background = document.getElementById(`nibg_${value}`) 39 | 40 | document.getElementById(`panel_${value}`).classList.toggle('show') 41 | curr_input.setAttribute('checked', '') 42 | i_background.classList.toggle('show') 43 | 44 | setData(value, navbar_data_tag) 45 | }) 46 | }) 47 | 48 | function setData(data, tag) { 49 | tag.setAttribute('content', data) 50 | 51 | return data 52 | } -------------------------------------------------------------------------------- /loader/src/include/daemon.h: -------------------------------------------------------------------------------- 1 | #ifndef DAEMON_H 2 | #define DAEMON_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif /* __cplusplus */ 7 | 8 | #include 9 | 10 | #include 11 | 12 | #ifdef __LP64__ 13 | #define LP_SELECT(lp32, lp64) lp64 14 | #else 15 | #define LP_SELECT(lp32, lp64) lp32 16 | #endif 17 | 18 | #define SOCKET_FILE_NAME LP_SELECT("cp32", "cp64") ".sock" 19 | 20 | enum rezygiskd_actions { 21 | PingHeartbeat, 22 | GetProcessFlags, 23 | GetInfo, 24 | ReadModules, 25 | RequestCompanionSocket, 26 | GetModuleDir, 27 | ZygoteRestart, 28 | SystemServerStarted, 29 | UpdateMountNamespace 30 | }; 31 | 32 | struct zygisk_modules { 33 | char **modules; 34 | size_t modules_count; 35 | }; 36 | 37 | enum root_impl { 38 | ROOT_IMPL_NONE, 39 | ROOT_IMPL_APATCH, 40 | ROOT_IMPL_KERNELSU, 41 | ROOT_IMPL_MAGISK 42 | }; 43 | 44 | struct rezygisk_info { 45 | struct zygisk_modules *modules; 46 | enum root_impl root_impl; 47 | pid_t pid; 48 | bool running; 49 | }; 50 | 51 | enum mount_namespace_state { 52 | Clean, 53 | Mounted 54 | }; 55 | 56 | #define TMP_PATH "/data/adb/nrezygisk" 57 | 58 | static inline const char *rezygiskd_get_path() { 59 | return TMP_PATH; 60 | } 61 | 62 | int rezygiskd_connect(uint8_t retry); 63 | 64 | bool rezygiskd_ping(); 65 | 66 | uint32_t rezygiskd_get_process_flags(uid_t uid, const char *const process); 67 | 68 | void rezygiskd_get_info(struct rezygisk_info *info); 69 | 70 | void free_rezygisk_info(struct rezygisk_info *info); 71 | 72 | bool rezygiskd_read_modules(struct zygisk_modules *modules); 73 | 74 | void free_modules(struct zygisk_modules *modules); 75 | 76 | int rezygiskd_connect_companion(size_t index); 77 | 78 | int rezygiskd_get_module_dir(size_t index); 79 | 80 | void rezygiskd_zygote_restart(); 81 | 82 | void rezygiskd_system_server_started(); 83 | 84 | bool rezygiskd_update_mns(enum mount_namespace_state nms_state, char *buf, size_t buf_size); 85 | 86 | #ifdef __cplusplus 87 | } 88 | #endif /* __cplusplus */ 89 | 90 | #endif /* DAEMON_H */ -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Untrusted CI 2 | 3 | on: 4 | pull_request: 5 | merge_group: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | with: 15 | submodules: "recursive" 16 | fetch-depth: 0 17 | 18 | - name: Setup Java 19 | uses: actions/setup-java@v4 20 | with: 21 | distribution: "temurin" 22 | java-version: "17" 23 | 24 | - name: Setup Gradle 25 | uses: gradle/actions/setup-gradle@v4 26 | 27 | - name: Build with Gradle 28 | run: | 29 | echo 'org.gradle.parallel=true' >> gradle.properties 30 | echo 'org.gradle.vfs.watch=true' >> gradle.properties 31 | echo 'org.gradle.jvmargs=-Xmx2048m' >> gradle.properties 32 | sed -i 's/org.gradle.unsafe.configuration-cache=true//g' gradle.properties 33 | ./gradlew zipRelease 34 | ./gradlew zipDebug 35 | 36 | - name: Prepare artifact 37 | if: success() 38 | id: prepareArtifact 39 | run: | 40 | releaseName=`ls module/build/outputs/release/NReZygisk-v*-release.zip | awk -F '(/|.zip)' '{print $5}'` && echo "releaseName=$releaseName" >> $GITHUB_OUTPUT 41 | debugName=`ls module/build/outputs/release/NReZygisk-v*-debug.zip | awk -F '(/|.zip)' '{print $5}'` && echo "debugName=$debugName" >> $GITHUB_OUTPUT 42 | unzip module/build/outputs/release/NReZygisk-v*-release.zip -d zksu-release 43 | unzip module/build/outputs/release/NReZygisk-v*-debug.zip -d zksu-debug 44 | 45 | - name: Upload release 46 | uses: actions/upload-artifact@v4 47 | with: 48 | name: ${{ steps.prepareArtifact.outputs.releaseName }} 49 | path: "./zksu-release/*" 50 | 51 | - name: Upload debug 52 | uses: actions/upload-artifact@v4 53 | with: 54 | name: ${{ steps.prepareArtifact.outputs.debugName }} 55 | path: "./zksu-debug/*" 56 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue_template.yml: -------------------------------------------------------------------------------- 1 | name: Issue report 2 | description: Report an issue 3 | title: "[BUG]: " 4 | labels: ["bug", "not confirmed"] 5 | 6 | body: 7 | - type: input 8 | id: version 9 | attributes: 10 | label: Version 11 | description: The version of the ReZygisk you're using. 12 | validations: 13 | required: true 14 | 15 | - type: textarea 16 | id: modules 17 | attributes: 18 | label: Modules 19 | description: "The modules you're using following the format: moduleName by authorName version x.x.x" 20 | validations: 21 | required: true 22 | 23 | - type: textarea 24 | id: description 25 | attributes: 26 | label: Description 27 | description: A clear and concise description of what the bug is. 28 | validations: 29 | required: true 30 | 31 | - type: textarea 32 | id: steps 33 | attributes: 34 | label: Steps to reproduce 35 | description: Steps to reproduce the behavior. 36 | validations: 37 | required: true 38 | 39 | - type: textarea 40 | id: logs 41 | attributes: 42 | label: Logs 43 | description: If applicable, add logs AS A FILE to help solve the issue. Most of the time it will be from logcat on boot. 44 | validations: 45 | required: false 46 | 47 | - type: checkboxes 48 | id: terms 49 | attributes: 50 | label: Confirmations 51 | description: The following confirmations are required to open a bug report. 52 | options: 53 | - label: My environment meets the minimum requirements. 54 | required: true 55 | - label: I have verified that this is not a duplicate issue. 56 | required: true 57 | 58 | - type: checkboxes 59 | id: code_of_conduct 60 | attributes: 61 | label: Code of Conduct 62 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/PerformanC/contributing/blob/main/CODE_OF_CONDUCT.md) 63 | options: 64 | - label: I agree to follow this project's Code of Conduct 65 | required: true 66 | -------------------------------------------------------------------------------- /module/src/service.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | DEBUG=@DEBUG@ 4 | 5 | MODDIR=${0%/*} 6 | if [ "$ZYGISK_ENABLED" ]; then 7 | exit 0 8 | fi 9 | 10 | cd "$MODDIR" 11 | 12 | if [ "$(which magisk)" ]; then 13 | for file in ../*; do 14 | if [ -d "$file" ] && [ -d "$file/zygisk" ] && ! [ -f "$file/disable" ]; then 15 | if [ -f "$file/service.sh" ]; then 16 | cd "$file" 17 | log -p i -t "zygisk-sh" "Manually trigger service.sh for $file" 18 | sh "$(realpath ./service.sh)" & 19 | cd "$MODDIR" 20 | fi 21 | fi 22 | done 23 | fi 24 | 25 | CPU_ABIS=$(getprop ro.product.cpu.abilist) 26 | 27 | if [[ "$CPU_ABIS" == *"arm64-v8a"* || "$CPU_ABIS" == *"x86_64"* ]]; then 28 | ./bin/zygisk-ptrace64 mount_ns_private 29 | else 30 | # INFO: Device is 32-bit only 31 | 32 | ./bin/zygisk-ptrace32 mount_ns_private 33 | fi 34 | 35 | p_s() { 36 | curr="$(resetprop "$1")" 37 | if [ -n "$curr" ] && [ "$curr" != "$2" ]; then 38 | resetprop -n "$1" "$2" 39 | fi 40 | } 41 | 42 | p_r() { 43 | case "$(resetprop "$1")" in 44 | *"$2"*) resetprop -n "$1" "$3" ;; 45 | esac 46 | } 47 | 48 | resetprop -w sys.boot_completed 0 49 | 50 | p_s ro.build.type user 51 | p_s ro.build.tags release-keys 52 | p_s ro.boot.vbmeta.device_state locked 53 | p_s ro.boot.verifiedbootstate green 54 | p_s vendor.boot.vbmeta.device_state locked 55 | p_s vendor.boot.verifiedbootstate green 56 | p_s sys.oem_unlock_allowed 0 57 | p_s ro.boot.veritymode enforcing 58 | p_s ro.boot.veritymode.managed yes 59 | p_s ro.boot.flash.locked 1 60 | p_s ro.boot.warranty_bit 0 61 | p_s ro.warranty_bit 0 62 | p_s ro.vendor.boot.warranty_bit 0 63 | p_s ro.vendor.warranty_bit 0 64 | p_s ro.debuggable 0 65 | p_s ro.force.debuggable 0 66 | p_s ro.secure 1 67 | p_s ro.adb.secure 1 68 | p_s ro.boot.realmebootstate green 69 | p_s ro.boot.realme.lockstate 1 70 | p_s ro.secureboot.lockstate locked 71 | p_s ro.is_ever_orange 0 72 | 73 | p_r ro.bootmode recovery unknown 74 | p_r ro.boot.mode recovery unknown 75 | p_r ro.boot.bootmode recovery unknown 76 | p_r vendor.boot.mode recovery unknown 77 | p_r vendor.boot.bootmode recovery unknown 78 | -------------------------------------------------------------------------------- /module/src/post-fs-data.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | MODDIR=${0%/*} 4 | if [ "$ZYGISK_ENABLED" ]; then 5 | exit 0 6 | fi 7 | 8 | cd "$MODDIR" 9 | 10 | if [ "$(which magisk)" ]; then 11 | for file in ../*; do 12 | if [ -d "$file" ] && [ -d "$file/zygisk" ] && ! [ -f "$file/disable" ]; then 13 | if [ -f "$file/post-fs-data.sh" ]; then 14 | cd "$file" 15 | log -p i -t "zygisk-sh" "Manually trigger post-fs-data.sh for $file" 16 | sh "$(realpath ./post-fs-data.sh)" 17 | cd "$MODDIR" 18 | fi 19 | fi 20 | done 21 | fi 22 | 23 | create_sys_perm() { 24 | mkdir -p $1 25 | chmod 555 $1 26 | chcon u:object_r:system_file:s0 $1 27 | } 28 | 29 | export TMP_PATH=/data/adb/nrezygisk 30 | 31 | if [ -d $TMP_PATH ]; then 32 | rm $TMP_PATH/cp32.sock 2>/dev/null 33 | rm $TMP_PATH/cp64.sock 2>/dev/null 34 | rm $TMP_PATH/init_monitor 2>/dev/null 35 | rm $TMP_PATH/mns32 2>/dev/null 36 | rm $TMP_PATH/mns64 2>/dev/null 37 | rm -rf "$TMP_PATH/tmp" 38 | fi 39 | 40 | create_sys_perm $TMP_PATH 41 | create_sys_perm $TMP_PATH/tmp 42 | 43 | mkdir $TMP_PATH/tmp/copy32_d 44 | mkdir $TMP_PATH/tmp/copy64_d 45 | touch $TMP_PATH/tmp/copy32_f 46 | touch $TMP_PATH/tmp/copy64_f 47 | 48 | if [ -f $MODDIR/lib64/libzygisk.so ];then 49 | create_sys_perm $TMP_PATH/lib64 50 | cp $MODDIR/lib64/libzygisk.so $TMP_PATH/lib64/libzygisk.so 51 | chcon u:object_r:system_file:s0 $TMP_PATH/lib64/libzygisk.so 52 | fi 53 | 54 | if [ -f $MODDIR/lib/libzygisk.so ];then 55 | create_sys_perm $TMP_PATH/lib 56 | cp $MODDIR/lib/libzygisk.so $TMP_PATH/lib/libzygisk.so 57 | chcon u:object_r:system_file:s0 $TMP_PATH/lib/libzygisk.so 58 | fi 59 | 60 | 61 | CPU_ABIS=$(getprop ro.system.product.cpu.abilist) 62 | CPU_ABIS=${CPU_ABIS:-$(getprop ro.product.cpu.abilist)} 63 | 64 | if [[ "$CPU_ABIS" == *"arm64-v8a"* || "$CPU_ABIS" == *"x86_64"* ]]; then 65 | ./bin/zygisk-ptrace64 monitor 66 | ./bin/zygisk-ptrace64 mount_ns 67 | ./bin/zygisk-ptrace64 mount_ns_private 68 | else 69 | # INFO: Device is 32-bit only 70 | 71 | ./bin/zygisk-ptrace32 monitor 72 | ./bin/zygisk-ptrace32 mount_ns 73 | ./bin/zygisk-ptrace32 mount_ns_private 74 | fi 75 | -------------------------------------------------------------------------------- /webroot/js/smallPage/language.js: -------------------------------------------------------------------------------- 1 | import { 2 | getTranslations, 3 | setNewLanguage, 4 | getAvailableLanguages 5 | } from '../language.js' 6 | import { smallPageDisabler } from '../smallPageDesabler.js' 7 | 8 | /* INFO: Initial setup */ 9 | let index = 0 10 | 11 | async function setAvailableLanguage() { 12 | const availableLanguages = await getAvailableLanguages() 13 | 14 | for (index; index < availableLanguages.length; index++) { 15 | const langCode = availableLanguages[index] 16 | const langData = await getTranslations(langCode) 17 | 18 | document.getElementById('lang_modal_list').innerHTML += ` 19 |
20 |
${langData.langName}
21 |
22 | ` 23 | } 24 | } 25 | setAvailableLanguage() 26 | 27 | /* INFO: Event setup */ 28 | const navbar_data_tag = document.getElementById('cache-navbar-previous') 29 | const small_panel_data_tag = document.getElementById('cache-page-small-previous') 30 | 31 | document.getElementById('lang_page_toggle').addEventListener('click', () => { 32 | const previous = !navbar_data_tag.getAttribute('content') ? setData('home', small_panel_data_tag) : navbar_data_tag.getAttribute('content') 33 | document.getElementById(`panel_${previous}`).classList.remove('show') 34 | document.getElementById('small_panel_language').classList.toggle('show') 35 | small_panel_data_tag.setAttribute('content', 'language') 36 | }) 37 | 38 | document.getElementById('sp_lang_close').addEventListener('click', () => smallPageDisabler('language', 'settings')) 39 | 40 | document.addEventListener('click', async (event) => { 41 | const getLangLocate = event.target.getAttribute('lang-data') 42 | if (!getLangLocate || typeof getLangLocate !== 'string') return 43 | 44 | smallPageDisabler('language', 'settings') 45 | await setNewLanguage(getLangLocate) 46 | 47 | localStorage.setItem('/system/language', getLangLocate) 48 | }, false) 49 | 50 | function setData(data, tag) { 51 | tag.setAttribute('content', data) 52 | 53 | return data 54 | } -------------------------------------------------------------------------------- /loader/src/include/elf_util.h: -------------------------------------------------------------------------------- 1 | #ifndef ELF_UTIL_H 2 | #define ELF_UTIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define SHT_GNU_HASH 0x6ffffff6 10 | 11 | struct symtabs { 12 | char *name; 13 | ElfW(Sym) *sym; 14 | }; 15 | 16 | typedef struct ElfImg { 17 | char *elf; 18 | void *base; 19 | ElfW(Ehdr) *header; 20 | size_t size; 21 | off_t bias; 22 | ElfW(Shdr) *section_header; 23 | 24 | ElfW(Shdr) *dynsym; 25 | ElfW(Off) dynsym_offset; 26 | ElfW(Sym) *dynsym_start; 27 | ElfW(Shdr) *strtab; 28 | ElfW(Off) symstr_offset; 29 | void *strtab_start; 30 | 31 | uint32_t nbucket_; 32 | uint32_t *bucket_; 33 | uint32_t *chain_; 34 | 35 | uint32_t gnu_nbucket_; 36 | uint32_t gnu_symndx_; 37 | uint32_t gnu_bloom_size_; 38 | uint32_t gnu_shift2_; 39 | uintptr_t *gnu_bloom_filter_; 40 | uint32_t *gnu_bucket_; 41 | uint32_t *gnu_chain_; 42 | 43 | ElfW(Shdr) *symtab; 44 | ElfW(Off) symtab_offset; 45 | size_t symtab_size; 46 | size_t symtab_count; 47 | ElfW(Sym) *symtab_start; 48 | ElfW(Off) symstr_offset_for_symtab; 49 | 50 | struct symtabs *symtabs_; 51 | 52 | const char *gnu_debugdata_start; 53 | size_t gnu_debugdata_size; 54 | struct ElfImg *gnu_debugdata; 55 | } ElfImg; 56 | 57 | void ElfImg_destroy(ElfImg *img); 58 | 59 | ElfImg *ElfImg_create(const char *elf, void *base); 60 | 61 | ElfImg *ElfImg_loadGnuDebugdata(ElfImg *img); 62 | 63 | ElfW(Addr) ElfLookup(ElfImg *restrict img, const char *restrict name, uint32_t hash); 64 | 65 | ElfW(Addr) GnuLookup(ElfImg *restrict img, const char *restrict name, uint32_t hash); 66 | 67 | ElfW(Addr) LinearLookup(ElfImg *restrict img, const char *restrict name); 68 | 69 | ElfW(Addr) LinearLookupByPrefix(ElfImg *restrict img, const char *name); 70 | 71 | int dl_cb(struct dl_phdr_info *info, size_t size, void *data); 72 | 73 | ElfW(Addr) getSymbOffset(ElfImg *img, const char *name); 74 | 75 | ElfW(Addr) getSymbAddress(ElfImg *img, const char *name); 76 | 77 | ElfW(Addr) getSymbAddressByPrefix(ElfImg *img, const char *prefix); 78 | 79 | void *getSymbValueByPrefix(ElfImg *img, const char *prefix); 80 | 81 | #endif /* ELF_UTIL_H */ 82 | -------------------------------------------------------------------------------- /webroot/lang/zh_CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "简体中文 (中国)", 3 | "global": { 4 | "unknown": "未知" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "选择语言" 9 | }, 10 | "theme": { 11 | "header": "选择主题风格", 12 | "dark": "暗色", 13 | "light": "浅色", 14 | "system": "跟随系统" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "复制", 19 | "clear": "清空日志" 20 | }, 21 | "header": "错误日志", 22 | "placeholder": "暂时没有错误日志" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "主页", 28 | "status": { 29 | "notWorking": "未运行", 30 | "ok": "运行中", 31 | "partially": "部分运行" 32 | }, 33 | "info": { 34 | "version": "版本", 35 | "root": "Root实现", 36 | "zygote": { 37 | "injected": "已注入", 38 | "notInjected": "未注入", 39 | "unknown": "未知" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "模块", 45 | "notAvaliable": "目前没有模块使用Zygisk", 46 | "arch": "架构: " 47 | }, 48 | "actions": { 49 | "header": "操作", 50 | "monitorButton": { 51 | "start": "启动", 52 | "stop": "停止", 53 | "pause": "暂停" 54 | }, 55 | "monitor": "监视器", 56 | "status": { 57 | "tracing": "追踪中", 58 | "stopping": "正在停止", 59 | "stopped": "已停止", 60 | "exiting": "正在退出", 61 | "unknown": "未知" 62 | } 63 | }, 64 | "settings": { 65 | "header": "设置", 66 | "font": { 67 | "header": "启用系统字体", 68 | "description": "此选项会在Web界面启用系统字体。可能与FlipFont不兼容。" 69 | }, 70 | "theme": { 71 | "header": "主题", 72 | "description": "选择Web界面的主题风格" 73 | }, 74 | "language": { 75 | "header": "语言", 76 | "description": "切换不同的语言" 77 | }, 78 | "logs": { 79 | "header": "错误日志", 80 | "description": "浏览所有错误日志" 81 | }, 82 | "credits": { 83 | "module": "模块开发者", 84 | "original": "源模块开发者", 85 | "web": "Web界面开发者" 86 | }, 87 | "license": { 88 | "module": "模块开源许可", 89 | "web": "Web界面开源许可" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /loader/src/common/utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "utils.hpp" 9 | 10 | bool MappedBuffer::grow(size_t target) { 11 | if (target <= capacity) return true; 12 | 13 | if (capacity == 0) { 14 | void *map = mmap(nullptr, target, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 15 | if (map == MAP_FAILED) return false; 16 | data = (char *) map; 17 | capacity = target; 18 | prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, data, capacity, "zygisk_buf", 0); 19 | return true; 20 | } 21 | 22 | size_t new_capacity = capacity * 2; 23 | while (new_capacity < target) { 24 | if (new_capacity > std::numeric_limits::max() / 2) { 25 | unmap(); 26 | return false; 27 | } 28 | new_capacity *= 2; 29 | } 30 | 31 | void *map = mremap(data, capacity, new_capacity, MREMAP_MAYMOVE); 32 | if (map == MAP_FAILED) { 33 | unmap(); 34 | return false; 35 | } 36 | 37 | data = (char *) map; 38 | capacity = new_capacity; 39 | prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, data, capacity, "zygisk_buf", 0); 40 | return true; 41 | } 42 | 43 | void MappedBuffer::unmap() { 44 | if (capacity > 0) { 45 | munmap(data, capacity); 46 | data = nullptr; 47 | size = 0; 48 | capacity = 0; 49 | } 50 | } 51 | 52 | bool MappedBuffer::file_read(const char *path, size_t expected_len) { 53 | size = 0; 54 | int fd = open(path, O_RDONLY | O_CLOEXEC); 55 | if (fd == -1) return false; 56 | 57 | if (!grow(expected_len + 4096)) { 58 | close(fd); 59 | return false; 60 | } 61 | 62 | ssize_t n; 63 | while ((n = TEMP_FAILURE_RETRY(read(fd, data + size, capacity - size))) > 0) { 64 | size += (size_t) n; 65 | if (!grow(size + 4096)) { 66 | close(fd); 67 | return false; 68 | } 69 | } 70 | 71 | close(fd); 72 | return n == 0; 73 | } 74 | 75 | bool MappedBuffer::operator==(MappedBuffer const &rhs) const { 76 | if (size != rhs.size) return false; 77 | return memcmp(data, rhs.data, size) == 0; 78 | } 79 | -------------------------------------------------------------------------------- /webroot/js/smallPage/errorHistory.js: -------------------------------------------------------------------------------- 1 | import { smallPageDisabler } from '../smallPageDesabler.js' 2 | const panel = document.getElementById('errorh_panel') 3 | 4 | /* INFO: Event setup */ 5 | const navbar_data_tag = document.getElementById('cache-navbar-previous') 6 | const small_panel_data_tag = document.getElementById('cache-page-small-previous') 7 | const fallback_open = document.getElementById('cache-fallback-open') 8 | 9 | document.getElementById('errorh_page_toggle').addEventListener('click', () => { 10 | const previous = !navbar_data_tag.getAttribute('content') ? setData('home', small_panel_data_tag) : navbar_data_tag.getAttribute('content') 11 | document.getElementById(`panel_${previous}`).classList.remove('show') 12 | document.getElementById('small_panel_errorh').classList.toggle('show') 13 | small_panel_data_tag.setAttribute('content', 'errorh') 14 | }) 15 | 16 | document.getElementById('backport_errorh').addEventListener('click', () => { 17 | const previous = !navbar_data_tag.getAttribute('content') ? setData('home', small_panel_data_tag) : navbar_data_tag.getAttribute('content') 18 | document.getElementById(`panel_${previous}`).classList.remove('show') 19 | document.getElementById('loading_screen').style.display = 'none' 20 | document.getElementById('small_panel_errorh').classList.toggle('show') 21 | document.getElementById('errorh_panel').style.bottom = '1em' 22 | fallback_open.setAttribute('content', 'opened') 23 | small_panel_data_tag.setAttribute('content', 'errorh') 24 | }) 25 | 26 | document.getElementById('sp_errorh_close').addEventListener('click', () => { 27 | const is_fallback = fallback_open.getAttribute('content') 28 | if (is_fallback) { 29 | document.getElementById('errorh_panel').style.bottom = '1em' 30 | document.getElementById('loading_screen').style.display = 'flex' 31 | } 32 | smallPageDisabler('errorh', is_fallback ? 'home' : 'settings', is_fallback ? 'home' : null) 33 | }) 34 | document.getElementById('errorh_copy').addEventListener('click', () => { 35 | navigator.clipboard.writeText(panel.innerHTML) 36 | }) 37 | 38 | document.getElementById('errorh_clear_all').addEventListener('click', () => { 39 | panel.innerHTML = '' 40 | localStorage.setItem('/system/error', '') 41 | }) 42 | 43 | function setData(mode, tag) { 44 | tag.setAttribute('content', mode) 45 | 46 | return mode 47 | } -------------------------------------------------------------------------------- /webroot/lang/ja_JP.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "日本語", 3 | "global": { 4 | "unknown": "不明" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "言語を選択してください" 9 | }, 10 | "theme": { 11 | "header": "テーマを選択してください", 12 | "dark": "ダーク", 13 | "light": "ライト", 14 | "system": "システムベース" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "コピー", 19 | "clear": "すべてのログを消去" 20 | }, 21 | "header": "エラーの履歴", 22 | "placeholder": "エラーログは記録されていません!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "ホーム", 28 | "status": { 29 | "notWorking": "動作していません", 30 | "ok": "動作中", 31 | "partially": "部分的に動作中" 32 | }, 33 | "info": { 34 | "version": "バージョン", 35 | "root": "Root の実装", 36 | "zygote": { 37 | "injected": "インジェクト済み", 38 | "notInjected": "未インジェクト", 39 | "unknown": "不明" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "モジュール", 45 | "notAvaliable": "Zygisk を使用するモジュールはありません。", 46 | "arch": "アーキテクチャ: " 47 | }, 48 | "actions": { 49 | "header": "アクション", 50 | "monitorButton": { 51 | "start": "開始", 52 | "stop": "停止", 53 | "pause": "一時停止" 54 | }, 55 | "monitor": "監視", 56 | "status": { 57 | "tracing": "トレース中", 58 | "stopping": "停止中", 59 | "stopped": "停止済み", 60 | "exiting": "終了中", 61 | "unknown": "不明" 62 | } 63 | }, 64 | "settings": { 65 | "header": "設定", 66 | "font": { 67 | "header": "システムフォントを有効化", 68 | "description": "現在の WebUI でシステムフォントの使用を有効化します。注意: FlipFont との互換性がない場合があります" 69 | }, 70 | "theme": { 71 | "header": "システムテーマ", 72 | "description": "WebUI のシステムテーマを変更します" 73 | }, 74 | "language": { 75 | "header": "言語の変更", 76 | "description": "言語を変更します" 77 | }, 78 | "logs": { 79 | "header": "エラーの履歴", 80 | "description": "すべてのエラーログを表示します" 81 | }, 82 | "credits": { 83 | "module": "モジュールの開発者", 84 | "original": "オリジナルの開発者", 85 | "web": "WebUI の開発者" 86 | }, 87 | "license": { 88 | "module": "モジュールのライセンス", 89 | "web": "WebUI のライセンス" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /.github/workflows/trusted_ci.yml: -------------------------------------------------------------------------------- 1 | name: Trusted CI 2 | 3 | on: 4 | push: 5 | branches: [ fork ] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | with: 14 | submodules: "recursive" 15 | fetch-depth: 0 16 | 17 | - name: Setup Java 18 | uses: actions/setup-java@v4 19 | with: 20 | distribution: "temurin" 21 | java-version: "17" 22 | 23 | - name: Setup Gradle 24 | uses: gradle/actions/setup-gradle@v4 25 | 26 | - name: Setup keys 27 | env: 28 | private_key: ${{ secrets.ORG_PRIVATE_KEY }} 29 | public_key: ${{ secrets.ORG_PUBLIC_KEY }} 30 | run: | 31 | if [ -z "$private_key" ] || [ -z "$public_key" ]; then 32 | echo "Private or public key is not set." 33 | else 34 | echo "$private_key" | base64 -d > module/private_key 35 | echo "$public_key" | base64 -d > module/public_key 36 | fi 37 | 38 | - name: Build with Gradle 39 | run: | 40 | echo 'org.gradle.parallel=true' >> gradle.properties 41 | echo 'org.gradle.vfs.watch=true' >> gradle.properties 42 | echo 'org.gradle.jvmargs=-Xmx2048m' >> gradle.properties 43 | sed -i 's/org.gradle.unsafe.configuration-cache=true//g' gradle.properties 44 | ./gradlew zipRelease 45 | ./gradlew zipDebug 46 | 47 | - name: Prepare artifact 48 | if: success() 49 | id: prepareArtifact 50 | run: | 51 | releaseName=`ls module/build/outputs/release/NReZygisk-v*-release.zip | awk -F '(/|.zip)' '{print $5}'` && echo "releaseName=$releaseName" >> $GITHUB_OUTPUT 52 | debugName=`ls module/build/outputs/release/NReZygisk-v*-debug.zip | awk -F '(/|.zip)' '{print $5}'` && echo "debugName=$debugName" >> $GITHUB_OUTPUT 53 | unzip module/build/outputs/release/NReZygisk-v*-release.zip -d zksu-release 54 | unzip module/build/outputs/release/NReZygisk-v*-debug.zip -d zksu-debug 55 | 56 | - name: Upload release 57 | uses: actions/upload-artifact@v4 58 | with: 59 | name: ${{ steps.prepareArtifact.outputs.releaseName }} 60 | path: "./zksu-release/*" 61 | 62 | - name: Upload debug 63 | uses: actions/upload-artifact@v4 64 | with: 65 | name: ${{ steps.prepareArtifact.outputs.debugName }} 66 | path: "./zksu-debug/*" 67 | -------------------------------------------------------------------------------- /webroot/lang/ar_EG.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "العربية", 3 | "global": { 4 | "unknown": "غير معروف" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "اختر اللغة" 9 | }, 10 | "theme": { 11 | "header": "اختر السمة", 12 | "dark": "مظلم", 13 | "light": "مضئ", 14 | "system": "تلقائي" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "نسخ", 19 | "clear": "حذف كل السجلات" 20 | }, 21 | "header": "سجلات الأخطاء", 22 | "placeholder": "لا توجد أخطاء!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "الصفحة الرئيسية", 28 | "status": { 29 | "notWorking": "لا يعمل", 30 | "ok": "يعمل", 31 | "partially": "يعمل بشكل جزئي" 32 | }, 33 | "info": { 34 | "version": "الإصدار", 35 | "root": "مدير الروت", 36 | "zygote": { 37 | "injected": "محقن", 38 | "notInjected": "غير محقن", 39 | "unknown": "غير معروف" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "الإضافات", 45 | "notAvaliable": "لا توجد إضافات تستخدم zygisk.", 46 | "arch": "النواة: " 47 | }, 48 | "actions": { 49 | "header": "زر الإجراء", 50 | "monitorButton": { 51 | "start": "تشغيل", 52 | "stop": "تعطيل", 53 | "pause": "إيقاف مؤقت" 54 | }, 55 | "monitor": "المراقبة", 56 | "status": { 57 | "tracing": "يتم التتبع", 58 | "stopping": "يتم الإيقاف", 59 | "stopped": "متوقف", 60 | "exiting": "يتم الخروج", 61 | "unknown": "غير معروف" 62 | } 63 | }, 64 | "settings": { 65 | "header": "الإعدادات", 66 | "font": { 67 | "header": "تشغيل خط النظام", 68 | "description": "هذا الخيار يقوم بعرض النص بخط النظام بدلا من خط WebUI. قد لا يتوافق مع FlipFont" 69 | }, 70 | "theme": { 71 | "header": "الثيمات", 72 | "description": "اختر الثيم المناسب" 73 | }, 74 | "language": { 75 | "header": "تغيير اللغة", 76 | "description": "غير إلى لغة أخرى" 77 | }, 78 | "logs": { 79 | "header": "سجل الأخطاء", 80 | "description": "إعرض كل سجلات الأخطاء" 81 | }, 82 | "credits": { 83 | "module": "مطور الإضافة", 84 | "original": "المطورون الأصليون", 85 | "web": "مطور واجهة الويب" 86 | }, 87 | "license": { 88 | "module": "ترخيص الإضافة", 89 | "web": "ترخيص واجهة الويب" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/en_US.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "English (United States)", 3 | "global": { 4 | "unknown": "Unknown" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Choose your new language" 9 | }, 10 | "theme": { 11 | "header": "Choose your new theme", 12 | "dark": "Dark", 13 | "light": "Light", 14 | "system": "System Based" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "COPY", 19 | "clear": "CLEAR ALL LOGS" 20 | }, 21 | "header": "Error History", 22 | "placeholder": "No error log recorded here!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Home", 28 | "status": { 29 | "notWorking": "Not Working", 30 | "ok": "Working", 31 | "partially": "Partially Working" 32 | }, 33 | "info": { 34 | "version": "Version", 35 | "root": "Root Implementation", 36 | "zygote": { 37 | "injected": "Injected", 38 | "notInjected": "Not Injected", 39 | "unknown": "Unknown" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Modules", 45 | "notAvaliable": "No modules using Zygisk here.", 46 | "arch": "Architecture: " 47 | }, 48 | "actions": { 49 | "header": "Action", 50 | "monitorButton": { 51 | "start": "Start", 52 | "stop": "Stop", 53 | "pause": "Pause" 54 | }, 55 | "monitor": "Monitor", 56 | "status": { 57 | "tracing": "Tracing", 58 | "stopping": "Stopping", 59 | "stopped": "Stopped", 60 | "exiting": "Exiting", 61 | "unknown": "Unknown" 62 | } 63 | }, 64 | "settings": { 65 | "header": "Settings", 66 | "font": { 67 | "header": "Enable system font", 68 | "description": "This option will enable system font in current WebUI. NOTE: May not be compatible with FlipFont" 69 | }, 70 | "theme": { 71 | "header": "System theme", 72 | "description": "Choose your system theme for current WebUI" 73 | }, 74 | "language": { 75 | "header": "Change language", 76 | "description": "Change to your new language" 77 | }, 78 | "logs": { 79 | "header": "Error History", 80 | "description": "View all of your error log" 81 | }, 82 | "credits": { 83 | "module": "Module Developer", 84 | "original": "Original Module Developer", 85 | "web": "WebUI Developer" 86 | }, 87 | "license": { 88 | "module": "Module License", 89 | "web": "WebUI License" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/tr_TR.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Türkçe (Türkiye)", 3 | "global": { 4 | "unknown": "Bilinmiyor" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Yeni dilinizi seçin" 9 | }, 10 | "theme": { 11 | "header": "Yeni temanızı seçin", 12 | "dark": "Koyu", 13 | "light": "Açık", 14 | "system": "Sistem Tabanlı" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "KOPYALA", 19 | "clear": "BÜTÜN KAYITLARI SİL" 20 | }, 21 | "header": "Hata Geçmişi", 22 | "placeholder": "Burada kaydedilmiş hata yok!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Anasayfa", 28 | "status": { 29 | "notWorking": "Aktif Değil", 30 | "ok": "Aktif", 31 | "partially": "Yarı-Aktif" 32 | }, 33 | "info": { 34 | "version": "Versiyon", 35 | "root": "Root İmplementasyonu", 36 | "zygote": { 37 | "injected": "Enjekte", 38 | "notInjected": "Enjekte Değil", 39 | "unknown": "Bilinmiyor" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Modüller", 45 | "notAvaliable": "Burada Zygisk kullanan modül yok.", 46 | "arch": "Mimari: " 47 | }, 48 | "actions": { 49 | "header": "Hareketler", 50 | "monitorButton": { 51 | "start": "Başlat", 52 | "stop": "Bitir", 53 | "pause": "Durdur" 54 | }, 55 | "monitor": "Monitör", 56 | "status": { 57 | "tracing": "İzleniyor", 58 | "stopping": "Durduluyor", 59 | "stopped": "Durdu", 60 | "exiting": "Çıkılıyor", 61 | "unknown": "Bilinmiyor" 62 | } 63 | }, 64 | "settings": { 65 | "header": "Ayarlar", 66 | "font": { 67 | "header": "Sistem yazı tipini aktifleştir", 68 | "description": "Bu seçenek anlık WebUI (Web Arayüzü) için sistem yazıt tipini aktifleştirir. NOT: FlipFont ile uyumlu olmayabilir!" 69 | }, 70 | "theme": { 71 | "header": "Sistem Teması", 72 | "description": "Anlık WebUI için sistem temanı seç" 73 | }, 74 | "language": { 75 | "header": "Dil değiştir", 76 | "description": "Yeni dilini seç" 77 | }, 78 | "logs": { 79 | "header": "Hata Geçmişi", 80 | "description": "Bütün hata kayıtlarını görüntüle" 81 | }, 82 | "credits": { 83 | "module": "Modül Geliştiricisi", 84 | "original": "Orijinal Modül Geliştiricisi", 85 | "web": "WebUI Geliştiricisi" 86 | }, 87 | "license": { 88 | "module": "Modül Lisansı", 89 | "web": "WebUI Lisansı" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/ms_MS.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Malay (Malaysia)", 3 | "global": { 4 | "unknown": "Tidak diketahui" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Pilih bahasa anda" 9 | }, 10 | "theme": { 11 | "header": "Pilih tema anda", 12 | "dark": "Gelap", 13 | "light": "Cerah", 14 | "system": "Berasaskan Sistem" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "Salin", 19 | "clear": "KOSONGKAN SEMUA LOG" 20 | }, 21 | "header": "Sejarah Ralat", 22 | "placeholder": "Tiada log ralat direkodkan di sini!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Home", 28 | "status": { 29 | "notWorking": "Tidak Berfungsi", 30 | "ok": "Berfungsi", 31 | "partially": "Separa Berfungsi" 32 | }, 33 | "info": { 34 | "version": "Versi", 35 | "root": "Pelaksanaan Root", 36 | "zygote": { 37 | "injected": "Disuntik", 38 | "notInjected": "Tidak Disuntik", 39 | "unknown": "Tidak diketahui" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Modul", 45 | "notAvaliable": "Tiada modul menggunakan Zygisk di sini.", 46 | "arch": "Arkitektur: " 47 | }, 48 | "settings": { 49 | "header": "Tetapan", 50 | "font": { 51 | "header": "Hidupkan fon sistem", 52 | "description": "Pilihan ini akan menghidupkan fon sistem dalam WebUI semasa. NOTA: Mungkin tidak serasi dengan FlipFont" 53 | }, 54 | "theme": { 55 | "header": "Tema sistem", 56 | "description": "Pilih tema sistem anda untuk WebUI semasa" 57 | }, 58 | "language": { 59 | "header": "Tukar bahasa", 60 | "description": "Tukar kepada bahasa baharu anda" 61 | }, 62 | "logs": { 63 | "header": "Sejarah Ralat", 64 | "description": "Lihat semua log ralat anda" 65 | }, 66 | "credits": { 67 | "module": "Pembangun Modul", 68 | "original": "Pembangun Modul Asal", 69 | "web": "Pembangun WebUI" 70 | }, 71 | "license": { 72 | "module": "Lesen Modul", 73 | "web": "Lesen WebUI" 74 | } 75 | }, 76 | "actions": { 77 | "header": "Tindakan", 78 | "monitorButton": { 79 | "pause": "Berhenti sebentar", 80 | "stop": "Berhenti", 81 | "start": "Mula" 82 | }, 83 | "monitor": "Pantau", 84 | "status": { 85 | "tracing": "Menjejak", 86 | "stopping": "Berhenti", 87 | "stopped": "Telah Berhenti", 88 | "exiting": "Keluar", 89 | "unknown": "Tidak diketahui" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/uk_UA.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Українська (Україна)", 3 | "global": { 4 | "unknown": "Невідомо" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Оберіть нову мову" 9 | }, 10 | "theme": { 11 | "header": "Оберіть нову тему", 12 | "dark": "Темна", 13 | "light": "Світла", 14 | "system": "За системною" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "Копіювати", 19 | "clear": "Очистити всі записи" 20 | }, 21 | "header": "Історія помилок", 22 | "placeholder": "Жодної помилки не було записано тут!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Головна", 28 | "status": { 29 | "notWorking": "Не працює", 30 | "ok": "Працює", 31 | "partially": "Частково працює" 32 | }, 33 | "info": { 34 | "version": "Версія", 35 | "root": "Root реалізація", 36 | "zygote": { 37 | "injected": "Ін'єктовано", 38 | "notInjected": "Не ін'єктовано", 39 | "unknown": "Невідомо" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Модулі", 45 | "notAvaliable": "Немає модулів, які б використовували Zygisk.", 46 | "arch": "Архітектура: " 47 | }, 48 | "actions": { 49 | "header": "Дії", 50 | "monitorButton": { 51 | "start": "Почати", 52 | "stop": "Зупинити", 53 | "pause": "Пауза" 54 | }, 55 | "monitor": "Моніторинг", 56 | "status": { 57 | "tracing": "Відстежується", 58 | "stopping": "Зупиняється", 59 | "stopped": "Зупинено", 60 | "exiting": "Виходить", 61 | "unknown": "Невідомий" 62 | } 63 | }, 64 | "settings": { 65 | "header": "Налаштування", 66 | "font": { 67 | "header": "Увімкнути системний шрифт", 68 | "description": "Ця опція увімкне системний шрифт у поточному WebUI. Примітка: Може бути несумісною з FlipFont" 69 | }, 70 | "theme": { 71 | "header": "Системна тема", 72 | "description": "Виберіть системну тему для поточного WebUI" 73 | }, 74 | "language": { 75 | "header": "Змінити мову", 76 | "description": "Змінити на вашу нову мову" 77 | }, 78 | "logs": { 79 | "header": "Журнал помилок", 80 | "description": "Переглянути весь журнал помилок" 81 | }, 82 | "credits": { 83 | "module": "Розробники модуля", 84 | "original": "Оригінальний розробник модуля", 85 | "web": "Розробник WebUI" 86 | }, 87 | "license": { 88 | "module": "Ліцензія модуля", 89 | "web": "Ліцензія WebUI" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/id_ID.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Bahasa Indonesia (Indonesia)", 3 | "global": { 4 | "unknown": "Tidak diketahui" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Pilih bahasa baru Anda" 9 | }, 10 | "theme": { 11 | "header": "Pilih tema baru Anda", 12 | "dark": "Gelap", 13 | "light": "Terang", 14 | "system": "Bawaan Sistem" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "SALIN", 19 | "clear": "BERSIHKAN SEMUA LOG" 20 | }, 21 | "header": "Log Error", 22 | "placeholder": "Tidak ada log error tercatat disini!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Beranda", 28 | "status": { 29 | "notWorking": "Tidak Bekerja", 30 | "ok": "Bekerja", 31 | "partially": "Bekerja Sebagian" 32 | }, 33 | "info": { 34 | "version": "Versi", 35 | "root": "Implementasi Root", 36 | "zygote": { 37 | "injected": "Terinjeksi", 38 | "notInjected": "Tidak Terinjeksi", 39 | "unknown": "Tidak diketahui" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Modul", 45 | "notAvaliable": "Tidak ada modul yang menggunakan Zygisk disini.", 46 | "arch": "Arsitektur: " 47 | }, 48 | "settings": { 49 | "header": "Pengaturan", 50 | "font": { 51 | "header": "Gunakan Font Sistem", 52 | "description": "Opsi ini akan mengaktifkan font sistem pada WebUI saat ini. (Mungkin tidak kompatibel dengan FlipFont)" 53 | }, 54 | "theme": { 55 | "header": "Tema Sistem", 56 | "description": "Pilih tema untuk tampilan WebUI Anda saat ini" 57 | }, 58 | "language": { 59 | "header": "Ubah Bahasa", 60 | "description": "Ubah ke bahasa baru Anda" 61 | }, 62 | "logs": { 63 | "header": "Log Error", 64 | "description": "Lihat semua log Error Anda" 65 | }, 66 | "credits": { 67 | "module": "Developer Modul", 68 | "original": "Developer Modul Asli", 69 | "web": "Developer WebUI" 70 | }, 71 | "license": { 72 | "module": "Lisensi Modul", 73 | "web": "Lisensi WebUI" 74 | } 75 | }, 76 | "actions": { 77 | "header": "Tindakan", 78 | "monitorButton": { 79 | "pause": "Jeda", 80 | "stop": "Berhenti", 81 | "start": "Mulai" 82 | }, 83 | "monitor": "Monitor", 84 | "status": { 85 | "tracing": "Melacak", 86 | "stopping": "Menghentikan", 87 | "stopped": "Terhenti", 88 | "exiting": "Terkeluar", 89 | "unknown": "Tidak diketahui" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/js/smallPage/theme.js: -------------------------------------------------------------------------------- 1 | import { smallPageDisabler } from '../smallPageDesabler.js' 2 | import { setAmoled } from '../themes/amoled.js' 3 | import { setDark } from '../themes/dark.js' 4 | import { setLight } from '../themes/light.js' 5 | import { setMonochrome } from '../themes/monochrome.js' 6 | 7 | // INFO: requirement variables 8 | let sys_theme 9 | const page_toggle = document.getElementById('theme_page_toggle') 10 | const themeList = { 11 | amoled: () => setAmoled(true), 12 | dark: () => setDark(true), 13 | light: () => setLight(true), 14 | monochrome: () => setMonochrome(true), 15 | system: (unavaliable) => { 16 | const isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches 17 | if (isDark && unavaliable) setDark() 18 | else setLight() 19 | }, 20 | } 21 | const setData = (mode) => { 22 | localStorage.setItem('/system/theme', mode) 23 | return mode 24 | } 25 | 26 | // INFO: Initial open logic 27 | sys_theme = localStorage.getItem('/system/theme') 28 | if (!sys_theme) sys_theme = setData('dark') 29 | themeList[sys_theme](true) 30 | 31 | // INFO: Event logic 32 | const navbar_data_tag = document.getElementById('cache-navbar-previous') 33 | const small_panel_data_tag = document.getElementById('cache-page-small-previous') 34 | 35 | document.getElementById('sp_theme_close').addEventListener('click', () => smallPageDisabler('theme', 'settings')) 36 | 37 | document.addEventListener('click', async (event) => { 38 | const themeListKey = Object.keys(themeList) 39 | const getThemeMode = event.target.getAttribute('theme-data') 40 | 41 | if (!getThemeMode || typeof getThemeMode !== 'string' || !themeListKey.includes(getThemeMode)) return 42 | 43 | themeList[getThemeMode](true) 44 | 45 | smallPageDisabler('theme', 'settings') 46 | 47 | sys_theme = setData(getThemeMode) 48 | }, false) 49 | 50 | page_toggle.addEventListener('click', () => { 51 | const previous = !navbar_data_tag.getAttribute('content') ? setTagData('home', small_panel_data_tag) : navbar_data_tag.getAttribute('content') 52 | document.getElementById(`panel_${previous}`).classList.remove('show') 53 | document.getElementById('small_panel_theme').classList.toggle('show') 54 | small_panel_data_tag.setAttribute('content', 'theme') 55 | }) 56 | 57 | window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { 58 | if (sys_theme !== "system") return 59 | const newColorScheme = event.matches ? "dark" : "light"; 60 | 61 | switch (newColorScheme) { 62 | case 'dark': 63 | setDark() 64 | break 65 | case 'light': 66 | setLight() 67 | break 68 | } 69 | }); 70 | 71 | function setTagData(data, tag) { 72 | tag.setAttribute('content', data) 73 | 74 | return data 75 | } 76 | -------------------------------------------------------------------------------- /webroot/lang/ru_RU.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Русский (Россия)", 3 | "global": { 4 | "unknown": "Неизвестно" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Выберите ваш новый язык" 9 | }, 10 | "theme": { 11 | "header": "Выберите свою новую тему", 12 | "dark": "Темная", 13 | "light": "Светлая", 14 | "system": "На основе системной темы" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "Копировать", 19 | "clear": "Очистить все логи" 20 | }, 21 | "header": "Журнал ошибок", 22 | "placeholder": "Журнал ошибок здесь не ведется!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Главная", 28 | "status": { 29 | "notWorking": "Не работает", 30 | "ok": "Работает", 31 | "partially": "Частично работает" 32 | }, 33 | "info": { 34 | "version": "Версия", 35 | "root": "Root реализация", 36 | "zygote": { 37 | "injected": "Инъецировано", 38 | "notInjected": "Не инъецировано", 39 | "unknown": "Неизвестно" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Модули", 45 | "notAvaliable": "Здесь нет модулей, использующих Zygisk.", 46 | "arch": "Архитектура: " 47 | }, 48 | "settings": { 49 | "header": "Настройки", 50 | "font": { 51 | "header": "Включить системный шрифт", 52 | "description": "Эта опция включит системный шрифт в текущем WebUI. ПРИМЕЧАНИЕ: Может быть несовместимо с FlipFont" 53 | }, 54 | "theme": { 55 | "header": "Системная тема", 56 | "description": "Выберите вашу системную тему для текущего WebUI" 57 | }, 58 | "language": { 59 | "header": "Сменить язык", 60 | "description": "Измените на ваш новый язык" 61 | }, 62 | "logs": { 63 | "header": "История ошибок", 64 | "description": "Просмотреть весь журнал ваших ошибок" 65 | }, 66 | "credits": { 67 | "module": "Разработчик модуля", 68 | "original": "Разработчик оригинального модуля", 69 | "web": "Разработчик WebUI" 70 | }, 71 | "license": { 72 | "module": "Лицензия модуля", 73 | "web": "Лицензия WebUI" 74 | } 75 | }, 76 | "actions": { 77 | "header": "Действия", 78 | "monitorButton": { 79 | "pause": "Пауза", 80 | "stop": "Стоп", 81 | "start": "Начать" 82 | }, 83 | "monitor": "Обзор", 84 | "status": { 85 | "tracing": "Состояние", 86 | "stopping": "Остановка", 87 | "stopped": "Остановлено", 88 | "exiting": "Выход", 89 | "unknown": "Неизвестно" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/de_DE.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Deutsch", 3 | "global": { 4 | "unknown": "Unbekannt" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Neue Sprache wählen" 9 | }, 10 | "theme": { 11 | "header": "Neues Theme wählen", 12 | "dark": "Dunkel", 13 | "light": "Hell", 14 | "system": "System Basiert" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "Kopieren", 19 | "clear": "ALLE LOGS LÖSCHEN" 20 | }, 21 | "header": "Fehler Verlauf", 22 | "placeholder": "Es wurde kein Fehlerprotokoll aufgezeichnet!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Startseite", 28 | "status": { 29 | "notWorking": "Funktioniert nicht", 30 | "ok": "Funktioniert", 31 | "partially": "Funktioniert zum Teil" 32 | }, 33 | "info": { 34 | "version": "Version", 35 | "root": "Root Implementierung", 36 | "zygote": { 37 | "injected": "Injiziert", 38 | "notInjected": "Nicht Injiziert", 39 | "unknown": "Unbekannt" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Module", 45 | "notAvaliable": "Kein Modul nutzt Zygisk.", 46 | "arch": "Architektur: " 47 | }, 48 | "settings": { 49 | "header": "Einstellungen", 50 | "font": { 51 | "header": "Systemschriftart aktivieren", 52 | "description": "Diese Option aktiviert die Systemschriftart in der aktuellen WebUI. HINWEIS: Möglicherweise nicht kompatibel mit FlipFont" 53 | }, 54 | "theme": { 55 | "header": "System Theme", 56 | "description": "Wählen Sie Ihr System-Theme für die aktuelle WebUI" 57 | }, 58 | "language": { 59 | "header": "Sprache auswählen", 60 | "description": "Wechsel zu deiner neuen Sprache" 61 | }, 62 | "logs": { 63 | "header": "Fehler Verlauf", 64 | "description": "Zeige den Fehler Verlauf" 65 | }, 66 | "credits": { 67 | "module": "Modul Entwickler", 68 | "original": "Original Modul Entwickler", 69 | "web": "WebUI Entwickler" 70 | }, 71 | "license": { 72 | "module": "Modul Lizenz", 73 | "web": "WebUI Lizenz" 74 | } 75 | }, 76 | "actions": { 77 | "header": "Aktionen", 78 | "monitorButton": { 79 | "pause": "Pause", 80 | "stop": "Stopp", 81 | "start": "Start" 82 | }, 83 | "monitor": "Überwachen", 84 | "status": { 85 | "tracing": "Nachverfolgung", 86 | "stopping": "Beenden", 87 | "stopped": "Beendet", 88 | "exiting": "Wird Beendet", 89 | "unknown": "Unbekannt" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/nl_NL.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Nederlands", 3 | "global": { 4 | "unknown": "Onbekend" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Kies uw nieuwe taal" 9 | }, 10 | "theme": { 11 | "header": "Kies uw nieuwe thema", 12 | "dark": "Donker", 13 | "light": "Licht", 14 | "system": "Systeem Gebaseerd" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "KOPIËREN", 19 | "clear": "VERWIJDER ALLE LOGS" 20 | }, 21 | "header": "Foutmelding Geschiedenis", 22 | "placeholder": "Er is hier geen foutlogboek geregistreerd!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Thuis", 28 | "status": { 29 | "notWorking": "Werkt Niet", 30 | "ok": "Werkt", 31 | "partially": "Werkt Gedeeltelijk" 32 | }, 33 | "info": { 34 | "version": "Versie", 35 | "root": "Root Implementatie", 36 | "zygote": { 37 | "injected": "Geïnjecteerd", 38 | "notInjected": "Niet Geïnjecteerd", 39 | "unknown": "Onbekend" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Modules", 45 | "notAvaliable": "Geen modules die Zygisk gebruiken.", 46 | "arch": "Architectuur: " 47 | }, 48 | "settings": { 49 | "header": "Instellingen", 50 | "font": { 51 | "header": "Systeem lettertype inschakelen", 52 | "description": "Deze optie zal het systeemlettertype inschakelen in huidige WebUI. Opmerking: Kan niet compatibel zijn met FlipFont" 53 | }, 54 | "theme": { 55 | "header": "Systeem thema", 56 | "description": "Kies uw systeemthema voor huidige WebUI" 57 | }, 58 | "language": { 59 | "header": "Taal wijzigen", 60 | "description": "Verander naar nieuwe taal" 61 | }, 62 | "logs": { 63 | "header": "Foutmelding Geschiedenis", 64 | "description": "Al uw foutenlogboek weergeven" 65 | }, 66 | "credits": { 67 | "module": "Module Ontwikkelaar", 68 | "original": "Originele Module Ontwikkelaar", 69 | "web": "WebUI Ontwikkelaar" 70 | }, 71 | "license": { 72 | "module": "Module Licentie", 73 | "web": "WebUI Licentie" 74 | } 75 | }, 76 | "actions": { 77 | "header": "Acties", 78 | "monitorButton": { 79 | "pause": "Pauzeren", 80 | "stop": "Stoppen", 81 | "start": "Starten" 82 | }, 83 | "monitor": "Bewaken", 84 | "status": { 85 | "tracing": "Traceren", 86 | "stopping": "Bezig met Stoppen", 87 | "stopped": "Gestopt", 88 | "exiting": "Wordt Beëindigd", 89 | "unknown": "Onbekend" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/vi_VN.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Tiếng Việt", 3 | "global": { 4 | "unknown": "Không xác định" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Chọn ngôn ngữ mới của bạn" 9 | }, 10 | "theme": { 11 | "header": "Chọn giao diện mới của bạn", 12 | "dark": "Tối", 13 | "light": "Sáng", 14 | "system": "Theo hệ thống" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "SAO CHÉP", 19 | "clear": "XOÁ TOÀN BỘ LOGS" 20 | }, 21 | "header": "Lịch Sử Lỗi", 22 | "placeholder": "Không có lỗi nào được ghi ở đây!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Trang Chủ", 28 | "status": { 29 | "notWorking": "Không hoạt động", 30 | "ok": "Đang hoạt động", 31 | "partially": "Đang hoạt động một phần" 32 | }, 33 | "info": { 34 | "version": "Phiên bản", 35 | "root": "Hệ thống root", 36 | "zygote": { 37 | "injected": "Đã can thiệp", 38 | "notInjected": "Chưa can thiệp", 39 | "unknown": "Không xác định" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Mô Đun", 45 | "notAvaliable": "Không có mô-đun nào sử dụng Zygisk ở đây!", 46 | "arch": "Cấu trúc: " 47 | }, 48 | "actions": { 49 | "header": "Trình điều khiển", 50 | "monitorButton": { 51 | "start": "Chạy", 52 | "stop": "Dừng", 53 | "pause": "Tạm Dừng" 54 | }, 55 | "monitor": "Trình theo dõi", 56 | "status": { 57 | "tracing": "Đang chạy", 58 | "stopping": "Đang Dừng", 59 | "stopped": "Đã Dừng", 60 | "exiting": "Đã Thoát", 61 | "unknown": "Không Xác Định" 62 | } 63 | }, 64 | "settings": { 65 | "header": "Cài đặt", 66 | "font": { 67 | "header": "Sử dụng phông chữ hệ thống", 68 | "description": "Tuỳ chọn này sẽ cho phép người dùng sử dụng phông chữ của hệ thống. LƯU Ý: Có thể sẽ không tương thích với FlipFont" 69 | }, 70 | "theme": { 71 | "header": "Giao diện hệ thống", 72 | "description": "Chọn giao diện cho WebUI hiện tại của bạn" 73 | }, 74 | "language": { 75 | "header": "Thay đổi ngôn ngữ", 76 | "description": "Thay đổi sang ngôn ngữ mới" 77 | }, 78 | "logs": { 79 | "header": "Lịch sử lỗi", 80 | "description": "Xem tất cả các lỗi" 81 | }, 82 | "credits": { 83 | "module": "Nhà phát triển mô-đun", 84 | "original": "Nhà phát triển mô-đun gốc", 85 | "web": "Nhà phát triển WebUI" 86 | }, 87 | "license": { 88 | "module": "Giấy phép bản quyền mô-đun", 89 | "web": "Giấy phép bản quyền WebUI" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/it_IT.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Italiano (Italia)", 3 | "global": { 4 | "unknown": "Sconosciuto" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Scegli la tua nuova lingua" 9 | }, 10 | "theme": { 11 | "header": "Scegli il tuo nuovo tema", 12 | "dark": "Scuro", 13 | "light": "Chiaro", 14 | "system": "Sistema" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "COPIA", 19 | "clear": "CANCELLA TUTTI I LOGS" 20 | }, 21 | "header": "Storico degli Errori", 22 | "placeholder": "Nessun errore è stato registrato qui!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Home", 28 | "status": { 29 | "notWorking": "Non funzionante", 30 | "ok": "Funzionante", 31 | "partially": "Funzionante Parzialmente" 32 | }, 33 | "info": { 34 | "version": "Versione", 35 | "root": "Implementazione root", 36 | "zygote": { 37 | "injected": "Iniettato", 38 | "notInjected": "Non Iniettato", 39 | "unknown": "Sconosciuto" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Moduli", 45 | "notAvaliable": "Nessun modulo che utilizza Zygisk qui.", 46 | "arch": "Architettura: " 47 | }, 48 | "settings": { 49 | "header": "Impostazioni", 50 | "font": { 51 | "header": "Abilita font di sistema", 52 | "description": "Questa opzione abiliterà il font di sistema nella WebUI. NOTA: Potrebbe non funzionare bene con FlipFont" 53 | }, 54 | "theme": { 55 | "header": "Tema di sistema", 56 | "description": "Scegli il tuo tema di sistema per la WebUI" 57 | }, 58 | "language": { 59 | "header": "Cambia lingua", 60 | "description": "Cambia alla tua nuova lingua" 61 | }, 62 | "logs": { 63 | "header": "Storico degli errori", 64 | "description": "Visualizza tutto il log dell'errore" 65 | }, 66 | "credits": { 67 | "module": "Programmatore del Modulo", 68 | "original": "Programmatore del Modulo Originale", 69 | "web": "Programmatore della WebUI" 70 | }, 71 | "license": { 72 | "module": "Licenza del modulo", 73 | "web": "Licenza della WebUI" 74 | } 75 | }, 76 | "actions": { 77 | "header": "Azioni", 78 | "monitorButton": { 79 | "pause": "Pausa", 80 | "stop": "Ferma", 81 | "start": "Avvia" 82 | }, 83 | "monitor": "Controlla", 84 | "status": { 85 | "tracing": "Tracing", 86 | "stopping": "Fermando", 87 | "stopped": "Fermato", 88 | "exiting": "Uscendo", 89 | "unknown": "Sconosciuto" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/es_AR.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Español", 3 | "global": { 4 | "unknown": "Desconocido" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Selecciona tu nuevo idioma" 9 | }, 10 | "theme": { 11 | "header": "Elige tu nuevo tema", 12 | "dark": "Oscuro", 13 | "light": "Claro", 14 | "system": "Basado en el sistema" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "COPIAR", 19 | "clear": "BORRAR TODOS LOS REGISTROS" 20 | }, 21 | "header": "Historial de errores", 22 | "placeholder": "¡No se registró ningún error aquí!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Inicio", 28 | "status": { 29 | "notWorking": "No funciona", 30 | "ok": "Funcionando", 31 | "partially": "Funciona parcialmente" 32 | }, 33 | "info": { 34 | "version": "Versión", 35 | "root": "Implementación de root", 36 | "zygote": { 37 | "injected": "Inyectado", 38 | "notInjected": "No inyectado", 39 | "unknown": "Desconocido" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Módulos", 45 | "notAvaliable": "No hay módulos que usen Zygisk aquí.", 46 | "arch": "Arquitectura: " 47 | }, 48 | "settings": { 49 | "header": "Ajustes", 50 | "font": { 51 | "header": "Activar fuente del sistema", 52 | "description": "Esta opción habilitará la fuente del sistema en el WebUI actual. NOTA: Puede no ser compatible con FlipFont" 53 | }, 54 | "theme": { 55 | "header": "Tema del sistema", 56 | "description": "Elija el tema del sistema para el WebUI actual" 57 | }, 58 | "language": { 59 | "header": "Cambiar idioma", 60 | "description": "Selecciona tu nuevo idioma" 61 | }, 62 | "logs": { 63 | "header": "Historial de errores", 64 | "description": "Ver todos tus registros de errores" 65 | }, 66 | "credits": { 67 | "module": "Desarrollador del módulo", 68 | "original": "Desarrollador original del módulo", 69 | "web": "Desarrollador de la WebUI" 70 | }, 71 | "license": { 72 | "module": "Licencia del módulo", 73 | "web": "Licencia de la WebUI" 74 | } 75 | }, 76 | "actions": { 77 | "header": "Acciones", 78 | "monitorButton": { 79 | "pause": "Pausar", 80 | "stop": "Detener", 81 | "start": "Iniciar" 82 | }, 83 | "monitor": "Monitor", 84 | "status": { 85 | "tracing": "Trazando", 86 | "stopping": "Deteniendo", 87 | "stopped": "Detenido", 88 | "exiting": "Saliendo", 89 | "unknown": "Desconocido" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/es_ES.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Español", 3 | "global": { 4 | "unknown": "Desconocido" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Selecciona tu nuevo idioma" 9 | }, 10 | "theme": { 11 | "header": "Elige tu nuevo tema", 12 | "dark": "Oscuro", 13 | "light": "Claro", 14 | "system": "Basado en el sistema" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "COPIAR", 19 | "clear": "BORRAR TODOS LOS REGISTROS" 20 | }, 21 | "header": "Historial de errores", 22 | "placeholder": "¡No se registró ningún error aquí!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Inicio", 28 | "status": { 29 | "notWorking": "No funciona", 30 | "ok": "Funcionando", 31 | "partially": "Funciona parcialmente" 32 | }, 33 | "info": { 34 | "version": "Versión", 35 | "root": "Implementación de root", 36 | "zygote": { 37 | "injected": "Inyectado", 38 | "notInjected": "No inyectado", 39 | "unknown": "Desconocido" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Módulos", 45 | "notAvaliable": "No hay módulos que usen Zygisk aquí.", 46 | "arch": "Arquitectura: " 47 | }, 48 | "settings": { 49 | "header": "Ajustes", 50 | "font": { 51 | "header": "Activar fuente del sistema", 52 | "description": "Esta opción habilitará la fuente del sistema en el WebUI actual. NOTA: Puede no ser compatible con FlipFont" 53 | }, 54 | "theme": { 55 | "header": "Tema del sistema", 56 | "description": "Elija el tema del sistema para el WebUI actual" 57 | }, 58 | "language": { 59 | "header": "Cambiar idioma", 60 | "description": "Selecciona tu nuevo idioma" 61 | }, 62 | "logs": { 63 | "header": "Historial de errores", 64 | "description": "Ver todos tus registros de errores" 65 | }, 66 | "credits": { 67 | "module": "Desarrollador del módulo", 68 | "original": "Desarrollador original del módulo", 69 | "web": "Desarrollador de la WebUI" 70 | }, 71 | "license": { 72 | "module": "Licencia del módulo", 73 | "web": "Licencia de la WebUI" 74 | } 75 | }, 76 | "actions": { 77 | "header": "Acciones", 78 | "monitorButton": { 79 | "pause": "Pausar", 80 | "stop": "Detener", 81 | "start": "Iniciar" 82 | }, 83 | "monitor": "Monitor", 84 | "status": { 85 | "tracing": "Trazando", 86 | "stopping": "Deteniendo", 87 | "stopped": "Detenido", 88 | "exiting": "Saliendo", 89 | "unknown": "Desconocido" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/es_MX.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Español (México)", 3 | "global": { 4 | "unknown": "Desconocido" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Elige tu nuevo tema" 9 | }, 10 | "theme": { 11 | "header": "Elige tu nuevo tema", 12 | "dark": "Oscuro", 13 | "light": "Claro", 14 | "system": "Basado en el sistema" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "COPIAR", 19 | "clear": "BORRAR TODOS LOS REGISTROS" 20 | }, 21 | "header": "Historial de errores", 22 | "placeholder": "¡No se registró ningún error aquí!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Inicio", 28 | "status": { 29 | "notWorking": "No funcionando", 30 | "ok": "Funcionando", 31 | "partially": "Funcionando parcialmente" 32 | }, 33 | "info": { 34 | "version": "Versión", 35 | "root": "Implementación de root", 36 | "zygote": { 37 | "injected": "Inyectado", 38 | "notInjected": "No inyectado", 39 | "unknown": "Desconocido" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Módulos", 45 | "notAvaliable": "No hay módulos que usen Zygisk aquí.", 46 | "arch": "Arquitectura: " 47 | }, 48 | "settings": { 49 | "header": "Ajustes", 50 | "font": { 51 | "header": "Activar fuente del sistema", 52 | "description": "Esta opción habilitará la fuente del sistema en el WebUI actual. NOTA: Puede no ser compatible con FlipFont" 53 | }, 54 | "theme": { 55 | "header": "Tema del sistema", 56 | "description": "Elige el tema del sistema para el WebUI actual" 57 | }, 58 | "language": { 59 | "header": "Cambiar idioma", 60 | "description": "Cambia a tu nuevo idioma." 61 | }, 62 | "logs": { 63 | "header": "Historial de errores", 64 | "description": "Ver todos tus registros de errores" 65 | }, 66 | "credits": { 67 | "module": "Desarrollador del módulo", 68 | "original": "Desarrollador original del módulo", 69 | "web": "Desarrollador de la WebUI" 70 | }, 71 | "license": { 72 | "module": "Licencia del módulo", 73 | "web": "Licencia de la WebUI" 74 | } 75 | }, 76 | "actions": { 77 | "header": "Acciones", 78 | "monitorButton": { 79 | "pause": "Pausar", 80 | "stop": "Detener", 81 | "start": "Iniciar" 82 | }, 83 | "monitor": "Monitor", 84 | "status": { 85 | "tracing": "Trazando", 86 | "stopping": "Deteniendo", 87 | "stopped": "Detenido", 88 | "exiting": "Saliendo", 89 | "unknown": "Desconocido" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/pt_BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Português (Brasil)", 3 | "global": { 4 | "unknown": "Desconhecido" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Escolha o seu novo idioma" 9 | }, 10 | "theme": { 11 | "header": "Escolha o seu novo tema", 12 | "dark": "Escuro", 13 | "light": "Claro", 14 | "system": "Baseado no do sistema" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "COPIAR", 19 | "clear": "LIMPAR TODOS OS REGISTROS" 20 | }, 21 | "header": "Histórico de Erros", 22 | "placeholder": "Nenhum registro de erros aqui!" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Início", 28 | "status": { 29 | "notWorking": "Não funcionando", 30 | "ok": "Funcionando", 31 | "partially": "Funcionando parcialmente" 32 | }, 33 | "info": { 34 | "version": "Versão", 35 | "root": "Implementação de Root", 36 | "zygote": { 37 | "injected": "Injetado", 38 | "notInjected": "Não Injetado", 39 | "unknown": "Desconhecido" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Módulos", 45 | "notAvaliable": "Nenhum módulo está usando Zygisk aqui.", 46 | "arch": "Arquitetura: " 47 | }, 48 | "actions": { 49 | "header": "Ações", 50 | "monitorButton": { 51 | "start": "Iniciar", 52 | "stop": "Parar", 53 | "pause": "Pausar" 54 | }, 55 | "monitor": "Monitor", 56 | "status": { 57 | "tracing": "Rastreando", 58 | "stopping": "Parando", 59 | "stopped": "Parado", 60 | "exiting": "Desligando", 61 | "unknown": "Desconhecido" 62 | } 63 | }, 64 | "settings": { 65 | "header": "Configurações", 66 | "font": { 67 | "header": "Usar a fonte do sistema", 68 | "description": "Esta opção irá usar a fonte do sistema no WebUI atual. Observação: Talvez não seja compatível com o FlipFont" 69 | }, 70 | "theme": { 71 | "header": "Tema do sistema", 72 | "description": "Escolha o tema do seu sistema para o WebUI atual" 73 | }, 74 | "language": { 75 | "header": "Alterar a língua", 76 | "description": "Mude para sua nova língua" 77 | }, 78 | "logs": { 79 | "header": "Histórico de Erros", 80 | "description": "Ver o histórico de erros inteiro" 81 | }, 82 | "credits": { 83 | "module": "Desenvolvedora do módulo", 84 | "original": "Desenvolvedores do módulo original", 85 | "web": "Desenvolvedor do WebUI" 86 | }, 87 | "license": { 88 | "module": "Licença do Módulo", 89 | "web": "Licença do WebUI" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /webroot/lang/fr_FR.json: -------------------------------------------------------------------------------- 1 | { 2 | "langName": "Français (France)", 3 | "global": { 4 | "unknown": "Inconnu" 5 | }, 6 | "smallPage": { 7 | "language": { 8 | "header": "Choisissez votre nouvelle langue" 9 | }, 10 | "theme": { 11 | "header": "Choisissez votre nouveau thème", 12 | "dark": "Sombre", 13 | "light": "Clair", 14 | "system": "Basé sur le système" 15 | }, 16 | "errorh": { 17 | "buttons": { 18 | "copy": "COPIER", 19 | "clear": "EFFACER TOUS LES JOURNEAUX" 20 | }, 21 | "header": "Historique d'erreurs", 22 | "placeholder": "Pas de journal d'erreur enregistré ici !" 23 | } 24 | }, 25 | "page": { 26 | "home": { 27 | "header": "Page d'accueil", 28 | "status": { 29 | "notWorking": "Inactif", 30 | "ok": "Actif", 31 | "partially": "Fonctionnement partiel" 32 | }, 33 | "info": { 34 | "version": "Version", 35 | "root": "Implémentation root", 36 | "zygote": { 37 | "injected": "Injecté", 38 | "notInjected": "Non injecté", 39 | "unknown": "Inconnu" 40 | } 41 | } 42 | }, 43 | "modules": { 44 | "header": "Modules", 45 | "notAvaliable": "Aucuns modules n'utilisent Zygisk actuellement.", 46 | "arch": " Architecture: " 47 | }, 48 | "settings": { 49 | "header": "Paramètres", 50 | "font": { 51 | "header": "Activer la police du système", 52 | "description": "Cette option activera la police de caractère du système d'interface WebUI. NOTE: N'est peut-être pas compatible avec FlipFont" 53 | }, 54 | "theme": { 55 | "header": "Thème système", 56 | "description": "Choisissez votre thème système pour le WebUI" 57 | }, 58 | "language": { 59 | "header": "Changez de langue", 60 | "description": "Changez vers votre nouvelle langue" 61 | }, 62 | "logs": { 63 | "header": "Historique d'erreur", 64 | "description": "Voir le détail du journal d'erreur" 65 | }, 66 | "credits": { 67 | "module": "Module développeur", 68 | "original": "Module Original du Développeur", 69 | "web": "WebUI Développeur" 70 | }, 71 | "license": { 72 | "module": "Module de licence", 73 | "web": "Licence WebUI" 74 | } 75 | }, 76 | "actions": { 77 | "header": "Actions", 78 | "monitorButton": { 79 | "pause": "Mettre en Pause", 80 | "stop": "Arrêter", 81 | "start": "Démarrer" 82 | }, 83 | "monitor": "Surveillance", 84 | "status": { 85 | "tracing": "Tracer", 86 | "stopping": "Stopper immédiatement", 87 | "stopped": "Arrêté", 88 | "exiting": "Sortir d'ici", 89 | "unknown": "Inconnu" 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /zygiskd/src/utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "utils.h" 14 | #include "utils.hpp" 15 | 16 | MappedBuffer mountinfo_buf; 17 | MappedBuffer mountinfo_prev; 18 | 19 | void sync_mns(int inner_ns) { 20 | if (access(TMP_PATH "/private_mounts", F_OK) != 0) return; 21 | 22 | if (mountinfo_buf.file_read("/proc/1/mounts", mountinfo_prev.size)) { 23 | if (mountinfo_buf == mountinfo_prev) return; 24 | std::swap(mountinfo_prev, mountinfo_buf); 25 | } 26 | 27 | struct mountinfos outer_mi; 28 | if (!parse_mountinfo("1", &outer_mi)) return; 29 | 30 | int outer_ns = open("/proc/1/ns/mnt", O_RDONLY | O_CLOEXEC); 31 | if (outer_ns == -1) return; 32 | 33 | if (setns(inner_ns, CLONE_NEWNS) == -1) { 34 | close(outer_ns); 35 | return; 36 | } 37 | 38 | struct mountinfos inner_mi; 39 | if (!parse_mountinfo("self", &inner_mi)) { 40 | close(outer_ns); 41 | return; 42 | } 43 | 44 | if (setns(outer_ns, CLONE_NEWNS) == -1) { 45 | close(outer_ns); 46 | return; 47 | } 48 | 49 | std::unordered_set inner_mp; 50 | std::unordered_set outer_mp; 51 | 52 | for (size_t i = 0; i < inner_mi.length; ++i) { 53 | inner_mp.insert(inner_mi.mounts[i].target); 54 | } 55 | 56 | for (size_t i = 0; i < outer_mi.length; ++i) { 57 | if (outer_mi.mounts[i].optional.shared) continue; 58 | std::string mountpoint = outer_mi.mounts[i].target; 59 | if (mountpoint.rfind("/storage", 0) == 0) continue; 60 | if (inner_mp.find(mountpoint) != inner_mp.end()) continue; 61 | if (outer_mp.find(mountpoint) != outer_mp.end()) continue; 62 | 63 | int fd = open(mountpoint.c_str(), O_RDONLY | O_CLOEXEC); 64 | struct stat st; 65 | if (fstat(fd, &st) != 0 || st.st_dev != outer_mi.mounts[i].device) { 66 | close(fd); 67 | continue; 68 | } 69 | 70 | const char *tmp; 71 | if (S_ISDIR(st.st_mode)) tmp = TMP_PATH "/tmp/" lp_select("copy32_d", "copy64_d"); 72 | else tmp = TMP_PATH "/tmp/" lp_select("copy32_f", "copy64_f"); 73 | 74 | if (mount(mountpoint.c_str(), tmp, nullptr, MS_BIND, nullptr) == -1) { 75 | close(fd); 76 | continue; 77 | } 78 | 79 | setns(inner_ns, CLONE_NEWNS); 80 | mount(tmp, mountpoint.c_str(), nullptr, MS_BIND, nullptr); 81 | setns(outer_ns, CLONE_NEWNS); 82 | 83 | umount2(tmp, MNT_DETACH); 84 | outer_mp.insert(mountpoint); 85 | close(fd); 86 | } 87 | 88 | free_mounts(&inner_mi); 89 | free_mounts(&outer_mi); 90 | } 91 | -------------------------------------------------------------------------------- /loader/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.nio.file.Paths 2 | import org.gradle.internal.os.OperatingSystem 3 | 4 | plugins { 5 | alias(libs.plugins.agp.lib) 6 | } 7 | 8 | val verCode: Int by rootProject.extra 9 | val verName: String by rootProject.extra 10 | val commitHash: String by rootProject.extra 11 | 12 | fun Project.findInPath(executable: String, property: String): String? { 13 | val pathEnv = System.getenv("PATH") 14 | return pathEnv.split(File.pathSeparator).map { folder -> 15 | Paths.get("${folder}${File.separator}${executable}${if (OperatingSystem.current().isWindows) ".exe" else ""}") 16 | .toFile() 17 | }.firstOrNull { path -> 18 | path.exists() 19 | }?.absolutePath ?: properties.getOrDefault(property, null) as? String? 20 | } 21 | 22 | val ccachePath by lazy { 23 | project.findInPath("ccache", "ccache.path")?.also { 24 | println("loader: Use ccache: $it") 25 | } 26 | } 27 | 28 | val defaultCFlags = arrayOf( 29 | "-D_GNU_SOURCE", 30 | 31 | "-Wall", "-Wextra", 32 | "-fno-rtti", "-fno-exceptions", 33 | "-fno-stack-protector", "-fomit-frame-pointer", 34 | "-Wno-builtin-macro-redefined", "-D__FILE__=__FILE_NAME__" 35 | ) 36 | 37 | val releaseFlags = arrayOf( 38 | "-O3", "-flto=thin", 39 | "-Wno-unused", "-Wno-unused-parameter", 40 | "-fvisibility=hidden", "-fvisibility-inlines-hidden", 41 | "-fno-unwind-tables", "-fno-asynchronous-unwind-tables", 42 | "-Wl,--exclude-libs,ALL", "-Wl,--gc-sections", "-Wl,--strip-all" 43 | ) 44 | 45 | android { 46 | buildFeatures { 47 | androidResources = false 48 | buildConfig = false 49 | prefab = true 50 | } 51 | 52 | externalNativeBuild.cmake { 53 | path("src/CMakeLists.txt") 54 | buildStagingDirectory = layout.buildDirectory.get().asFile 55 | } 56 | 57 | defaultConfig { 58 | externalNativeBuild.cmake { 59 | arguments += "-DANDROID_STL=none" 60 | arguments += "-DLSPLT_STANDALONE=ON" 61 | arguments += "-DCMAKE_BUILD_PARALLEL_LEVEL=${Runtime.getRuntime().availableProcessors()}" 62 | cFlags("-std=c18", *defaultCFlags) 63 | cppFlags("-std=c++20", *defaultCFlags) 64 | ccachePath?.let { 65 | arguments += "-DNDK_CCACHE=$it" 66 | } 67 | } 68 | } 69 | 70 | buildTypes { 71 | debug { 72 | externalNativeBuild.cmake { 73 | arguments += "-DZKSU_VERSION=$verName-$verCode-$commitHash-debug" 74 | } 75 | } 76 | release { 77 | externalNativeBuild.cmake { 78 | cFlags += releaseFlags 79 | cppFlags += releaseFlags 80 | arguments += "-DZKSU_VERSION=$verName-$verCode-$commitHash-release" 81 | } 82 | } 83 | } 84 | } 85 | 86 | dependencies { 87 | implementation("dev.rikka.ndk.thirdparty:cxx:1.2.0") 88 | } 89 | -------------------------------------------------------------------------------- /loader/src/injector/solist.h: -------------------------------------------------------------------------------- 1 | #ifndef SOLIST_H 2 | #define SOLIST_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif /* __cplusplus */ 7 | 8 | typedef void SoInfo; 9 | 10 | #define FuncType(name) void (*name) 11 | 12 | struct pdg { 13 | void *(*ctor)(); 14 | void *(*dtor)(); 15 | }; 16 | 17 | /* 18 | INFO: When dlopen'ing a library, the system will save information of the 19 | opened library so a structure called soinfo, which contains another 20 | called solist, a list with the information of opened objects. 21 | 22 | Due to special handling in ptracer, however, it won't heave gaps in the 23 | memory of the list since we will remove the info immediatly after loading 24 | libzygisk.so, so that it doesn't create gaps between current module info 25 | and the next (soinfo). 26 | 27 | To do that, we use 2 functions: set_size and dlclose, which will first zero 28 | zero the size that the linker believes the shared library is, and then dlclose. 29 | Because the size is 0, it won't munmap the library, allowing us to keep loaded while 30 | having all other traces removed. 31 | 32 | For the case of modules, which are arbitrary, we won't call dlclose, as it could break 33 | the module. Instead of using dlclose, we separately call soinfo_free, which will free 34 | the soinfo structure. That will allow to keep the data initialized by constructors 35 | mmaped, hence properly dropping most traces without breaking the module. 36 | 37 | SOURCES: 38 | - https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker.cpp#1712 39 | */ 40 | bool solist_drop_so_path(void *lib_memory, bool unload); 41 | 42 | /* 43 | INFO: When dlopen'ing a library, the system will increment 1 to a global 44 | counter that tracks the amount of libraries ever loaded in that process, 45 | the same happening in dlclose. 46 | 47 | This cannot directly be used to detect if ReZygisk is present, however, with 48 | enough data about specific environments, this can be used to detect if any 49 | other library (be it malicious or not) was loaded. To avoid future detections, 50 | we patch that value to the original value. 51 | 52 | To do that, we retrieve the address of both "g_module_load_counter" and "g_module 53 | _unload_counter" variables and force set them to the original value, based on 54 | the modules dlopen'ed. 55 | 56 | SOURCES: 57 | - https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker.cpp#1874 58 | - https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker.cpp#1944 59 | - https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker.cpp#3413 60 | */ 61 | void solist_reset_counters(size_t load, size_t unload); 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif /* __cplusplus */ 66 | 67 | #endif /* SOLIST_H */ 68 | -------------------------------------------------------------------------------- /webroot/js/language.js: -------------------------------------------------------------------------------- 1 | import { exec } from './kernelsu.js' 2 | 3 | import { setError } from './main.js' 4 | import { translateActionsPage } from './translate/actions.js' 5 | import { translateHomePage } from './translate/home.js' 6 | import { translateModulesPage } from './translate/modules.js' 7 | import { translateSettingsPage } from './translate/settings.js' 8 | 9 | export async function setNewLanguage(locate, initialize) { 10 | const main_html = document.getElementById('main_html') 11 | const old_translations = await getTranslations(initialize ? 'en_US' : localStorage.getItem('/system/language')) 12 | const new_translations = await getTranslations(locate) 13 | 14 | if (locate.includes('ar_')) main_html.setAttribute("dir", "rtl"); 15 | else main_html.setAttribute("dir", "none"); 16 | 17 | translateHomePage(old_translations, new_translations) 18 | translateModulesPage(new_translations) 19 | translateActionsPage(old_translations, new_translations) 20 | translateSettingsPage(new_translations) 21 | 22 | /* INFO: navbar info */ 23 | document.getElementById('nav_home_title').innerHTML = new_translations.page.home.header 24 | document.getElementById('nav_modules_title').innerHTML = new_translations.page.modules.header 25 | document.getElementById('nav_actions_title').innerHTML = new_translations.page.actions.header 26 | document.getElementById('nav_settings_title').innerHTML = new_translations.page.settings.header 27 | 28 | /* INFO: Language small page */ 29 | document.getElementById('small_panel_lang_title').innerHTML = new_translations.smallPage.language.header 30 | 31 | /* INFO: Theme small page */ 32 | document.getElementById('small_panel_theme_title').innerHTML = new_translations.smallPage.theme.header 33 | document.getElementById('small_panel_theme_dark_option').innerHTML = new_translations.smallPage.theme.dark 34 | document.getElementById('small_panel_theme_light_option').innerHTML = new_translations.smallPage.theme.light 35 | document.getElementById('small_panel_theme_system_option').innerHTML = new_translations.smallPage.theme.system 36 | 37 | /* INFO: Error history small page */ 38 | document.getElementById('errorh_copy').innerHTML = new_translations.smallPage.errorh.buttons.copy 39 | document.getElementById('errorh_clear_all').innerHTML = new_translations.smallPage.errorh.buttons.clear 40 | document.getElementById('small_panel_errorh_title').innerHTML = new_translations.smallPage.errorh.header 41 | document.getElementById('errorh_panel').placeholder = new_translations.smallPage.errorh.placeholder 42 | } 43 | 44 | export async function getTranslations(locate) { 45 | const translateData = await fetch(`./lang/${locate}.json`) 46 | .catch((err) => setError('WebUI', err.stack ? err.stack : err.message)) 47 | 48 | return translateData.json() 49 | } 50 | 51 | export async function getAvailableLanguages() { 52 | const lsCmd = await exec('ls /data/adb/modules/rezygisk/webroot/lang') 53 | 54 | if (lsCmd.errno !== 0) return setError('WebUI', lsCmd.stderr) 55 | 56 | const languages = [] 57 | lsCmd.stdout.split('\n').forEach((lang) => { 58 | if (lang.length !== 0) 59 | languages.push(lang.replace('.json', '')) 60 | }) 61 | 62 | return languages 63 | } -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /webroot/js/kernelsu.js: -------------------------------------------------------------------------------- 1 | /* https://github.com/tiann/KernelSU/tree/main/js / https://www.npmjs.com/package/kernelsu */ 2 | 3 | let callbackCounter = 0; 4 | function getUniqueCallbackName(prefix) { 5 | return `${prefix}_callback_${Date.now()}_${callbackCounter++}`; 6 | } 7 | 8 | export function exec(command, options) { 9 | if (typeof options === "undefined") { 10 | options = {}; 11 | } 12 | 13 | return new Promise((resolve, reject) => { 14 | // Generate a unique callback function name 15 | const callbackFuncName = getUniqueCallbackName("exec"); 16 | 17 | // Define the success callback function 18 | window[callbackFuncName] = (errno, stdout, stderr) => { 19 | resolve({ errno, stdout, stderr }); 20 | cleanup(callbackFuncName); 21 | }; 22 | 23 | function cleanup(successName) { 24 | delete window[successName]; 25 | } 26 | 27 | try { 28 | ksu.exec(command, JSON.stringify(options), callbackFuncName); 29 | } catch (error) { 30 | reject(error); 31 | cleanup(callbackFuncName); 32 | } 33 | }); 34 | } 35 | 36 | function Stdio() { 37 | this.listeners = {}; 38 | } 39 | 40 | Stdio.prototype.on = function (event, listener) { 41 | if (!this.listeners[event]) { 42 | this.listeners[event] = []; 43 | } 44 | this.listeners[event].push(listener); 45 | }; 46 | 47 | Stdio.prototype.emit = function (event, ...args) { 48 | if (this.listeners[event]) { 49 | this.listeners[event].forEach((listener) => listener(...args)); 50 | } 51 | }; 52 | 53 | function ChildProcess() { 54 | this.listeners = {}; 55 | this.stdin = new Stdio(); 56 | this.stdout = new Stdio(); 57 | this.stderr = new Stdio(); 58 | } 59 | 60 | ChildProcess.prototype.on = function (event, listener) { 61 | if (!this.listeners[event]) { 62 | this.listeners[event] = []; 63 | } 64 | this.listeners[event].push(listener); 65 | }; 66 | 67 | ChildProcess.prototype.emit = function (event, ...args) { 68 | if (this.listeners[event]) { 69 | this.listeners[event].forEach((listener) => listener(...args)); 70 | } 71 | }; 72 | 73 | export function spawn(command, args, options) { 74 | if (typeof args === "undefined") { 75 | args = []; 76 | } else if (!(args instanceof Array)) { 77 | // allow for (command, options) signature 78 | options = args; 79 | } 80 | 81 | if (typeof options === "undefined") { 82 | options = {}; 83 | } 84 | 85 | const child = new ChildProcess(); 86 | const childCallbackName = getUniqueCallbackName("spawn"); 87 | window[childCallbackName] = child; 88 | 89 | function cleanup(name) { 90 | delete window[name]; 91 | } 92 | 93 | child.on("exit", code => { 94 | cleanup(childCallbackName); 95 | }); 96 | 97 | try { 98 | ksu.spawn( 99 | command, 100 | JSON.stringify(args), 101 | JSON.stringify(options), 102 | childCallbackName 103 | ); 104 | } catch (error) { 105 | child.emit("error", error); 106 | cleanup(childCallbackName); 107 | } 108 | return child; 109 | } 110 | 111 | export function fullScreen(isFullScreen) { 112 | ksu.fullScreen(isFullScreen); 113 | } 114 | 115 | export function toast(message) { 116 | ksu.toast(message); 117 | } -------------------------------------------------------------------------------- /zygiskd/src/root_impl/common.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "../utils.h" 9 | #include "kernelsu.h" 10 | #include "apatch.h" 11 | #include "magisk.h" 12 | 13 | #include "common.h" 14 | 15 | static struct root_impl impl; 16 | 17 | void root_impls_setup(void) { 18 | struct root_impl_state state_ksu; 19 | ksu_get_existence(&state_ksu); 20 | 21 | struct root_impl_state state_apatch; 22 | apatch_get_existence(&state_apatch); 23 | 24 | struct root_impl_state state_magisk; 25 | magisk_get_existence(&state_magisk); 26 | 27 | /* INFO: Check if it's only one supported, if not, it's multile and that's bad. 28 | Remember that true here is equal to the integer 1. */ 29 | if ((state_ksu.state == Supported ? 1 : 0) + (state_apatch.state == Supported ? 1 : 0) + (state_magisk.state == Supported ? 1 : 0) >= 2) { 30 | impl.impl = Multiple; 31 | } else if (state_ksu.state == Supported) { 32 | impl.impl = KernelSU; 33 | impl.variant = state_ksu.variant; 34 | } else if (state_apatch.state == Supported) { 35 | impl.impl = APatch; 36 | } else if (state_magisk.state == Supported) { 37 | impl.impl = Magisk; 38 | impl.variant = state_magisk.variant; 39 | } else { 40 | impl.impl = None; 41 | } 42 | 43 | switch (impl.impl) { 44 | case None: { 45 | LOGI("No root implementation found.\n"); 46 | 47 | break; 48 | } 49 | case Multiple: { 50 | LOGI("Multiple root implementations found.\n"); 51 | 52 | break; 53 | } 54 | case KernelSU: { 55 | LOGI("KernelSU root implementation found.\n"); 56 | 57 | break; 58 | } 59 | case APatch: { 60 | LOGI("APatch root implementation found.\n"); 61 | 62 | break; 63 | } 64 | case Magisk: { 65 | if (state_magisk.variant == 0) { 66 | LOGI("Magisk Official root implementation found.\n"); 67 | } else { 68 | LOGI("Magisk Kitsune root implementation found.\n"); 69 | } 70 | 71 | break; 72 | } 73 | } 74 | } 75 | 76 | void get_impl(struct root_impl *uimpl) { 77 | uimpl->impl = impl.impl; 78 | uimpl->variant = impl.variant; 79 | } 80 | 81 | bool uid_granted_root(uid_t uid) { 82 | switch (impl.impl) { 83 | case KernelSU: { 84 | return ksu_uid_granted_root(uid); 85 | } 86 | case APatch: { 87 | return apatch_uid_granted_root(uid); 88 | } 89 | case Magisk: { 90 | return magisk_uid_granted_root(uid); 91 | } 92 | default: { 93 | return false; 94 | } 95 | } 96 | } 97 | 98 | bool uid_should_umount(uid_t uid, const char *const process) { 99 | switch (impl.impl) { 100 | case KernelSU: { 101 | return ksu_uid_should_umount(uid); 102 | } 103 | case APatch: { 104 | return apatch_uid_should_umount(uid); 105 | } 106 | case Magisk: { 107 | return magisk_uid_should_umount(process); 108 | } 109 | default: { 110 | return false; 111 | } 112 | } 113 | } 114 | 115 | bool uid_is_manager(uid_t uid) { 116 | switch (impl.impl) { 117 | case KernelSU: { 118 | return ksu_uid_is_manager(uid); 119 | } 120 | case APatch: { 121 | return apatch_uid_is_manager(uid); 122 | } 123 | case Magisk: { 124 | return magisk_uid_is_manager(uid); 125 | } 126 | default: { 127 | return false; 128 | } 129 | } 130 | } 131 | 132 | void root_impl_cleanup(void) { 133 | if (impl.impl == KernelSU) ksu_cleanup(); 134 | } 135 | -------------------------------------------------------------------------------- /loader/src/ptracer/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "utils.h" 5 | #include "monitor.h" 6 | #include "daemon.h" 7 | #include "mount.h" 8 | 9 | int main(int argc, char **argv) { 10 | printf("The ReZygisk Tracer %s\n\n", ZKSU_VERSION); 11 | 12 | if (argc >= 2 && strcmp(argv[1], "mount_ns") == 0) { 13 | mount_ns_main(argv); 14 | 15 | return 0; 16 | } if (argc >= 2 && strcmp(argv[1], "mount_ns_private") == 0) { 17 | mount_ns_private(); 18 | 19 | return 0; 20 | } else if (argc >= 2 && strcmp(argv[1], "monitor") == 0) { 21 | int ready_pipe[2] = {-1, -1}; 22 | pipe(ready_pipe); 23 | if (fork() == 0) { 24 | close(ready_pipe[0]); 25 | init_monitor(ready_pipe[1]); 26 | _exit(0); 27 | } 28 | close(ready_pipe[1]); 29 | char dummy; 30 | TEMP_FAILURE_RETRY(read(ready_pipe[0], &dummy, 1)); 31 | return 0; 32 | } else if (argc >= 3 && strcmp(argv[1], "trace") == 0) { 33 | if (argc >= 4 && strcmp(argv[3], "--restart") == 0) rezygiskd_zygote_restart(); 34 | 35 | long pid = strtol(argv[2], 0, 0); 36 | if (!trace_zygote(pid)) { 37 | kill(pid, SIGKILL); 38 | 39 | return 1; 40 | } 41 | 42 | return 0; 43 | } else if (argc >= 2 && strcmp(argv[1], "ctl") == 0) { 44 | enum rezygiskd_command command; 45 | 46 | if (strcmp(argv[2], "start") == 0) command = START; 47 | else if (strcmp(argv[2], "stop") == 0) command = STOP; 48 | else if (strcmp(argv[2], "exit") == 0) command = EXIT; 49 | else { 50 | printf("[ReZygisk]: Usage: %s ctl \n", argv[0]); 51 | 52 | return 1; 53 | } 54 | 55 | if (send_control_command(command) == -1) { 56 | printf("[ReZygisk]: Failed to send the command, is the daemon running?\n"); 57 | 58 | return 1; 59 | } 60 | 61 | printf("[ReZygisk]: command sent\n"); 62 | 63 | return 0; 64 | } else if (argc >= 2 && strcmp(argv[1], "version") == 0) { 65 | /* INFO: Noop*/ 66 | 67 | return 0; 68 | } else if (argc >= 2 && strcmp(argv[1], "info") == 0) { 69 | struct rezygisk_info info; 70 | rezygiskd_get_info(&info); 71 | 72 | printf("Daemon process PID: %d\n", info.pid); 73 | 74 | switch (info.root_impl) { 75 | case ROOT_IMPL_NONE: { 76 | printf("Root implementation: none\n"); 77 | 78 | break; 79 | } 80 | case ROOT_IMPL_APATCH: { 81 | printf("Root implementation: APatch\n"); 82 | 83 | break; 84 | } 85 | case ROOT_IMPL_KERNELSU: { 86 | printf("Root implementation: KernelSU\n"); 87 | 88 | break; 89 | } 90 | case ROOT_IMPL_MAGISK: { 91 | printf("Root implementation: Magisk\n"); 92 | 93 | break; 94 | } 95 | } 96 | 97 | if (info.modules->modules_count != 0) { 98 | printf("Modules: %zu\n", info.modules->modules_count); 99 | 100 | for (size_t i = 0; i < info.modules->modules_count; i++) { 101 | printf(" - %s\n", info.modules->modules[i]); 102 | } 103 | } else { 104 | printf("Modules: N/A\n"); 105 | } 106 | 107 | free_rezygisk_info(&info); 108 | 109 | return 0; 110 | } else { 111 | printf( 112 | "Available commands:\n" 113 | " - monitor\n" 114 | " - trace [--restart]\n" 115 | " - ctl \n" 116 | " - version: Shows the version of ReZygisk.\n" 117 | " - info: Shows information about the created daemon/injection.\n" 118 | "\n" 119 | "<...>: Obligatory\n" 120 | "[...]: Optional\n"); 121 | 122 | return 1; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /webroot/js/translate/home.js: -------------------------------------------------------------------------------- 1 | export function translateHomePage(old_translations, new_translations) { 2 | /* INFO: Translate variables */ 3 | const rezygisk_state = document.getElementById('rezygisk_state') 4 | const zygote32_status_div = document.getElementById('zygote32_status') 5 | const zygote64_status_div = document.getElementById('zygote64_status') 6 | 7 | switch (rezygisk_state.innerHTML.replace(/(\r\n|\n|\r)/gm, '').trim()) { 8 | case old_translations.page.home.status.ok: { 9 | rezygisk_state.innerHTML = new_translations.page.home.status.ok 10 | 11 | break 12 | } 13 | case old_translations.page.home.status.partially: { 14 | rezygisk_state.innerHTML = new_translations.page.home.status.partially 15 | 16 | break 17 | } 18 | case old_translations.page.home.status.notWorking: { 19 | rezygisk_state.innerHTML = new_translations.page.home.status.notWorking 20 | 21 | break 22 | } 23 | case old_translations.page.home.status.unknown: { 24 | rezygisk_state.innerHTML = new_translations.global.unknown 25 | 26 | break 27 | } 28 | } 29 | 30 | if (zygote32_status_div) { 31 | switch (zygote32_status_div.innerHTML.replace(/(\r\n|\n|\r)/gm, '').trim()) { 32 | case old_translations.page.home.info.zygote.injected: { 33 | zygote32_status_div.innerHTML = new_translations.page.home.info.zygote.injected 34 | 35 | break 36 | } 37 | case old_translations.page.home.info.zygote.notInjected: { 38 | zygote32_status_div.innerHTML = new_translations.page.home.info.zygote.notInjected 39 | 40 | break 41 | } 42 | case old_translations.page.home.info.zygote.unknown: { 43 | zygote32_status_div.innerHTML = new_translations.global.unknown 44 | 45 | break 46 | } 47 | } 48 | } 49 | 50 | if (zygote64_status_div) { 51 | switch (zygote64_status_div.innerHTML.replace(/(\r\n|\n|\r)/gm, '').trim()) { 52 | case old_translations.page.home.info.zygote.injected: { 53 | zygote64_status_div.innerHTML = new_translations.page.home.info.zygote.injected 54 | 55 | break 56 | } 57 | case old_translations.page.home.info.zygote.notInjected: { 58 | zygote64_status_div.innerHTML = new_translations.page.home.info.zygote.notInjected 59 | 60 | break 61 | } 62 | case old_translations.page.home.info.zygote.unknown: { 63 | zygote64_status_div.innerHTML = new_translations.global.unknown 64 | 65 | break 66 | } 67 | } 68 | } 69 | 70 | const android_version_div = document.getElementById('android_version_div') 71 | if (android_version_div.innerHTML === old_translations.global.unknown) 72 | android_version_div.innerHTML = new_translations.global.unknown 73 | 74 | const kernel_version_div = document.getElementById('kernel_version_div') 75 | if (kernel_version_div.innerHTML === old_translations.global.unknown) 76 | kernel_version_div.innerHTML = new_translations.global.unknown 77 | 78 | /* INFO: info card */ 79 | document.getElementById('version_info_title').innerHTML = new_translations.page.home.info.version 80 | document.getElementById('root_info_title').innerHTML = new_translations.page.home.info.root 81 | 82 | // const version_code = document.getElementById('version_code') 83 | // const root_impl = document.getElementById('root_impl') 84 | 85 | // if (version_code.innerHTML.replace(/(\r\n|\n|\r)/gm, '').trim() === old_translations.global.unknown) 86 | // version_code.innerHTML = new_translations.global.unknown 87 | 88 | // if (root_impl.innerHTML.replace(/(\r\n|\n|\r)/gm, '').trim() === old_translations.global.unknown) 89 | // root_impl.innerHTML = new_translations.global.unknown 90 | } -------------------------------------------------------------------------------- /loader/src/injector/art_method.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logging.h" 4 | #include "jni_helper.hpp" 5 | 6 | template 7 | constexpr inline auto RoundUpTo(T v, size_t size) { 8 | return v + size - 1 - ((v + size - 1) & (size - 1)); 9 | } 10 | 11 | inline static constexpr auto kPointerSize = sizeof(void *); 12 | 13 | namespace lsplant::art { 14 | 15 | class ArtMethod { 16 | 17 | public: 18 | void *GetData() { 19 | return *reinterpret_cast(reinterpret_cast(this) + data_offset); 20 | } 21 | 22 | static art::ArtMethod *FromReflectedMethod(JNIEnv *env, jobject method) { 23 | if (art_method_field) [[likely]] { 24 | return reinterpret_cast( 25 | JNI_GetLongField(env, method, art_method_field)); 26 | } else { 27 | return reinterpret_cast(env->FromReflectedMethod(method)); 28 | } 29 | } 30 | 31 | static bool Init(JNIEnv *env) { 32 | ScopedLocalRef executable{env, nullptr}; 33 | executable = JNI_FindClass(env, "java/lang/reflect/Executable"); 34 | if (!executable) { 35 | LOGE("Failed to found Executable"); 36 | return false; 37 | } 38 | 39 | if (art_method_field = JNI_GetFieldID(env, executable, "artMethod", "J"); 40 | !art_method_field) { 41 | LOGE("Failed to find artMethod field"); 42 | return false; 43 | } 44 | 45 | auto throwable = JNI_FindClass(env, "java/lang/Throwable"); 46 | if (!throwable) { 47 | LOGE("Failed to found Executable"); 48 | return false; 49 | } 50 | auto clazz = JNI_FindClass(env, "java/lang/Class"); 51 | static_assert(std::is_same_v); 52 | jmethodID get_declared_constructors = JNI_GetMethodID(env, clazz, "getDeclaredConstructors", 53 | "()[Ljava/lang/reflect/Constructor;"); 54 | const auto constructors = 55 | JNI_Cast(JNI_CallObjectMethod(env, throwable, get_declared_constructors)); 56 | if (constructors.size() < 2) { 57 | LOGE("Throwable has less than 2 constructors"); 58 | return false; 59 | } 60 | auto &first_ctor = constructors[0]; 61 | auto &second_ctor = constructors[1]; 62 | auto *first = FromReflectedMethod(env, first_ctor.get()); 63 | auto *second = FromReflectedMethod(env, second_ctor.get()); 64 | art_method_size = reinterpret_cast(second) - reinterpret_cast(first); 65 | LOGD("ArtMethod size: %zu", art_method_size); 66 | if (RoundUpTo(4 * 9, kPointerSize) + kPointerSize * 3 < art_method_size) [[unlikely]] { 67 | LOGW("ArtMethod size exceeds maximum assume. There may be something wrong."); 68 | } 69 | entry_point_offset = art_method_size - kPointerSize; 70 | data_offset = entry_point_offset - kPointerSize; 71 | LOGD("ArtMethod::entrypoint offset: %zu", entry_point_offset); 72 | LOGD("ArtMethod::data offset: %zu", data_offset); 73 | return true; 74 | } 75 | 76 | private: 77 | inline static jfieldID art_method_field = nullptr; 78 | inline static size_t art_method_size = 0; 79 | inline static size_t entry_point_offset = 0; 80 | inline static size_t data_offset = 0; 81 | }; 82 | 83 | } // namespace lsplant::art 84 | -------------------------------------------------------------------------------- /READMEs/README_ja-JP.md: -------------------------------------------------------------------------------- 1 | # ReZygisk 2 | 3 | [Bahasa Indonesia](/READMEs/README_id-ID.md)|[Tiếng Việt](/READMEs/README_vi-VN.md)|[Português Brasileiro](/READMEs/README_pt-BR.md)|[French](/READMEs/README_fr-FR.md) 4 | 5 | ReZygiskはZygiskのスタンドアローン実装であるZygisk Nextのフォークです。ReZygiskは、KernelSU、APatch、Magisk(オフィシャルバージョンとKitsuneバージョン両方)それぞれへのZygisk APIサポートを備えています。 6 | 7 | ReZygiskはコードベースをCに移行し、よりモダンなコードで書き換えることを目標にしています。これにより、Zygisk APIのより効率的かつ高速な実装と、FOSSライセンスの両方を備えることができています。 8 | 9 | ## なぜReZygiskを選ぶべきか 10 | 11 | Zygisk Nextの最新リリースはオープンソースではなく、コードをその開発者のみにアクセス可能にしています。これは我々のように一般の開発者の貢献を無下にするだけでなく、Zygisk Nextがroot権限で走るアプリなのにもかかわらずコードにアクセスできないため、セキュリティ上でも深刻な問題が有ります。 12 | 13 | Zygisk Nextの開発者達は有名かつコミュニティからも信頼されていますが、これはコードが100%悪意が無いことや脆弱性が無いことを意味しません。我々(PerformanC)は彼らがZygisk Nextをクローズドソースにする理由も理解していますが、我々はその逆を信じます。 14 | 15 | ## メリット 16 | 17 | - FOSS (無制限) 18 | 19 | ## 依存関係 20 | 21 | | ツール | 説明 | 22 | |-----------------|----------------------------------------| 23 | | `Android NDK` | Native Development Kit for Android | 24 | 25 | ### C++ 依存関係 26 | 27 | | 依存関係 | 説明 | 28 | |------------|-------------------------------| 29 | | `lsplt` | Simple PLT Hook for Android | 30 | 31 | ## インストール 32 | 33 | ### 1. 必要なZipファイルを選択 34 | 35 | ReZygiskの安定性や匿名性のためには、ビルドファイル/Zipファイルの選択は**非常に重要**です。しかしながら、これはそこまで難しくもありません。 36 | 37 | - `release` バージョンが基本的にはおすすめです。アプリレベルのログが出力されなかったりなど、より効率化されたバイナリが提供されるためです。 38 | - `debug` バージョンはreleaseバージョンの反対です。重いログの出力がなされたり、高速化されていないバイナリが提供されます。このため、このバージョンは**デバッグ用に**、もしくは**Issueを作るためにログを入手する**ときのみに使われるべきです。 39 | 40 | ブランチに関しては、基本的に`main`ブランチを選択すべきです。しかしながら、PerformanCの開発者に違うブランチを使うように言われたり、あなたがベータ版のコードを使うことのリスクを理解しかつ実装されたばかりの機能を使いたいのならば違うブランチを選択することも選択肢の一つでしょう。 41 | 42 | ### 2. Zipファイルをフラッシュ 43 | 44 | 正しいビルドを選択したあとは、ReZygiskのビルドを現在使用しているルートマネージャー(MagiskやKernelSU等)を使用してフラッシュしてください。これは、マネージャーで`Modules`セクションを開きダウンロードしたビルドファイルを選択することでできます。 45 | 46 | フラッシュしたあとは、インストールログを確認して、エラーがないか確かめてください。なんのエラーも起きていなければ、デバイスを再起動してください。 47 | 48 | > [!WARNING] 49 | > Magiskを使用しているのならば、ビルトインのZygiskがReZygiskと競合するため無効化してください。Magiskの`設定`セクションを開き、Zygiskオプションを無効化することでできます。 50 | ### 3. インストールを確認 51 | 52 | 再起動後、ルートマネージャーの`Modules`セクションをチェックすることによりReZygiskが正常に動いているかどうか確認できます。 53 | 説明欄は、必要なデーモンが動作していることを示しているはずです。例えば、あなたの端末が64bitと32bitの両方をサポートしている場合、右記のように見えるはずです: `[monitor: 😋 tracing, zygote64: 😋 injected, daemon64: 😋 running (...) zygote32: 😋 injected, daemon32: 😋 running (...)] Standalone implementation of Zygisk.` 54 | 55 | ## 翻訳 56 | 57 | There are currently two different ways to contribute translations for ReZygisk: 58 | 59 | - READMEの翻訳は、`READMEs`フォルダに`README_.md`というファイルを作り、そこに翻訳を書き込んでください。その後、プルリクエストを送信してくださいlang` folder and your credits to the `TRANSLATOR.md` file, in alphabetic order. 60 | - ReZygisk WebUIの翻訳のためには、まず[Crowdin](https://crowdin.com/project/rezygisk)で貢献する必要が有ります。一度貢献を許可され、`.json`ファイルを入手したならば、そのファイルを元に新しい言語のファイルを作り、その`.json`ファイルを`webroot/lang`フォルダに入れてください。更に、TRANSLATOR.mdにあなたのクレジットを付与するのも忘れないでください!(なお名前の順番はアルファベット順です) 61 | 62 | ## サポート 63 | 64 | ReZygiskやPerformanCのプロジェクトに関して質問がある場合、以下のいずれかに参加して質問してください。 65 | 66 | - Discord チャンネル: [PerformanC](https://discord.gg/uPveNfTuCJ) 67 | - ReZygisk Telegram チャンネル: [@rezygisk](https://t.me/rezygisk) 68 | - PerformanC Telegram チャンネル: [@performancorg](https://t.me/performancorg) 69 | - PerformanC Signal Group: [@performanc](https://signal.group/#CjQKID3SS8N5y4lXj3VjjGxVJnzNsTIuaYZjj3i8UhipAS0gEhAedxPjT5WjbOs6FUuXptcT) 70 | 71 | ## 貢献 72 | 73 | [Contribution Guidelines](https://github.com/PerformanC/contributing)に従ってください。セキュリティポリシー、コードスタイル等、すべて従う必要が有ります。 74 | 75 | ## ライセンス 76 | 77 | ReZygiskはDr-TSNGによるGPLライセンスと、PerformanCが書き直したコードに関してはThe PerformanC OrganizationによるAGPL 3.0ライセンスの元に配布されます。[Open Source Initiative](https://opensource.org/licenses/AGPL-3.0)で、より詳しい情報を得ることができます。 78 | -------------------------------------------------------------------------------- /loader/src/ptracer/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif /* __cplusplus */ 7 | 8 | #include 9 | 10 | #include "daemon.h" 11 | 12 | #ifdef __LP64__ 13 | #define LOG_TAG "zygisk-ptrace64" 14 | #else 15 | #define LOG_TAG "zygisk-ptrace32" 16 | #endif 17 | 18 | #include "logging.h" 19 | 20 | struct map { 21 | uintptr_t start; 22 | uintptr_t end; 23 | uint8_t perms; 24 | bool is_private; 25 | uintptr_t offset; 26 | dev_t dev; 27 | ino_t inode; 28 | const char *path; 29 | }; 30 | 31 | struct maps { 32 | struct map *maps; 33 | size_t size; 34 | }; 35 | 36 | struct maps *parse_maps(const char *filename); 37 | 38 | void free_maps(struct maps *maps); 39 | 40 | #if defined(__x86_64__) 41 | #define REG_SP rsp 42 | #define REG_IP rip 43 | #define REG_RET rax 44 | #define REG_SYSNR orig_rax 45 | #define SYSCALL_LEN(regs) 2 46 | #elif defined(__i386__) 47 | #define REG_SP esp 48 | #define REG_IP eip 49 | #define REG_RET eax 50 | #define REG_SYSNR orig_eax 51 | #define SYSCALL_LEN(regs) 2 52 | #elif defined(__aarch64__) 53 | #define REG_SP sp 54 | #define REG_IP pc 55 | #define REG_RET regs[0] 56 | #define REG_SYSNR regs[8] 57 | #define SYSCALL_LEN(regs) (((regs)->pstate & 0x30) == 0x30 ? 2 : 4) 58 | #elif defined(__arm__) 59 | #define REG_SP uregs[13] 60 | #define REG_IP uregs[15] 61 | #define REG_RET uregs[0] 62 | #define REG_SYSNR uregs[7] 63 | #define user_regs_struct user_regs 64 | #define SYSCALL_LEN(regs) (((regs)->ARM_cpsr & PSR_T_BIT) ? 2 : 4) 65 | #endif 66 | 67 | ssize_t write_proc(int pid, uintptr_t remote_addr, const void *buf, size_t len); 68 | 69 | ssize_t read_proc(int pid, uintptr_t remote_addr, void *buf, size_t len); 70 | 71 | bool get_regs(int pid, struct user_regs_struct *regs); 72 | 73 | bool set_regs(int pid, struct user_regs_struct *regs); 74 | 75 | void get_addr_mem_region(struct maps *map, uintptr_t addr, char *buf, size_t buf_size); 76 | 77 | const char *position_after(const char *str, const char needle); 78 | 79 | void *find_module_return_addr(struct maps *map, const char *suffix); 80 | 81 | void *find_func_addr(struct maps *local_info, struct maps *remote_info, const char *module, const char *func); 82 | 83 | void align_stack(struct user_regs_struct *regs, long preserve); 84 | 85 | uintptr_t push_string(int pid, struct user_regs_struct *regs, const char *str); 86 | 87 | uintptr_t remote_call(int pid, struct user_regs_struct *regs, uintptr_t func_addr, uintptr_t return_addr, long *args, size_t args_size); 88 | 89 | int fork_dont_care(); 90 | 91 | void wait_for_trace(int pid, int* status, int flags); 92 | 93 | void parse_status(int status, char *buf, size_t len); 94 | 95 | #define WPTEVENT(x) (x >> 16) 96 | 97 | #define CASE_CONST_RETURN(x) case x: return #x; 98 | 99 | static inline const char *parse_ptrace_event(int status) { 100 | status = status >> 16; 101 | 102 | switch (status) { 103 | CASE_CONST_RETURN(PTRACE_EVENT_FORK) 104 | CASE_CONST_RETURN(PTRACE_EVENT_VFORK) 105 | CASE_CONST_RETURN(PTRACE_EVENT_CLONE) 106 | CASE_CONST_RETURN(PTRACE_EVENT_EXEC) 107 | CASE_CONST_RETURN(PTRACE_EVENT_VFORK_DONE) 108 | CASE_CONST_RETURN(PTRACE_EVENT_EXIT) 109 | CASE_CONST_RETURN(PTRACE_EVENT_SECCOMP) 110 | CASE_CONST_RETURN(PTRACE_EVENT_STOP) 111 | default: 112 | return "(no event)"; 113 | } 114 | } 115 | 116 | static inline const char *sigabbrev_np(int sig) { 117 | if (sig > 0 && sig < NSIG) return sys_signame[sig]; 118 | 119 | return "(unknown)"; 120 | } 121 | 122 | int get_program(int pid, char *buf, size_t size); 123 | 124 | /* INFO: pid = 0, fd != nullptr -> set to fd 125 | pid != 0, fd != nullptr -> set to pid ns, give orig ns in fd 126 | */ 127 | bool switch_mnt_ns(int pid, int *fd); 128 | 129 | #ifdef __cplusplus 130 | } 131 | #endif /* __cplusplus */ 132 | 133 | #endif /* UTILS_H */ -------------------------------------------------------------------------------- /loader/src/injector/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "raw_syscalls.h" 11 | 12 | /* 13 | * INFO: Things in this file will be ran in a state where this .so is not properly loaded. 14 | * Library functions must not be called, raw syscalls must be used instead. 15 | * Other essential things are also not working, like TLS or relocations. 16 | */ 17 | 18 | 19 | /* 20 | * INFO: visibility("default") must not be used, as it makes accesses go through the GOT, 21 | * which is not supported due to the aforementioned reasons of half-assed .so loading. 22 | */ 23 | #define EXPORT __attribute__((visibility("protected"))) 24 | 25 | #define DCL_HOOK_FUNC(ret, func, ...) \ 26 | EXPORT ret (*init_old_##func)(__VA_ARGS__); \ 27 | EXPORT ret init_new_##func(__VA_ARGS__) 28 | 29 | EXPORT volatile bool init_is_unhooked; 30 | 31 | static int init_sock; 32 | static struct sockaddr_un init_sock_addr = { 33 | .sun_family = AF_UNIX, 34 | .sun_path = "/data/adb/nrezygisk/init_con.sock\0" 35 | }; 36 | 37 | DCL_HOOK_FUNC(pid_t, fork) { 38 | if (init_is_unhooked || raw_gettid() != 1) { 39 | return init_old_fork(); 40 | } 41 | 42 | char dummy = 0; 43 | int pipefd[2] = {-1}; 44 | raw_pipe2(pipefd, O_CLOEXEC); 45 | 46 | pid_t new_pid = init_old_fork(); 47 | 48 | if (new_pid == 0) { 49 | raw_close(pipefd[1]); 50 | raw_read_n(pipefd[0], &dummy, 1); 51 | raw_close(pipefd[0]); 52 | raw_close(init_sock); 53 | } else { 54 | raw_close(pipefd[0]); 55 | raw_write_n(init_sock, &new_pid, sizeof(new_pid)); 56 | raw_read_n(init_sock, &dummy, 1); 57 | raw_write_n(pipefd[1], &dummy, 1); 58 | raw_close(pipefd[1]); 59 | } 60 | 61 | return new_pid; 62 | } 63 | 64 | static int init_fork_pipe[2]; 65 | 66 | static void init_atfork_prepare() { 67 | init_fork_pipe[0] = -1; 68 | if (init_is_unhooked || raw_gettid() != 1) return; 69 | raw_pipe2(init_fork_pipe, O_CLOEXEC); 70 | } 71 | 72 | static void init_atfork_parent() { 73 | if (init_fork_pipe[0] < 0) return; 74 | raw_close(init_fork_pipe[0]); 75 | 76 | char dummy; 77 | raw_read_n(init_sock, &dummy, 1); 78 | raw_write_n(init_fork_pipe[1], &dummy, 1); 79 | raw_close(init_fork_pipe[1]); 80 | } 81 | 82 | static void init_atfork_child() { 83 | if (init_fork_pipe[0] < 0) return; 84 | raw_close(init_fork_pipe[1]); 85 | 86 | pid_t new_pid = raw_gettid(); 87 | raw_write_n(init_sock, &new_pid, sizeof(new_pid)); 88 | raw_close(init_sock); 89 | 90 | char dummy; 91 | raw_read_n(init_fork_pipe[0], &dummy, 1); 92 | raw_close(init_fork_pipe[0]); 93 | } 94 | 95 | EXPORT int init_entry(void (*pthread_atfork)(void*, void*, void*)) { 96 | int sockets[2]; 97 | long r = raw_socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sockets); 98 | if (r < 0) { 99 | return 1000 - r; 100 | } 101 | 102 | long socket = raw_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); 103 | if (socket < 0) { 104 | return 2000 - socket; 105 | } 106 | 107 | r = raw_connect(socket, &init_sock_addr, sizeof(init_sock_addr)); 108 | if (r < 0) { 109 | return 3000 - r; 110 | } 111 | 112 | r = raw_send_fd(socket, sockets[1]); 113 | if (r < 0) { 114 | return 4000 - r; 115 | } 116 | 117 | raw_close(sockets[1]); 118 | raw_close(socket); 119 | 120 | if (pthread_atfork) { 121 | init_is_unhooked = false; 122 | pthread_atfork(init_atfork_prepare, init_atfork_parent, init_atfork_child); 123 | } else { 124 | init_is_unhooked = true; 125 | } 126 | 127 | init_sock = sockets[0]; 128 | init_old_fork = 0; 129 | 130 | return 42; 131 | } -------------------------------------------------------------------------------- /loader/src/common/socket_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "logging.h" 9 | 10 | #include "socket_utils.h" 11 | 12 | 13 | ssize_t read_n(int fd, void *buf, size_t n) { 14 | size_t total = 0; 15 | while (total < n) { 16 | ssize_t r = TEMP_FAILURE_RETRY(read(fd, (char*)buf + total, n - total)); 17 | if (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && total > 0) { 18 | struct pollfd pfd = { .fd = fd, .events = POLLIN }; 19 | TEMP_FAILURE_RETRY(poll(&pfd, 1, -1)); 20 | continue; 21 | } 22 | if (r <= 0) return r; 23 | total += r; 24 | } 25 | return (ssize_t) total; 26 | } 27 | 28 | 29 | ssize_t write_n(int fd, const void *buf, size_t n) { 30 | size_t total = 0; 31 | while (total < n) { 32 | ssize_t w = TEMP_FAILURE_RETRY(write(fd, (char*)buf + total, n - total)); 33 | if (w == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { 34 | struct pollfd pfd = { .fd = fd, .events = POLLOUT }; 35 | TEMP_FAILURE_RETRY(poll(&pfd, 1, -1)); 36 | continue; 37 | } 38 | if (w <= 0) return w; 39 | total += w; 40 | } 41 | return (ssize_t) total; 42 | } 43 | 44 | /* TODO: Standardize how to log errors */ 45 | int read_fd(int fd) { 46 | char cmsgbuf[CMSG_SPACE(sizeof(int))]; 47 | 48 | int cnt = 1; 49 | struct iovec iov = { 50 | .iov_base = &cnt, 51 | .iov_len = sizeof(cnt) 52 | }; 53 | 54 | struct msghdr msg = { 55 | .msg_iov = &iov, 56 | .msg_iovlen = 1, 57 | .msg_control = cmsgbuf, 58 | .msg_controllen = sizeof(cmsgbuf) 59 | }; 60 | 61 | ssize_t ret = TEMP_FAILURE_RETRY(recvmsg(fd, &msg, MSG_WAITALL)); 62 | if (ret == -1) { 63 | PLOGE("recvmsg"); 64 | 65 | return -1; 66 | } 67 | 68 | struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); 69 | if (cmsg == NULL) { 70 | PLOGE("CMSG_FIRSTHDR"); 71 | 72 | return -1; 73 | } 74 | 75 | int sendfd; 76 | memcpy(&sendfd, CMSG_DATA(cmsg), sizeof(int)); 77 | 78 | return sendfd; 79 | } 80 | 81 | ssize_t write_string(int fd, const char *str) { 82 | size_t str_len = strlen(str); 83 | ssize_t write_bytes = write_n(fd, &str_len, sizeof(size_t)); 84 | if (write_bytes != (ssize_t)sizeof(size_t)) { 85 | LOGE("Failed to write string length: Not all bytes were written (%zd != %zu).\n", write_bytes, sizeof(size_t)); 86 | 87 | return -1; 88 | } 89 | 90 | write_bytes = write_n(fd, str, str_len); 91 | if (write_bytes != (ssize_t)str_len) { 92 | LOGE("Failed to write string: Promised bytes doesn't exist (%zd != %zu).\n", write_bytes, str_len); 93 | 94 | return -1; 95 | } 96 | 97 | return write_bytes; 98 | } 99 | 100 | char *read_string(int fd) { 101 | size_t str_len = 0; 102 | ssize_t read_bytes = read_n(fd, &str_len, sizeof(size_t)); 103 | if (read_bytes != (ssize_t)sizeof(size_t)) { 104 | LOGE("Failed to read string length: Not all bytes were read (%zd != %zu).\n", read_bytes, sizeof(size_t)); 105 | 106 | return NULL; 107 | } 108 | 109 | char *buf = malloc(str_len + 1); 110 | if (buf == NULL) { 111 | PLOGE("allocate memory for string"); 112 | 113 | return NULL; 114 | } 115 | 116 | read_bytes = read_n(fd, buf, str_len); 117 | if (read_bytes != (ssize_t)str_len) { 118 | LOGE("Failed to read string: Promised bytes doesn't exist (%zd != %zu).\n", read_bytes, str_len); 119 | 120 | free(buf); 121 | 122 | return NULL; 123 | } 124 | 125 | if (str_len > 0) buf[str_len] = '\0'; 126 | 127 | return buf; 128 | } 129 | 130 | #define write_func(type) \ 131 | ssize_t write_## type(int fd, type val) { \ 132 | return write_n(fd, &val, sizeof(type)); \ 133 | } 134 | 135 | #define read_func(type) \ 136 | ssize_t read_## type(int fd, type *val) { \ 137 | return read_n(fd, val, sizeof(type)); \ 138 | } 139 | 140 | write_func(uint8_t) 141 | read_func(uint8_t) 142 | 143 | write_func(uint32_t) 144 | read_func(uint32_t) 145 | 146 | write_func(size_t) 147 | read_func(size_t) 148 | -------------------------------------------------------------------------------- /loader/src/injector/clear.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "logging.h" 15 | 16 | static bool seccomp_filters_visible() { 17 | FILE *status_file = fopen("/proc/self/status", "r"); 18 | if (!status_file) { 19 | return true; 20 | } 21 | 22 | const char *needle = "Seccomp_filters:"; 23 | char line[256]; 24 | 25 | while (fgets(line, sizeof(line), status_file)) { 26 | if (strncmp(line, needle, strlen(needle)) == 0) { 27 | fclose(status_file); 28 | return true; 29 | } 30 | } 31 | 32 | fclose(status_file); 33 | return false; 34 | } 35 | 36 | static bool has_ptrace_message() { 37 | int pipefd[2] = {-1}; 38 | int status; 39 | pipe(pipefd); 40 | pid_t outer_pid = fork(); 41 | if (outer_pid == 0) { 42 | close(pipefd[0]); 43 | pid_t inner_pid = fork(); 44 | if (inner_pid == 0) { 45 | ptrace(PTRACE_ATTACH, getppid(), 0, 0); 46 | TEMP_FAILURE_RETRY(waitpid(getppid(), &status, 0)); 47 | unsigned long msg = 0; 48 | ptrace(PTRACE_GETEVENTMSG, getppid(), 0, &msg); 49 | char result = msg != 0 ? 1 : 0; 50 | TEMP_FAILURE_RETRY(write(pipefd[1], &result, 1)); 51 | _exit(0); 52 | } 53 | TEMP_FAILURE_RETRY(waitpid(inner_pid, &status, 0)); 54 | _exit(0); 55 | } 56 | close(pipefd[1]); 57 | char result = 1; 58 | TEMP_FAILURE_RETRY(read(pipefd[0], &result, 1)); 59 | TEMP_FAILURE_RETRY(waitpid(outer_pid, &status, 0)); 60 | close(pipefd[0]); 61 | return result; 62 | } 63 | 64 | void send_seccomp_event() { 65 | if (seccomp_filters_visible()) { 66 | return; 67 | } 68 | 69 | if (!has_ptrace_message()) { 70 | return; 71 | } 72 | 73 | __u32 args[4] = {0}; 74 | 75 | int rnd_fd = open("/dev/urandom", O_RDONLY); 76 | if (rnd_fd == -1) { 77 | PLOGE("send_seccomp_event: open(/dev/urandom)"); 78 | return; 79 | } 80 | 81 | if (read(rnd_fd, &args, sizeof(args)) != sizeof(args)) { 82 | PLOGE("send_seccomp_event: read(rnd_fd)"); 83 | close(rnd_fd); 84 | return; 85 | } 86 | 87 | close(rnd_fd); 88 | 89 | args[0] |= 0x10000; 90 | 91 | struct sock_filter filter[] = { 92 | /* INFO: Check syscall number */ 93 | BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)), 94 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_exit_group, 0, 9), 95 | 96 | /* INFO: Load and check arg0 (lower 32 bits) */ 97 | BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), 98 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[0], 0, 7), 99 | 100 | /* INFO: Load and check arg1 (lower 32 bits) */ 101 | BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[1])), 102 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[1], 0, 5), 103 | 104 | /* INFO: Load and check arg2 (lower 32 bits) */ 105 | BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[2])), 106 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[2], 0, 3), 107 | 108 | /* INFO: Load and check arg3 (lower 32 bits) */ 109 | BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[3])), 110 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[3], 0, 1), 111 | 112 | /* INFO: All match: return TRACE => will trigger PTRACE_EVENT_SECCOMP */ 113 | BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRACE), 114 | 115 | /* INFO: Default: allow */ 116 | BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), 117 | }; 118 | 119 | struct sock_fprog prog = { 120 | .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])), 121 | .filter = filter, 122 | }; 123 | 124 | if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { 125 | PLOGE("send_seccomp_event: prctl(SECCOMP)"); 126 | return; 127 | } 128 | 129 | /* INFO: This will trigger a ptrace event, syscall will not execute due to tracee_skip_syscall */ 130 | syscall(__NR_exit_group, args[0], args[1], args[2], args[3]); 131 | } 132 | -------------------------------------------------------------------------------- /zygiskd/src/companion.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include "utils.h" 19 | 20 | #undef LOG_TAG 21 | #define LOG_TAG lp_select("zygiskd-companion32", "zygiskd-companion64") 22 | 23 | typedef void (*zygisk_companion_entry)(int); 24 | 25 | struct companion_module_thread_args { 26 | int fd; 27 | zygisk_companion_entry entry; 28 | }; 29 | 30 | zygisk_companion_entry load_module(int fd) { 31 | char path[PATH_MAX]; 32 | snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); 33 | 34 | void *handle = dlopen(path, RTLD_NOW); 35 | 36 | if (!handle) return NULL; 37 | 38 | void *entry = dlsym(handle, "zygisk_companion_entry"); 39 | if (!entry) { 40 | LOGE("Failed to dlsym zygisk_companion_entry: %s\n", dlerror()); 41 | 42 | dlclose(handle); 43 | 44 | return NULL; 45 | } 46 | 47 | return (zygisk_companion_entry)entry; 48 | } 49 | 50 | /* WARNING: Dynamic memory based */ 51 | void *entry_thread(void *arg) { 52 | struct companion_module_thread_args *args = (struct companion_module_thread_args *)arg; 53 | 54 | int fd = args->fd; 55 | zygisk_companion_entry module_entry = args->entry; 56 | 57 | struct stat st0 = { 0 }; 58 | if (fstat(fd, &st0) == -1) { 59 | LOGE(" - Failed to get initial client fd stats: %s\n", strerror(errno)); 60 | 61 | free(args); 62 | 63 | return NULL; 64 | } 65 | 66 | module_entry(fd); 67 | 68 | /* INFO: Only attempt to close the client fd if it appears to be the same file 69 | and if we can successfully stat it again. This prevents double closes 70 | if the module companion already closed the fd. 71 | */ 72 | struct stat st1; 73 | if (fstat(fd, &st1) != -1 || st0.st_ino == st1.st_ino) { 74 | LOGI(" - Client fd changed after module entry\n"); 75 | 76 | close(fd); 77 | } 78 | 79 | free(args); 80 | 81 | return NULL; 82 | } 83 | 84 | /* WARNING: Dynamic memory based */ 85 | void companion_entry(int fd) { 86 | LOGI("New companion entry.\n - Client fd: %d\n", fd); 87 | 88 | char name[256 + 1]; 89 | ssize_t ret = read_string(fd, name, sizeof(name)); 90 | if (ret == -1) { 91 | LOGE("Failed to read module name\n"); 92 | 93 | goto cleanup; 94 | } 95 | 96 | LOGI(" - Module name: \"%s\"\n", name); 97 | 98 | int library_fd = read_fd(fd); 99 | if (library_fd == -1) { 100 | LOGE("Failed to receive library fd\n"); 101 | 102 | goto cleanup; 103 | } 104 | 105 | LOGI(" - Library fd: %d\n", library_fd); 106 | 107 | zygisk_companion_entry module_entry = load_module(library_fd); 108 | close(library_fd); 109 | 110 | if (module_entry == NULL) { 111 | LOGE(" - No companion module entry for module: %s\n", name); 112 | 113 | ret = write_uint8_t(fd, 0); 114 | ASSURE_SIZE_WRITE("ZygiskdCompanion", "module_entry", ret, sizeof(uint8_t)); 115 | 116 | goto cleanup; 117 | } else { 118 | LOGI(" - Module entry found\n"); 119 | 120 | ret = write_uint8_t(fd, 1); 121 | ASSURE_SIZE_WRITE("ZygiskdCompanion", "module_entry", ret, sizeof(uint8_t)); 122 | } 123 | 124 | struct sigaction sa = { .sa_handler = SIG_IGN }; 125 | sigaction(SIGPIPE, &sa, NULL); 126 | 127 | while (1) { 128 | if (!check_unix_socket(fd, true)) { 129 | LOGE("Something went wrong in companion. Bye!\n"); 130 | 131 | break; 132 | } 133 | 134 | int client_fd = read_fd(fd); 135 | if (client_fd == -1) { 136 | LOGE("Failed to receive client fd\n"); 137 | 138 | break; 139 | } 140 | 141 | struct companion_module_thread_args *args = malloc(sizeof(struct companion_module_thread_args)); 142 | if (args == NULL) { 143 | LOGE("Failed to allocate memory for thread args\n"); 144 | 145 | close(client_fd); 146 | 147 | break; 148 | } 149 | 150 | args->fd = client_fd; 151 | args->entry = module_entry; 152 | 153 | LOGI("New companion request.\n - Module name: %s\n - Client fd: %d\n", name, client_fd); 154 | 155 | ret = write_uint8_t(client_fd, 1); 156 | ASSURE_SIZE_WRITE("ZygiskdCompanion", "client_fd", ret, sizeof(uint8_t)); 157 | 158 | pthread_t thread; 159 | if (pthread_create(&thread, NULL, entry_thread, (void *)args) == 0) 160 | continue; 161 | 162 | LOGE(" - Failed to create thread for companion module\n"); 163 | 164 | close(client_fd); 165 | free(args); 166 | 167 | break; 168 | } 169 | 170 | cleanup: 171 | close(fd); 172 | LOGE("Companion thread exited\n"); 173 | 174 | exit(0); 175 | } 176 | -------------------------------------------------------------------------------- /READMEs/README_pt-BR.md: -------------------------------------------------------------------------------- 1 | # ReZygisk 2 | 3 | [English](../README.md) 4 | 5 | ReZygisk é uma fork do Zygisk Next, uma implementação do Zygisk independente, fornecendo a API do Zygisk para o KernelSU, APatch e Magisk (além do embutido). 6 | 7 | Ele foca em modernizar e re-escrever todo o código fonte para C, permitindo uma implementação da API do Zygisk com uma licença mais permissiva e amigável a FOSS. 8 | 9 | ## Por quê? 10 | 11 | Os últimos lançamentos do Zygisk Next não possuem código aberto, reservando-o para os seus desenvolvedores. Isso não só limita nossa capacidade de contribuir com o projeto, mas também impossibilita a auditoria do código, uma preocupação grave de segurança, já que o Zygisk Next é um módulo que roda como superuser (super usuário/root), tendo acesso a todo o sistema. 12 | 13 | Os desenvolvedores do Zygisk Next são famosos e confiados pela comunidade Android, mas isso não significa que o código não seja nem malicioso nem vulnerável. Nós (PerformanC) reconhecemos seus motivos de manterem o código recluso a eles, mas a gente acredita no contrário. 14 | 15 | ## Vantagens 16 | 17 | - FOSS (Pra sempre) 18 | 19 | ## Dependências 20 | 21 | | Ferramenta | Descrição | 22 | |-----------------|----------------------------------------------| 23 | | `Android NDK` | Kit de Desenvolvimento Nativo para o Android | 24 | 25 | ### Dependências C++ 26 | 27 | | Dependência | Descrição | 28 | |-------------|----------------------------------| 29 | | `lsplt` | PLT Hook simples para o Android | 30 | 31 | ## Instalação 32 | 33 | ### 1. Selecionando o zip apropriado 34 | 35 | A seleção da build/zip é importate, já que vai determinar o quão escondido e estável o ReZygisk vai ser. Isso, no entanto, não é uma tarefa difícil: 36 | 37 | - `release` deve ser a escolha para a maioria dos casos, ele remove o log de nível de app e oferece binários mais otimizados. 38 | - `debug`, no entanto, oferece o oposto, com logs extensos, e sem otimizações. Por isso, **você deve usar apenas para fins de depuração** e **ao obter logs para criar um Issue**. 39 | 40 | ### 2. "Flash"ando o zip 41 | 42 | Depois de escolher a build apropriada, você deve "flashar" ela usando seu gerenciador de root atual, como o Magisk ou o KernelSU. Você pode fazer isso indo na seção `Módulos` do seu gerenciador de root e selecionando o zip que você fez download. 43 | 44 | Depois de "flashar", confira os logs de instalação para garantir que não houve erros, e se tudo estiver certo, você pode reiniciar seu dispositivo. 45 | 46 | > [!WARNING] 47 | > Usuários do Magisk devem desabilitar o Zygisk embutido, já que ele vai conflitar com o ReZygisk. Isso pode ser feito indo na seção `Configurações` do Magisk e desabilitando a opção `Zygisk`. 48 | 49 | ### 3. Verificando a instalação 50 | 51 | Depois de reiniciar, você pode verificar se o ReZygisk está funcionando corretamente indo na seção `Módulos` do seu gerenciador de root. A descrição deve indicar que os daemons necessários estão rodando. Por exemplo, se seu ambiente suporta tanto 64-bit quanto 32-bit, deve estar parecido com isso: `[monitor: 😋 tracing, zygote64: 😋 injected, daemon64: 😋 running (...) zygote32: 😋 injected, daemon32: 😋 running (...)] Standalone implementation of Zygisk.` 52 | 53 | ## Tradução 54 | 55 | Tem duas formas diferentes de contribuir com traduções para o ReZygisk: 56 | 57 | - Para traduções do README, você pode criar um novo arquivo na pasta `READMEs`, seguindo a padronização de nome de `README_.md`, onde `` é o código do idioma (ex: `README_pt-BR.md` para português brasileiro), e abrir um pull request para o branch `main` com suas mudanças. 58 | - Para traduções da WebUI do ReZygisk, você deve primeiro contribuir no nosso [Crowdin](https://crowdin.com/project/rezygisk). Depois de aprovado, pegue o arquivo `.json` de lá e abra um pull request com suas mudanças -- adicionando o arquivo `.json` na pasta `webroot/lang` e seus créditos no arquivo `TRANSLATOR.md`, em ordem alfabética. 59 | 60 | ## Suporte 61 | 62 | Para quaisquer problemas no ReZygisk ou qualquer projeto da PerformanC, sinta-se livre para entrar em qualquer canal abaixo: 63 | 64 | - Server do Discord: [PerformanC](https://discord.gg/uPveNfTuCJ) 65 | - Canal do Telegram do ReZygisk: [@rezygisk](https://t.me/rezygisk) 66 | - Canal do Telegram da PerformanC: [@performancorg](https://t.me/performancorg) 67 | - Grupo do Signal da PerformanC: [@performanc](https://signal.group/#CjQKID3SS8N5y4lXj3VjjGxVJnzNsTIuaYZjj3i8UhipAS0gEhAedxPjT5WjbOs6FUuXptcT) 68 | 69 | ## Contribuição 70 | 71 | É obrigatório seguir as [Regras de Contribuição](https://github.com/PerformanC/contributing) da PerformanC para contribuir ao ReZygisk, seguindo sua Política de Segurança, Código de Conduta, e padronização de sintaxe. 72 | 73 | ## Licença 74 | 75 | ReZygisk é majoritamente licenciado em GPL, por Dr-TSNG, mas também em AGPL 3.0, pela A Organização PerformanC (The PerformanC Organization) para código re-escrito. Você pode ler mais em [Open Source Initiative](https://opensource.org/licenses/AGPL-3.0). 76 | -------------------------------------------------------------------------------- /module/src/META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | ################# 4 | # Initialization 5 | ################# 6 | 7 | umask 022 8 | 9 | # echo before loading util_functions 10 | ui_print() { echo "$1"; } 11 | 12 | require_new_magisk() { 13 | ui_print "*******************************" 14 | ui_print " Please install Magisk v19.0+! " 15 | ui_print "*******************************" 16 | exit 1 17 | } 18 | 19 | ######################### 20 | # Load util_functions.sh 21 | ######################### 22 | 23 | OUTFD=$2 24 | ZIPFILE=$3 25 | 26 | mount /data 2>/dev/null 27 | 28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk 29 | . /data/adb/magisk/util_functions.sh 30 | [ $MAGISK_VER_CODE -lt 19000 ] && require_new_magisk 31 | 32 | if [ $MAGISK_VER_CODE -ge 20400 ]; then 33 | # New Magisk have complete installation logic within util_functions.sh 34 | install_module 35 | exit 0 36 | fi 37 | 38 | ################# 39 | # Legacy Support 40 | ################# 41 | 42 | TMPDIR=/dev/tmp 43 | PERSISTDIR=/sbin/.magisk/mirror/persist 44 | 45 | is_legacy_script() { 46 | unzip -l "$ZIPFILE" install.sh | grep -q install.sh 47 | return $? 48 | } 49 | 50 | print_modname() { 51 | local len 52 | len=`echo -n $MODNAME | wc -c` 53 | len=$((len + 2)) 54 | local pounds=`printf "%${len}s" | tr ' ' '*'` 55 | ui_print "$pounds" 56 | ui_print " $MODNAME " 57 | ui_print "$pounds" 58 | ui_print "*******************" 59 | ui_print " Powered by Magisk " 60 | ui_print "*******************" 61 | } 62 | 63 | # Override abort as old scripts have some issues 64 | abort() { 65 | ui_print "$1" 66 | $BOOTMODE || recovery_cleanup 67 | [ -n $MODPATH ] && rm -rf $MODPATH 68 | rm -rf $TMPDIR 69 | exit 1 70 | } 71 | 72 | rm -rf $TMPDIR 2>/dev/null 73 | mkdir -p $TMPDIR 74 | 75 | # Preperation for flashable zips 76 | setup_flashable 77 | 78 | # Mount partitions 79 | mount_partitions 80 | 81 | # Detect version and architecture 82 | api_level_arch_detect 83 | 84 | # Setup busybox and binaries 85 | $BOOTMODE && boot_actions || recovery_actions 86 | 87 | ############## 88 | # Preparation 89 | ############## 90 | 91 | # Extract prop file 92 | unzip -o "$ZIPFILE" module.prop -d $TMPDIR >&2 93 | [ ! -f $TMPDIR/module.prop ] && abort "! Unable to extract zip file!" 94 | 95 | $BOOTMODE && MODDIRNAME=modules_update || MODDIRNAME=modules 96 | MODULEROOT=$NVBASE/$MODDIRNAME 97 | MODID=`grep_prop id $TMPDIR/module.prop` 98 | MODPATH=$MODULEROOT/$MODID 99 | MODNAME=`grep_prop name $TMPDIR/module.prop` 100 | 101 | # Create mod paths 102 | rm -rf $MODPATH 2>/dev/null 103 | mkdir -p $MODPATH 104 | 105 | ########## 106 | # Install 107 | ########## 108 | 109 | if is_legacy_script; then 110 | unzip -oj "$ZIPFILE" module.prop install.sh uninstall.sh 'common/*' -d $TMPDIR >&2 111 | 112 | # Load install script 113 | . $TMPDIR/install.sh 114 | 115 | # Callbacks 116 | print_modname 117 | on_install 118 | 119 | # Custom uninstaller 120 | [ -f $TMPDIR/uninstall.sh ] && cp -af $TMPDIR/uninstall.sh $MODPATH/uninstall.sh 121 | 122 | # Skip mount 123 | $SKIPMOUNT && touch $MODPATH/skip_mount 124 | 125 | # prop file 126 | $PROPFILE && cp -af $TMPDIR/system.prop $MODPATH/system.prop 127 | 128 | # Module info 129 | cp -af $TMPDIR/module.prop $MODPATH/module.prop 130 | 131 | # post-fs-data scripts 132 | $POSTFSDATA && cp -af $TMPDIR/post-fs-data.sh $MODPATH/post-fs-data.sh 133 | 134 | # service scripts 135 | $LATESTARTSERVICE && cp -af $TMPDIR/service.sh $MODPATH/service.sh 136 | 137 | ui_print "- Setting permissions" 138 | set_permissions 139 | else 140 | print_modname 141 | 142 | unzip -o "$ZIPFILE" customize.sh -d $MODPATH >&2 143 | 144 | if ! grep -q '^SKIPUNZIP=1$' $MODPATH/customize.sh 2>/dev/null; then 145 | ui_print "- Extracting module files" 146 | unzip -o "$ZIPFILE" -x 'META-INF/*' -d $MODPATH >&2 147 | 148 | # Default permissions 149 | set_perm_recursive $MODPATH 0 0 0755 0644 150 | fi 151 | 152 | # Load customization script 153 | [ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh 154 | fi 155 | 156 | # Handle replace folders 157 | for TARGET in $REPLACE; do 158 | ui_print "- Replace target: $TARGET" 159 | mktouch $MODPATH$TARGET/.replace 160 | done 161 | 162 | if $BOOTMODE; then 163 | # Update info for Magisk Manager 164 | mktouch $NVBASE/modules/$MODID/update 165 | cp -af $MODPATH/module.prop $NVBASE/modules/$MODID/module.prop 166 | fi 167 | 168 | # Copy over custom sepolicy rules 169 | if [ -f $MODPATH/sepolicy.rule -a -e $PERSISTDIR ]; then 170 | ui_print "- Installing custom sepolicy patch" 171 | PERSISTMOD=$PERSISTDIR/magisk/$MODID 172 | mkdir -p $PERSISTMOD 173 | cp -af $MODPATH/sepolicy.rule $PERSISTMOD/sepolicy.rule 174 | fi 175 | 176 | # Remove stuffs that don't belong to modules 177 | rm -rf \ 178 | $MODPATH/system/placeholder $MODPATH/customize.sh \ 179 | $MODPATH/README.md $MODPATH/.git* 2>/dev/null 180 | 181 | ############# 182 | # Finalizing 183 | ############# 184 | 185 | cd / 186 | $BOOTMODE || recovery_cleanup 187 | rm -rf $TMPDIR 188 | 189 | ui_print "- Done" 190 | exit 0 -------------------------------------------------------------------------------- /READMEs/README_id-ID.md: -------------------------------------------------------------------------------- 1 | # ReZygisk 2 | 3 | [English](https://github.com/PerformanC/ReZygisk) 4 | 5 | ReZygisk adalah turunan dari Zygisk Next, sebuah implementasi mandiri dari Zygisk, menyediakan dukungan API Zygisk untuk KernelSU, APatch, dan Magisk (Versi Resmi dan Kitsune). 6 | 7 | Tujuannya adalah untuk memodernisasi dan menulis ulang kode sumber sepenuhnya dalam bahasa C, memungkinkan implementasi API Zygisk yang lebih efisien dan cepat dengan lisensi yang lebih permisif dan ramah terhadap FOSS (Free and Open Source Software). 8 | 9 | ## Mengapa? 10 | 11 | Rilisan terbaru dari Zygisk Next tidak bersifat open-source, dengan kode yang sepenuhnya dikendalikan oleh developernya. Hal ini tidak hanya membatasi kemampuan kami untuk berkontribusi pada proyek ini, tetapi juga membuat kode tidak dapat diaudit, yang menjadi masalah utama keamanan karena Zygisk Next adalah modul yang berjalan dengan hak superuser (root), yang memiliki akses ke seluruh sistem. 12 | 13 | Meskipun developer Zygisk Next terkenal dan dipercaya dalam komunitas Android, hal ini tidak menjamin bahwa kode tersebut bebas dari bahaya atau kerentanan. Kami (PerformanC) memahami alasan mereka untuk menjaga kode tetap tertutup, tetapi kami memiliki pandangan yang berbeda. 14 | 15 | ## Keunggulan 16 | 17 | - FOSS (Free and Open Source Software) Selamanya. 18 | 19 | ## Komponen Pendukung 20 | 21 | | Alat | Deskripsi | 22 | |------------------|--------------------------------------------| 23 | | `Android NDK` | Native Development Kit untuk Android | 24 | 25 | ### Komponen Pendukung C++ 26 | 27 | | Ketergantungan | Deskripsi | 28 | |----------------|---------------------------------| 29 | | `lsplt` | Simple PLT Hook untuk Android | 30 | 31 | ## Instalasi 32 | 33 | ### 1. Pilih file ZIP yang tepat 34 | 35 | Pemilihan build/zip sangat penting, karena ini akan menentukan seberapa tersembunyi dan stabil ReZygisk. Namun, ini bukan tugas yang sulit: 36 | 37 | - `release`: Direkomendasikan untuk penggunaan normal. Binary lebih optimal, logging minimal. 38 | - `debug`: Untuk keperluan debug. Logging lengkap, tanpa optimasi. 39 | 40 | Untuk branch, selalu gunakan main branch, kecuali diinstruksikan oleh pengembang, atau jika Anda ingin menguji fitur mendatang dan menyadari risikonya. 41 | 42 | ### 2. Flash file ZIP 43 | 44 | Setelah memilih build yang tepat, Anda harus mem-flash-nya menggunakan pengelola root Anda saat ini, seperti Magisk atau KernelSU. Anda dapat melakukannya dengan masuk ke bagian Modules di pengelola root Anda dan memilih zip yang telah diunduh. 45 | 46 | Setelah mem-flash, periksa log instalasi untuk memastikan tidak ada kesalahan, dan jika semuanya selesai, Anda dapat me-reboot perangkat Anda 47 | 48 | > [!WARNING] 49 | > Pengguna Magisk harus menonaktifkan Zygisk bawaan, karena ini akan bentrok dengan ReZygisk. Ini dapat dilakukan dengan masuk ke bagian `Settings` di Magisk dan menonaktifkan opsi `Zygisk`. 50 | 51 | ### 3. Verifikasi Instalasi 52 | 53 | Setelah reboot, Anda dapat memverifikasi apakah ReZygisk bekerja dengan baik dengan memeriksa deskripsi modul di bagian Modules pada pengelola root Anda. Deskripsi tersebut harus menunjukkan bahwa daemon yang diperlukan sedang berjalan. Misalnya, jika lingkungan Anda mendukung 64-bit dan 32-bit, itu akan terlihat seperti ini: 54 | `[monitor: 😋 tracing, zygote64: 😋 injected, daemon64: 😋 running (...) zygote32: 😋 injected, daemon32: 😋 running (...)] Standalone implementation of Zygisk.` 55 | 56 | ## Terjemahan 57 | 58 | Saat ini ada dua cara untuk berkontribusi dalam terjemahan untuk ReZygisk: 59 | 60 | - Untuk terjemahan README, Anda dapat membuat file baru di folder `READMEs`, mengikuti konvensi penamaan `README_.md`, di mana `` adalah kode bahasa (misalnya, `README_id-ID.md` untuk Bahasa Indonesia), dan membuka pull request ke `main` branch. 61 | - Untuk terjemahan WebUI ReZygisk, Anda harus berkontribusi terlebih dahulu di [Crowdin](https://crowdin.com/project/rezygisk). Setelah disetujui, ambil file `.json` dari sana dan buka pull request dengan perubahan Anda -- tambahkan file `.json` ke folder `webroot/lang` dan kredit Anda ke file TRANSLATOR.md, dalam urutan alfabet. 62 | 63 | ## Dukungan 64 | 65 | Untuk pertanyaan terkait ReZygisk atau proyek PerformanC lainnya, jangan ragu untuk bergabung dengan salah satu saluran berikut: 66 | 67 | Untuk pertanyaan terkait ReZygisk atau proyek PerformanC lainnya, silakan bergabung ke salah satu saluran berikut: 68 | 69 | - Saluran Discord: [PerformanC](https://discord.gg/uPveNfTuCJ) 70 | - Saluran Telegram ReZygisk: [@rezygisk](https://t.me/rezygisk) 71 | - Saluran Telegram PerformanC: [@performancorg](https://t.me/performancorg) 72 | - Grup Signal PerformanC: [@performanc](https://signal.group/#CjQKID3SS8N5y4lXj3VjjGxVJnzNsTIuaYZjj3i8UhipAS0gEhAedxPjT5WjbOs6FUuXptcT) 73 | 74 | ## Kontribusi 75 | 76 | Wajib mengikuti [Pedoman Kontribusi](https://github.com/PerformanC/contributing) PerformanC's untuk berkontribusi pada ReZygisk. Sesuai dengan Kebijakan Keamanan, Kode Etik, standar struktur dan format yang berlaku. 77 | 78 | ## Lisensi 79 | 80 | ReZygisk sebagian besar berlisensi di bawah GPL, oleh Dr-TSNG, tetapi juga AGPL 3.0, oleh The PerformanC Organization, untuk kode yang ditulis ulang. Anda dapat juga membaca lebih lanjut di [Open Source Initiative](https://opensource.org/licenses/AGPL-3.0). 81 | -------------------------------------------------------------------------------- /READMEs/README_vi-VN.md: -------------------------------------------------------------------------------- 1 | # ReZygisk 2 | 3 | [English](../README.md) 4 | 5 | ReZygisk làm một nhánh phát triển lấy từ ZygiskNext, một triển khai độc lập của Zygisk, cung cấp và hỗ trợ Zygisk API cho KernelSU, APatch và Magisk (chính thức và Kitsune). 6 | 7 | Mục tiêu của ReZygisk là mô-đun hoá và viết lại toàn bộ codebase sang C, cho phép triển khai API Zygisk hiệu quả hơn và nhanh hơn với giấy phép dễ dàng tái sử dụng hơn. 8 | 9 | ## Tại sao nhánh phát triển này lại xuất hiện? 10 | 11 | Bản ra mắt mới nhất của Zygisk Next không còn là mã nguồn mở, dành toàn bộ quyền phát triển phần mềm cho những nhà phát triển gốc. Không chỉ giới hạn chúng ta đóng gốp cho dự án, mà còn bất khả thi trong việc kiểm trả độ đảm bảo của mã, điều mà có thể coi là mối quan tâm lớn về tính bảo mật và độ an toàn, bởi Zygisk Next là mô-đun chạy dưới quyền quản trị (root), có khả năng truy cập vào toàn bộ hệ thống trong thiết bị của bạn. 12 | 13 | Các nhà phát triển Zygisk Next đều là những người nổi tiếng và được tin tưởng bởi cộng đồng sử dụng Android, tuy nhiên, điều đó không có nghĩa là mã nguồn của họ không có lỗ hổng hoặc có nguy cơ bị tấn công. Chúng tôi (PerformanC) thông cảm được lý do mà học đóng mã nguồn của họ vào, tuy nhiễn chúng tôi tin vào điều ngược lại. 14 | 15 | ## Ưu điểm 16 | 17 | - Mã nguồn mở (Vĩnh Viễn) 18 | 19 | ## Các công cụ/thư viện được sử dụng 20 | 21 | | Công cụ / Thư Viện | Mô tả | 22 | |---------------------------|-------------------------------------------| 23 | | `Android NDK` | Bộ công cụ phát triển cốt lõi cho Android | 24 | 25 | ### Các công cụ/thư viện của C++ được sử dụng 26 | 27 | | Thư Viện | Mô Tả | 28 | |------------|----------------------------------------------| 29 | | `lsplt` | Công cụ **móc** vào PLT đơn giản cho Android | 30 | 31 | ## Cài Đặt 32 | 33 | ### 1. Sử dụng đúng tệp zip 34 | 35 | Chọn đúng tệp bản dựng / zip là một điều tất yếu, bởi nó sẽ xác định khả năng ẩn của ReZygisk. Về cơ bản đây không phải là một việc khó: 36 | 37 | - `release` bản này sẽ được chọn trong hầy hết các trường hợp sử dụng, bản này loại bỏ nhật ký phát triển cấp độ ứng dụng và cung cấp các tệp nhị phân được tối ưu hóa hơn. 38 | - `debug`, bản này tuy nhiên không được tối ưu và đi kèm với nó là ghi lại nhật ký phát triển khá nhiều. Vì lý do này, **chỉ nên sử dụng khi cần gỡ lỗi** và **khi cần ghi lại nhật lý để tạo báo về lỗi hoặc gì đó**. 39 | 40 | As for branches, you should always use the `main` branch, unless told otherwise by the developers, or if you want to test upcoming features and are aware of the risks involved. 41 | 42 | ### 2. Flash the zip 43 | 44 | Sau khi chọn một bản dựng phù hợp với bạn, điều cần làm là flash nó bằng trình quản lý root như Magisk hay KernelSU. Bạn có thể làm điều này bằng cách vào mục `Mô-đun / Module` của trình quản lý root của bạn và chọn tệp zip vừa tải xuống. 45 | 46 | Sau khi flash, kiểm tra lại nhật ký lỗi để chắc chắn rằng không có lỗi nào xảy ra, nếu mọi thứ xuôn sẻ, khởi động lại thiết bị. 47 | 48 | > [!WARNING] 49 | > Người dùng Magisk cần phải tắt `built-in Zygisk`, bởi nó sẽ xung đột với ReZygisk. Điều này có thể thực hiện bằng cách vào `Cài Đặt` và tắt tùy chọn `ZygiskZygisk` 50 | 51 | ### 3. Verify the installation 52 | 53 | Sau khi khởi động lại, bạn có thể xác minh ReZygisk có hoạt động bình thường không bằng cách kiểm tra mô tả module trong phần `Modules` của trình quản lý gốc. Mô tả sẽ chỉ ra rằng các daemon cần thiết đang chạy. Ví dụ, nếu môi trường của bạn hỗ trợ cả cấu trúctrúc 64-bit và 32-bit, nó sẽ trông giống như thế này: `[monitor: 😋 tracing, zygote64: 😋 inject, daemon64: 😋 running (...) zygote32: 😋 inject, daemon32: 😋 running (...)] Standalone implementation of Zygisk.` 54 | 55 | ## Dịch WebUI cho mô-đun 56 | 57 | Hiện tại có hai cách khác nhau để đóng góp bản dịch cho ReZygisk: 58 | 59 | - Đối với bản dịch của README, bạn có thể tạo một tệp mới trong thư mục `READMEs`, theo quy ước đặt tên `README_.md`, trong đó `` là mã ngôn ngữ (ví dụ: `README_pt-BR.md` cho tiếng Bồ Đào Nha Brazil) và mở yêu cầu kéo đến nhánh `main` với các thay đổi của bạn. 60 | - Đối với bản dịch của ReZygisk WebUI, trước tiên bạn phải đóng góp cho [Crowdin](https://crowdin.com/project/rezygisk) của chúng tôi. Sau khi được chấp thuận, hãy lấy tệp `.json` từ đó và mở yêu cầu kéo với các thay đổi của bạn -- thêm tệp `.json` vào thư mục `webroot/lang` và ghi công của bạn vào tệp `TRANSLATOR.md`, theo thứ tự bảng chữ cái. 61 | 62 | ## Hỗ trợ 63 | 64 | Nếu bạn có những câu hỏi nào dành cho ReZygisk hoặc bất kì một dự án nào của PerformanC, hãy tự nhiên tham gia các kênh trò chuyện dưới đây: 65 | 66 | - Kênh Discord: [PerformanC](https://discord.gg/uPveNfTuCJ) 67 | - Kênh Telegram ReZygisk: [@rezygisk](https://t.me/rezygisk) 68 | - Kênh Telegram PerformanC: [@performancorg](https://t.me/performancorg) 69 | - Nhóm Signal PerformanC: [@performanc](https://signal.group/#CjQKID3SS8N5y4lXj3VjjGxVJnzNsTIuaYZjj3i8UhipAS0gEhAedxPjT5WjbOs6FUuXptcT) 70 | 71 | ## Đóng góp cho dự án này 72 | 73 | Tuân theo [hướng dẫn đóng góp](https://github.com/PerformanC/contributing) của PerformanC là một điều tất yếu mà bạn bắt buộc phải làm. Hãy tuân theo chính sách bảo mật, quy tắc ứng xử/đóng góp mã nguồn và tiêu chuẩn cú pháp riêng. 74 | 75 | ## Bản quyền 76 | 77 | Hầu hết các thành phần của ReZygisk để dưới bản quyền GPL (bởi Dr-TSNG) và AGPL 3.0 (bởiThe PerformanC Organization) cho những phần được viết lại. Bạn có thể xem thêm trong trang [Open Source Initiative](https://opensource.org/licenses/AGPL-3.0). 78 | -------------------------------------------------------------------------------- /zygiskd/src/root_impl/apatch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../constants.h" 8 | #include "../utils.h" 9 | #include "common.h" 10 | 11 | #include "apatch.h" 12 | 13 | void apatch_get_existence(struct root_impl_state *state) { 14 | struct stat s; 15 | if (stat("/data/adb/apd", &s) != 0) { 16 | if (errno != ENOENT) { 17 | LOGE("Failed to stat APatch apd binary: %s\n", strerror(errno)); 18 | } 19 | errno = 0; 20 | 21 | state->state = Inexistent; 22 | 23 | return; 24 | } 25 | 26 | char *PATH = getenv("PATH"); 27 | if (PATH == NULL) { 28 | LOGE("Failed to get PATH environment variable: %s\n", strerror(errno)); 29 | errno = 0; 30 | 31 | state->state = Inexistent; 32 | 33 | return; 34 | } 35 | 36 | if (strstr(PATH, "/data/adb/ap/bin") == NULL) { 37 | LOGE("APatch's APD binary is not in PATH\n"); 38 | 39 | state->state = Inexistent; 40 | 41 | return; 42 | } 43 | 44 | char apatch_version[32]; 45 | char *const argv[] = { "apd", "-V", NULL }; 46 | 47 | if (!exec_command(apatch_version, sizeof(apatch_version), "/data/adb/apd", argv)) { 48 | LOGE("Failed to execute apd binary: %s\n", strerror(errno)); 49 | errno = 0; 50 | 51 | state->state = Inexistent; 52 | 53 | return; 54 | } 55 | 56 | int version = atoi(apatch_version + strlen("apd ")); 57 | 58 | if (version == 0) state->state = Abnormal; 59 | else if (version >= MIN_APATCH_VERSION && version <= 999999) state->state = Supported; 60 | else if (version >= 1 && version <= MIN_APATCH_VERSION - 1) state->state = TooOld; 61 | else state->state = Abnormal; 62 | } 63 | 64 | struct package_config { 65 | uid_t uid; 66 | bool root_granted; 67 | bool umount_needed; 68 | }; 69 | 70 | struct packages_config { 71 | struct package_config *configs; 72 | size_t size; 73 | }; 74 | 75 | /* WARNING: Dynamic memory based */ 76 | bool _apatch_get_package_config(struct packages_config *restrict config) { 77 | config->configs = NULL; 78 | config->size = 0; 79 | 80 | FILE *fp = fopen("/data/adb/ap/package_config", "r"); 81 | if (fp == NULL) { 82 | LOGE("Failed to open APatch's package_config: %s\n", strerror(errno)); 83 | 84 | return false; 85 | } 86 | 87 | char line[1048]; 88 | /* INFO: Skip the CSV header */ 89 | if (fgets(line, sizeof(line), fp) == NULL) { 90 | LOGE("Failed to read APatch's package_config header: %s\n", strerror(errno)); 91 | 92 | fclose(fp); 93 | 94 | return false; 95 | } 96 | 97 | while (fgets(line, sizeof(line), fp) != NULL) { 98 | config->configs = realloc(config->configs, (config->size + 1) * sizeof(struct package_config)); 99 | if (config->configs == NULL) { 100 | LOGE("Failed to realloc APatch config struct: %s\n", strerror(errno)); 101 | 102 | fclose(fp); 103 | 104 | return false; 105 | } 106 | 107 | strtok(line, ","); 108 | 109 | char *exclude_str = strtok(NULL, ","); 110 | if (exclude_str == NULL) continue; 111 | 112 | char *allow_str = strtok(NULL, ","); 113 | if (allow_str == NULL) continue; 114 | 115 | char *uid_str = strtok(NULL, ","); 116 | if (uid_str == NULL) continue; 117 | 118 | config->configs[config->size].uid = (uid_t)atoi(uid_str); 119 | config->configs[config->size].root_granted = strcmp(allow_str, "1") == 0; 120 | config->configs[config->size].umount_needed = strcmp(exclude_str, "1") == 0; 121 | 122 | config->size++; 123 | } 124 | 125 | fclose(fp); 126 | 127 | return true; 128 | } 129 | 130 | void _apatch_free_package_config(struct packages_config *restrict config) { 131 | free(config->configs); 132 | } 133 | 134 | bool apatch_uid_granted_root(uid_t uid) { 135 | struct packages_config config; 136 | if (!_apatch_get_package_config(&config)) { 137 | _apatch_free_package_config(&config); 138 | 139 | return false; 140 | } 141 | 142 | for (size_t i = 0; i < config.size; i++) { 143 | if (config.configs[i].uid != uid) continue; 144 | 145 | /* INFO: This allow us to copy the information to avoid use-after-free */ 146 | bool root_granted = config.configs[i].root_granted; 147 | 148 | _apatch_free_package_config(&config); 149 | 150 | return root_granted; 151 | } 152 | 153 | _apatch_free_package_config(&config); 154 | 155 | return false; 156 | } 157 | 158 | bool apatch_uid_should_umount(uid_t uid) { 159 | struct packages_config config; 160 | if (!_apatch_get_package_config(&config)) { 161 | _apatch_free_package_config(&config); 162 | 163 | return false; 164 | } 165 | 166 | for (size_t i = 0; i < config.size; i++) { 167 | if (config.configs[i].uid != uid) continue; 168 | 169 | /* INFO: This allow us to copy the information to avoid use-after-free */ 170 | bool umount_needed = config.configs[i].umount_needed; 171 | 172 | _apatch_free_package_config(&config); 173 | 174 | return umount_needed; 175 | } 176 | 177 | _apatch_free_package_config(&config); 178 | 179 | return false; 180 | } 181 | 182 | bool apatch_uid_is_manager(uid_t uid) { 183 | struct stat s; 184 | if (stat("/data/user_de/0/me.bmax.apatch", &s) == -1) { 185 | if (errno != ENOENT) { 186 | LOGE("Failed to stat APatch manager data directory: %s\n", strerror(errno)); 187 | } 188 | errno = 0; 189 | 190 | return false; 191 | } 192 | 193 | return s.st_uid == uid; 194 | } 195 | --------------------------------------------------------------------------------