賈舵先生的議題以NRF52平臺的模擬為案例,深入淺出的介紹了如何結合虛擬仿真技術對物聯網中的藍牙固件進行全狀態的模擬,實現動態執行與調試,並且進一步就模擬器在實際漏洞挖掘應用中的實踐經驗進行分享。
下面就讓我們來回顧2021看雪第五屆安全開發者峰會上《基於模擬仿真的藍牙協議棧漏洞挖掘》此議題的精彩內容。
賈舵:阿里IoT研究團隊安全專家
專注物聯網安全、汽車安全、虛擬化仿真技術的應用。
各位來賓朋友大家好,我叫賈舵,目前在阿里做IoT的安全研究,今天我跟大家分享的議題是《基於模擬仿真的的藍牙協議棧的漏洞挖掘》。議題分為五個部分,首先是做一個背景介紹,第二部分是我們模擬技術的實現,然後是模擬在我們漏洞挖掘中的應用,第四部分是案例展示,最後會做一個總結。首先第一部分是我們的背景介紹,這部分會介紹兩個內容:一是我們的IoT藍牙協議棧;第二是我們為什麼要去做模擬?我們的智能設備目前的話是有兩個明顯的一個發展方向,一個是朝著我們功能化的方向,這裡面典型的有我們的路由器,還有智能音箱、智能電視,以及現在比較流行的智能汽車。另外一個方向是我們的可穿戴的方向,它逐漸是向這種小型化的一個方向發展。這裡面典型的有我們無線的耳機,還有運動手環等。在這些設備裡面的話,其實我們的藍牙的應用是非常廣泛的,承載我們藍牙功能的是藍牙協議棧,我們今天針對的是我們可穿戴方向的藍牙協議棧,為了區分,我們稱之為IoT的藍牙協議棧。根據它的一個應用場景的一個不同,我們 Iot的藍牙協議棧它會區別於我們的 PC或者是作業系統,它會有一些自己的特點。對於我們運行IOT藍牙協議棧的一個平臺,它的資源是非常有限的,體現在它的一個 CPU的資源上,還有的話是它的一個存儲限制,這樣要求協議棧往往是一個非常輕量化的實現。那麼同時的話我們iot設備往往會要求一些實時性,那麼需要一個快速的響應的能力,同時我們無線的設備往往是用移動的電池來供電,所以的話它會有一些低功耗的特性。正是因為有這些特點的話,所以我們實際在做 IoT協議棧的應用的過程中,它往往會和我們的硬體去結合在一起,也就是我們的藍牙SOC。我們常用的一些藍牙SOC包括nordic的nrf52系列,還有 TI的CC系列。藍牙協議棧其實是我們物聯網中基礎的一個組件之一,它的一個漏洞的話往往會影響到一個範圍的設備。我們今天其實要講的是通過模擬的方法去對它做一個漏洞挖掘方法的闡述。這裡面就有一個問題,就是我們為什麼要去做一個模擬?我們模擬的一個目的其實是為了解決我們物理世界的阻礙因素,建立一個我們理想的虛擬世界。當我們採用一個新的方法的時候,一定是傳統的方法給我們帶來一些不利的因素,實際上我們在做藍牙的漏洞挖掘的過程中會面臨一些困難,主要體現在幾個方面。首先的話是一個環境的幹擾,我們周邊的話其實有很多這種2.4G的設備,包括我們的耳機或者滑鼠鍵盤,同時還有2.4G的wifi,會形成一些幹擾;然後就是藍牙自身跳頻的一個影響,這會直接影響到我們對數據的一個監聽。那麼對於BLE藍牙來說的話,我們可以對它的廣播信道做一個非常好的監聽,但是對它的數據信道的話,如果我們做一個真正的旁路監聽還是比較困難的。第二個部分是我們調試上的困難。我們如果想去通過硬體去建立一個完整的一個調試環境的話,還是有一定難度的,主要受限於硬體對調試的一個限制,還有就是硬體自身的一個熔斷機制。第三個方面是我們工具的一個依賴性,在我們漏洞挖掘的過程中會應用到很多的工具軟體和硬體,我們很多精力要去做這個軟體跟硬體的穩定性的維護,這就導致我們沒有辦法去專注數據本身的一個操作。另外工具的依賴性也會造成我們測試範圍的受限,這個圖的是我們 BLE藍牙的一個協議結構圖,我們常用的一些測試的工具,比如說nrf52 dongle和cc系列的dongle,還有一些USB藍牙的適配器的話,他們是基於一個hci接口來控制,我們 PC端的話可以通過一些協議棧的工具去做一個訪問,那麼最後實現對我們應用的屬性藍牙屬性的一個讀和寫。那麼這裡面的話,因為我們這些工具其實是建立在物理層和鏈路層上的,鏈路層的邏輯其實是固化在我們的硬體工具當中的,這就導致我們沒有辦法對鏈路層去做一個測試。那第二個的話就是我們這些工具的話,一般是通過 hci接口來去訪問的,hci接口本身它是一個功能性的接口,它並不是一個測試接口,所以本身也會受到一些限制。我們通過模擬的手段就是為了將我們一些複雜問題簡單化,這個圖的話是我們在物理環節中想對藍牙協議棧的測試場景,這裡面可能會用到一些軟體無線電或者ubertooth等。對於我們這個圖的本質,其實是為了做藍牙數據的一個交互,對於我們安全研究者來說的話,我們最希望的其實是有一個接口,通過這個接口的話做協議的一個交互,達到我們測試的過程。實現這個過程的轉換,其實就是我們需要做的模擬實現的部分,也就是我們第二個內容要講的模擬技術。這一塊的話我會講兩個內容,一個是對我們模擬對象的分析,第二個是我們模擬的設計方法。首先剛才我們講了幾個藍牙的SOC的平臺,這裡面我們會以 nrf52作為對標的模擬對象,這裡面有一些參數可以看一下,在這裡面我們其實最關心的還是協議棧的問題。nrf52平臺目前有兩個應用比較廣泛的藍牙協議棧,一個是 softdevice,這是nordic官方的一個協議戰,是有商業化的。第二個的話是一個開源的協議棧叫Zephyr,這個也是非常活躍,由現在的一個社區去維護的。這是我們整體的一個設計思路,我們模擬器的話是基於 qemu5.1的版本,建立在 arm的架構的模擬基礎之上,我們模擬的目標是基於Zephyr和SoftDevice的應用固件,當然也可以包含我們普通的基於這個平臺的固件,那麼具體怎麼實現?從硬體的一個角度來講的話,我們的固件其實可以分為兩個層次,一個部分是我們固件裡面其實是大量的這種arm的指令,這些指令的話它會對我們的特定的一些數據做一些讀寫的操作,形成我們對外設的訪問。這些外設的話可能會包括比如GPIO、I2C或UART這些,我們要實現一個模擬的話,首先我們要對它的一個CPU的核心做一個模擬,qemu目前已經對Cortex-M4的一個內核做了支持,我們可以直接拿來用。以此為基礎,我們可以做一些基礎硬體模擬的擴展,包括內存中斷還有寄存器,但是這些還是遠遠不夠的。在模擬實現的過程中,最重要的是我們 SOC外設的模擬,對外設模擬其實是區分我們模擬器是不是能夠用在MCU上的重要指標,模擬器是針對於PC的還是針對於MCU的,很關鍵的就在於外設的功能,這一塊也是我們後面重點會去模擬的一個對象。我們模擬的對象是一個固件,所以我們首先要對固件做一個分析,這裡面還是以 SoftDevice的協議棧為例,一個使用SoftDevice作為應用的一個完整部件,它的結構是這樣的,會包含兩個部分,一部分是我們的應用層的代碼固件,然後第二部分是協議棧本身,他們之間會通過一個svc的指令去做一個調用,SoftDEvice其實就是我們協議站實現的一個部分,它是不開源的,所以需要我們去做一個逆向分析。通過分析,我們要確定我們模擬什麼以及模擬到什麼程度,首先我們要知道我們模擬什麼,這裡面的話其實要去知道的是它使用了哪些外設,對於硬體來說的話,特定的外設其實是映射到特定的地址上,根據這個特點的話,我們可以通過數據手冊去查找他用了哪些外設,然後做一些統計。單純知道這些的話還是不夠的,那麼對於我們每一個外設來講的話,它的邏輯還是非常複雜的。對於 IoT協議棧來說,為了實現一些非常高效的一些操作,往往會跟我們的硬體做一些聯動和結合。因此的話我們要對一些關鍵的邏輯去做一個逆向的分析,這裡面是對它的一個廣播的邏輯,藍牙的廣播做了一個逆向分析以後的結果,在廣播的邏輯當中,它使用了三個主要的外設,分別是 RTC、Timer定時器,還有 Radio的一個功能。廣播它其實是有一個廣播周期的周期,一般會在60毫秒到1秒之間,這個是由RTC模塊來維護的。同時對於單個的一個廣播周期內的話,也有它會在三個不同的信道上進行廣播,這一部分是由 timer來維護,對於我們radio的話,它主要是做數據的收發處理,當我們有藍牙數據請求過來的時候,他要做一個response的操作,這裡面我們講到的這三個模塊,是通過我們的硬體事件、硬體的中斷,還有PPI這三個部分進行一個連接的,PPI是我們 nrf52裡面特有的一個外設,它的一個功能是可以實現把我們硬體的事件和我們硬體的動作進行一個連接。這樣的話其實就可以實現一個自動化的操作,實際上在整個的廣播的邏輯當中,80%的工作是硬體自動來完成的,從另一個角度來說,也就是說我們80%的邏輯需要我們去做模擬的一個實現。在對這個部件的分析過程當中,我們也發現了一些反調試的現象,它的基本的邏輯是這樣的,當我們在做調試的過程中,在我們斷點以後,我們的PC指針它停止了,它的指令流停止了,但是它的硬體外設其實還是在跑,這裡面典型的就是一個定時器,定時器在運行的過程中它會產生一個時間差,時間差如果被我們的固件去檢測到的話,它會產生一個錯誤。具體的話其實是兩種表現形式,一種的話它會直接讀我們的定時器的一個數值做一個比較,第二種的話就更隱蔽,它會設定一個預期的值。那麼在檢測點去查看這個有沒有一些超時事件。反調式怎麼會影響到模擬的實現,是因為我們在模擬的過程中,其實所有的模擬器其實它的模擬的速度其實是不均等的,這樣的話就會產生一個時間差,這個時間差的話在一定概率上就是觸發這些問題。那當然我們針對這個也做了一些解決的方法,因為誤差是是我們模擬導致的,所以可以通過提高硬體的一個精度,模擬的精度來解決。還有的話我們可以適當的去降低定時器的一個頻率,增加時間的一個冗餘。最後,我們也可以去對它的特定的一些邏輯做一些補丁或者修改,實際上在最後的模擬實現過程當中,從結果來看,我們只需要做一處的這種補丁,所以的話最後它整個固件的話還是比較完整的。這是我們固件分析以後統計的這些外設的一個模擬的情況,實際上最後我們是對13個主要的外設做了模擬,外設功能的覆蓋度達到了80%,這個程度已經完全可以支撐我們協議棧固件的運行,這些外設裡面其實可以分為兩類,一類是我們強依賴的外設。就是說我們必須要去實現,如果不實現的話,我們的固件可能會卡死或者是報錯,或者說進入一些非預期的一些邏輯,這些是我們不希望看到的。第二個的話就是通信接口,通信接口的話它反映在我們的固件跟外部的設備的交互上,典型的是我們的SPI的接口還有I2C的接口,當然也包括藍牙接口。那麼這些外設具體是怎麼實現?首先外設模擬的本質是對地址讀寫的一個實例化,我們固件對我們硬體的一個訪問往往是通過特定的一些地址讀寫來操作的,所以的話我們要實現模擬的話,其實是對讀寫過程進行賦能。我們在模擬的過程當中,我們對固件的一些讀寫操作會進行過濾,通過模擬器的一些callback的機制,然後過渡到我們外設的實現當中,我們的外設實現過程當中,除了要對這個地址的讀寫進行數據的一個反饋,還有保存的話,其實最關鍵的其實要對他它讀寫硬體行為做一個模擬,這是我們非常核心的一個部分。在所有的外設裡面,其實我們最關心的還是藍牙,實現藍牙的一個模擬的話,其實是實現它的一個組包跟拆包的一個過程,它的組包跟拆包其實發生在我們的硬體層,因此在硬體模擬的時候,我們就可以做一個組包拆包的實現,其實我們模擬的是藍牙的一個物理層。但是對於藍牙來講的話,僅僅這些還是不夠的,因為藍牙它不可能去單獨的存在,它一定是兩個或兩個以上的設備存在的,因為它要建立一個連接的交互,那麼這裡面的話我們通過一個接口來實現,通過 interface接口來實現。那麼對於這個接口的話,基於接口協議,可以在模擬器的主體外部去做一些腳本的編程,從而我們對藍牙協議的一個通信。這個結構其實也是有一定的靈活性跟擴展性的。基於這個接口的話,我們除了藍牙,我們還可以擴展一些其他的外部設備,比如說spi的flash,還有一些按鍵交互,甚至還有 LCD的一個顯示。這是我們模擬以後藍牙數據的一個體現,它是一個我們自己定義的json的格式是一個非常易讀的。這裡面我們一個具體的例子來講解,那麼這是一個真實的固件模擬的案例,那麼對於這個固件的目標設備,它其實外面接了兩個晶片,一個spi flash用來存儲一些數據,還有I2C的控制器用來做一些機械的控制,當然還有藍牙的通信。我們在做設備模擬的過程中,我們可以基於一些高級的語言去來做編程,一般安全人員喜歡用這種Python的格式,我們可以用Python來實現三個設備的模擬,進而實現一個電路級別的模擬。那麼它模擬的結果是什麼樣的?這裡面我列舉了一些它的數據日誌,從這一點來看,我們可以看到固件對我們spi flash還有 I2C的數據的一個讀寫,這裡面比較關鍵的就是我們藍牙的數據,藍牙大多數它還是一個 client server的模型,我們這裡面也是用一個方向進行了標識。剛才介紹的就是我們模擬實現的一個過程,分別講了我們模擬器主體的一個實現,還有我們外部設備的模擬。下面的話第三部分就是講模擬技術如何應用到漏洞挖掘中?首先,模擬在藍牙漏洞挖掘當中其實有兩個非常直接的意義,首先說可能給我們建立一個比較好的動態分析的環境,第二個的話就是可以高效率的建立自定義交互數據。這是我們虛擬環境中的一個概況,這裡面包含幾個部分,首先是物理設備,物理設備可以認為是我們的被挖掘的真實的設備,或者說我們可以理解為固件,那麼模擬器主體的話就是我們 CPU的模擬,還有外設的一個模擬實現,外部設備的一個模擬就是我們剛才講的基於通信接口來做的,比如說LCD或者flash或者eeproom這些,同時的話針對外部設備的模擬,我們也會增加一些可視化的一個輔助,這樣的話更形象的把我們固件所對外表現出來的行為進行一個直觀表現。作為一個安全研究者的話,其實是模擬器的一個使用者,那麼我們固件在模擬的過程中,它與外界的所有的交互都會通過 interface接口來體現出來,我們安全的人員可以去接口去做監聽或者分析,還有進一步的做修改和反饋,達到測試的目的。那麼具體針對這個接口,我們從藍牙來講,這裡面主要是有兩種表現形式,一種是Guest to Geust,首先Guest的意思就是說是我們的模擬器,其實這是一個中間人模擬的場景,我們需要同時模擬兩個固件,分別是固件一還有固件二,同時通過一個中間的腳本對他們所產生的藍牙數據做一個連接,在這個連接過程當中我們就可以去過濾我們感興趣的欄位,然後去做一些修改,甚至做一些重複的一些操作,這種場景的話就比較適合我們同時對藍牙的中心設備,還有外圍設備去做同步的這種分析。第二的話是Guest to Host,它是一種點對點的模擬,Host指的就是我們的 PC端,在這裡面的話我們只需要模擬單一的一個固件,同時的話基於我們剛才講的接口協議,我們可以編寫一些測試腳本,這裡面的話是對BLE藍牙的connect請求的一個fuzz的一個場景,它其實是對我們連接數據包中的AccessAddr,還有ChannelMap的欄位做了一個fuzz的測試。同時我們的模擬器在對這個漏洞的驗證,還有調試的過程中也是支持比較好的。首先我們直接可以基於 shell環境來做漏洞的驗證,對於已知的一些CVE的話,我們可以直接在命令行裡面跑,即使一些複雜的話,我們其實也可以編寫一些簡單的腳本來做。我們對調試的一個支持,還是基於 qemu的 GDB調試。我這裡面我們做了一個東西,就是說把程序的斷點跟我們的硬體模擬做了一個強綁定。當我們這個斷點的時候,我們的硬體狀態其實是真正的去暫停了,像我們剛才講的這種基於時間的這種反調試的話,它就不再起作用,起到了一個去反調試的效果。我自己的話也是基於這些方法去做了一些研究,然後發現了一些問題,這些這幾個漏洞的話都是非接觸式的漏洞,因為今天我們主要還是以概括的方法為主,所以對於這一部分就不做詳細的介紹。第4部分是做一個案例的演示,我們剛才講了,其實藍牙模擬交互有兩種方式,這裡面也會有兩個演示,首先是一個中間人的案例,中間人的話肯定是一個三個角色去存在的,首先這裡面我們要有一個藍牙的中心設備,然後第二個的話是藍牙的一個周邊設備,然後我們通過一個中間腳本把這個數據做一個交互的連接,從而建立兩個固件的一個通信,實現一個連接。基於這個的話,我們可以針對特定的去報文去做一個修改和重放。(此處為視頻,點擊文末閱讀原文前往下載ppt查看)