- 系统编程
- 移动开发
【免费下载链接】APatch
The patching of Android kernel and Android system
APatch 是一个面向 Android 的、以“直接修补内核”为核心的全新 Root 方案,它在安装体验上继承了 Magisk 通过boot.img快速部署的优势,在能力上继承了 KernelSU 内核级修补的强大扩展性。本文以仓库docs/id/faq.md(与docs/en/faq.md同源的官方 FAQ)为骨架,结合 apd 守护进程与 SuperCall UAPI 等源码实现,逐一拆解 APatch 与 Magisk、KernelSU 的差异、Kernel Patch Module(KPM)、SuperKey 认证机制与 SELinux 处理策略,帮助读者理解这套方案的底层工作原理,并掌握相关命令与配置的落地方式。
APatch 是什么:Magisk 与 KernelSU 的融合
官方 FAQ 对 APatch 的定义非常直接:APatch 是一种类似于 Magisk 或 KernelSU 的 Root 解决方案,它取两者之长——既拥有 Magisk 通过boot.img进行的便捷安装方式,又具备 KernelSU 强大的内核修补(kernel patching)能力。仓库 README.md 将其概括为一句定位语:
The patching of Android kernel and Android system.
APatch 的完整能力面包括三部分:
- APM(APatch Module):提供与 Magisk 类似的模块化支持(systemless 机制),模块目录位于
/data/adb/modules,详细开发指南见 模块(APM)开发指南; - KPM(Kernel Patch Module):支持向内核注入任意代码,提供内核级
inline-hook与syscall-table-hook能力; - SuperKey / SuperCall:由内核新增系统调用提供的 userspace 能力入口与访问凭证。
在部署前提上,官方 README.md 明确了两点约束:
- 仅支持ARM64 架构;
- 仅支持Android 内核版本 3.18 – 6.12。
此外,内核需要开启符号导出相关配置:CONFIG_KALLSYMS=y且CONFIG_KALLSYMS_ALL=y可获得完整支持;若CONFIG_KALLSYMS_ALL=n则提供初步支持。这些约束决定了 APatch 与 Magisk(几乎不依赖内核配置)在底层实现上的根本差异。
APatch 与 Magisk 的区别:修补 ramdisk 还是直接修补内核
FAQ 用一句话点出了 APatch 与 Magisk 的核心分水岭:
Magisk 通过在 boot image 的 ramdisk 中加入补丁来修改系统的 init 流程,而 APatch 是直接修补内核(kernel)本身。
Magisk 的工作方式是在启动早期对 init 进程进行注入(patch 位于boot.img的 ramdisk 部分),从而在 userspace 层接管系统;而 APatch 的“直接修补内核”体现在:它依赖 KernelPatch 在内核镜像上直接植入代码,再通过内核中的 SuperCall 机制为 userspace 提供能力。
仓库的构建资产也能印证这一点——app/src/main/assets 下提供了boot_extract.sh、boot_patch.sh、boot_unpatch.sh等脚本,其操作对象是设备的boot.img:先提取(extract),再修补(patch),并支持还原(unpatch)。而安装完成后真正承载运行时的,是位于/data/adb/apd的 apd 守护进程(见 apd/src/defs.rs 中DAEMON_PATH定义)以及/data/adb/ap工作目录(WORKING_DIR)。
APatch 与 KernelSU 的对比:只需原厂 boot.img,无需内核源码
KernelSU 是另一款知名的内核级 Root 方案,但它的部署强依赖设备的内核源码。FAQ 指出:
KernelSU 需要你设备内核的源代码,而 OEM 并不总是提供它;APatch 只需你手上的原厂
boot.img即可工作。
这一点对普通用户极为关键:内核源码往往是厂商闭源或未公开的,导致 KernelSU 在大量机型上无法部署。而 APatch 直接对官方boot.img进行修补,绕开了源码依赖,大大拓宽了适用机型范围。
从源码看,这一设计还延伸到“越狱模式(jailbreak mode)”:apd/src/late_load.rs 中的late-load流程允许在未预置修补的原厂内核上运行时加载 KernelPatch 内核模块:
- 自动检测内核 KMI(Kernel Module Interface,形如
android14-5.15),支持从内核 release 字符串解析(parse_kmi); - 查找
/data/adb/ap/{kmi}_kernelpatch.ko,若无显式--module参数则使用该默认路径; - 通过 apd/src/insmod.rs 绕过内核严格的版本校验(vermagic / modversions CRC 检查)加载模块,未定义符号从
/proc/kallsyms解析; - 在线注入 Magisk 策略(
apply_magisk_policy_live),写入/data/adb/ap/jailbreak标记,重启管理器应用并恢复 SELinux enforcing。
其中 apd/src/insmod.rs 的实现细节——临时置kptr_restrict=1以便读取/proc/kallsyms地址、解析 ELF 重定位、调用init_module(2)——正是“无需内核源码也能完成内核级修补”的技术支撑。
APatch vs Magisk 与 KernelSU 的组合对比:线程级 Root 与可选 SELinux 修改
FAQ 进一步指出 APatch 相对 Magisk、KernelSU 的两个差异化能力:
- APatch 允许你选择不修改 SELinux,这意味着应用(APP)的线程本身就可以被 Root,libsu 与 IPC 都不是必需的。
- 提供Kernel Patch Module(KPM)。
线程级 Root:免 libsu、免 IPC
在传统方案(如 Magisk)中,Root 一个应用通常需要通过su启动一个全新的进程,再由客户端通过 IPC 与服务端通信——即 libsu 体系。APatch 借助内核直接注入的 SuperCall,可以在应用自己的线程上下文内完成 Root 化,无需拉起新进程,自然也就不需要 libsu 与 IPC。
UAPI 头文件 app/src/main/cpp/uapi/scdefs.h 中对此有直接佐证:
#define SUPERCALL_SU 0x1010 #define SUPERCALL_SU_TASK 0x1011 // syscall(__NR_gettid)SUPERCALL_SU_TASK的注释表明它基于线程 ID(gettid)工作,可以在指定线程上执行提权操作——这正是“APP 线程可被 Root”的内核侧实现通道。
KPM:内核空间的代码注入能力
FAQ 对 KPM 的定义是:
一些代码运行在 Kernel Space(内核空间),类似于可加载内核模块(Loadable Kernel Modules,LKM)。此外,KPM 还提供在内核空间进行inline-hook和syscall-table-hook的能力。
UAPI 中同样能看到 KPM 的管理命令族:
#define SUPERCALL_KPM_LOAD 0x1020 #define SUPERCALL_KPM_UNLOAD 0x1021 #define SUPERCALL_KPM_CONTROL 0x1022 #define SUPERCALL_KPM_NUMS 0x1030 #define SUPERCALL_KPM_LIST 0x1031 #define SUPERCALL_KPM_INFO 0x1032这与 apd 守护进程的两个相关子命令对应:apd insmod <module.ko>(不带版本检查地加载内核模块,见 apd/src/cli.rs)以及apd late-load(越狱模式,见 apd/src/cli.rs)。更完整的 KPM 编写指南由上游 KernelPatch 项目提供(其仓库中的doc/module.md),属于内核模块开发者的进阶主题。
APatch 与 KernelPatch 的关系:依赖、继承与扩展
FAQ 明确了二者的关系:
APatch 依赖 KernelPatch,继承了它的全部能力,并在此之上进行了扩展。你也可以只安装 KernelPatch,但这样你将无法使用 Magisk 模块(APM)。
也就是说,KernelPatch 是 APatch 的内核底座(README 的 Credits 部分也把 KernelPatch 称为 “The core”),负责内核修补、SuperCall 注入等底层能力;APatch 在其上叠加了模块机制(APM)、SELinux 策略支持(magiskpolicy)、管理器 UI 等 userspace 生态。只装 KernelPatch 只能获得内核层能力,无法享受 APatch 的模块化生态。
从代码层面看,apd 甚至把 KernelPatch 的版本号作为常量编译进 SuperCall 调用中:apd/src/supercall.rs 通过build.rs生成kp_version.rs,并在ver_and_cmd()中把KP_MAJOR/KP_MINOR/KP_PATCH编码进系统调用的高 32 位(apd/src/supercall.rs):
fn ver_and_cmd(cmd: c_long) -> c_long { let version_code: u32 = ((KP_MAJOR << 16) + (KP_MINOR << 8) + KP_PATCH) .try_into() .unwrap(); ((version_code as c_long) << 32) | (0x1158 << 16) | (cmd & 0xFFFF) }这里的0x1158正是 UAPI 中定义的SUPERCALL_HELLO_MAGIC低 16 位(app/src/main/cpp/uapi/scdefs.h),用于内核侧校验调用协议的合法性。
SuperKey 与 SuperCall:内核级的能力入口与访问凭证
这是 FAQ 中最具技术分量的部分:
KernelPatch 新增了一个系统调用(syscall),为 userspace 的应用与程序提供全部能力,这个系统调用被称为SuperCall。当应用/程序尝试调用 SuperCall 时,需要提供访问凭证,即SuperKey。只有当 SuperKey 正确时 SuperCall 才能被成功调用;否则调用方不会受到任何影响。
调用约定与命令码
SuperCall 复用了truncate的系统调用号(ARM64 上为 45),通过命令码分发不同功能。UAPI 头文件 app/src/main/cpp/uapi/scdefs.h 明确定义:
// #define __NR_supercall __NR3264_truncate // 45 #define __NR_supercall 45所有功能按命令码组织,涵盖:
| 命令码 | 宏定义 | 功能 |
|---|---|---|
| 0x1000 | SUPERCALL_HELLO | 握手探测(hello) |
| 0x1008 / 0x1009 | SUPERCALL_KERNELPATCH_VER/SUPERCALL_KERNEL_VER | 查询 KernelPatch 与内核版本 |
| 0x100a–0x100c | SUPERCALL_SKEY_GET/SET/ROOT_ENABLE | SuperKey 读取、设置与 Root 使能 |
| 0x1010 / 0x1011 | SUPERCALL_SU/SUPERCALL_SU_TASK | 提权(进程级 / 线程级) |
| 0x1020–0x1032 | SUPERCALL_KPM_* | KPM 模块的加载、卸载、控制与枚举 |
| 0x1040–0x1046 | SUPERCALL_KSTORAGE_* | 内核存储(kernel storage)读写与分组管理 |
| 0x1100–0x1112 | SUPERCALL_SU_* | SU 授权管理:授予/撤销 UID、列表、安全模式等 |
其中与“Root 授权管理”直接相关的一组(SUPERCALL_SU_GRANT_UID 0x1100、SUPERCALL_SU_REVOKE_UID 0x1101、SUPERCALL_SU_NUMS 0x1102、SUPERCALL_SU_LIST 0x1103)在 apd 中被封装为完整的管理流程:apd/src/supercall.rs 的refresh_ap_package_list()会先查询已授权 UID 数量、拉取列表、逐个撤销,再依据包配置重新授予,实现 Root 授权列表与系统包管理的同步。
密钥校验:SuperKey 如何工作
SuperCall 的身份验证发生在内核侧:调用者把 SuperKey 以 C 字符串指针传入系统调用,内核用与 UAPI 中hash_key()相同的算法(app/src/main/cpp/uapi/scdefs.h,初值1000000007、逐字符hash * 31 + c)对密钥做哈希比对,匹配才放行。密钥有长度上限SUPERCALL_KEY_MAX_LEN 0x40(64 字节)。
提权时的目标描述结构su_profile(app/src/main/cpp/uapi/scdefs.h)包含三个字段:
struct su_profile { uid_t uid; uid_t to_uid; char scontext[SUPERCALL_SCONTEXT_LEN]; // 0x60 };即“当前 UID → 目标 UID(通常为 0/root)”以及目标 SELinux 上下文。apd 在启动时若带有--superkey参数,会先以该结构自我提权(privilege_apd_profile,见 apd/src/supercall.rs),使用的上下文为u:r:magisk:s0。
在 userspace,apd 的 CLI 把 SuperKey 作为全局参数暴露(apd/src/cli.rs):
-s, --superkey <KEY> Super key for authentication root所有需要内核能力的子命令(如post-fs-data、boot-completed、soft-reboot)都会携带该参数。日常使用中,内核也会以argv[0]为/system/bin/kp或/system/bin/su的方式直接 exec apd,进入 su 兼容的 Root Shell(见 apd/src/cli.rs 与 apd/src/apd.rs 的root_shell())。
安全警告:SuperKey 权限高于 Root
由于 SuperKey 直接控制内核注入的 SuperCall 通道,README 的 Security Alert 特别强调:
SuperKey 拥有比 Root 更高的权限。弱密钥或被泄露的密钥可能导致设备被未授权控制。使用强健的密钥并妥善保管至关重要。
这与 FAQ 中“SuperCall 只有在 SuperKey 正确时才能成功调用”的描述互为印证——SuperKey 本质上是内核级能力总开关,其安全级别高于普通的su授权。
SELinux 处理:hook 绕过不改变上下文,magiskpolicy 补充策略
FAQ 的最后一个技术点聚焦 SELinux:
- KernelPatch不修改 SELinux 上下文,而是通过 hook 绕过 SELinux 检查。这使得你可以直接在应用上下文内 Root 一个 Android 线程,而无需借助 libsu 启动新进程再做 IPC,非常实用。
- 此外,APatch直接使用 magiskpolicy提供额外的 SELinux 支持。
两套并行的 SELinux 策略
理解这一点需要区分“绕过”与“补充”两条路径:
- KernelPatch 的 hook 绕过:不触碰 SELinux 的上下文属性(context),也不改动策略文件,而是在内核中对 SELinux 检查点做 hook,从而在保留原上下文的条件下放行目标操作——这正是线程级 Root 得以实现的前提。
- APatch 的 magiskpolicy 注入:apd 移植了 Magisk 的 magiskpolicy 工具,在启动阶段向内核加载策略补丁。相关实现位于 apd/src/sepolicy.rs:其
apply_magisk_policy_live()(apd/src/sepolicy.rs)等价于执行magiskpolicy --magisk --live——从/sys/fs/selinux/policy加载当前策略、注入内置的 Magisk 规则、再写回/sys/fs/selinux/load。
magiskpolicy 的完整用法
apd 还通过 multicall 方式直接提供magiskpolicy命令(argv[0]以magiskpolicy结尾时进入该模式,见 apd/src/cli.rs),选项与 Magisk 原生工具一致,见 apd/src/sepolicy.rs:
| 选项 | 说明 |
|---|---|
--load FILE | 从指定文件加载单一 sepolicy |
--load-split | 从预编译 sepolicy 或编译 split cil 策略加载 |
--compile-split | 编译 split cil 策略 |
--save FILE | 将策略导出到文件 |
--live | 立即将策略载入内核(写入/sys/fs/selinux/load) |
--magisk | 应用内置的 Magisk sepolicy 规则 |
--apply FILE | 按行读取并应用策略语句文件(可多次指定) |
--print-rules | 打印已加载策略中的全部规则 |
| (位置参数) | 直接追加的 policy statements |
在启动事件中的实际应用
SELinux 策略注入不是孤立操作,它被编排进完整的启动事件流。以post-fs-data阶段为例(apd/src/event.rs),apd 依次执行:加载 live policy 并应用 Magisk 规则、写入/sys/fs/selinux/load、重新为自身提权(刷新 SuperCall 上下文)、执行模块脚本与 Lua 阶段钩子、加载system.prop、触发post-mount等。整个生命周期由 apd/src/cli.rs 中的子命令驱动:
apd post-fs-data # 触发 post-fs-data 事件 apd services # 触发 service 事件 apd boot-completed # 触发 boot-completed 事件 apd uid-listener # 监听包列表变化,同步 Root 授权 apd soft-reboot # 模拟系统重启(保留运行时加载的模块) apd resetprop ... # Magisk 兼容的属性读写工具 apd sepolicy ... # magiskpolicy 的封装入口从 FAQ 到实践:常用路径、命令与注意事项
为了让 FAQ 中的概念落地,这里汇总仓库中可确认的运行时关键路径与常用入口:
- 工作目录:
/data/adb/ap,二进制位于/data/adb/ap/bin(含 Magisk 同源编译的 BusyBox,见 apd/src/defs.rs 与 模块开发指南); - 守护进程:
/data/adb/apd,同时承担su/kp/resetprop/magiskpolicy的 multicall 入口; - 模块目录:
/data/adb/modules(APM),/data/adb/metamodule(元模块),详见 apd/src/defs.rs; - SuperCall 事件通道:内核通过
truncate二进制(SUPERCMD,app/src/main/cpp/uapi/scdefs.h)向 apd 上报事件(见 apd/src/event.rs 的report_kernel); - 安全模式:
/dev/.safemode标记(app/src/main/cpp/uapi/scdefs.h),进入安全模式会跳过模块脚本并禁用全部模块,避免 bootloop。
需要留意的部署限制
- 仅支持 ARM64,且内核版本需在 3.18 – 6.12 区间内(README.md);
- 内核需满足
CONFIG_KALLSYMS相关配置要求(详见本文第一节); - 安装基于官方
boot.img的修补流程,脚本见 app/src/main/assets(boot_extract.sh、boot_patch.sh、boot_unpatch.sh、InstallAP.sh、UninstallAP.sh); - 启用/卸载请务必遵循官方安装说明;SuperKey 请使用高强度的密钥并妥善保管。
结语
APatch 的 FAQ 虽短,但每个条目都指向一组清晰的工程决策:用直接修补内核的方式取代 ramdisk 注入(vs Magisk),用原厂boot.img取代内核源码依赖(vs KernelSU),用 SuperCall + SuperKey 实现线程级 Root 与内核级能力开放(vs libsu/IPC 体系),并用“hook 绕过 + magiskpolicy 补充”双轨处理 SELinux。理解这些底层机制,有助于开发者更安全、更高效地使用 APM/KPM 生态,也能在排障时(如安全模式、SuperKey 失效、SELinux 策略冲突)快速定位问题所在的层次——是内核侧(KernelPatch/SuperCall)还是 userspace 侧(apd/模块脚本/magiskpolicy)。
- 系统编程
- 移动开发
【免费下载链接】APatch
The patching of Android kernel and Android system
相关推荐
APatch 官方 FAQ 深度解读:内核级 Root 方案、KPM 内核模块与 SuperKey 安全模型
APatch 官方 FAQ 深度解读:内核级 Root 方案、KPM 内核模块与 SuperKey 安全模型 APatch 是一个基于内核补丁(Kernel P
系统编程移动开发APatch FAQ 深度解读:boot.img 内核修补、SuperKey/SuperCall 授权机制与 KPM 内核补丁模块全解析
APatch FAQ 深度解读:boot.img 内核修补、SuperKey/SuperCall 授权机制与 KPM 内核补丁模块全解析 本篇以官方西班牙语文档
系统编程移动开发APatch 内核 Root 方案全面解析:KernelPatch、SuperKey、KPM 内核模块与 SELinux 机制详解
APatch 内核 Root 方案全面解析:KernelPatch、SuperKey、KPM 内核模块与 SELinux 机制详解 APatch 是一款基于内核
系统编程移动开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考