1. 程式人生 > >可怕!CPU竟成了黑客的幫凶!

可怕!CPU竟成了黑客的幫凶!

`本故事根據CPU真實漏洞改編` ## 前情回顧 還記得我嗎,我是阿Q,就是那個CPU一號車間的阿Q啊。如果你忘記了我,記得看看這裡回憶一下哦:[完了!CPU一味求快出事兒了!](https://mp.weixin.qq.com/s/5_JN7trS_lS3Nnw5u12p6g) 自從我們車間用上了`亂序執行`和`分支預測`後,生產效率那是大大提升,領導不僅在全廠的員工大會表揚了我們,還把這兩項技術向全廠推廣,在我們8個CPU核心車間都鋪開了,效能甩開競爭對手CPU幾條街。 可是,就在我們還沉醉在取得的成績時,不知不覺我們竟埋下了災難的種子······ ![](https://imgkr.cn-bj.ufileos.com/e1b88034-76fd-435d-a94e-76352a135b6b.png) 事情還得從不久前的一個晚上說起。 ## 神祕程式碼 這天晚上,我們一號車間遇到了這樣一段程式碼: ```cpp uint8_t array1[160] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; uint8_t array2[256 * 512]; uint8_t temp = 0; void bad_guy(int x) { if (x < 16) { temp &= array2[array1[x] * 512]; } } ``` 不到一會兒功夫,我們就執行了這個`bad_guy()`函式很多次,這不,又來了。 負責取指令的小A向記憶體那傢伙打了一通電話,讓記憶體把引數x的內容傳輸過來,我們知道,以記憶體那蝸牛的速度,估計得讓我們好等。 這時,負責指令譯碼的小胖忍不住說了:“你們看,我們這都執行這個函式好多次了,每次的引數x都是小於16的,這一次估計也差不多,要不咱們啟動`分支預測`功能,先把小於16分支裡的指令先提前做一些?大家看怎麼樣” ![](https://imgkr.cn-bj.ufileos.com/b17a4960-5d71-4d43-8879-5744b3ba85ae.png) 我和負責資料回寫的老K互相看了一眼,都點頭表示同意。 於是,就在等待的間隙,我們又給記憶體那傢伙打了電話,讓他把`array1[x]`的內容也傳過來。 等了一會兒,資料總算傳了過來: ``` x: 2 array1[x]: 3 ``` 拿到結果之後,我們開始一邊執行`x<16`的比較指令,一邊繼續打電話給記憶體索要`array2[3]`的內容。 比較指令執行的結果不出所料,果然是`true`,接下來就要走入我們預測的分支,而我們提前已經將需要的資料準備到快取中,省去了不少時間。 就這樣,我們成功的預測了後續的路線,我們真是一群機智的小夥伴。 ![](https://imgkr.cn-bj.ufileos.com/d94da529-e7c2-4b57-b36a-6a512f21e45f.png) ## 遭遇滑鐵盧 天有不測風雲,不久,事情發生了變化。 “呀!比較結果是`false`,這一次的x比16大了”,我執行完結果後發現和我們預期的有了出入。 小A聞訊而來,“額,咱們提前執行了不該執行的指令不會有問題吧?” ![](https://imgkr.cn-bj.ufileos.com/422adff8-7da4-437e-b52e-7413107e1d27.png) 老K安慰道:“沒事兒,咱們只是提前把資料讀到了我們的快取中,沒問題的,放心好啦” 我想了想也對,大不了我們提前做的準備工作白費了,沒有多想就繼續去執行>16的分支指令了。 隨後,同樣的事情也時有發生,漸漸的我們就習慣了。 ## 災難降臨 夜越來越深,我們都有點犯困了,突然,領導來了一通電話,讓我們放下手裡的工作火速去他辦公室。 我們幾個不敢耽誤,趕緊出發。 來到領導的辦公室,裡面多了兩個陌生人,其中一個還被綁著,領導眉頭緊鎖,氣氛很是緊張。 ![](https://imgkr.cn-bj.ufileos.com/fd43c572-9d5c-4a05-8bc1-51898a2d689f.png) “阿Q啊,你知不知道你們新發明的`亂序執行`和`分支預測`技術闖了大禍了?” 我們幾個一聽傻眼了,“領導,這是從何說起啊?” 領導從椅子上站了起來,指著旁邊的陌生人說到:“給你們介紹一下,這是作業系統那邊過來的安全員,讓他告訴你們從何說起吧!” 這位安全員向大家點了點頭,指著被捆綁那人說道:“大家好,我們抓到這個執行緒在讀取系統核心空間的資料,經過我們的初審,他交代了是通過你們CPU的`亂序執行`和`分支預測`功能實現的這一目的。” 我和小A幾個一聽都是滿臉問號,我們這兩個提升工作效率的技術怎麼就能洩漏系統核心資料呢? ![](https://imgkr.cn-bj.ufileos.com/c2dfd5c2-c2f1-4fb6-8485-57f2a496891e.png) ## 真相大白 安全員顯然看出了我們的疑惑,指著被捆綁的那個執行緒說道:“你把之前交代的再說一遍” “幾位大爺,你們之前是不是遇到了分支預測失敗的情況?”,那人抬頭看著我們。 “有啊,跟這有什麼關係?失敗了很正常嘛,既然是預測那就不能100%打包票能預測正確啊”,我回答道。 “**您說的沒錯,不過如果這個失敗是我故意策劃的呢?**” ![](https://imgkr.cn-bj.ufileos.com/74d82f18-936f-4ea2-b915-60ad4bfec542.png) 聽他這麼一說,我的心一下懸了起來,“納尼,你乾的?” “是的,就是我,我先故意給你連續多次小於16的引數,誤導你們,誤以為後面的引數還是小於16的,然後突然來一個特意構造的大於16的引數,你們果然上鉤了,預測失敗,提前執行了一些本不該執行的指令。” “那又如何呢?我們只是把後面需要的資料提前準備到了快取中,並沒有進一步做什麼啊”,我還是不太明白。 “**這就夠了!**” “你小子都被捆上了,就別吊胃口了,一次把話說清楚”,一旁急性子的老K忍不住了。 ![](https://imgkr.cn-bj.ufileos.com/36498026-2263-4b75-8cdc-042fe4f071f2.png) “好好好,我這就交代。你們把資料提前準備到了快取中,我後面去訪問這部分資料的時候,發現比訪問其他記憶體快了很多” “那可不,我們的快取技術可不是吹牛的!哎等等,怎麼又扯到快取上去了?”,老K繼續問道。 那人繼續說道:“**如果我想知道某個地址單元內的值,我就以它作為陣列的偏移,去訪問一片記憶體區域。利用你們會提前預測執行而且會把資料快取的機制。你們雖然預測失敗了,但對應的那一塊資料已經在快取中了,接著,我依次去訪問那一片記憶體,看看誰的訪問時間明顯比其他部分短,那就知道哪一塊被快取了,再接著反推就能知道作為偏移的數值是多少了**,按照這個思路我可以知道每一個地址單元的內容” ![](https://imgkr.cn-bj.ufileos.com/9ef6ece7-2545-48bf-9fe6-1cda126718ae.png) 我們幾個一邊聽著一邊想著,琢磨了好一會兒總算弄清楚了這傢伙的套路,老K氣得火冒三丈,差點就想動手修理那人。 “好你個傢伙,倒是挺聰明的,可惜都不用在正途上!好好的加速優化機制竟然成為了你們的幫凶”,我心中也有一團火氣。 ## 亡羊補牢 事情的真相總算弄清楚了,我們幾個此刻已經汗流浹背。 經過和安全員的協商,作業系統那邊推出了全新的`KPTI`技術來解決這個問題,也就是`核心頁表隔離`。 ![](https://imgkr.cn-bj.ufileos.com/97d2aed0-962c-4b3f-8fb1-5251e2383506.png) 以前的時候,執行緒執行在使用者態和核心態時用的是同一本地址翻譯手冊,也就是人們說的`頁表`,通過這本手冊,我們CPU就能通過虛擬地址找到真實的記憶體頁面。 現在好了,讓執行緒執行在使用者態和核心態時使用不同的手冊,使用者態執行緒的手冊中,核心地址空間部分是一片空白,來一招釜底抽薪! 本以為我們可以回去了,沒想到領導卻給我們出了難題,“這禍是你們闖下的,人家作業系統那邊雖然做了保護,你們是不是也該拿出點辦法來呢,要不然以後我們CPU還怎麼抬得起頭來?” 你有什麼好辦法嗎,幫幫我們吧! ## 幕後 >
本文描述的是兩年前爆發的大名鼎鼎的CPU的`熔斷`與`幽靈`漏洞。 > > `亂序執行`與`分支預測`是現代處理器普遍採用的優化機制。和傳統軟體漏洞不同,硬體級別的漏洞影響更大更深也更難以修復。 > > 通過判斷記憶體的訪問速度來獲知是否有被快取,這類技術有一個專門的術語叫`側通道`,即通過一些場外資訊來分析得出重要結論,進而達成正常途徑無法達成的目的。 > > 後面的文章中此類手法的故事還將繼續上演,敬請期待! `特別鳴謝:網友幾多風雨勁提供的技術支援` ## 往期熱門回顧 [完了!CPU一味求快出事兒了!](https://mp.weixin.qq.com/s/5_JN7trS_lS3Nnw5u12p6g) [雜湊表哪家強?幾大程式語言吵起來了!](https://mp.weixin.qq.com/s/h0FqX9AZByfpgUZrsRVTWg) [核心地址空間大冒險4:執行緒切換](https://mp.weixin.qq.com/s/v6nc9aIBY_R1S6ToPzj5Qg) [震撼!全網第一張原始碼分析全景圖揭祕Nginx](https://mp.weixin.qq.com/s/XrtH9-Eo7pzJu-Fzt89voQ) [一個整數+1引發的災難](https://mp.weixin.qq.com/s/gZPxqZzY2rnngxvvzexWTw) [一網打盡!每個程式猿都該瞭解的黑客技術大彙總](https://mp.weixin.qq.com/s/V7wBdl-5W4ehTAnACQFjGQ) [看過無數Java GC文章,這5個問題你也未必知道!](https://mp.weixin.qq.com/s/Bb2ugXYPR6r11QaGKbNBSw) [一個Java物件的回憶錄:垃圾回收](https://mp.weixin.qq.com/s/xp2S4_3UQTZ0TOIlVqM8uw) [誰動了你的HTTPS流量?](https://mp.weixin.qq.com/s/lxpHhHVIh6DktoHzrRLaKA) [路由器裡的廣告祕密](https://mp.weixin.qq.com/s/7gM31s4-hTJTprJnxsHgEA) [一個HTTP資料包的奇幻之旅](https://mp.weixin.qq.com/s/suzicCzb2g5b8NN71S5Ngw) [我是一個流氓軟體執行緒](https://mp.weixin.qq.com/s/-ggUa3aWkjjHjr9VwQL9TQ) ![](https://imgkr.cn-bj.ufileos.com/62b181b0-cb63-47a0-b836-131de3a562c7.png) ![](https://imgkr.cn-bj.ufileos.com/06d25f4e-bd38-404b-a901-173737bb7ccf.png)