SuperCall 系统调用 — SuperKey 验证的唯一入口
它是什么
KernelPatch(APatch 的内核补丁核心)在内核里添加了一个新的系统调用,叫 SuperCall。这个系统调用是 APatch root 能力对外暴露的唯一入口——不管是 App 获取 root 权限、还是管理器验证密钥、还是 KPM 加载,都必须走 SuperCall。
工作流程
一个 App 想获得 root 权限,必须:
- 在用户态执行
syscall(APATCH_SUPERCALL, operation, arg) - 陷入内核态,进入 SuperCall 的内核处理函数
- 第一步:验证 SuperKey —— SuperCall 首先要求提供密钥,内核检查密钥是否匹配
- 密钥正确 → 继续执行请求的操作;密钥错误 → 直接返回(调用方完全不知道这里有个 root 门)
不同的 operation 值代表不同的请求:
| operation | 含义 |
|---|---|
| ROOT_THREAD | 给当前线程授予 root 权限 |
| LOAD_KPM | 加载一个 KPM |
| UNLOAD_KPM | 卸载一个 KPM |
| GET_STATUS | 查询内核补丁状态 |
| ... | 其他操作 |
为什么密钥错误时"无感"
这是 APatch 权限体系最聪明的设计:如果 SuperKey 错误,SuperCall 的内核处理函数让 syscall 正常返回——不是返回错误码,而是像这个 syscall 根本不存在一样。
// 内核处理函数伪代码
asmlinkage long apatch_supercall(long op, long arg) {
// 验证密钥
if (!superkey_matches(arg.superkey)) {
// 密钥错误 → 直接返回 0,好像什么都没发生过
return 0;
}
// 密钥正确 → 执行请求的操作
switch (op) {
case ROOT_THREAD:
root_current_thread();
break;
case LOAD_KPM:
load_kpm_from_user(arg.kpm_ptr);
break;
// ...
}
return 0;
}
这个设计的意义是——任何试图"探测" APatch 是否存在的代码,都会被静默地骗过。SafetyNet、Play Integrity、银行 App 的 root 检测代码里,如果它们尝试探测 SuperCall,得到的结果和探测不存在的 syscall 一模一样。
和 Magisk su 的对比
| 维度 | Magisk su 守护进程 | APatch SuperCall |
|---|---|---|
| root 授予位置 | 用户空间(su 进程 fork 子进程) | 内核空间(当前线程直接改凭证) |
| IPC 开销 | 需要(App 和 su 进程 socket 通信) | 不需要(同一次 syscall 完成) |
| 密钥泄露风险 | su 守护进程是 root 进程,可能被利用 | SuperKey 在调用时传入内核,不暴露到用户空间 |
| 被检测的可见性 | su 二进制 + socket + 属性都可检测 | 完全不可见(密钥错误时静默返回) |
关于密钥存储
SuperKey 在修补 boot.img 时写进了内核镜像里——但因为整个 boot.img 都被 KernelPatch 加密保护了,所以这不是什么安全漏洞。设备运行时,SuperKey 只在内核内存中存在,不会被写入任何用户空间文件。