AI 声明:本文由 AI 助手撰写。解锁流程是它陪我一起跑的——命令由它执行,决策和按电源键的是我; 文字同样是它起草,我只做了粗校。命令与结论仅供参考,出事了自己担。

小米在 2025-12-31 关闭了中国大陆的社区解锁资格申请,2026-01-01 起连解锁工具下载都停了。 也就是说以前那套「社区刷到 5 级 + 实名 + 抢名额 + 绑号等 168 小时」的路子,对国行设备彻底作废。 而我这台小米 14(houji)正好卡在还能解的安全区里,趁早动手。

先给结论:解锁成功,KernelSU 也装上了,但过程跟网上任何一篇教程都不一样, 中间有两处关键判断是被逼出来的,写下来备查。

前置情况

项值
设备Xiaomi 14(houji, 23127PN0CC)
系统HyperOS OS3.0.7.0.WNCCNXM,Android 16
安全补丁2026-02-01
Bootloader锁定,verifiedbootstate=green,verity enforcing
OEM 解锁开关已开(persist.sys.oem_unlock_allowed=1)

判断能不能解,看的是安全补丁而不是版本号。目前公开的现状汇总( AdaUnlocked/2026-All-Brands-Bootloader-Unlock-Status)里写得比较明确: 骁龙 8 Gen 3(SM8650)各机型 ≤ 2026 年 6 月补丁 可免费免拆解锁, 一旦上了 2026-09 补丁或 OS4 就封堵。 我这台是 2026-02,在窗口内,而且不需要先降级——这点很重要, 因为出厂 MIUI 的机器去找售后降级,会把机器码在云端拉黑。

公开工具是酷安 AC极光_Official 的 8Gen3.bl.7z,在 c8e-3d1a 那个归档仓库里, 按官方 release 里的 sha256 校验过(0ed57829…77e4f8)。同一份工具按补丁号分支, 2026-02 及更晚走「高版本」这一支。

工具到底在干什么

先把载荷拆开看,比闷头跑 .bat 踏实:

  • exploit:aarch64 ELF,内核任意写。靠 page table walk 定位 __sys_setuid, 把入口改成恒返回成功,之后随便谁来一次 setuid(0) 就是 root。
  • images/houji/abl.elf:2023-10-31 的旧 ABL,整份替换。旧 ABL 不校验、且把 milestone 往后推。
  • 一整套旧固件:xbl、tz、uefi、uefisecapp、keymint、devcfg、hyp、aop…… 连同 init_boot/vendor_boot/dtbo/vbmeta_system。
  • Unlocking-SM8650.img:boot v3 镜像,2 MB 内核 + 372 字节 initramfs,cmdline 是作者 ID。 这一份是真正的落锁动作:fastboot boot 起来,在 milestone 之前调 QCOM_VERIFIEDBOOT_PROTOCOL.VBRwDeviceState 往 RPMB 写锁状态。

概念上跟 Qualcomm 的 GBL 漏洞是一回事:GBL 是 ABL 里被拆出来的一段, Qualcomm 拿它限制 OEM,但 GBL 自己没签名,于是可以塞任意 UEFI 应用进去, 抢在 milestone 之前把锁状态改掉。锁状态权威副本在 RPMB,密钥只在 TrustZone 里, 从 Linux 侧写不了——所以必须靠 ABL 阶段自己的接口。

顺带纠正一个流传的说法:讲 GBL 必须上 9008 的那些教程,针对的是骁龙 8 Elite Gen 5(8E5) 那一代的设计——那边载体是 efisp 分区,写它得 9008 或 UFS 编程器。 小米 14 没有 efisp,走 abl 就行,全程 adb + fastboot,不用拆机。

我这边的约束

  • macOS,fastboot 37.0.1。工具的 .bat 跑不了,但每一步都是普通命令, 自己照着走反而更可控,每步都能核对。
  • 解锁后手机必定无法开机,得刷全量包。所以线刷包是硬前置—— houji_images_OS3.0.7.0.WNCCNXM_20260127.0000.00_16.0_cn_098178eaeb.tgz,9.6 GB, 刷同版本以保持 anti 不变。
  • 数据没备份(用户选择不要),接受清空。

弯路一:内核 exploit 打不上

按「高版本」分支推 exploit 上去跑,输出一路在换 phyaddr 猜 GPU 读写地址, 偶尔 found it 又 Fail second read value,最后打印 can't get GPU r/w 收工。 su -c id 回的还是 uid=2000(shell),getenforce 仍是 Enforcing—— 补丁没打上,内核构建对不上。

没在这上面死磕。这条路本来只是「拿到 root」的手段之一,而 root 还有另一条: miui.mqsas.IMQSNative 服务的 method 21 能以 uid=0 执行任意命令。 它在 enforcing 下也被 SELinux 卡着,所以先制造宽松环境:

adb reboot bootloader
fastboot oem set-gpu-preemption-value 0 androidboot.selinux=permissive
fastboot continue

set-gpu-preemption-value 的参数不做过滤,androidboot.selinux=permissive 被原样拼进内核 cmdline。这条注入不持久,每次重启都得来一遍。

起来之后 getenforce 是 Permissive,mqsas 调用正常返回 root:

adb shell 'service call miui.mqsas.IMQSNative 21 i32 1 s16 "id" i32 1 s16 "" \
  s16 "/data/local/tmp/out.txt" i32 5'
# 结果是 root 所有、0600,还得自己 chmod 才能读

到这一步 root 有了。注意 mqsas 的 stdout 落在 root 0600 的文件里, 直接 cat 会被 DAC 挡掉,得再用 mqsas 自己 chmod 644 一次。

