9 Commits

Author SHA1 Message Date
Rifat Azad
bc1b757bb8 update: CMD_HOOK_MODE and CMD_GET_MANAGER_UID values (#200)
This commit updates the values for "CMD_HOOK_MODE" to match newest KernelSU Next value and "CMD_GET_MANAGER_UID", now unified in both KernelSU and KernelSU Next.

Signed-off-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-07-11 09:32:17 -03:00
Re*Index. (ot_inc)
a0a54f2153 add: ja_JP translation to WebUI (#195)
This commit adds Japanese translation to ReZygisk WebUI.

Signed-off-by: Re*Index. (ot_inc) <32851879+reindex-ot@users.noreply.github.com>
2025-07-05 00:30:22 -03:00
Ada
295a62b649 update: tr_TR credits in TRANSLATOR.md (#192)
This commit updates the credits for "tr_TR" translator, updating witchfuneral's GitHub account name.

Signed-off-by: Ada <65596971+witchfuneral@users.noreply.github.com>
2025-07-05 00:25:45 -03:00
ThePedroo
b6f02b39b3 fix: runtime KSUN manager switch detection
This commit fixes the issue where the new KernelSU Next manager wouldn't be recognized if it was changed without a reboot.
2025-07-01 14:31:06 -03:00
ThePedroo
e036b1f40a add: KernelSU Next spoofed manager recognition support
This commit adds support for ReZygiskd to identify which app is the manager in KSUN (KernelSU Next) builds with spoofed manager package name.
2025-07-01 14:11:39 -03:00
ThePedroo
9a3b2f4a79 fix: KernelSU variant detection
This commit fixes the KSU variant detection, which previously was hardcoded on accident to always set it to KernelSU Next.
2025-06-29 14:23:04 -03:00
nampud
9810eb3974 improve: ptrace_message reset with seccomp (#191)
This commit improves how "ptrace_message" is cleaned by utilizing seccomp (Secure Computation Mode) to clear its value.

"ptrace_message" not being cleared is a Linux kernel vulnerability/bug that impacts all versions below 6.1, as the fix only came in 6.1, and because of that, we need to find ways to "0" it. This is the second fix for that, being the GKI2 fix the first: 70697be9a5
2025-06-29 03:41:42 -03:00
ThePedroo
823623a96f improve: set ZYGISK_ENABLED in all supported managers' process
This commit sets the environment variable "ZYGISK_ENABLED" for all managers' process, not limiting to Magisk anymore, so that managers can easily detect (Re)Zygisk.
2025-06-27 14:39:36 -03:00
ThePedroo
a75b2fe2b8 add: KernelSU Next recognition support
This commit adds support for recognizing KernelSU (KSUN) manager to ReZygiskd.
2025-06-27 14:39:21 -03:00
15 changed files with 299 additions and 20 deletions

View File

@@ -6,13 +6,13 @@
- **es_ES** by [@LuchoModzzz](https://github.com/Lxchoooo)
- **es_MX** by [@LuchoModzzz](https://github.com/Lxchoooo)
- **fr_FR** by [@GhostFRR](https://github.com/GhostFRR)
- **ja_JP** by [@Fyphen1223](https://github.com/Fyphen1223)
- **ja_JP** by [@Fyphen1223](https://github.com/Fyphen1223) & [@reindex-ot](https://github.com/reindex-ot)
- **id_ID** by [@bpanca05](https://github.com/bpanca05) & [@LuckyKiddos](https://github.com/GuitarHeroStyles)
- **it_IT** by [@thasave14](https://github.com/thasave14)
- **pt_BR** by [@ThePedroo](https://github.com/ThePedroo)
- **ro_RO** by [@ExtremeXT](https://github.com/ExtremeXT)
- **ru_RU** by [@Emulond](https://github.com/Emulond) & [@AJleKcAHgP68](https://github.com/AJleKcAHgP68)
- **tr_TR** by [@dyingwillow](https://github.com/dyingwillow)
- **tr_TR** by [@witchfuneral](https://github.com/witchfuneral)
- **uk_UA** by [@Kittyskj](https://github.com/Kittyskj)
- **vi_VN** by [@RainyXeon](https://github.com/RainyXeon)
- **zh_CN** by [@Meltartica](https://github.com/Meltartica) & [@SheepChef](https://github.com/SheepChef)

View File

@@ -0,0 +1,97 @@
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <linux/audit.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "logging.h"
static bool seccomp_filters_visible() {
FILE *status_file = fopen("/proc/self/status", "r");
if (!status_file) {
return true;
}
const char *needle = "Seccomp_filters:";
char line[256];
while (fgets(line, sizeof(line), status_file)) {
if (strncmp(line, needle, strlen(needle)) == 0) {
fclose(status_file);
return true;
}
}
fclose(status_file);
return false;
}
void send_seccomp_event() {
if (seccomp_filters_visible()) {
return;
}
__u32 args[4] = {0};
int rnd_fd = open("/dev/urandom", O_RDONLY);
if (rnd_fd == -1) {
PLOGE("send_seccomp_event: open(/dev/urandom)");
return;
}
if (read(rnd_fd, &args, sizeof(args)) != sizeof(args)) {
PLOGE("send_seccomp_event: read(rnd_fd)");
close(rnd_fd);
return;
}
close(rnd_fd);
args[0] |= 0x10000;
struct sock_filter filter[] = {
/* INFO: Check syscall number */
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_exit_group, 0, 9),
/* INFO: Load and check arg0 (lower 32 bits) */
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[0], 0, 7),
/* INFO: Load and check arg1 (lower 32 bits) */
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[1])),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[1], 0, 5),
/* INFO: Load and check arg2 (lower 32 bits) */
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[2])),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[2], 0, 3),
/* INFO: Load and check arg3 (lower 32 bits) */
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[3])),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, args[3], 0, 1),
/* INFO: All match: return TRACE => will trigger PTRACE_EVENT_SECCOMP */
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRACE),
/* INFO: Default: allow */
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
};
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
.filter = filter,
};
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
PLOGE("send_seccomp_event: prctl(SECCOMP)");
return;
}
/* INFO: This will trigger a ptrace event, syscall will not execute due to tracee_skip_syscall */
syscall(__NR_exit_group, args[0], args[1], args[2], args[3]);
}

View File

@@ -25,4 +25,5 @@ void entry(void* addr, size_t size, const char* path) {
void *module_addrs[1] = { addr };
clean_trace(path, module_addrs, 1, 1, 0, false);
send_seccomp_event();
}

View File

@@ -773,15 +773,18 @@ void ZygiskContext::app_specialize_pre() {
update_mnt_ns(Clean, true);
}
if ((info_flags & (PROCESS_IS_MANAGER | PROCESS_ROOT_IS_MAGISK)) == (PROCESS_IS_MANAGER | PROCESS_ROOT_IS_MAGISK)) {
if ((info_flags & PROCESS_IS_MANAGER) == PROCESS_IS_MANAGER) {
LOGD("Manager process detected. Notifying that Zygisk has been enabled.");
/* INFO: This environment variable is related to Magisk Zygisk/Manager. It
it used by Magisk's Zygisk to communicate to Magisk Manager whether
Zygisk is working or not.
Zygisk is working or not, allowing Zygisk modules to both work properly
and for the manager to mark Zygisk as enabled.
To allow Zygisk modules to both work properly and for the manager to
identify Zygisk, being it not built-in, as working, we also set it. */
However, to enhance capabilities of root managers, it is also set for
any other supported manager, so that, if they wish, they can recognize
if Zygisk is enabled.
*/
setenv("ZYGISK_ENABLED", "1", 1);
} else {
/* INFO: Because we load directly from the file, we need to do it before we umount

View File

@@ -8,3 +8,5 @@ extern size_t block_size;
void hook_functions();
void clean_trace(const char *path, void **module_addrs, size_t module_addrs_length, size_t load, size_t unload, bool spoof_maps);
extern "C" void send_seccomp_event();

View File

@@ -403,7 +403,7 @@ bool trace_zygote(int pid) {
int status;
if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_EXITKILL) == -1) {
if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_EXITKILL | PTRACE_O_TRACESECCOMP) == -1) {
PLOGE("seize");
return false;

View File

@@ -522,6 +522,32 @@ int fork_dont_care() {
return pid;
}
void tracee_skip_syscall(int pid) {
struct user_regs_struct regs;
if (!get_regs(pid, &regs)) {
LOGE("failed to get seccomp regs");
exit(1);
}
regs.REG_SYSNR = -1;
if (!set_regs(pid, &regs)) {
LOGE("failed to set seccomp regs");
exit(1);
}
/* INFO: It might not work, don't check for error */
#if defined(__aarch64__)
int sysnr = -1;
struct iovec iov = {
.iov_base = &sysnr,
.iov_len = sizeof (int),
};
ptrace(PTRACE_SETREGSET, pid, NT_ARM_SYSTEM_CALL, &iov);
#elif defined(__arm__)
ptrace(PTRACE_SET_SYSCALL, pid, 0, (void*) -1);
#endif
}
void wait_for_trace(int pid, int *status, int flags) {
while (1) {
pid_t result = waitpid(pid, status, flags);
@@ -532,7 +558,13 @@ void wait_for_trace(int pid, int *status, int flags) {
exit(1);
}
if (!WIFSTOPPED(*status)) {
if (*status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) {
tracee_skip_syscall(pid);
ptrace(PTRACE_CONT, pid, 0, 0);
continue;
} else if (!WIFSTOPPED(*status)) {
char status_str[64];
parse_status(*status, status_str, sizeof(status_str));

View File

@@ -37,18 +37,22 @@ void free_maps(struct maps *maps);
#define REG_SP rsp
#define REG_IP rip
#define REG_RET rax
#define REG_SYSNR orig_rax
#elif defined(__i386__)
#define REG_SP esp
#define REG_IP eip
#define REG_RET eax
#define REG_SYSNR orig_eax
#elif defined(__aarch64__)
#define REG_SP sp
#define REG_IP pc
#define REG_RET regs[0]
#define REG_SYSNR regs[8]
#elif defined(__arm__)
#define REG_SP uregs[13]
#define REG_IP uregs[15]
#define REG_RET uregs[0]
#define REG_SYSNR uregs[7]
#define user_regs_struct user_regs
#endif

93
webroot/lang/ja_JP.json Normal file
View File

@@ -0,0 +1,93 @@
{
"langName": "日本語",
"global": {
"unknown": "不明"
},
"smallPage": {
"language": {
"header": "言語を選択してください"
},
"theme": {
"header": "テーマを選択してください",
"dark": "ダーク",
"light": "ライト",
"system": "システムベース"
},
"errorh": {
"buttons": {
"copy": "コピー",
"clear": "すべてのログを消去"
},
"header": "エラーの履歴",
"placeholder": "エラーログは記録されていません!"
}
},
"page": {
"home": {
"header": "ホーム",
"status": {
"notWorking": "動作していません",
"ok": "動作中",
"partially": "部分的に動作中"
},
"info": {
"version": "バージョン",
"root": "Root の実装",
"zygote": {
"injected": "インジェクト済み",
"notInjected": "未インジェクト",
"unknown": "不明"
}
}
},
"modules": {
"header": "モジュール",
"notAvaliable": "Zygisk を使用するモジュールはありません。",
"arch": "アーキテクチャ: "
},
"actions": {
"header": "アクション",
"monitorButton": {
"start": "開始",
"stop": "停止",
"pause": "一時停止"
},
"monitor": "監視",
"status": {
"tracing": "トレース中",
"stopping": "停止中",
"stopped": "停止済み",
"exiting": "終了中",
"unknown": "不明"
}
},
"settings": {
"header": "設定",
"font": {
"header": "システムフォントを有効化",
"description": "現在の WebUI でシステムフォントの使用を有効化します。注意: FlipFont との互換性がない場合があります"
},
"theme": {
"header": "システムテーマ",
"description": "WebUI のシステムテーマを変更します"
},
"language": {
"header": "言語の変更",
"description": "言語を変更します"
},
"logs": {
"header": "エラーの履歴",
"description": "すべてのエラーログを表示します"
},
"credits": {
"module": "モジュールの開発者",
"original": "オリジナルの開発者",
"web": "WebUI の開発者"
},
"license": {
"module": "モジュールのライセンス",
"web": "WebUI のライセンス"
}
}
}
}

View File

@@ -30,6 +30,7 @@ void root_impls_setup(void) {
impl.impl = Multiple;
} else if (state_ksu.state == Supported) {
impl.impl = KernelSU;
impl.variant = state_ksu.variant;
} else if (state_apatch.state == Supported) {
impl.impl = APatch;
} else if (state_magisk.state == Supported) {

View File

@@ -19,6 +19,12 @@
#define CMD_GET_VERSION 2
#define CMD_UID_GRANTED_ROOT 12
#define CMD_UID_SHOULD_UMOUNT 13
#define CMD_GET_MANAGER_UID 16
#define CMD_HOOK_MODE 0xC0DEAD1A
static enum kernelsu_variants variant = KOfficial;
static bool supports_manager_uid_retrieval = false;
void ksu_get_existence(struct root_impl_state *state) {
int version = 0;
@@ -42,6 +48,26 @@ void ksu_get_existence(struct root_impl_state *state) {
}
state->state = Supported;
char mode[16] = { 0 };
prctl((signed int)KERNEL_SU_OPTION, CMD_HOOK_MODE, mode, 0, 0);
if (mode[0] != '\0') state->variant = KNext;
else state->variant = KOfficial;
variant = state->variant;
/* INFO: CMD_GET_MANAGER_UID is a KernelSU Next feature, however we won't
limit to KernelSU Next only in case other forks wish to implement
it. */
int reply_ok = 0;
prctl((signed int)KERNEL_SU_OPTION, CMD_GET_MANAGER_UID, 0, 0, &reply_ok);
if (reply_ok == KERNEL_SU_OPTION) {
LOGI("KernelSU implementation supports CMD_GET_MANAGER_UID.\n");
supports_manager_uid_retrieval = true;
}
}
else if (version >= 1 && version <= MIN_KSU_VERSION - 1) state->state = TooOld;
else state->state = Abnormal;
@@ -68,8 +94,24 @@ bool ksu_uid_should_umount(uid_t uid) {
}
bool ksu_uid_is_manager(uid_t uid) {
/* INFO: If the manager UID is set, we can use it to check if the UID
is the manager UID, which is more reliable than checking
the KSU manager data directory, as spoofed builds of
KernelSU Next have different package names.
*/
if (supports_manager_uid_retrieval) {
uid_t manager_uid = 0;
prctl(KERNEL_SU_OPTION, CMD_GET_MANAGER_UID, &manager_uid, NULL, NULL);
return uid == manager_uid;
}
const char *manager_path = NULL;
if (variant == KOfficial) manager_path = "/data/user_de/0/me.weishu.kernelsu";
else if (variant == KNext) manager_path = "/data/user_de/0/com.rifsxd.ksunext";
struct stat s;
if (stat("/data/user_de/0/me.weishu.kernelsu", &s) == -1) {
if (stat(manager_path, &s) == -1) {
if (errno != ENOENT) {
LOGE("Failed to stat KSU manager data directory: %s\n", strerror(errno));
}

View File

@@ -3,6 +3,11 @@
#include "../constants.h"
enum kernelsu_variants {
KOfficial,
KNext
};
void ksu_get_existence(struct root_impl_state *state);
bool ksu_uid_granted_root(uid_t uid);

View File

@@ -28,7 +28,7 @@ char *magisk_managers[] = {
#define DEBUG_RAMDISK_MAGISK lp_select("/debug_ramdisk/magisk32", "/debug_ramdisk/magisk64")
#define BITLESS_DEBUG_RAMDISK_MAGISK "/debug_ramdisk/magisk"
enum magisk_variants variant = Official;
static enum magisk_variants variant = MOfficial;
/* INFO: Longest path */
static char path_to_magisk[sizeof(DEBUG_RAMDISK_MAGISK)] = { 0 };
bool is_using_sulist = false;
@@ -74,7 +74,7 @@ void magisk_get_existence(struct root_impl_state *state) {
return;
}
state->variant = (uint8_t)Official;
state->variant = (uint8_t)MOfficial;
for (unsigned long i = 0; i < sizeof(supported_variants) / sizeof(supported_variants[0]); i++) {
if (strstr(magisk_info, supported_variants[i])) {

View File

@@ -4,8 +4,8 @@
#include "../constants.h"
enum magisk_variants {
Official,
Kitsune
MOfficial,
MKitsune
};
void magisk_get_existence(struct root_impl_state *state);

View File

@@ -20,6 +20,7 @@
#include "utils.h"
#include "root_impl/common.h"
#include "root_impl/kernelsu.h"
#include "root_impl/magisk.h"
int clean_namespace_fd = 0;
@@ -436,7 +437,8 @@ void stringify_root_impl_name(struct root_impl impl, char *restrict output) {
break;
}
case KernelSU: {
strcpy(output, "KernelSU");
if (impl.variant == KOfficial) strcpy(output, "KernelSU");
else strcpy(output, "KernelSU Next");
break;
}
@@ -446,11 +448,8 @@ void stringify_root_impl_name(struct root_impl impl, char *restrict output) {
break;
}
case Magisk: {
if (impl.variant == 0) {
strcpy(output, "Magisk Official");
} else {
strcpy(output, "Magisk Kitsune");
}
if (impl.variant == MOfficial) strcpy(output, "Magisk Official");
else strcpy(output, "Magisk Kitsune");
break;
}
@@ -786,7 +785,7 @@ int save_mns_fd(int pid, enum MountNamespaceState mns_state, struct root_impl im
return -1;
}
if (impl.impl == Magisk && impl.variant == Kitsune && mns_state == Clean) {
if (impl.impl == Magisk && impl.variant == MKitsune && mns_state == Clean) {
LOGI("[Magisk] Magisk Kitsune detected, will skip cache first.");
/* INFO: MagiskSU of Kitsune has a special behavior: It is only mounted