我們知道,我們平時編程寫的高級語言,是經過編譯器編譯以后,變成了CPU可以執行的機器指令:
而CPU能支持的指令,都在它的指令集里面了。很久以來,我都在思考一個問題:CPU有沒有未公開的指令?或者說:CPU有沒有隱藏的指令?為什么會有這個問題?平常我們談論網絡安全問題的時候,大多數時候都是在軟件層面。談應用程序的漏洞、后端服務的漏洞、第三方開源組件的漏洞乃至操作系統的漏洞。但很少有機會去觸及硬件,前幾年爆發的熔斷和幽靈系列漏洞,就告訴我們,CPU也不是可信任的。要是CPU隱藏有某些不為人知的指令,這是一件非常可怕的事情。如果某一天,某些國家或者某些團體組織出于某種需要,利用這些隱藏的指令來發動攻擊,后果不堪設想。雖然想到過這個問題,但我一直沒有付諸實踐去認真的研究。直到前段時間,有一位老師分享了一份PDF給我,解答了我的疑惑。這份PDF內容是2017年頂級黑客大會Black Hat上的一篇報告:
這份PDF深度研究了x86架構CPU中隱藏的指令,原報告因為是英文,看起來有些晦澀,這篇文章,我嘗試用大家易懂的語言來給大家分享一下這篇非常有意思的干貨。有些人會問:真的會有隱藏指令的存在嗎,CPU的指令集不是都寫在指令手冊里了嗎?我們以單字節指令為例,單字節的范圍是0x00-0XFF,總共256種組合,Intel的指令手冊中是這樣介紹單字節指令的:
橫向為單字節的高四位,縱向為單字節的低四位,順著表格定位,可以找到每一個單字節指令的定義。比如我們常見的nop指令的機器碼是0x90,就是行為9,列為0的那一格。但是不知道你發現沒有,這張表格中還有些單元格是空的,比如0xF1,那CPU拿到一個為0xF1的指令,會怎么執行呢?指令手冊沒告訴你。這篇報告的主要內容就是告訴你,如何去尋找這些隱藏的指令。
該算法的指導思想在于:快速跳過指令中無關緊要的字節。
怎么理解這句話?比如壓棧的指令push,下面幾條雖然字節序列不同,但變化的只是數據,其實都是壓棧指令,對于這類指令,就沒必要花費時間去遍歷:
觀察指令中的有意義的字節,它們對指令的長度和異常表現會產生沖擊。又該怎么理解這句話?還是上面那個例子,當嘗試修改第一個字節68的時候,這一段二進制序列可能就完全變成了別的指令,甚至指令長度都會發生變化(比如把68改成90,那就變成了一個字節的nop指令),那么就認為這第一個字節是一個有意義的字節,修改了它會對指令的長度產生重要影響。反之,如果修改后面字節的數據,會發現這仍然是一條5個字節的壓棧指令,長度沒變化,也沒有其他異常行為表現與之前不同,那么就認為后面幾個字節是無關緊要的字節。在這個指導思想下,我們來看一個例子:從下面這一段數據開始出發:
我們從兩個字節的指令開始遍歷:
把最后那個字節的內容+1,嘗試去執行它:
發現指令長度沒有變化,那就繼續+1,再次嘗試執行它:
一直這樣加下去,直到發現加到4的時候,指令長度發生了變化,長度超過了2(但具體是多少還不知道,后文會解釋):
那么在這個基礎上,長度增加1位,以指令長度為3的指令來繼續上面的探索過程:從最后一位開始+1做起。
隨著分析的深入,梳理一下指令搜索的路徑圖:
當某一條的最后一個字節遍歷至FF時,開始往回走(就像遞歸,不能一直往下,總有回去的時候):
往回走一個字節,將其+1,繼續再來:
按照這個思路,整個要搜索的指令空間壓縮到可以接受遍歷的程度:![5c81a9c0-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l6ABkvQAABkkeTrrW8426.png)
可能第一個字節0F就是一條指令。也可能前面兩個字節0F 6A是一條指令。還可能前面五個字節0F 6A 60 6A 79 6D是一條指令。到底是什么情況,我們不知道,讓我們用程序來嘗試推導出來。準備兩個連續的內存頁面,前面一個擁有可執行的權限,后面一個不能執行。
記住:當CPU發現指令位于不可執行的頁面中時,它會拋異常!現在,在內存中這樣放置上面的數據流:第一個字節放在第一個頁面的末尾位置,后面在字節放在第二個不可執行的頁面上。
然后JMP到這條指令的地址,嘗試去執行它,CPU中的譯碼器開始譯碼:
譯碼器譯碼發現是0F,不是單字節指令,還需要繼續分析后面的字節,繼續取第二個字節:
但注意,第二個字節是位于不可執行的頁面,CPU檢查發現后會拋出頁錯誤異常:
如果我們發現CPU拋了異常,并且異常的地址指向了第二個頁面的地址,那么我們可以斷定:這條指令的長度肯定不止一個字節。
既然不止一個字節,那就往前挪一下,放兩個字節在可執行頁面,從第三個字節開始放在不可執行頁面,繼續這個過程。
繼續上面這個過程,放三個字節在可執行頁面:
四個:
當放了四個字節在可執行頁面之后,事情發生了變化:指令可以執行了!雖然也拋了異常(因為天知道這是個什么指令,會拋什么異常),但頁錯誤的地址不再是第二個頁面的地址了!
有了這個信號,我們就知道,前面4個字節是一條完整的指令:![5e26b680-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mCAczdRAACL6nojpVw515.png)
挖掘成果,收獲頗豐:![5e81527a-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mGAfa5NAABkdjIJcdY253.png)
這些都是Intel指令集手冊中未交待,但CPU卻能執行的指令。然后是AMD Athon的CPU:
挖掘成果:
那這些隱藏的指令是做什么的呢?有些已經被逆向工程分析了。還有的就是毫無記錄,只有Intel/AMD自己人知道了,誰知道它們用這些指令是來干嘛的?軟件即便是開源都能爆出各種各樣的問題,何況是黑盒一樣的硬件。CPU作為計算機中的基石,它要是出了問題,那可是大問題。我不是陰謀論,害人之心不可有,但防人之心不可無。看完這些,我對國產、安全、自主可控這幾個字的理解又加深了一層。
![5a0e623c-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_luAM8aTAAA1_JA4Ss0037.png)
《us-17-Domas-Breaking-The-x86-ISA》
,作者是大神:@xoreaxeaxeax
,熟悉匯編的同學知道這名字是什么意思嗎?![5a9e36be-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_luAK3HQAAF-xnveFGI852.png)
![5ad4e8ee-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_luAbheFAAFrUgEKawU371.png)
指令集的搜索空間
想要找到隱藏的指令,得先明確一個問題:一條指令到底有多長,換句話說,有幾個字節,我們應該在什么樣的一個范圍內去尋找隱藏指令。如果指令長度是固定的,比如JVM那樣的虛擬機,那問題好辦,直接遍歷就行了。但問題難就難在,x86架構CPU的指令集屬于復雜指令集CISC,它的指令不是固定長度的。有單字節指令,比如:90 nopCC int 3C3 ret也有雙字節指令,比如:
8B C8 mov ecx,eax6A 20 push 20h還有三四節、四字節、五字節···最長能有十幾個字節,比如這條指令:
指令:lock add qword cs:[eax + 4 * eax + 07e06df23h], 0efcdab89h機器碼:2e 67 f0 48 818480 23df067e 89abcdef一個字節、兩個字節,甚至三個四個遍歷都還能接受,4個字節最多也就42億多種組合,對于計算機來說,也還能接受。但越往后,容量是呈指數型增長,這種情況再去遍歷,顯然是不現實的。
指令搜索算法
這份報告中提出了一種深度優先的搜索算法:![5b0d9d60-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_luAD3erAAAMKzRRGUA467.png)
![5b20ce3a-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_lyATs1NAAAn5Yrg3RU048.png)
第一個字節68就是關鍵字節,后面的四個字節都是壓入棧中的數據,就屬于無關緊要的字節。如果能識別出這類,快速跳過,將能夠大面積減少需要遍歷的搜索空間。上面只是一個例子,如何能夠系統化的過濾掉這類指令呢?報告中提出了一個方案:
- 68 6F 72 6C 64 push 646C726Fh
- 68 6F 2C 20 77 push 77202C6Fh
- 68 68 65 6C 6C push 6C6C6568h
![5b4bd922-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_lyAbw1wAABTvHCaozo801.png)
![5b77483c-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_lyAeWqfAAAfJE-rtLY199.png)
![5b877360-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_lyAbFVQAABMz8AOPkI567.png)
![5b970866-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_lyAG-ELAABH9Rz6Qm0748.png)
![5ba819c6-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l2AGxKoAABPFiFG818903.png)
![5bcbc2d6-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l2AStkvAABYbV-18lk161.png)
![5bdd47ea-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l2AIOz7AABNzq5gNbM560.png)
![5c09b56e-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l2ASlcdAAFvb1uqu3w166.png)
![5c3b728e-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l6AXUpsAABX4LC4JmU505.png)
![5c513330-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l6APgEmAABK90aFNtI108.png)
![5c81a9c0-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l6ABkvQAABkkeTrrW8426.png)
如何判定指令長度
現在來解答前面遺留的一個問題。上面這個算法能夠工作的一個重要前提是:我們得知道,給末尾字節+1后,有沒有影響指令的長度。要判斷某個字節是不是關鍵字節,就得知道這個字節的內容變化,會不會影響到指令長度,所以如果無法判斷長度有沒有變化,那上面的算法就無從談起了。所以如何知道長度有沒有變化呢?報告中用到了一個非常巧妙的方法。假設我們要評估下面這一串數據,前面開頭到底多少個字節是一條完整指令。![5cb11408-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l6AYr0LAAB3q7SFCDI099.png)
![5ccfdbd6-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l-AfXJpAACcD9a1gtk920.png)
![5cf21f02-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l-ASaMSAACqN1rs9UM644.png)
![5d0f38c6-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l-AQgRyAACNaeWR-Zs915.png)
![5d606ae8-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l-AaUE7AACh4JBGH3c818.png)
![5d6f3ab4-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_l-Accr5AACi6XO0G9E782.png)
![5d964280-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mCADQY4AAC1Nsie078105.png)
![5dc835ce-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mCAQCAzAAB2KKAb3Eo528.png)
![5dd8f238-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mCAeD5XAACt4khfRIQ540.png)
![5e02d0ee-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mCARpjIAAB3ajtfDLA809.png)
![5e181e90-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mCAA3u4AADMRxfiBxA035.png)
![5e26b680-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mCAczdRAACL6nojpVw515.png)
挖掘隱藏指令
現在核心算法和判斷指令長度的方法都介紹完了,可以正式來開挖,挖出那些隱藏的指令了!以一臺Intel Core i7的CPU為目標,來挖一挖:![5e52da3a-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mCAMwgzAAAMWkgygG4584.png)
![5e81527a-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mGAfa5NAABkdjIJcdY253.png)
![5eabeee0-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mGAGSQhAABjWET4iuU056.png)
![5ed36ee8-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mGAbtMVAAAQU4me8IE634.png)
![5ee6eec8-d4cc-11ec-bce3-dac502259ad0.png](https://file1.elecfans.com//web2/M00/95/5A/wKgZomTm_mGAWI9tAAA8kiNm-R0716.png)
審核編輯 :李倩
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
cpu
+關注
關注
68文章
10921瀏覽量
213222 -
編譯器
+關注
關注
1文章
1642瀏覽量
49326
原文標題:可怕!CPU 暗藏了這些未公開的指令!
文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
前端總線頻率怎么看的
前端總線的定義 前端總線是計算機系統中CPU與內存、北橋芯片之間數據傳輸的通道。它負責將CPU的指令和數據傳輸到內存和北橋芯片,同時也將內存和北橋芯片的數據傳輸回CPU。前端總線的性
CPU時鐘周期、機器周期和指令周期的關系
CPU時鐘周期、機器周期和指令周期是計算機體系結構中三個緊密相連且至關重要的概念,它們共同構成了CPU執行指令和處理數據的基本時間框架。以下是對這三個周期之間關系的詳細解析。
怎么看編碼器上的參數?
編碼器是一種用于測量運動和位置的設備,常用于工業控制、機器人和自動化設備等領域。編碼器的工作原理基于數碼信號與機械旋轉之間的特定關系,可以將物理運動轉換為數字信號。 一、怎么看編碼器上的參數 (一
![<b class='flag-5'>怎么看</b>編碼器上的參數?](https://file1.elecfans.com/web2/M00/F2/2B/wKgZomZ32cWAHG4zAAB3Aji_EYg129.png)
三星貼片電容怎么看電壓呢?看電壓的方式有哪些?
對于三星貼片電容怎么看參數呢?現在看三星貼片電容的電壓參數的方式也是比較多的,今天給大家分享兩種,看三星貼片電容電壓的方式吧。其實對于懂技術的人員直接看三星貼片電容的外面參數就能夠知道三星貼片電容
微軟推進CPU指令集更新,舊版CPU或無法運行Edge瀏覽器
按照微軟的計劃,Microsoft Edge 126.0正式版將于2024年6月13日發布。屆時,未支持SSE3指令集的舊CPU用戶可能需繼續使用現有的版本。
三星貼片電容的批次號怎么看?
三星貼片電容的批次號怎么看?在這個問題之前我們先普及一下,怎么分辨三星貼片電容是不是正品? 原裝三星貼片電容標簽在字樣底部設置精細白點作防偽標記,圖像清晰,布面密集,橫縱距離一致,并沒有其它模糊圖像
TDK貼片電容怎么看參數?這些簡單的知識你一看就懂.
? TDK貼片電容:外觀單一,外觀單一,表面無絲印油墨,無旋光性。有多種色調,包括深棕色、深灰色、淺紫色等。 ?(1)容量與誤差:實際容量與標稱容量的最大誤差范圍; ?(2)附加工作電壓:電容器能在電路中長期穩定可靠地工作,最大允許直流電壓也稱為耐壓; ?? ?(3)溫度系數:必須是溫標。溫度每變化1℃,電容的相對變化值,溫度系數越小越好; ?(4)絕緣電阻:用于顯示漏電流大小。小容量電容器具有高絕緣電阻。電解電容的絕緣電阻比較小。;反
![TDK貼片電容<b class='flag-5'>怎么看</b>參數?<b class='flag-5'>這些</b>簡單的知識<b class='flag-5'>你</b>一<b class='flag-5'>看</b>就懂.](https://file1.elecfans.com/web2/M00/C5/6B/wKgaomXz8UiAe3uMAACZ-g9E8JE887.png)
三星電容怎么看型號呢?
現在對于三星電容的挑選型號的方式,完全要多去了解自我的需求,然后在選擇適合自己型號的三星電容,這樣的選擇是比較合理的。那么,三星電容是怎么進行選擇的呢!這些方面都是需要咱們了解清楚哦。 看三星電容
![三星電容<b class='flag-5'>怎么看</b>型號呢?](https://file1.elecfans.com/web2/M00/C3/53/wKgZomXqqD2AHpVoAABjbZF6iS0836.png)
評論