Repository navigation
KSuRoot 4.1.0 —— 蓝厂 vr.ko 反 root 实装 + 「解析完整包链接」
KSuRoot 4.1.0 —— 蓝厂 vr.ko 反 root 实装 + 「解析完整包链接」
versionCode = 410·versionName = 4.1.0· AOSP testkey 签名(a40da80a…5dc,可原地升级)
上一个正式版本:4.0.0
编译:debug / release 双变体通过 · 单测 362 条 0 失败(1 条环境门控跳过)· 0 警告
〇、先看这一条:4.0.0 的包不含蓝厂绕过
KSuRoot-4.0.0.apk 打包于 03:55,而蓝厂 vr.ko 那批改动落在 04:32 之后。
所以:
4.1.0 才是第一个真正带上
vr.ko反 root 绕过的正式版本。
一、蓝厂 vr.ko 反 root 实装
1.1 两份自编族基线:从「没有」到「有」
| 文件 | 旧 | 新 | strings -a | grep -c "vr detag" |
|---|---|---|---|
libbaseline_6_1.so |
135184 B | 175792 B | 0 → 2 |
libbaseline_6_12.so |
135184 B | 175776 B | 0 → 2 |
重编时发现并修掉两个独立缺陷:
- 不带
vr.ko抹标记 —— 这是任务书里点名的那一个; - 旧产物根本 load 不起来(任务书里没有)—— 旧构建只编了
fops.c main.c pipe.c posture.c preload.c slide.c util.c,没编root.c/io_daemon.c,
也没提供wallpaper_blob.S需要的素材。后果是install_android_root/
io_daemon_main/embedded_wallpaper_start/_end成了指向 UND 的动态重定位 ——
这份.so连dlopen都过不去。判定依据是readelf -sW … | awk '$4=="FILE"'的
文件符号表对比。
修完之后:NEEDED 只剩 libdl.so / libc.so,STT_FILE 里出现了 root.c / io_daemon.c。
⚠️ 上表是源码树里的尺寸。 APK 里装的那两份更小(154872 B / 154856 B)——
release 构建会走 AGP 的 native 符号剥离。剥离不影响vr detag,
已从成品包里取出来复核过:vr detag仍是 2。
别拿这两个数字对不上当成构建出错。
1.2 能力与闸门成对出现
按任务书 §4 的结论,Kotlin 侧写不了内核内存 —— 所以实装落点在载荷的 C 代码里
(pipe_phys_write_data / pipe_write64 那段),Kotlin 只做校验与呈现:
| 层 | 文件 | 作用 |
|---|---|---|
| 能力 | 载荷 .so 里的 patch_task_vr_tag(已内联进 install_android_root) |
先清 thread_info.flags 的 0x400,再逐字节清 task+0x06 / task+0x2c 两个标记,最后回读自证 |
| 校验 | com.kernelpack.vivo.VrKoPayloadCheck |
只读字节,判定"这份载荷带没带绕过" |
| 闸门 | com.kernelpack.vivo.VrKoPayloadGate |
只对蓝厂方案生效;通用方案短路,一次 ELF 解析都不做 |
判据是两条组合:日志串 vr detag + 机器码特征(add #0x2c 且 AND ~0x400)。
全量 126 份载荷实测:
| 份数 | 命中判据 | |
|---|---|---|
| 带绕过 | 36 | 36 / 36 |
| 不带 | 89 | 0 / 89(零假阳性) |
任务书 §6.3 的建议是错的:它建议扫
movz/movk找0x2c与0x400。
实测 clang 折成的是add立即数与AND逻辑立即数 —— 照movz扫会漏判 36/36。
为此在AArch64.kt补了两个解码器(decodeAddImmediate/decodeLogicalImmediate)。
1.3 两份无源码载荷:降级标注(按你选的方案 A)
libksu_vivo_iqoo12_a15.so 与 libksu_vivo_iqooz95gvivot35grootghos_any_3cc6.so
没有源码、无法重编,所以不假装它们带绕过:vivoVrBypass = false →
载荷列表标红 + 选中时一次确认对话框(可以"仍要选用",但得先看过这句话)。
二、新增功能:「解析完整包链接」
载荷构建页的第三条路:粘一个完整包(OTA ZIP)直链,自动解出 boot.img 交给已有流程。
2.1 它不是"下载整个包"
完整包通常 4–8 GiB。实际网络代价:
| 取什么 | 大约 |
|---|---|
| 文件尾部(找 ZIP 中央目录) | 64 KiB |
| ZIP 中央目录本体 | 几百 KiB |
payload.bin 头 + 分区清单 |
24 B + 几百 KiB |
boot 分区真正用到的那几块 |
~64–96 MiB |
实现方式:HTTP Range 请求 + 手工跟随重定向(厂商 CDN / GitHub Release 大量用 302)。
2.2 两种完整包形态都认
| 形态 | 识别 | 处理 |
|---|---|---|
| A/B 完整包 | 包里有 payload.bin(必须是 Stored) |
读 update_engine 清单,按 dst_extents 还原分区;支持 REPLACE / REPLACE_XZ / ZERO / DISCARD |
| recovery 风格 | 包里直接放 boot.img / init_boot.img |
Stored 原样落盘;Deflate 流式解压 |
2.3 出处分级(Apache-2.0)
com.kernelpack.ota 下的 5 个文件移植自
YuKongA/ghostlock-app 的 data/ota/:
| 文件 | 移植方式 |
|---|---|
XzDecoder.kt |
逐字节原样(只改 package) |
PayloadBinUtils.kt |
逐字节原样(只改 package) |
ZipCentralDirectory.kt |
原实现 + 三处只加不改(改名 / 候选条目表 / 边界检查) |
HttpRangeReader.kt |
原实现 + probe()(原版拿不到"服务器支不支持 Range")+ readToFile()(流式落盘) |
OtaPayloadExtractor.kt |
见下 §四 的改动清单 |
许可证沿用 app/src/main/assets/GL_LICENSE_Apache2.txt。
三、其它打磨
- 清掉构建里全部 5 条警告(1 条生产代码 + 4 条测试代码),现在编译 0 警告:
InstallViewModel.kt的Condition is always 'true'(similar由snapshot?.let{}推出,
顺序倒过来即消,语义不变);- 测试用例名里的半角引号 /
**(会触发 Windows 路径警告); - 3 处多余的
!!(编译器对 JUnit 的assertNotNull有数据流支持)。
- 载荷构建页的输入现在有两条互斥来源(
content://URI 与本地文件),
ViewModel 里互斥赋值 —— 避免"界面写着 A、实际构建用的是 B"。 - 解出的镜像放应用缓存目录,只保留最近一份(boot 镜像 96 MiB,堆着会被系统无预告清掉)。
- 给 payload 操作长度加了上限闸(256 MiB),防
toInt()溢出把"包有问题"伪装成"应用崩了"。
四、OtaPayloadExtractor 相对上游的改动(逐条)
- package 名;对象名不变;
ZipFileUtils→ZipCentralDirectory;- 去掉
REPLACE_BZ支持 —— 它要commons-compress,而现代 OTA 的 boot 分区用的是
REPLACE/REPLACE_XZ。为几乎不会出现的旧操作类型引一个第三方依赖不值得;遇到时明确报错; - 新增直取条目路径 —— recovery 风格完整包(国内厂商常见)里根本没有
payload.bin; xbl_config改为可选(默认不取)—— 本工程走 kallsyms 扫符号,不需要物理加载地址,
取它只是白白多下几十 MiB;- 日志中文化,产物文件名前缀
ghostlock_ota_→ksuroot_ota_。
五、没做的事(如实列出)
- 一次真机都没跑过。 这一条对所有 4.1.0 的内容都成立 ——
包括vr.ko绕过本身。vr detag=2只证明代码被编进去了,不证明它在真机上抹掉了标记。 - 没有验证过真实 OTA 的
REPLACE_XZ操作是单块还是多块 —— 见下面第 3 条。 - 内置 XZ 解码器只支持单块流,这是上游的缺陷,没有修。
实测:xz --block-size=16384 -9产出的 5 块流,第 1 块 16384 字节完全正确,
第 2 块从第 2 个字节起发散(期望0356: KS,实得00000000),随后抛
XzException: match distance beyond decoded data。
各块的 LZMA2 头解析(reset=3/props=93/packSize/ 偏移)与xz侧完全一致,
输入字节也一致 —— 问题在解码状态而非定位。
没有去修:这是一段算术编码器,"差一位"和"完全正确"之间没有中间状态,
在没有吃透它之前动手改,风险比不修大得多。
处理方式:单块流已用 3 条真实xz向量逐字节验证(含 crc32 / crc64 两种 check);
多块流由XzDecoderTest钉住"会抛异常"这一现状;OtaPayloadExtractor把它翻成
一句人能看懂的话。谁将来修它,那条测试会先红。 REPLACE_BZ(bzip2)不支持 —— 理由见 §四.3。- 没有下载整包的能力:服务器不支持
Range时直接拒绝。这是有意的 ——
不该在用户没同意的情况下下几个 GB。 BundledPayloadImported.kt是生成器产物:为加vivoVrBypass字段,
生成器(载荷搜寻/gen_catalog.py)与产物两边都改了,但生成器没有重跑
(重跑会把全部 83 条 imported 条目一起刷新,超出本次范围)。- 任务书 §6.2 点名的
tokay-CP2A.260605.012/target.h与它自己给的数字矛盾:
该文件是TASK_CRED_OFF 0x820(不是0x838),且没有TASK_PI_LOCK_OFF。
配方用的是与旧构建现场cmp逐字节相同的targets_6_1/tokay.h。
这条需要人来确认哪份才权威。 neutralize_vr()全局关开关没做(Option B):它需要
SYS_EXIT_TP_OFF/RVH_COMMIT_CREDS_TP_OFF,这两个偏移在 6.1 / 6.12 上
没有可核实的来源,按"不许猜"的原则留空,只做 per-task 抹标记。- 载荷列表里那两份无源码载荷是降级标注,不是修好了(见 §1.3)。
六、怎么自己复核
# 1. 编译 + 全部单测(会同步源码树,防止"编的是旧代码")
bash ksu-toolchain/compile_check.sh /绝对路径/merge-repo
# 期望:SCRIPT_RC=0 · 362 条 0 失败 · 0 警告
# 2. 两份族基线真的带上了绕过
strings -a merge-repo/app/src/main/jniLibs/arm64-v8a/libbaseline_6_1.so | grep -c "vr detag" # 2
strings -a merge-repo/app/src/main/jniLibs/arm64-v8a/libbaseline_6_12.so | grep -c "vr detag" # 2
# 3. 旧产物为什么 load 不起来(对比用)
readelf -sW <旧.so> | awk '$4=="FILE"' # 缺 root.c / io_daemon.c
readelf -dW <旧.so> | grep -E "UND|NEEDED" # install_android_root 等是 UND
# 4. 出包
bash ksu-toolchain/package_beta.sh /绝对路径/merge-repo
# 脚本自带三道断言:versionCode == 410 · 签名 == testkey · 成品指纹比对七、本轮改动的文件
新增(com.kernelpack.ota,5 个)
HttpRangeReader.kt · ZipCentralDirectory.kt · PayloadBinUtils.kt · XzDecoder.kt · OtaPayloadExtractor.kt
新增(单测 3 个)
ota/XzDecoderTest.kt · ota/XzVectors.kt(4 条真实 xz 向量)· ota/ZipCentralDirectoryTest.kt · ota/PayloadBinUtilsTest.kt
改动(生产代码)
PayloadBuilderViewModel.kt(新增 OtaLinkState + parseOtaLink() + 输入双来源)
MainActivity.kt(构建页第三个按钮 + 对话框 + 状态行)
res/values/strings.xml · res/values-zh-rCN/strings.xml(10 条新字符串)
InstallViewModel.kt(消警告)· app/build.gradle.kts(版本号)
改动(文档)
README.md · MODULE.md
改动(构建脚本)
ksu-toolchain/package_beta.sh(VERSION=4.1.0 / VCODE=410)