溺的文档
ReZygisk · 第 4 篇 / 共 4 篇

ReZygisk 外围:IPC、模块脚本、构建与 WebUI

2026-06-30 · 阅读 1

本文是 ReZygisk 源码解读系列第 5 篇(末篇)。全系列:

  • 00 总览与整体架构
  • 01 守护进程 zygiskd 与 Root 适配
  • 02 注入机制:monitor 监控与 ptracer 注入
  • 03 注入体 injector 与反检测基石
  • 04 外围:IPC 协议、模块脚本、构建签名与 WebUI(本篇)

代码引用格式 文件:行号


一、本篇定位

前四篇讲清了 ReZygisk 的核心机制。本篇收束剩下的"骨架与外壳",分四块:

  1. IPC 与通信协议——把散落在 01/02/03 的三类 socket 汇总成一张完整的通信图谱;
  2. 模块脚本——一个模块是怎么被安装、开机拉起、卸载的;
  3. 构建、签名与打包——源码如何变成一个可刷入、带完整性校验的 zip;
  4. WebUI——webroot/ 这个单页应用如何展示状态、控制 monitor。

二、IPC 与通信协议总览

ReZygisk 各组件靠 三类 Unix domain socket 通信:

flowchart TB MON["monitor"] D["zygiskd64 / 32"] LIB["libzygisk.so (注入在 zygote)"] COMP["companion 进程"] APP["APP 内模块代码"] WEB["WebUI"] LIB -->|"① daemon socket cp64.sock<br/>SOCK_STREAM, DaemonSocketAction"| D D -.->|"② controller socket init_monitor<br/>SOCK_DGRAM, 状态上报"| MON WEB -->|"exec: cat state.json / ctl 命令"| MON D -->|"③ companion socketpair + 转交 fd(SCM_RIGHTS)"| COMP APP -->|"③ companion 通道"| COMP
# socket 类型 路径 端点 协议
daemon socket SOCK_STREAM /data/adb/rezygisk/cp32.sockcp64.sock libzygisk/injector ↔ zygiskd enum DaemonSocketAction(9 动作)
controller socket SOCK_DGRAM /data/adb/rezygisk/init_monitor zygiskd → monitor,用户 ctl → monitor enum rezygiskd_command
companion socket socketpair + fd 转交 匿名 zygiskd ↔ companion,APP ↔ companion 模块自定义

2.1 daemon socket(详见 01 篇)

zygiskd 用 create_daemon_socketzygiskd/src/zygiskd.c:135)建 SOCK_STREAM 监听 socket,客户端在 loader/src/common/daemon.crezygiskd_connectdaemon.c:18)连接。一次请求一次短连接,裸二进制、主机字节序。9 个动作(ZygoteInjected..RemoveModule)语义见 01 篇第五节。

2.2 controller socket(详见 02 篇)

monitor 用 rezygiskd_listener_initloader/src/ptracer/monitor.c:150)建 SOCK_DGRAM socket(路径 TMP_PATH "/init_monitor")。两个方向:

  • zygiskd → monitorunix_datagram_sendtozygiskd/src/utils.c:121)发送状态。命令码在 constants.hLP_SELECT 按位宽编码:ZYGOTE_INJECTED = LP_SELECT(5,4)DAEMON_SET_INFO = LP_SELECT(7,6)DAEMON_SET_ERROR_INFO = LP_SELECT(9,8),对应 monitor.henum rezygiskd_command(4..9)。
  • 用户/WebUI → monitorsend_control_commandmonitor.c:1053)发送 START/STOP/EXIT(1/2/3)。

2.3 companion socket(详见 01 篇第六节)

spawn_companionzygiskd.c:141)用 socketpair 建立 zygiskd↔companion 通道,再用 write_fdSCM_RIGHTS)把 APP 的连接 fd 转交给 companion,此后 APP 与 companion 直连。

2.4 两套编码原语

协议两端各有一套等价原语,这是两端能对话的基础

