Repository navigation
KSuRoot 4.1.2 —— 从镜像读 vr.ko 标记偏移 + 导入完整刷机包
versionCode = 412·versionName = 4.1.2· AOSP testkey 签名(a40da80a…5dc,可直接覆盖 4.1.1 原地升级)
上一个正式版本:4.1.1
单测 41 个类 / 417 个用例 · 0 失败(1 条环境门控跳过)
一、vr.ko 的标记偏移:从「赌一个」变成「读出来」
vr.ko 会给来自 app 的 task 打两个标记字节,该 task 一旦持有 euid 0,
sys_exit 探针就把它杀掉 —— 提权看着成功,子进程随即被杀,日志里一切正常。
要抹掉那两个字节,就得知道它们在哪个偏移。而那是编译期烤进载荷、patch 不了的。
麻烦在于它有 0x04 / 0x06 两种取值 —— 而且同一台设备的两份 vr.ko 就各一种:
| 路径 | vermagic | tag A |
|---|---|---|
lib/modules/vr.ko |
…aarch64 vivo |
0x04 |
lib/modules/6.1-gki/vr.ko |
…aarch64 |
0x06 |
两份的 srcversion 完全相同(同一份源码编的),差别只在编译配置。
这台机器实际加载的那份 vr.ko,就在 vendor_boot.img 里。 所以:
- 蓝厂方案现在要求你提供
vendor_boot.img—— 应用从里面那份平铺的
lib/modules/vr.ko(按 Android 的modprobe查找顺序,uname -r是完整串而非
6.1-gki,命中的就是平铺那份)反汇编出真正的偏移; - 然后改写载荷里那个值,而不是"对不上就停下";
- 通用方案不需要它:通用方案不做 vr.ko 绕过,也就没有这个偏移要定。
界面上会直接把结论摊开:本机 vr.ko tag A = 0x04 · 已改写载荷 3 处。
二、四份自带/自编库强制配自己的档位
打补丁是「拿档位里的旧值去 .so 里找字面量」,所以库与档位必须同源。
而"选哪份库"按结构体族走、"选哪一档"按三级路由(内核串)走 —— 两条路会选岔:
- X100 Pro 6.1.145:库是
libbaseline_6_1.so(旧值来自 tokay target.h),
档位却命中上游档up-6-1-145-…(旧值来自 GhostLock offsets.h)→ 26 项一处没匹配上 - 本机 PD2463 6.6.89:库是
libbs.so(旧值来自 PD2520 target.h),
档位命中up-6-6-89-…-vivo→ 25 项一处没匹配上
两次的产物都只是原样拷贝,装到机器上必然失败 —— 而界面显示的是"跑完了"。
现在四份库全部强制配对,选岔了由零命中闸门当场拦下:
| 库 | 配到 |
|---|---|
libbaseline_6_1.so |
baseline-6-1-tokay |
libbaseline_6_12.so |
baseline-6-12-honor |
libbs.so |
PD2520-BP2A.250605.031.A3 |
libionstack.so |
IONSTACK-P10-CP2A.260605.012 |
三、导入完整刷机包
载荷构建页新增入口:直接选你下载的 OTA zip 或 fastboot tgz,
它自己把 boot 和 vendor_boot 一起取出来 —— 不用你先解压,也不用手动提取。
- OTA zip:认
payload.bin,支持REPLACE/REPLACE_XZ/REPLACE_ZSTD/REPLACE_BZ/ZERO/DISCARD,ZIP64 也认 - fastboot tgz:流式解析 gzip + tar,只把需要的那一个文件读出来
实测:真实的 6.5 GB 完整包上跑通,boot / vendor_boot 与独立参考实现
(Python + zstd CLI)逐字节一致。
⚠️ 代价要说明白:完整包要整份拷进应用缓存才能随机读(ZIP 中央目录在包尾,
而 SAF 的 uri 变不成 File)。6.5 GB 的包就要拷 6.5 GB —— 空间不够会当场拒绝
并说清差多少,抽完立刻删缓存(失败路径也删)。
四、本版修掉的其它问题
- 蓝厂方案被自己的闸门 100% 拦死:构建开始时重建状态时把
vendorBootName清成了"",
而闸门正是拿它判的 → 选不选 vendor_boot 都被拦。现在状态重置用copy保留输入,
且判据改用真正的输入句柄,不再拿展示名当控制变量。 payloadSource两份来源不同步:Compose 状态与持久化偏好各一份,
而真正决定装哪份载荷的是偏好。构建自动落库那条路径只写了偏好 →
界面高亮「内置」,点安装装的却是刚构建的自定义载荷。- 移交 root 那一串弹窗统一到 miuix(确认 / 进行中 / 结果 / 选管理器)。
它们原来还是 Material3AlertDialog;换成 miuixOverlayDialog时
必须放进 Scaffold 里 —— miuix 的 Overlay 组件依赖 Scaffold 提供的
CompositionLocal,放在外面根本不渲染(表现就是"点了没反应")。 KallsymsFinder.kt里有个裸 NUL 字节(注释里想写x\0,写进了真的0x00)→
grep把整个 1161 行文件当二进制跳过。
五、边界(不掩饰)
- 「抹标记」这一步仍然没有在任何真机上跑过。
vr detag只证明代码编进去了,
不证明它抹对了、更不证明抹完就不被杀 —— 三族基线一律仍标beta。 - 整包导入没在真机跑过(只做了编译 + 单测 + 在真实包上的离线验证)。
- fastboot tgz 没有厂商真包样本:成功路径是用 GNU tar 现场造包验证的,
错误路径用了真实 tar.gz。 0x04/0x06由什么决定还没查清:目前只有"vermagic 里含vivo"这条
5 样本的相关性,因果未查明。所以别把它当规律用。- 第三方载荷的许可证正文仍未补齐:随包 127 份
.so来自多个上游仓库,
登记表里逐条署了名(source字段写明仓库与文件名),但许可证正文只带了
GhostLock 的 Apache-2.0。其中一份来自
qsvggff-spec/oppo-A5-PRO-5G-CVE-2026-43499(MIT,
与包内libksu_oppo_oppoa5pro5gcve202643499_any_d77f.sosha256 完全相同)——
那个仓库是失败研究的归档,作者自己的结论是「利用链无法收敛」。
该载荷仍在软件中(可供对照与研究),但不建议作为提权载荷使用,
列表里会标红说明原因。