Jump to content

在過去的四五年裡,圍繞加密貨幣錢包的安全性進行了大量研究。大部分研究都集中在故障注入領域,這是破壞嵌入式系統的常見手段,其目的是找到允許修改設備行為,以授予攻擊者升級的訪問權限。這方面的示例可能包括跳過指令、破壞內存讀取操作等。

故障注入故障注入包括引入足夠小的錯誤或修改以在目標上導致未定義的行為,但不足以阻止目標完全運行。這通常涉及注入高壓脈衝或暫時從目標系統上的目標電源或“軌道”排出電壓。

通過引起瞬間電壓調製(高於或低於預期電壓),我們可以迫使目標系統進入一個未定義的行為領域。有足夠針對性的錯誤可以繞過各種安全檢查或其他可能阻礙攻擊者或逆向工程的功能。

關於常見的故障注入方法,我們可以嘗試引入幾種不同類型的故障:時鐘故障和電壓故障。

時鐘故障對於時鐘故障,我們的目標是跳過或修改指令。這個想法是,通過注入另一個時鐘週期,我們可以讓處理器跳過一條指令。

1.png

當我們嘗試修改或操作特定的時鐘週期序列以獲得我們想要的結果時,這些需要精確。時鐘故障以CPU 或微控制器上的外部時鐘為目標,最終目標是在適當的時間注入時鐘信號,從而導致指令被跳過。

電壓故障電壓故障涉及針對整個系統的電源。通過短暫切斷目標系統的電源,我們可以修改其行為/性能。

2.png

對於電壓故障,我們的目標是在足夠短的時間內降低電壓,以便處理器不會完全關閉,而是進入一個未定義狀態或導致某種類型的未定義行為。不幸的是,這項任務並不容易,因為許多處理器都是專門為避免這種情況而設計的,有時需要攻擊者使用組件移除或註入方法。

如果你想了解更多關於這些方法的信息,可以點擊有關教程、論壇和文檔。

電磁故障注入我們還可以使用PicoEMP或chipshouter等工具向目標註入故障,這些工具以不同於上述兩種方法的方式註入故障。

這些工具用於執行EMFI(電磁故障注入)攻擊。這些攻擊涉及產生可能導致硬件故障的大電場,從而導致潛在的位翻轉和其他未定義的行為。想要了解更多關於EMFI攻擊的信息,請查看Colin O’flynn關於錢包的介紹。

本文旨在重現使用故障注入繞過STM32F2 系列MCU bootrom 中的RDP 檢查的過程,允許攻擊者通過SWD 訪問設備的內部存儲器。

目標設備目標是Trezor One 錢包,這是一款流行的低成本錢包,它是基於STM32F2微控制器構建的。 Trezor的硬件和軟件都是開源的,這很好,因為它讓我們能夠訪問硬件圖和固件源,這將有助於逆向工程。

4.jpg

Trezor One 使用STM32F2 MCU,讓我們先回顧一下CPU的相關特性。

STM32 安全概述在STM32微處理器上可以啟用多種安全功能:

1.RDP 0 ——閃存解鎖,閃存/內存可通過調試接口訪問;

2.RDP 1——閃存鎖定,你可以連接調試器並讀取RAM/外設,但不能讀取閃存;

3.RDP 2——閃存鎖定、RAM 讀取鎖定、調試接口鎖定;

由於我們需要啟用保護級別RDP2,所以我們需要找到繞過它的方法,為此,我們必須稍微仔細研究一下STM32 中的電源管理和調節方式。

STM32 電源管理/調節在任何微控制器中,都有多個電源域(power domain),電源域對於一款芯片來說,其是由許多模塊、子系統集成之後才會發揮它的功能,不同模塊之間的工作速度和性能要求不同,它們為各種芯片外設和內部操作和比較器供電。我們將以內部電壓調節器為目標。下面是STM32電源域的簡要概述:

5.PNG

該圖顯示VCAP_1 和VCAP_2 線為我們提供了通往內部調節器的直接路徑,影響內核邏輯、閃存和IO 邏輯等內容。因此,如果我們可以簡單地操作這條線,我們就有希望影響這些外圍設備的行為方式!

6.PNG

對於這項工作,我們將通過嘗試操作上圖中顯示的VCAP 線來瞄準內部穩壓器。我們為什麼要瞄準這條線?或者更重要的是,當我們轉向其他目標進行故障注入時,我們如何才能找到類似的電壓軌來定位其他處理器?

VCAP 線路確保所有內部比較器和穩壓器都得到適當管理。如果我們可以操作這條線,則有可能改變CPU 核心存儲器和數字外設的行為,並導致未定義/修改的行為。希望這個內部調節器出現的故障(可能在涉及RDP 設置的特定內存操作期間)允許我們修改設備的RDP 狀態。

