裝置是 myron,POCO F8 Ultra / Redmi K90 Pro Max,Snapdragon 8 Elite Gen 5。我手上有兩支。第一支是臺版,第二支也是臺版——會買第二支,就是因為第一支的 root 死活做不出來。
2026 年 7 月 7 日,Nebula Security 公開了 GhostLock(CVE-2026-43499):Linux 核心 futex PI requeue 路徑的 use-after-free,2011 年就存在,影響幾乎所有核心,公開 exploit 成功率 97%,還是 Google kernelCTF 強制公開的那種。大陸社群反應很快,幾天內各機型的偏移量就算好了,包成 payload 在酷安到處發。K90 Pro Max 的現成品一堆。
我的臺版,全部不能用。
十幾天的嘗試、AI 陪跑三天三夜,都算不出來。最後我放棄,買了第二支手機走另一條路。直到這個月回頭拆開三個 ROM,才看到答案:同一支手機、同一個 codename,臺版和陸版的核心根本不是同一顆 binary。而那些 payload 寫死的,恰恰是跟著 binary 走的東西。
三個 ROM,三顆核心
手上的 ROM:臺版 3.0.1.0(出廠版本)、臺版 3.0.6.0、xiaomi.eu 306 和 308(陸版底)。把 boot.img 解開,先看核心版本字串:
| ROM | uname -r | 編譯時間 |
|---|---|---|
| 臺版 3.0.1.0.WPMTWXM | ...-ga5f232d1ead0-ab14083253-4k |
2025-09-11 |
| 臺版 3.0.6.0.WPMTWXM | ...-g5a0e85dd9db0-ab14499855-4k |
2025-11-26 |
| 陸版 306/308.WPMCNXM | ...-g16e473de48a3-abogki462654244-4k |
2025-11-19 |
base 都是 6.12.23-android16-5,但 git commit 三個都不同。更關鍵的是 build ID:陸版是 abogki 開頭,代表它貼著 Google 官方 GKI release 分支走;臺版是 ab1xxxxxxx,小米自己的整合分支自己編。
接著把三顆核心的 kallsyms 整個抽出來,各約 12.5 萬個符號,直接對:
| 符號 | 臺版(兩版相同) | 陸版 | 差距 |
|---|---|---|---|
init_task |
...823ecf00 |
...823fcf00 |
+0x10000 |
init_cred |
...82402a68 |
...82412a68 |
+0x10000 |
selinux_state |
...826684f0 |
...8267a5b8 |
+0x120c8 |
random_table |
三版全不同 | — | — |
注意 selinux_state 那行:差距是 0x120c8,不是跟別人一樣的 0x10000。這代表不是整體平移,是符號配置真的被洗亂了。而且連臺版自己 3.0.1 升 3.0.6,rt_mutex 那幾個漏洞相關函數的位置都已經換過。config 也有差:陸版多開了七個 XIAOMI_* 選項。
為什麼偏移量不能共用
GhostLock 是 data-only exploit。它要的不是 shellcode,是「這一次編譯出來的 init_cred 在哪個位址」。十幾個位址,寫死在 payload 裡。
我用核心內嵌的 BTF 把三版的 struct 布局整個解析出來:task_struct 都是 5184 bytes,cred 都在 0x900,pi_blocked_on 都在 0xA18,一個 byte 都沒差。也就是說,觸發邏輯通用、結構欄位通用,唯一不通用的就是那張位址表。
但 exploit 沒有那張表就是打空氣。打錯位址,最好的情況是沒反應,常見的情況是 kernel panic 直接重開機。
所以結論很硬:所有為陸版 ogki 核心算的 payload,在臺版核心上永遠是錯的。不是小米故意擋,是兩條發版線本來就各編各的——陸版追官方 GKI 分支求快,國際版有自己的 patch queue 和認證凍結點,加上全部用 +pgo +bolt +lto 編譯,PGO/BOLT 會依 profiling 重排函數位置,任何一點程式碼差異都會把符號表整個洗亂。會被這件事打到的人,在小米的使用者統計裡小到不存在,所以永遠不會有人有動機對齊。
我付過的三種成本
回頭看,當時擺在面前的是三條路:
蹲官方解鎖名額。 小米國際版每天零點放名額,限量,跟你競爭的是一堆腳本。今晚蹲不到,明天再蹲。成本是健康,無上限,而且付了不保證有。我的身體狀況熬夜不了,這條路對我來說等於不存在。
算臺版偏移。 成本是時間。十幾天沒結果,AI 陪跑三天三夜也沒出來。當時等於無解。
買第二支。 成本是錢,一次性,確定性交付。兩支加起來四萬六,後來第一支便宜賣給家人,回收一萬五,淨成本三萬一。
順帶一提過程裡的另一個變數:美國的模型看到 kernel exploit 就拒絕幫忙,不管你的理由是「自己的手機、要做無障礙工具、漏洞已公開」。最後是 DeepSeek 陪我耗那三天三夜。願意和能夠,是兩個獨立的軸。
事後檢討這個決策:用當時掌握的資訊,買手機是對的——三個選項裡唯一成本可預測的。但誠實說,這筆錢有一部分是知識溢價。解法當時就存在,只是我和陪我的 AI 都不知道那條路。
三天三夜和半小時的差別,不是算力,是路線
當年卡死的原因是:想在沒有 root 的手機上,從執行期 leak 出符號位址。那是難路,要靠側信道、要靠運氣。
這次走的路是靜態的:ROM 本來就躺在我自己的 Downloads 裡。boot.img 解開,完整 kallsyms 就在裡面,12.5 萬個符號全部直接可讀。不需要 root、不需要 leak、不需要運氣。
而且靜態路線還有一個意料之外的好處:乾淨。我第二支手機後來刷了第三方核心、套了 KSU,從實機 dump 出來的 kallsyms 已經是被改過的。ROM 裡的 boot.img 才是沒被汙染的 ground truth。
只抽符號還不夠,還要證明抽出來的是對的。交叉驗證的做法是:用抽出來的位址,回讀 binary 裡對應位置的內容——init_task 的 comm 欄位讀出來要是「swapper」、init_cred 的 usage 要是個小整數、init_uts_ns 的 release 欄位要逐字元等於這顆核心的 uname 字串。三個獨立來源(kallsyms 提取、BTF 欄位、原始 binary)互相對得上,臺版和陸版各自驗證都通過。到這裡,不需要實機就能信任這份偏移。
後面的組裝就很順:以 ghostlock-oneplus 為底加一個臺版 target,它內建的 struct 偏移跟我從 BTF 算的逐欄吻合;反組譯確認 pselect 的棧配置,跟已驗證可行的 Xiaomi 17 完全相同;NDK 一次編過,零警告。
從動手到編出 binary,半小時。
放出來,以及放出來的方式
東西在 github.com/jason5545/ghostlock-myron-tw:臺版偏移表、分析、編好的 binary,還有把我這次整套流程工具化的三支腳本——抽偏移、驗 struct、驗棧配置,都內建「驗證不過就不准用」的檢查。
刻意沒放的東西:小米的專有韌體、別人的 EFI 工具、FRP 相關的步驟。原因是看過前車之鑑:之前有一套同類的一鍵解鎖工具,作者的封存公告寫得很直白——極大比例的使用者拿它只是為了跑遊戲外掛,還有人拿去收錢代刷、自己不懂原理把客戶手機刷成磚,最後一個學生開發者被白嫖到心累收攤。一鍵包養出那種生態,所以我發的是教科書,不是槍。會自己編譯的人,就是這些東西該到的人手上;「要自己編」這道門檻,恰好就是過濾器。
還有一個已知限制:這份偏移只覆蓋 WPMTWXM。MIXM、EUXM 這些其他區域版本,核心可能又不同。但方法是可以帶走的,工具都公開了,任何冷門區域版本的持有者都能自己產生他那份表。
卡我最久的,不是技術難度
第一支手機現在在家人手上,我故意讓它停在 3.0.6.0 沒更新。這次編出來的東西,就是要拿去救它的。
回頭看整件事,最貴的從來不是漏洞本身。是「會算偏移的人都在陸版」這個結構:漏洞在臺版核心裡躺著,會躺到 OTA 修補把它關掉為止,期間不會有人碰它,因為沒有人有動機為小眾區域版本算那張表。如果不是這次自己拆,臺版大概永遠不會有人解。
知識不對稱的價格,是一支手機。現在臺版的表算出來了、工具也公開了,這個結構裡至少少一個要付這筆錢的人。