守护进程侧 zygiskd/src/utils.c 注入端侧 loader/src/common/socket_utils.c 作用
write_string/read_string 同名 "size_t 长度 + 原始字节"
write_uint8_t/uint32_t/size_t(宏生成) 同名 定长整型,主机字节序
write_fd/read_fd 同名 SCM_RIGHTS 传递文件描述符

SCM_RIGHTS fd 传递用 sendmsg/recvmsg 的辅助数据携带一个 int fd,是 companion 接力、模块目录 fd(GetModuleDir)、namespace fd 等"跨进程交接"的关键。

2.5 SELinux 上下文

socket 要让 zygote 有权连接,必须打对标签:

  • set_socket_create_context("u:r:zygote:s0")utils.c:56):让 daemon socket 带 zygote 域上下文。
  • chcon(path, "u:object_r:zygisk_file:s0")unix_listener_from_pathutils.c:174):给 socket 文件打 zygisk_file 标签。

这两个标签的权限由 sepolicy.rule 授予(见第三节)。


三、模块脚本与安装/启动/卸载

ReZygisk 以标准 Magisk 模块格式 的 zip 分发,兼容 KernelSU / APatch 安装器。

3.1 安装流程

flowchart TB FLASH["root 管理器刷入 zip"] --> UB["META-INF/.../update-binary<br/>(标准 Magisk 安装器)"] UB --> CUST["customize.sh (SKIPUNZIP=1)"] CUST --> C1["检测来源 KSU/APatch/Magisk + 版本下限"] C1 --> C2["拒绝 Multiple root (KSU 环境检测到 magisk → abort)"] C2 --> C3["API≥25(Android 7.1) + 架构检查"] C3 --> C4["verify.sh: 逐文件 sha256 校验"] C4 --> C5["释放 module.prop/脚本/webroot"] C5 --> C6["rezygisk.sh → post-fs-data.d/ + post-mount.d/"] C6 --> C7["按 CPU abilist 判定 32/64 → 提取对应架构 binaries"] C7 --> C8["module.prop → module.prop.bak + 设 system_lib_file 权限"] C8 --> C9["Huawei Maple: ro.maple.enable=0"]

customize.shmodule/src/customize.sh)要点:

  • 来源与版本:10-52):必须从 KSU/APatch/Magisk app 安装(非 recovery),各自检查最低版本(@MIN_*_VERSION@ 在构建时被替换为 common.mk 的值)。
  • 拒绝多 root:25-30):KSU 环境下 which magisk 命中则 abort——与 zygiskd 的 Multiple 检测(01 篇)呼应,从安装期就拦截。
  • 架构 binaries:159-203):按设备 ABI 提取并重命名——bin/<arch>/zygiskdbin/zygiskd{32,64}lib/<arch>/libzygisk_ptrace.sobin/zygisk-ptrace{32,64}lib/<arch>/libzygisk.solib(64)/libzygisk.so,并提取 machikado.<arch>
  • 权限:205-214):bin/0755lib/lib64system_lib_file 上下文(让 zygote 能加载注入体)。
  • Huawei Maple:216-221):若启用则写 system.prop 关闭(Maple 的 system_server 创建在 Zygisk 控制之外)。

verify.shextract 函数:解压每个文件的同时校验其 .sha256,防下载损坏/篡改。

3.2 开机启动链

sequenceDiagram autonumber participant Boot as 开机 participant PFD as post-fs-data.sh (模块) participant RZ as rezygisk.sh (post-fs-data.d) participant MON as zygisk-ptrace monitor participant SVC as service.sh (模块) Boot->>PFD: post-fs-data 阶段 PFD->>PFD: ZYGISK_ENABLED? 是→退出(冲突) PFD->>RZ: 执行 post-fs-data.d/rezygisk.sh RZ->>RZ: 恢复 module.prop.bak (清状态痕迹) PFD->>PFD: 创建 /data/adb/rezygisk PFD->>MON: 按 ABI 启动 ./bin/zygisk-ptrace64/32 monitor & Boot->>SVC: late_start service 阶段 SVC->>SVC: ZYGISK_ENABLED? 是→改 module.prop 提示
  • post-fs-data.sh:核心启动点。ZYGISK_ENABLED(Magisk 内置 Zygisk 已开)则退出避免冲突;Magisk 环境下手动触发其它模块的 post-fs-data.sh;创建 /data/adb/rezygisk;按 CPU abilist 启动 zygisk-ptrace64/32 monitor:50-56)——这是 02 篇 monitor 的起点。
  • service.sh:若 ZYGISK_ENABLED 则改 module.prop 描述提醒关掉内置 Zygisk;手动触发其它模块的 service.sh
  • rezygisk.sh:被装到 /data/adb/post-fs-data.d//data/adb/post-mount.d/,把 module.propmodule.prop.bak 还原——即使 ReZygisk 被禁用,描述也回到干净初始状态、不残留旧状态文字。(注释解释 KSU 2.x 在挂载前跑 post-fs-data.d,故同时放一份到 post-mount.d。)