綜上所述,我們希望嘗試將設備的RDP狀態從RDP2修改為RDP1,我們希望通過故障或短暫中斷VCAP_1/VCAP_2線路上的電壓來實現這一點,VCAP_1/VCAP_2線路用於幫助調節內部穩壓器。如果我們能改變內部電壓調節器的行為,我們就有可能改變處理器的行為。現在我們已經回顧了目標的內部安全特徵和我們要攻擊的電源軌,接下來讓我們談談攻擊的細節。

攻擊過程這項工作旨在重現chip.fail 研究中提出的實踐路徑,該研究導致在STM32F2 微控制器的bootrom 中發現錯誤。對於那些可能不熟悉的人,bootrom 負責處理微控制器的許多早期啟動功能(類似於現代計算機上的BIOS)。 bootrom 負責執行基本的外設初始化、安全檢查、啟動模式檢查,最後將主應用程序加載到內存中並執行。引導過程的概要如下所示:

7.png

如果攻擊者可以在處理器開始執行其bootrom 大約170 微秒後注入故障,那麼RDP檢查就可以被繞過。這將允許攻擊者將STM32 從RDP2 釋放到RDP1,從而允許通過SWD 訪問SRAM。此外,可以通過讀取SRAM 來提取恢復密鑰,從而可以訪問錢包的內容。注意:Trezor 已修復了此漏洞。

攻擊過程如下:

1.開啟錢包;

2.當斷言(assert)RESET線時,開始故障倒計時;

3.在170 微秒時,將VCAP 拉低;

4.通過SWD 測試RDP 繞過;

5.從目標設備讀取SRAM。

8.png

如果步驟4 成功並且錢包繼續啟動,則故障成功,並且可以從目標中讀取內部SRAM。

那麼像這樣的攻擊在信號層面是什麼樣的呢?我們如何知道處理器何時開始執行引導ROM?如果分析新的目標/電源軌跡,將如何進行?讓我們首先從目標中移除一些組件並查看電源軌跡。

準備我們的目標為了確保我們的故障盡可能有效,我們需要移除連接到VCAP 線和復位線的外部電容器。這些電容器(在下面的示意圖中突出顯示)用於確保電壓保持穩定,這是我們在進行故障注入時不想要的。

以下是Trezor One 的默認示意圖:

9.png

下方紅色突出顯示的組件勾勒出了需要移除的電容器。

10.jpg

下面是錢包的圖片,被移除的電容用紅色標出:

11.jpg

捕獲電源軌跡除了已經確定的需要移除的組件和我們關心的線路,我們還需要捕獲一些示例電源跟踪數據。為此,我們將使用示波器。我們在本文中使用了Siglent SDS1104X-E 100Mhz 數字示波器和該示波器附帶的標准直流測量探頭。

在執行這樣的功率捕獲時,必須確保正確設置示波器。這意味著示波器將在檢測到復位線上升時開始捕獲。

在撥動示波器的觸發器時,花一些時間是必要的。雖然使用連續捕獲或“滾動”模式可能很有效,但這會大大降低你的捕獲率並導致更細粒度的電源跟踪。對於我們稍後將查看的樣本,我們的採樣率為500MSa/s。

還應該注意的是,當我們捕獲踪跡時,我們沒有使用分流電阻,關於如何正確利用分流電阻進行功率測量的文章可以點擊這裡。

接下來,讓我們回顧一些示例電源軌跡。下面是帶有外部電容器的VCAP 線上電壓的示例視圖:

12.png

移除電容器時也有同樣的反應:

13.png

現在線路噪音更大且更不穩定,這正是我們在嘗試將故障或故障注入電源軌時想要的。移除電容器並焊接測試焊盤後,就可以開始從與復位線相關的目標線(VCAP)開始進行一些初始功率分析。當系統復位線達到3.3V 閾值時,bootrom 開始執行。因此,通過監控復位線,我們可以確定引導ROM 何時開始執行,我們將使用它作為我們的故障觸發器。

粉線代表VCAP線上的電壓,而黃線是RESET線上的電壓:

14.png

我們可以在下面的gif 中看到突出顯示的各種活動區域:注意這些區域的電壓波動。基於這個MCU的啟動方式,我們可以對這些多重波動的含義做出一些假設。

15.gif

可以查看大約170 微秒的跟踪,可以在主應用程序開始執行之前看到flash 活動。

16.png

現在我們已經移除了相關的電容器,接下來我們需要連接到SWD 端口。這可以通過PCB 右側的導通孔訪問,如下圖所示:

17.jpg

在將這些行插入到breadboard上之後,就可以重現攻擊了。

重現攻擊下圖是一些要準備的裝置:

18.jpg

STL 文件可在此處的GitHub 存儲庫中找到。

硬件在設置中,我們使用了Raspberry Pi、ChipWhisperer 和STLink。 STLink 連接到Trezor 的SWD 端口,我們使用它來檢測RDP 繞過是否已成功執行。 ChipWhisperer 用於為錢包供電、觸發復位線和乾擾VCAP 線。下面是一個簡單的接線表:

