菜单

Zygisk 框架

相关源文件

Zygisk 是 Magisk 用于将代码注入 Android 的 Zygote 进程的框架。由于 Zygote 进程是 Android 中所有应用程序进程的父进程,因此该框架为系统范围内的代码注入和修改提供了一个强大的机制。Zygisk 支持传统 Magisk 模块无法实现的更高级功能,例如改进的 root 隐藏能力、运行时应用修改和深度系统定制。

有关 Magisk 模块的通用信息,请参阅 模块系统

架构概述

Zygisk 通过几个关键组件与 Magisk 系统和 Android 框架集成

来源: native/src/core/zygisk/entry.cpp native/src/core/module.cpp native/src/core/daemon.rs

Native Bridge 实现

Zygisk 巧妙地利用了 Android 最初为 CPU 架构翻译设计的 Native Bridge 接口来将代码注入 Zygote 进程

native bridge hook 实现在 native/src/core/zygisk/entry.cpp101-112 采用了一种简单而巧妙的方法

当 Zygote 进程加载 native bridge 库时会调用此函数。 hook_entry() 调用会安装必要的 hook 来启用 Zygisk 功能。

来源: native/src/core/zygisk/entry.cpp native/src/core/module.cpp289-339

模块系统

Zygisk 模块是以原生库(.so 文件)的形式实现的,这些库组织在特定的目录结构中

/data/adb/modules/<module_name>/
├── zygisk/
│   ├── arm64-v8a.so       # 64-bit ARM library
│   ├── armeabi-v7a.so     # 32-bit ARM library
│   ├── x86_64.so          # 64-bit x86 library
│   ├── x86.so             # 32-bit x86 library
│   └── unloaded           # Optional marker file
└── module.prop            # Module information

模块加载过程下图所示

在模块收集期间,Magisk 会扫描所有模块以进行 Zygisk 兼容性检查。如果模块包含设备架构所需的库,则这些库会被加载到内存文件描述符 (memfd) 中,使其更难被反 root 检测措施发现。此过程实现在 native/src/core/module.cpp403-481

来源: native/src/core/module.cpp native/src/core/lib.rs198

Zygisk 守护进程

Zygisk 守护进程 (zygiskd) 是管理模块加载和通信的关键组件

Zygisk 守护进程在 native/src/core/zygisk/entry.cpp16-90 中作为独立进程实现。它

  1. 从主 Magisk 守护进程接收模块文件描述符
  2. 使用线程池处理多个并发请求
  3. 使用 Unix 套接字与应用程序进程通信
  4. 在适当的时候将模块加载到请求进程中

当加载 native bridge 时或当 Magisk 守护进程收到 Zygisk 相关请求时,会启动该守护进程。

来源: native/src/core/zygisk/entry.cpp native/src/core/daemon.cpp202

与拒绝列表集成

Zygisk 与 Magisk 的拒绝列表功能紧密配合,以提供更强的 root 隐藏能力

集成逻辑通过以下方式实现:

  1. update_deny_flags 函数 native/src/core/deny/utils.cpp433-440 - 根据拒绝列表状态设置标志
  2. zygisk_should_load_module 函数 native/src/core/lib.rs198 - 确定是否应加载模块

此集成确保 Zygisk 模块不会在可能被检测到的进程中加载,从而提高了 root 隐藏能力。

来源: native/src/core/deny/utils.cpp native/src/core/lib.rs198

启用和禁用 Zygisk

可以通过 Magisk 设置启用或禁用 Zygisk,这些设置存储在 Magisk 数据库中

设置通过 Magisk 数据库中的 ZygiskConfig 键进行管理 native/src/core/db.rs71 当禁用 Zygisk 时,restore_zygisk_prop 函数 native/src/core/zygisk/entry.cpp114-120 会恢复(如果有的话)原始的 native bridge 属性。

来源: native/src/core/daemon.rs native/src/core/module.cpp native/src/core/zygisk/entry.cpp114-120

通信协议

Zygisk 组件使用基于 Unix 套接字和文件描述符传递的复杂协议进行通信

通信使用了在 native/src/core/socket.rs 中实现的几个关键函数

  1. send_fdsend_fds - 通过 Unix 套接字发送文件描述符
  2. recv_fdrecv_fds - 从 Unix 套接字接收文件描述符

请求在 ZygiskRequest 枚举中定义,native/src/core/lib.rs97-101,包括以下操作:

  • GetInfo:请求模块信息
  • ConnectCompanion:连接到模块的伴侣进程
  • GetModDir:获取模块目录路径

来源:native/src/core/socket.rs140-257 native/src/core/lib.rs97-101

技术细节

模块加载决策

是否加载模块的核心决策逻辑实现在 zygisk_should_load_module 函数中,native/src/core/lib.rs198

此函数确保模块不会在可能被检测到的进程中加载,从而提高了隐藏 root 的能力。

内存文件描述符技术

为了让 Zygisk 模块更难被检测,它们使用 memfd_create 系统调用加载到内存文件描述符中,native/src/core/module.cpp459-472

这种技术使得模块文件仅存在于内存中,而不是存储在磁盘上,有助于避免被反 root 措施检测到。

状态标志系统

Zygisk 使用状态标志系统来跟踪进程属性并做出加载决策。

标志描述
ProcessGrantedRoot进程已被授予 root 访问权限
ProcessOnDenyList进程在拒绝列表中
DenyListEnforced拒绝列表当前已强制执行
ProcessIsMagiskApp进程是 Magisk 应用

这些标志定义在 native/src/core/lib.rs104-109,并在 Zygisk 框架中用于决定模块加载和进程处理。

来源:native/src/core/module.cpp459-474 native/src/core/lib.rs198 native/src/core/lib.rs104-109

结论

Zygisk 是 Magisk 功能的强大扩展,实现了深入的系统集成和复杂的应用修改。通过将代码注入 Zygote 进程,它使模块能够以前所未有的方式访问 Android 运行时环境,同时保持与 Magisk 现有功能(如拒绝列表)的兼容性。这使其成为需要高级自定义选项或改进的 root 隐藏功能的用户的重要工具。

来源:native/src/core/lib.rs native/src/core/module.cpp native/src/core/zygisk/entry.cpp