3.3 sepolicy.rule

module/src/sepolicy.rule 增加的 SELinux 规则(节选):

type zygisk_file file_type                              # 定义 zygisk_file 类型
allow zygote zygisk_file sock_file { read write }       # zygote 可读写 socket
allow zygote su dir search                              # setns 到子进程 mns
allow zygote ksu { lnk_file file } read                 # KSU 改名的 su 上下文
allow zygote zygote process execmem                     # 执行注入的内存
allow system_server system_server process execmem
allow zygote system_lib_file file execmod               # Tango Zygote 需要

这些规则让注入、namespace 切换、socket 通信在 SELinux enforcing 下可行;execmem/execmod 是远程注入可执行内存的必要权限。

3.4 设备目录布局

/data/adb/modules/rezygisk/
├── module.prop  module.prop.bak           # 元信息 + 备份
├── customize.sh post-fs-data.sh service.sh uninstall.sh
├── sepolicy.rule  rezygisk.sh
├── machikado.<arch>  misaki.sig  *.sha256 # 签名(第四节)
├── system.prop                            # (仅 Huawei Maple)
├── bin/   zygiskd32 zygiskd64 zygisk-ptrace32 zygisk-ptrace64
├── lib/    libzygisk.so                    # 32 位注入体
├── lib64/  libzygisk.so                    # 64 位注入体
└── webroot/                                # WebUI

/data/adb/rezygisk/                         # 运行时目录 (TMP_PATH)
├── cp32.sock  cp64.sock                    # daemon socket
├── init_monitor                            # controller socket
├── state.json                              # 状态(供 WebUI)
└── webui_error.log                         # WebUI 错误日志

/data/adb/post-fs-data.d/rezygisk.sh
/data/adb/post-mount.d/rezygisk.sh

3.5 卸载

uninstall.sh:删除 /data/adb/rezygisk 运行时目录,删除 post-fs-data.d/post-mount.d 里的 rezygisk.sh,目录空时 rmdir


四、构建、签名与打包

4.1 三层 Makefile

flowchart TB TOP["顶层 Makefile (make all = debug + release)"] CM["common.mk: 版本/模块/最低版本/架构/NDK"] LM["loader/Makefile"] ZM["zygiskd/Makefile"] SIGN["scripts/sign.py"] TOP --> CM TOP -->|"make -C loader"| LM TOP -->|"make -C zygiskd"| ZM LM --> LZ["libzygisk.so (-nostartfiles)<br/>libzygisk_ptrace.so (-fPIE)"] ZM --> ZD["zygiskd (-fPIE -pie)"] LZ --> ASM["组装 MODULE_OUT<br/>(sed 定制 + 复制 binaries/webroot)"] ZD --> ASM ASM --> SIGN SIGN -->|"machikado/misaki/sha256"| ZIP["zip -r9 → ReZygisk-v*-{release,debug}.zip"]
  • common.mk 集中定义:MODULE_NAME=ReZygiskMODULE_ID=rezygiskVERSION=v1.0.0VER_CODEgit rev-list --count HEAD)、COMMIT_HASHgit rev-parse --short HEAD)、ARCHS = arm64-v8a armeabi-v7a x86_64 x86NDK_VARIANT=27ANDROID_PLATFORM=21C_STANDARD=gnu23,以及安装期最低版本 MIN_KSU_VERSION=12096/MIN_KSUD_VERSION=12096/MIN_MAGISK_VERSION=26402/MIN_APATCH_VERSION=11010
  • 顶层 Makefile$(MODULE_DONE)Makefile:62)做组装:sedmodule.prop${moduleId} 等和脚本里的 @DEBUG@/@MIN_*_VERSION@ 替换为实际值,按架构复制 binaries,复制 webroot,调用 sign.py,最后 zip -r9 打包。
  • loader/Makefilelibzygisk.so = injector + common + PLTI + CSOLoader,-nostartfiles 链接(呼应 03 篇裸 entry());libzygisk_ptrace.so = ptracer + common,-fPIE。release 用 -O3 -flto -DNDEBUG,debug 用 -g -O0
  • zygiskd/Makefilezygiskd-fPIE -pie 链接成可执行文件。