19.png

軟件完成所有適當的連接後,是時候與ChipWhisperer連接,並輸入我們想要的故障參數。如前所述,NewAE 教程是一個很好的起點,可以作為攻擊的模板。

在使用ChipWhisperer時,需要輸入一些關鍵的東西,我們現在將介紹其中一些。參考代碼可以在這裡找到。

整個程序的流程很簡單:

20.png

從連接到我們的CW 開始;這可以通過以下代碼完成:

21.png

我們需要確保我們設置了CW的內部時鐘頻率以及輸出模式和触發源,可以使用以下代碼行來完成此操作:

22.png

接下來,我們來談談觸發。我們之前提到過,將使用複位行來指示引導ROM何時開始執行。如果故障不成功並且需要重新運行,此行也將用於重置目標。

23.png

reboot_flush 函數負責完全重置設備並解除故障。每當我們想要重置STM32 並測試新的故障參數時,我們都會調用此函數:

24.png

接下來,我們將定義我們的故障參數,我們將使用如下所示的GlitchController類來完成。

25.png

最後三行對於我們故障注入至關重要。

故障形成故障形成的三個變量是寬度、重複和偏移變量。請注意,這些定義來自Newaetech 教程。還應該注意的是,除了電線長度和質量等變量之外,還有許多因素會影響故障的形狀。根據一般經驗,使用SMA連接器的短屏蔽線是最佳做法。

寬度:產生故障的寬度。這是一個週期的百分比。對於我們的示例,我們將在進行電壓故障而不是時鐘故障時使用最大值。

重複:重複故障的時鐘週期數。較高的值會增加可能出現故障的指令數量,但通常會增加目標崩潰的風險。但較高的重複次數通常會導致更強的故障。

偏移:在輸出時鐘中放置故障的位置。

故障時間最終的範圍定義ext_offset定義了FPGA在觸發後執行故障之前等待的時鐘週期。由於我們之前指定了100 MHz的時鐘速率,15000個時鐘週期相當於大約150微秒。這意味著在Trezor上的RESET線升高後,我們將開始從ext_offset值開始倒計時,當它達到零時,我們將乾擾VCAP 線!

另一件需要注意的事情是,GlitchController類將遍歷所有提供的glitch參數。因此,對於每個可能的參數組合,我們將重新設置錢包,嘗試gitch,然後嘗試通過SWD連接到STM32。這意味著,對於測試大範圍的值,我們可能需要幾天來完成一系列測試。

我們在監控範圍的同時運行了故障的第一次迭代,並看到我們正確地生成了故障。

調試攻擊在運行攻擊一段時間沒有結果後,就開始對我們的設置進行故障排除。我們想要調試的第一件事是STLink SWD枚舉代碼,用於檢測一個成功的故障:

26.png

首先,我們在RDP級別0使用STM32開發板測試了成功的故障檢測,這在第一次迭代中立即有效。

這是一個好跡象,但是我們想測試多次調用swd_check函數時會發生什麼。

在發現swd 庫無法枚舉設備後(這將在故障嘗試失敗時發生),直到通過USB 重新枚舉STLink 後,它才能再次運行!

這意味著對於我們所有的測試,只有我們的第一次迭代使用STLink 正確測試了SWD。如果一次失敗,SWD 將無法再次工作,直到探針被拔出並通過USB插入!

有了這些新的知識和信心,我們發現了實踐中的問題,並修改了一個簡單的c程序,在每次故障嘗試後重置STLink設備。

27.png

不過,經過幾天的測試和調整故障參數後,我們仍然沒有看到結果。

最後,我們決定取出示波器並檢查故障。我們用16000、17000 和18000 的ext_offset 檢查了故障,雖然看起來是合理的,但是,當ext_offset 為0 時,我們看到以下內容:

28.png

在上面的截圖中,黃線是我們的RST 線,紫線是VCAP 線。注意故障和復位線達到其目標電壓之間的間隙。 ChipWhisperer 在復位線達到3.3V 之前觸發。這個早期的觸發導致我們的故障在復位線完全被斷言之前開始倒計時。這導致故障提前了大約20微秒觸發。

我們可以使用示波器上的光標計算準確的延遲,如下圖所示:

29.png

我們確定使用示波器提前了大約24 微秒觸發。有了這些新信息,我們將ext_offset 範圍修改為17000 到20000 之間,並在周末繼續運行。

過了一段時間,STLink LED 是綠色的,這意味著它已經通過SWD 成功訪問了設備!

30.png

更有趣的是,我們的故障在ChipWhisperer 觸發後大約197 微秒發生。回想一下在chip.fail 中的工作,它們的偏移量大約為170 微秒。我們的延遲為24 微秒,這與之前的實驗相差無幾(197-24=173)。這個偏移範圍是可重複的,我們可以在194-197微秒

0 Comments

Recommended Comments

There are no comments to display.

Guest
Add a comment...