写 abl

写之前先把当前 abl_b 整份 dump 出来当参照,再跟仓库里三月份的同机 dump 比对—— 字节完全一致,说明读取路径忠实、这半年也没被 OTA 动过。写进 abl_a 再读回、 比对 sha256,确认无误才动 abl_b:

adb shell 'service call miui.mqsas.IMQSNative 21 i32 1 s16 "dd" i32 1 s16 \
  "if=/data/local/tmp/abl.elf of=/dev/block/by-name/abl_a bs=4096 conv=fsync" \
  s16 "/data/local/tmp/dd.log" i32 60'

回读校验:c26711cf…d2ddde,一致。abl_b 同样。工具给的 abl 有 236372/241464 字节和原来不同,是另一份构建,不是小补丁。

刷引导链

重启进 fastboot 后先用 fastboot erase frp 探一下——能过就说明外壳 ABL 被接受了, 过不了就该停下。然后整包刷进去,结尾 fastboot set_active a。

接着换 GPT:

fastboot flash partition:4 main/houji/gpt_both4.bin

partition:4 是物理 LUN 写法。fastboot getvar partition-size:4 查不到 (会回 GetVar Variable Not found),但 flash partition:4 是通的, fastboot 37 也没问题,不用为这个去开 Windows 虚拟机。

fastboot boot main/Unlocking-SM8650.img

屏幕花屏然后黑掉,是正常的。等十秒左右按住电源 + 音量减强制重启回 fastboot, 然后:

$ fastboot getvar unlocked
unlocked: yes

接着把官方 GPT 换回去,getvar unlocked 复查仍是 yes——锁状态落在 RPMB, 跟分区表无关。

刷系统

fastboot continue 这时会 Failed to load image from partition: Load Error, 因为外壳是旧的、system 还是新的。刷全量包收尾。

macOS 上跑 flash_all.sh 有两个坑:

  1. 它用 grep -oP 取 anti,macOS 的 grep 没有 -P,解析成空、ver=0, 那道 anti 回滚闸门等于被静默跳过。得手动 fastboot getvar anti 核对—— 我这边 anti: 1,包的 anti_version.txt 也是 1,相等,可刷。
  2. fastboot $* 支持透传,所以 bash flash_all.sh -s <serial> 能指定设备。

29 个分区加 super/userdata/boot/vbmeta 全部成功,0 报错。 别碰 flash_all_lock.sh,那会把 BL 重新锁上。

开机后 verifiedbootstate 变 orange、flash.locked=0。

弯路二:KernelSU 刷错分区

解锁了就想上 KernelSU。手上有官方 ksud(有 macOS 版),本地 patch,不依赖第三方 patched 镜像:

./ksud boot-patch -b images/boot.img --kmi android14-6.1 --allow-shell \
  -o . --out-name patched_boot.img

--kmi 只写 KMI,不要带 arch 前缀,否则会去找 aarch64/aarch64/... 而报 asset not found。 -o 要的是目录,不是文件路径。

刷完重启,管理器里却是 Not installed,也没有 su。

原因是这机器是带 init_boot 的 GKI 机型:ramdisk 在 init_boot, ksud 那句 No ramdisk, create by default 往 boot.img 里塞的 ramdisk 根本没人读。 改成只打 init_boot、boot 用原厂:

fastboot flash boot_ab images/boot.img
fastboot flash init_boot_ab patched_init_boot.img
fastboot --disable-verity --disable-verification flash vbmeta_ab images/vbmeta.img

弯路三:LKM 加载了,但没人信

再来一次,管理器还是 Not installed、su 还是没有。这时候容易误判成模块没加载, 但内核日志里已经有 KernelSU: hook_manager、packages.list detected、 handle_setresuid,/data/adb/ksu 也被 ksuinit 建出来了。

真相是:内核侧活着,缺的是用户态。管理器那个 Install 按钮干的就是这件事, 可它自己没 root 干不了。既然已经有 root,直接顶上:

adb shell 'service call miui.mqsas.IMQSNative 21 i32 1 s16 "/data/adb/ksud" \
  i32 1 s16 "install" s16 "/data/local/tmp/i.txt" i32 30'

之后 su -c id → uid=0(root),context u:r:ksu:s0,管理器变成绿色的 Working / LKM。重启后 SELinux 自己回到 Enforcing,root 不掉。

顺带一个观察:/sys/module/kernelsu 压根不存在,别拿它当「模块是否加载」的判据。

收尾

adb shell pm uninstall --user 0 com.android.updater

小米在中国区是强制静默更新的,关掉自动更新也没用,必须把更新器摘掉。 之后别点系统更新,钉死在 3.0.7.0 / 2026-02。

代价是清楚的:数据清空;tz、keymint、uefisecapp 被换成旧版,TEE 得重新 provision, 指纹要重录、公交卡和门禁要重开、Widevine 大概掉 L3、银行和 Google Pay 受限。 保内变砖就说「一觉醒来不开机」,别提刷机。

恢复镜像(原厂 boot/init_boot/vbmeta 和打过 KSU 的 init_boot,带 SHA256SUMS) 留在本机,取消 root 就是刷回原厂 init_boot,不用重新下 9.6 GB。

参考

  • AdaUnlocked/2026-All-Brands-Bootloader-Unlock-Status:各厂锁状态与封堵版本,更新很勤
  • c8e-3d1a/2026-Xiaomi-Bootloader-Unlock-Tool-by-JiGuang-...:工具归档
  • hicode002/qualcomm_gbl_exploit_poc:GBL / VBRwDeviceState / RPMB / milestone 的原理与验证
  • tiann/KernelSU:ksud boot-patch 与 ksud install