救回"开机后所有应用无响应"的一键脚本:系统正常进桌面,但点任何应用都提示"重启后需等待应用响应,请稍后再试",锁屏也不再弹出。
起因是有人的 recovery 在解密时触发了 KeyMint 密钥升级但没把新 blob 写回,重启后整部手机的应用全部瘫痪,最后靠换用备用钥匙救了回来。这个脚本把那次手动救援自动化了。原理通用,适用于所有 FBE(文件级加密)设备,即 Android 10 以上的主流机型。
锁屏密码本身并不直接加密数据。系统用 Synthetic Password(SP)保护凭据加密区(CE),SP 再由 KeyMint 密钥包裹,存在 /data/system_de/<uid>/spblob/ 下。一台机器通常同时存两把保护钥匙:
- weaver:走安全芯片,防暴力破解,平时主力
- secdis:软件回退路径,备用
每把 KeyMint 密钥 blob 里封印着生成时的环境(Android 版本、安全补丁级别)。当用一个比封印环境更新的环境去 begin() 这把钥匙时,KeyMint 会自动"升级"blob,同时安全芯片立刻把旧 blob 永久作废——升级后的新 blob 必须写回 keystore 数据库,否则升级就等于销毁。
典型的翻车场景:某个 recovery 把 keystore 数据库复制到内存盘里跑,或者干脆伪装了版本/补丁级别。解密当时"成功"了,但升级后的新 blob 随内存盘消失,磁盘上的旧 blob 已是尸体。重启后系统解不开 CE,锁屏服务认为设备未锁,于是所有应用卡在"等待应用响应"。
本脚本做的事只有一件:spblob 目录里的 handle 文件决定系统用哪一把钥匙。把它指向还活着的另一把,回系统用原来的锁屏密码解一次,CE 就回来了。
- 进 TWRP(或任意有 root shell 的 recovery),连 USB
- Windows 双击
rescue.cmd;Linux/macOS 运行./rescue.sh - 脚本列出当前和备用钥匙,输入
YES确认后写入(自动备份原 handle) - 重启进系统,用原来的 PIN/图案/密码解锁一次
成功的话应用立即恢复,数据完整。
切换完全可逆。原件备份在 /data/system_de/<uid>/spblob/handle.rescue.bak,回退方式:
./rescue.sh restore
也可以多次来回切换尝试不同的备用钥匙。
- 备用钥匙也死了就救不回来,只能回备份或格式化 data
- 脚本会拒绝在正常启动的 Android 系统里运行(运行中的 locksettings 服务缓存了状态,必须 offline 改)
- 只救"钥匙失效"这一种故障;如果提示的是密码错误,那是另一回事
在 recovery 里做 FBE 解密时:
- 读不到已安装系统的真实版本/补丁级别就终止解密,不要拿 recovery 自己的属性兜底
- keystore2 要么直接跑真数据库(升级落盘是无害的正常行为),要么把升级后的 blob 写回去
- 不要在失败重试时来回切换 KeyMint 环境,一次错误环境就可能永久毁掉一把钥匙
One-click rescue for Android devices that boot fine but show "app not responding, wait after reboot" for every app: the KeyMint key blob wrapping the synthetic password was invalidated (typically by a recovery that upgraded the blob in a mismatched environment and lost the upgraded copy), so credential-encrypted storage never unlocks. spblob-rescue.sh runs in recovery and repoints /data/system_de/<uid>/spblob/handle at the still-valid sibling protector (weaver/secdis). Reboot, unlock once with your normal PIN/pattern/pattern, done. Fully reversible via rescue.sh restore.
MIT