Repository navigation
KSuRoot 4.0.0 —— 三族内核(6.1/6.6/6.12)+ GhostLock 50 档内核适配
KSuRoot 4.0.0 —— 三族内核(6.1 / 6.6 / 6.12)+ GhostLock 50 档内核适配
versionCode = 400·versionName = 4.0.0· AOSP testkey 签名(a40da80a…5dc,可原地升级)
上一个正式版本:3.2.0(2026-09-24)
编译:debug / release 双变体通过 · 单测 304 条 0 失败(1 条环境门控跳过)
一、这个版本做了什么
1. 内核覆盖:从「一条 6.6」到「三族 6.1 / 6.6 / 6.12」
3.2.0 实际只有 6.6 一条线。4.0.0 扩到三个结构体族,
而且不是靠"版本号外推" —— 每一族都有自己的基线库:
| 结构体族 | pi_lock |
cred |
tasks |
基线库 | 来源 |
|---|---|---|---|---|---|
6_1 |
0x924 |
0x838 |
0x550 |
libbaseline_6_1.so |
自编(tokay target.h) |
6_6 |
0x90C |
0x820 |
0x550 |
libionstack.so / libbs.so |
沿用 |
6_12 |
0x9EC |
0x900 |
0x638 |
libbaseline_6_12.so |
自编(GhostLock + 荣耀 BTF) |
为什么必须按族选库:结构体偏移是编译期烤死的,patch 改不了。
拿 6.6 的库去打 6.1 的内核,符号就算全 patch 对,写进去的也是错位置的字段 ——
这比"符号对不上"隐蔽得多(符号对不上会报错,字段错位不会)。
6.1 的口径变更(留档):6.1 曾在 2026-09-12 被移出主线,理由是"它是 flat 形态
(88 字节 / task@0x30),与 6.6/6.12 的 nested(112 字节 / task@0x50)不是一套"。
这个理由本身是对的;变的是我们后来为 6.1 编出了专属基线,
于是"拿 6.6 的偏移硬打 6.1"这个危险不再存在。
⚠️ 两条要一起读:6.1 能进主线的唯一前提是它有自己的族基线 ——
那份基线若被拿掉,6.1 必须同时退回拒绝。
2. 登记档位 51(通用)+ 52(蓝厂)= 103 档
引入上游 ghostlock-app 源码登记的
50 个内核适配(每档 9 个符号地址 + 结构体族),"通用方案"从 1 档扩到 51 档;
蓝厂方案把这 51 档全部挂上 vr.ko 绕过 → 52 档。
⚠️ 这 50 档一律标UPSTREAM_TARGET_H+beta:数据是真的(来自上游源码),
但我方未在真机上验证过。界面上与实测档分开计数显示,不谎报验证状态。
3. 双向符号对齐闸门(新的安全闸)
打补丁只能改写基线 .so 里本来就有的字面量,所以"基线有哪些键"与
"boot.img 解出哪些键"必须双向对齐。原先的写法是
baseline.symbolOffsets[key] ?: continue(直接跳过)—— 于是"看起来支持、实际写错内存"。
现在 SymbolAlignment 对不齐就阻断打包。
4. 与 GhostLock 的 offsets.json 互通
采用它的 offsets.json 作为互通格式(字段命名与结构已逐键核对),
实现读 / 写 / 合并(三种冲突策略),往返不丢未知键 ——
别人文件里我们不认识的键原样保留,不会被静默丢掉。
5. 内置厂商载荷:39 → 122 条(126 个 .so)
新增并入批次 83 份:Pixel 6~11 全系、三星 Galaxy 全系、
OPPO / realme / 一加 / 华硕 / 魅族等。读不出内核版本的 77 份一律
kernelUnknown —— 只允许手动选择、绝不参与自动匹配(载荷靠编译期常量寻址内核符号,
拿错一份就是提权失败)。
6. 设置页新增「基线覆盖面」
把注册表真实覆盖面摊开给用户看,而不是让人猜:三个主线系列 × 两个方案各登记多少档
(实测 / beta 分开计数)· 上游清单对账(GhostLock 登记的 50 档 vs 我方登记,必须零差异)
· 偏移可信度直方图。
7. 其它
- 删除孤儿库
libgl_universal.so(全工程 0 引用)与重复载荷libksu_vivo_sixmodels_a.so - 单测 154 → 304 条
二、修掉的 bug:两处「基线 ABI 冲突」误报
实测 6.1.145 的 boot.img 时被拒,提示
「基线 ABI 档位是 GKI 6.6,而 boot.img 是 6.1」。根因有两层,
都是"两套东西对不上",而且都表现为同一句话,极易误判:
| 症状 | 根因 | 修法 | |
|---|---|---|---|
| 第 1 层 | 两张表 | 路由查 BaselineRegistry.allEntries(103 档),打包却查 BaselineProfiles.byId(只有 2 档,都是 6.6)→ 查不到就兜底回落 PD2520 |
统一到 BaselineRegistry.byId / findByBytes(两个调用点都改) |
| 第 2 层 | 两套词汇 | 上游档的 abi.kernelSeries 填的是三段小版本(6.6.118),而闸门比的是两段大系列(6.6)→ 50 档一档都构建不出来 |
拆开两个语义:路由键保留三段小版本,ABI 比较键压成两段 |
同源的第 3 处:lookup() / coverageReport() / availableLabels() 也只查那 2 档 ——
导致报缺文案会在明明有档位时说"没有基线"。已一并修正。
并且不再兜底猜系列:认不出基础 .so 就如实报缺并停止打包,
而不是"取第一档顶上" —— 那等于拿 6.6 的旧值去打 6.1 的库。
回归测试
新增 BaselineRoutingLookupTest(11 条),把两条不变量写成断言:
- 路由给出的每一个
profileId,byId都必须能取到(防"两张表"再次分叉); - 每一档都必须能通过 ABI 硬闸门(用它的真实内核串端到端跑一遍)——
这条直接复现用户看到的那句「基线 ABI 冲突」,只不过是在单测里。
三、参考了 GhostLock 的哪些源码
上游仓库:YuKongA/ghostlock-app(Apache-2.0)。
本项目只取方法与数据,不复制其 C 代码;其许可证随包携带于
app/src/main/assets/GL_LICENSE_Apache2.txt。
| 上游路径 | 取用了什么 | 落在本项目哪里 |
|---|---|---|
src/kernels/<内核串>/offsets.h |
50 个内核各自的 9 个符号地址 | GhostLockKernelOffsets.KERNELS |
src/kernels/offsets.h |
3 个结构体族的字段偏移 | GhostLockKernelOffsets.STRUCT_FAMILIES |
src/core/main.c |
_RSO(field, fallback) 覆盖模型:运行时值 > 编译期基线 > 载荷兜底常量 |
UnifiedOffsetResolver |
src/core/offsets_json.c / .h |
offsets.json 读写与字段命名 |
GhostLockOffsets · GhostLockOffsetsIo · MiniJsonCodec |
src/core/runtime_struct_offsets.h |
运行时结构体偏移键名 | SymbolKeyMapping(上游 9 键 ↔ 我方 11 键) |
src/core/target.h |
目标描述形态 | BaselineProfile / AbiProfile 字段对照 |
buildSrc/.../GenerateSupportedKernelsTask.kt |
内核清单由扫描源码树生成 | GhostLockKernelCatalog(50 条 + 出处标记) |
反向核对:它的数据经我们独立验证过(4 处零差异)
不是"抄了就信":
| 上游数据 | 独立佐证 | 结果 |
|---|---|---|
STRUCT_OFFSETS_6_6 |
frankel-CP2A.260605.012/target.h |
一致 |
STRUCT_OFFSETS_6_12 |
pyyyc 荣耀 YLP-W00 6.12.38 BTF 实测 offsets.json |
15 字段 0 差异 |
| 编译期兜底常量(11 项) | 荣耀 struct_fields |
一致 |
STRUCT_OFFSETS_6_1 |
tokay-CP2A.260605.012/target.h |
一致(pi_lock=0x924、compact_waiter=1) |
手写档 PD2520 |
boxiaolanya2008 PD2520-BP2A.250605.031.A3/target.h |
28/28 键 0 差异 |
明确没有引用(高风险,拒绝照搬)
libextract.so(3.88 MB Rust 黑盒):kallsyms 提取口径我方没审过,
且具备 LZ4 重压缩回写 boot.img 的能力。在没验证其提取结果与我方口径一致之前,
引入它等于把校验权外包 —— 不得用于生成可刷写产物。libghostlock.so的运行时架构:它是"1 份通用载荷 + 运行时读 json",
与我方"编译期常量写进.so"根本不同。我们只采用它的格式与覆盖模型,
主线仍是直接写入.so。
四、已知限制(如实说明)
- 50 档上游内核 + 两份自编族基线均未在真机验证(一律标 beta)。
- 6.12 基线的符号是
CROSS_REFERENCE(取自荣耀 YLP-W00 6.12.38,是别的机型)。
构建时会被 boot.img 解析出的新值逐项改写,且SymbolAlignment保证改写不齐就阻断。
结构体偏移才是编译期烤死、决定成败的那一半。 - 蓝厂 vr.ko 绕过尚未接入提权路径:数据层(
VrKoBypass,12 条单测)已完成,
但"清零0x28-0x2f"这一步需要在真机上先确认安全才敢接线。 offsets.json导入目前是阶段 1(读取与呈现):UnifiedOffsetResolver
的合并流水线已实现并有 10 条单测,但尚未接入构建路径。
五、发布资产
| 文件 | 内容 |
|---|---|
KSuRoot-4.0.0.apk |
签名 APK(versionCode 400,AOSP testkey,可原地升级) |
KSuRoot-4.0.0-source-full.zip |
完整构建源码(含 UI 外壳、厂商载荷目录、全部 jniLibs) |
KSuRoot-4.0.0-module-src.zip |
仅构建与模块相关源码(com.kernelpack 载荷引擎 + 对接点 + 构建脚本 + 两份自编族基线) |
单测:304 条 0 失败(./gradlew :app:testDebugUnitTest)。