安装期 vs 运行期版本下限:common.mk 的 MIN_MAGISK_VERSION=26402/MIN_APATCH_VERSION=11010 用于 customize.sh 安装检查;而 magisk.h 硬编码 26000apatch.h 硬编码 10657 用于运行时检测(01 篇)。两者独立,安装检查更严格。

4.2 依赖来源

  • zygote_internal.gitmodules 唯一 git submodule,来自 Dr-TSNG/ZygiskNext(ReZygisk fork 自 Zygisk Next)。
  • PLTI / CSOLoader:位于 loader/src/external/pltiloader/src/external/csoloader,各有独立 Makefile 被 loader/Makefile 递归构建。CI 用 submodules: recursive 拉取。PLTI 是 PLT hook 库(03 篇),CSOLoader 是自定义 ELF 加载器(02/03 篇)。

4.3 三层签名体系(scripts/sign.py)

Ed25519 实现三层完整性校验:

flowchart LR M["machikado.&lt;arch&gt;<br/>每架构运行时文件签名"] -->|"运行时验证关键文件未被篡改"| RT["zygiskd/ptracer/injector"] SHA[".sha256<br/>每文件哈希"] -->|"安装期 verify.sh 校验"| INST["customize.sh"] MI["misaki.sig<br/>整模块签名"] -->|"整模块完整性"| WHOLE["whole-module"]
  • machikado.sign_machikadosign.py:41):对该架构关键运行时文件(module.prop、各脚本、sepolicy.rulelibzygisk.sozygisk-ptrace{32/64}zygiskd{32/64})按设备虚拟路径排序,逐文件构造 name + 0x00 + 8字节LE大小 + 内容 数据块,整体 Ed25519 签名。文件 = 签名(64B) + 公钥。供运行时验证自身加载的文件未被替换。
  • misaki.sigsign_misakisign.py:114):整个模块所有文件的 Ed25519 签名。
  • .sha256compute_sha256_hashessign.py:93):每文件一个哈希,安装期 verify.sh 校验。
  • --no-sign 模式(sign.py:150):无密钥时创建空 machikado/misaki,仅算 sha256——普通用户自构建(未签名)的产物。

4.4 CI

  • .github/workflows/ci.yml(Untrusted CI,PR 触发):make all,不签名。
  • .github/workflows/trusted_ci.yml(Trusted CI,push main 触发):先从 secrets.ORG_PRIVATE_KEY/PUBLIC_KEY 写入 module/private_key/public_keymake all——产出官方签名版

这解释了 README 里 release/debug 两种 zip,以及"官方签名版"与"自构建版"的区别。


五、WebUI(webroot)

webroot/纯前端单页应用,由 root 管理器内置 WebView 加载,展示状态、控制 monitor。

5.1 架构与桥接

