Skip to content
This repository was archived by the owner on Oct 3, 2026. It is now read-only.

KSuRoot 4.1.1 —— 零命中闸门 + 动态库库房 + 滑动删除

Choose a tag to compare

@hmascs hmascs released this 01 Oct 13:27
· 2 commits to main since this release

KSuRoot 4.1.1 —— 零命中闸门 + 动态库库房 + 滑动删除

versionCode = 411 · versionName = 4.1.1 · AOSP testkey 签名(a40da80a…5dc,可直接覆盖 4.1.0 原地升级)
上一个正式版本:4.1.0(18 个提交之前)
单测 39 个类 / 398 个用例 · 0 失败(1 条环境门控跳过)· 全矩阵 14/14 blocked = false


〇、先说最要紧的一条:6.1 上「看着跑完了,其实一行都没改」

用 X100 Pro(6.1.145)构建时,界面给的是:

偏移解析: 28 / 28 项
需要改写: 26 项 · 校验通过: 0 项
该动态库未引用 26 项偏移

校验通过: 0 不是「没什么可改」,是「一个都没找到」。 根因是两条独立的路选岔了:

选什么 按什么选 6.1.145 上选到 旧值来自
基础库 结构体族 F6_1 libbaseline_6_1.so baseline-6.1-tokay/target.h
档位 三级路由(内核串) up-6-1-145-… GhostLock 的 offsets.h

打补丁的方式是「拿档位里的旧值去 .so 里找字面量」。两套旧值毫无交集,于是 26 项一处都对不上,产物等于把基础库原样拷贝了一份 —— 装到机器上必然失败,而界面看起来是"跑完了"。

为什么原来的硬闸门没拦住:hasFailures 的判据是 changed && !ok && !absent —— absent 被明确排除在外。那个理由("老版本 .so 可能没有对应代码路径")对个别键成立,对"全部键都 absent"不成立。

修法两条:

  1. 库与档位强制同源 —— 自编族基线必须配它自己的档(baseline-6-1-tokay / baseline-6-12-honor),上游 up-* 档只适用于上游那份 .so。
  2. 零命中硬闸门 —— 只要偏移规格一条都没落到站点上就停止打包。基址那条不计入:它即使全不匹配也常常会变,会把"一条偏移都没改"掩盖过去。

回归用例 BaselineLibraryPairingTest(4 条),其中一条直接断言两套旧值没有交集 —— 把"为什么必须配对"变成可执行的事实。


一、动态库:导入之后「点了没用」

# 缺陷 后果
1 「载荷构建 → 用作载荷」用的是内存里的产物;进程被回收后 outputLibrary 为 null,旧代码是 ?: return 点了什么都不发生 —— 没 Toast、没报错、按钮不变
2 PayloadStaging 缓存键是「同名 + 同长度」,而自定义载荷在私有目录里固定叫 payload.so 换一份字节数恰好相同的载荷 → 静默复用上一份
3 shizukuStage 缓存键只有长度 同一个坑在 Shizuku 路径上又踩一次

第 2、3 条最阴:它们不报错,只是加载了错的载荷。 现在缓存键改成内容哈希 / 逐字节比对。


二、动态库库房:Download/动态库/<机型>/<文件名>.so

  • 库房(用户可见、可自己整理):Download/动态库/<机型>/<文件名>.so
  • 活动副本(真正被加载的那份):files/active_payload/payload.so
  • 界面新增按机型分组的库房列表,每份可直接「使用」设为当前,左右滑动删除
  • 同名但内容不同的两份不会互相覆盖(自动加哈希后缀)
  • 删掉当前生效那条时会真正激活下一条(旧写法只改 id 不拷文件,会留下"界面说当前、实际没有活动副本"的自相矛盾状态)

为什么库房那份不能直接 dlopen:分区存储下应用只能读自己经 MediaStore 创建的那批文件;
而且 /storage 是 FUSE(u:object_r:fuse:s0),非 untrusted_app 的域根本读不到 ——
这一条是在 pm install 时被 SELinux 当场拦出来的(avc: denied { read } ... tclass=file)。
所以库房负责"让用户看得见、管得住",私有副本负责"一定能被加载"。

⚠️ 搜寻边界(如实说):库房不能自动扫描 Download/动态库/ 里你自己丢进去的文件 ——
分区存储不允许应用读取别的应用(包括文件管理器)创建的下载文件。
条目只有两个来源:本应用写进去的、以及你通过系统选择器显式授权的那一个。

