FNERoot 是 GhostLock 在荣耀 FNE-AN00 上的封装形态:一套 HOCON 配置驱动的 内核提权工具链。路由、几何字段、凭据模板全部写在配置里,Kotlin 侧解析校验, native 侧只做几何使用——换内核不改代码,改一行配置。
不是"一键 root 按钮",而是一套把内核利用参数化的框架。每个内核的偏移、路由、凭据布局 差异极大,传统做法是一机一份硬编码二进制;FNERoot 把这些全部抽成配置文件。
HOCON 配置文件声明路由、task_struct / cred / offset 三组几何字段。Kotlin 侧解析合并后, 以类型化二进制送入 native,native 不再做参数校验,只按几何使用。
字段校验在 validateProfileFields 完成,任何越界或不满足的字段都会进入 invalidPaths,UI 把执行按钮置灰——不等到运行时才崩。
fallback.to 支持 tcp_zerocopy 失败后切到 select_stack 重试, 两套路由用独立的字段,互不干扰。
shared → builtin → imported → general override → route override → advanced override → 快照。 低优先级只提供默认值,你只写差异,不重复劳动。
内置 KernelSnitch 采样,用 slide_* 锚点推算运行时基址, 配合 kernel_phys_load 完成 symbol → direct-map 换算。
direct 与 Shizuku 两条执行通道都把同一份二进制字节写进 native 的 stdin, 不存在"两种模式行为不同"的问题。
整条链路只有一次类型转换,Kotlin 负责"懂配置",native 负责"用几何"。这个边界是刻意设计的。
native 侧 legacy/ 的 JSON 解码器已删除。v2 类型化二进制省掉解析开销, 也让 Kotlin 与 native 的版本强制绑定——写错版本就解不出来,不会静默用错字段。
配置是用户可改的。把校验提到 Java 层,能给出具名错误路径(cred.caps_offset 之类), 而不是在 native 里段错误。native 只信已经验过的输入。
路由不再靠内核版本或字段存在性推断,而是配置里显式声明。一个 profile 只允许命中一条路由分支, 未采用的分支完全不写。
| 关键字段 | tcp_zerocopy | select_stack | multicast_waiter |
|---|---|---|---|
| offset.init_task / init_cred | 必填 | 必填 | 必填 |
| task_struct.prio / pi_lock / pi_waiters | 必填 | 必填 | 必填 |
| cred.copy_size / caps_count | 必填 | 必填 | 必填 |
| route.*.compact_waiter | 必填 | — | 必填 |
| waiter_shift | — | 必填(0 合法) | — |
| waiter_off(>0) | — | — | 必填 |
| buffer_size / task_offset / lock_offset | — | — | 必填 |
| offset.empty_zero_page | — | — | 必填 |
| kernelsnitch.mm_struct_sz | — | — | 必填 |
靠 compact_waiter 调整 waiter 布局,适合 pinfo 与 waiter 相邻的紧凑内核。 失败可回退到 select_stack。
用 waiter_shift 做小幅位移,0 也是合法值——这是最轻的一档, 偏移刚好的内核用它最稳。
字段最多的一档:需要伪造多播对象,waiter_off、buffer_size 和 cred.ref_count 全部要算准。
就是 HOCON。JSON 是它的子集,所以老配置直接能用;额外支持注释、尾逗号、 ${var} 变量替换和 include。
# GhostLock kernel profile (HOCON; JSON stays valid) release = "5.4.289-qgki-gf6cb1f712a6e" schema_version = 1 kernel_major = 5 route { select_stack { waiter_shift = -2 } } fallback { to = "none" } kernelsnitch { collisions = 4, mm_struct_sz = 4096 } task_struct { prio = 132, cred = 2080, pi_lock = 2316 } cred { copy_size = 136, caps_offset = 48, caps_count = 5 } offset { init_task = 34464384, init_cred = 34538824 }
usage_offset + 4 ≤ copy_size; caps_offset + caps_count × 8 ≤ copy_size; ref_count ≤ 4。越一条就直接进 invalidPaths, 这是防"差一点点"导致写坏内核的最后一道闸。
ghostlock-extract 从镜像里拿到多少字段就写多少, 拿不到的留空,绝不借相邻内核族的猜值。所以生成成功 ≠ 设备受支持, 真正的判据是导入后 invalidPaths 是否为空。
这里写的是真的。跑通的部分和卡住的部分分开列,不做模糊处理。
HONOR FNE-AN00 · MagicOS 8.0.0.220
Kernel 5.4.289-qgki-gf6cb1f712a6e · Android 14
包名 com.edge.Jinglian.fneroot, 基线 v1.6 / versionCode 7,APK 9,581,961 字节,minSdk 24 / targetSdk 33。
通过 Shizuku(moe.shizuku / rikka.shizuku / rikka.sui)获得 shell 级权限,工作目录 /data/local/tmp/ksu_fne。 执行链路:runExploit → checkKernel → unpackAssets → execStream(fne_local.sh)。
KASLR 每次重启都会重新随机化 phys_offset / page_offset / slide, 写死一个真值只在单次 boot 内有效。调试时可以用 GL_MEMSTART=<真值> 跳过整个 perf 采样直接 apply, 但那是验证手段,不是产品形态。
GitHub:MSEDGE-CORE/GhostLock-HonorFne
整条链路的骨架都出自他:exploit 核心、offset 拓扑与符号表、 电脑端工具链(profile 提取器与配置生成),以及三路由设计、 v2 二进制协议、KernelSnitch 采样思路。
没有他那套 offset 体系和电脑端产出,手机侧无从谈起——本页所述的全部配置字段, 追到根都是他的工作。
设备:HONOR FNE-AN00(Honor 70)
负责把上游产物落到这台机器上:
· 手机端 com.edge.Jinglian.fneroot 封装与 assets/e native 交叉编译
· 5.4.289-qgki 的 ms_spans 对齐 kallsyms 校验(64 项全对)
· 内核校验分支的字节级 patch 与 dex 头重算
· memstart probe 三处缺陷定位(下界 / 索引 / 提前退出)
· APK 重组、zipalign、v1+v2+v3 签名与装机验证
exploit 核心工程基线来自 JoinChang/ghostlock-oneplus (commit 9b2a7ba),含 memstart.c / slide.c / pipe.c / umh_root.c 等模块。oneplus 分支的适配经验是本次移植的直接参考。
这是内核漏洞利用工具,仅用于自有设备的合法安全研究。它可能触发 kernel panic、 导致数据丢失或设备无法启动。请确认你拥有设备完全控制权、能自行恢复, 并遵守所在地法律。作者与本封装不承担任何因使用造成的损失。