flowchart TB PL["pageLoader.js<br/>一次性加载所有页+切换"] KSU["kernelsu.js<br/>exec/spawn/toast 桥"] PAGES["home / modules / actions / settings"] PL --> PAGES PAGES --> KSU KSU -->|"ksu.exec(cmd, cb)"| SHELL["root shell"] SHELL -->|"cat state.json"| STATE["/data/adb/rezygisk/state.json"] SHELL -->|"zygisk-ptrace64 ctl ..."| MON["monitor"]
  • 桥接webroot/js/kernelsu.js):exec(command, options) 通过全局 ksu.exec(root 管理器注入的 JS 接口)执行 shell 命令,回调返回 {errno, stdout, stderr}ksu 未定义(PC 测试)时回退到 development_kit.js 假响应。
  • 页面加载webroot/js/pages/pageLoader.js):所有页面 HTML/CSS/JS 一次性加载再切换显示(避免动态渲染闪烁),每页有 loadOnce/loadOnceView/load 生命周期。

5.2 数据流:state.json 与 ctl

WebUI 与守护进程的全部交互都通过 shell 命令:

操作 命令 来源
读运行状态 /system/bin/cat /data/adb/rezygisk/state.json home/actions/modules
读版本 cat /data/adb/modules/rezygisk/module.prop home
系统信息 uname -r / getprop ro.build.version.release home
控制 monitor /data/adb/modules/rezygisk/bin/zygisk-ptrace64 ctl start|stop|exit actions

state.json 由 monitor 的 update_status(02 篇,monitor.c:879)写入,含 rootmonitor.staterezygiskd.{64,32}.{state,modules}zygote.{64,32}。各页解析:

  • homehome/index.js):整体健康度(ok/partially/notWorking)、Android/内核版本、ReZygisk 版本、root 实现、Zygote32/64 注入状态。
  • actionsactions/index.js):monitor 状态(0 tracing/1 stopping/2 stopped/3 exiting),三按钮发 ctl start(启动)、ctl exit(停止)、ctl stop(暂停)——对应 02 篇 send_control_command
  • modulesmodules/index.js):列出 rezygiskd.{64,32}.modules,grep 各模块 module.prop 取显示名 + 架构(32/64)。
  • settingssettings/index.js):全屏/系统字体开关、语言/主题入口、致谢(PerformanC / Dr-TSNG / 5ec1cff / ThePedroo / RainyXeon)、许可证 AGPL 3。

5.3 i18n 与主题

  • i18n:HTML 用 {{key}} 占位,pageLoader.jssolveStringslang/<lang>.json(14 种语言)替换;语言存 localStorage,settings 的语言 minipage 切换。
  • 主题themes/main.js):amoled/dark/light/system,每个设置一组 CSS 变量(themes/dark.js 等)+ 导航栏图标模式(darkNavbar.js/lightNavbar.js)。
  • 动画pages/animator.js):MD3 shared-axis 页面切换(左右推动)+ minipage 右侧滑入。

六、小结

ReZygisk 的"外壳"同样讲究:

  1. 三类 socket 织成通信网:daemon socket(stream,DaemonSocketAction)承载注入端↔守护进程 RPC,controller socket(datagram,init_monitor)承载状态上报与 ctl 控制,companion socket 承载模块伴生进程接力;SCM_RIGHTS 与 SELinux 上下文是其在受限环境工作的关键。
  2. 模块脚本 实现"开机即注入":post-fs-data.sh 拉起 monitor,rezygisk.sh 维持 module.prop 干净,sepolicy.rule 授予 SELinux 权限,安装期就拒绝多 root / 旧版本 / recovery。
  3. 构建是分层 Makefile + Ed25519 三层签名make all 多架构编译 → 组装(占位符替换 + 复制)→ sign.py 生成 machikado/misaki/sha256 → 打包;Trusted CI 用组织密钥产出官方签名版。
  4. WebUI 是零后端单页应用:全部数据靠 ksu.exec 执行 cat state.json 等命令获取,控制靠 zygisk-ptrace64 ctl,配合 i18n 与主题给出直观状态面板。

至此,ReZygisk 源码解读系列完结。从守护进程的中枢调度(01),到 ptrace 注入的精巧时机(02),到注入体的 hook 与反检测(03),再到外围的协议、脚本、构建与界面(04),共同构成了这个"纯 C、防检测、FOSS"的 Zygisk 独立实现。

评论

  • 还没有评论,来说点什么吧。

无需注册或登录,填个昵称即可评论。