滑动删除踩到的两个坑

  1. 最后一条永远删不掉:items.forEach 没有 key(),Compose 只能按位置复用;而手势的 pointerInput(enabled, triggerPx) 两个 key 换数据时都不变,于是手势块从不重启,一直握着第一次组合时捕获的 onDelete(指向已经删掉的条目)。修法两处缺一不可:key(entry.id) + rememberUpdatedState(onDelete)。
  2. 删除底色不统一:之前是硬编码红 + 直角 + 文字随方向左右跳。现在用主题 error 色、与行同一个圆角常量、同高同内边距、图标 + 文字垂直居中,红底不透明度跟着滑动进度长出来。

手势没有用 detectHorizontalDragGestures,而是沿用本工程在底栏滑块上验证过的写法 —— 本机系统 touchSlop 实测约 75px(≈19dp),且它的回调只给越过阈值之后的增量,那段距离会被永久丢掉(表现为"开头要空拖一小段才动")。这里是自定义 4dp 阈值 + 位移从按下点起算,并且在阈值之内一个事件都不消费,所以行内的「使用」按钮照常能点。


三、vr.ko 标记偏移分族

内核族 tag A tag B 样本
6.1 0x04 0x2c X100 Pro (PD2324) · 6.1.145
6.6 0x06 0x2c 本机 PD2463 · 6.6.89
6.12 0x06 0x2c iQOO 15 (PD2505) · 6.12.58

6.1 与 6.6 只差半代,tag A 就挪了 2 个字节 —— 而这个值编译期烤死、patch 改不了。填错的表现是"真机上标记一个字节都没抹掉,而自检报成功"。

  • VR_TAG_A_OFF 由单一常量改为分族,新增 tagAOffForSeries() / tagAOffForRelease(),认不出返回 null,不猜
  • 早先那段「跨内核版本未经证实、假定相同、从未验证」的结论留档保留(它当时是对的,而且明确把"假定"标了出来),但结论已随实测更新

顺带说一个被实测否掉的想法:曾加 add#0x4 计数想"分族把 tag A 也数上"。
add #0x4 是极常见指令 —— 89 份没有绕过的载荷里 86 份命中,放出来只会误导。
换成正确的指令形态(ldrb/strb 的立即数)再测,仍然 19/25 命中负例。
所以 tag A 只能当声明,不能当判据:判定继续只用「tag B + 清 0x400」(37/37 与 0/89)。


四、这一版包含的其余修复(4.1.0 之后累积)

  • 6.4+ 内核整档失败的总根源:kallsyms 偏移表定位用了负数取模(Python 语义直译)
  • 偏移表判据从「前三项单调」换成查表的形状 —— 单调几乎没有区分度
  • BASELINE_6_12.imageBase 填成目标基址 → 绝对地址形式的构造点全部漏改(39 处 → 9 处)
  • 符号对不齐时只置空产物、gate 仍是 Proceed → blocked=false 且产物 0 B,UI 不弹阻断框
  • FopsSlot 的 fallback 从来没被用上
  • 6.12 真正跑通:ashmem 在 6.12 变成 Rust 实现、符号名全 mangled → 改成运行时从 miscdevice 的 fops 槽读出来
  • 6.1 / 6.12 在通用 / 蓝厂两个方案下都可用(四个组合各 16 / 16 / 13 / 13 档)

五、边界(不掩饰)

  1. 偏移是实测的,「抹标记」这一步没在任何真机上跑过。 vr detag 只证明代码编进去了,不证明它抹对了、更不证明抹完就不被杀 —— 所以三族基线一律仍标 beta。
  2. 库房不能自动扫描 Download/动态库/ 里外部添加的文件(分区存储限制,见上)。
  3. 安装包与源码归档:本 Release 提供已签名 APK;源码归档由 GitHub 依据 tag 自动生成。
  4. 有一份随包载荷标了「不建议使用」。 libksu_oppo_oppoa5pro5gcve202643499_any_d77f.so(OPPO A5 Pro 5G)与上游仓库 qsvggff-spec/oppo-A5-PRO-5G-CVE-2026-43499 的 preload-tokay-PKP110.so sha256 完全相同 —— 而那个仓库是失败研究的归档,作者自己的结论是「利用链无法收敛:三条 KASLR 泄露路线全堵死」(并注明 iQOO Neo9s PRO / Z10x / vivo X Fold5 的独立研究结论相同)。
    它仍然留在软件里(仍可选取,供对照与研究),但不建议作为提权载荷使用 —— 列表里会直接标红写明原因,点选时会先弹一次确认。