# [Fuzzware: Using Precise MMIO Modeling for Effective Firmware Fuzzing](https://www.usenix.org/system/files/sec22summer_scharnowski.pdf) ## Abstract * 在 IoT 裝置上做模糊測試並不簡單,容易有效率低下的問題,因此最新的方法是透過 re-hosting 跑 firmware * 現有的 fuzzing 方法使用簡化的硬體行為模型或是手動 re-hosting * 本論文提出 FUZZWARE,新的輕量化程式分析、rehosting 和 fuzzing 的組合來面對這些挑戰 * FUZZWARE 透過確認硬體如何生成值來自動生成模型,幫助 fuzzing 集中在重要的輸入上,而提高有效性 * 評估 19 個硬體平台和 77 個 firmware * 和最新的技術比較,FUZZWARE 有高達 3.25 倍的覆蓋率,建模將輸入空間減少 95.5% * 樣本中包含 66 個對各種硬體互動的單元測試,FUZZWARE 是第一個自動化通過所有測試的方法 * 發現 15 個全新 bug,確認了 12 個 CVE ## Introduction * fuzzing 是安全檢測常見的方式,但在 IoT 設備上常因有限的資源而降低速度 * 透過 rehosting 在模擬環境執行來解決 * 大多數使用 rehosting 動態分析 based on Unix Firmware 的方式都不適用於單片 Firmware(monolithic firmware);而現有能跑單片 Firmware 的方式通常需要分析人員手動查找外部設備,相當耗時 * 最近的研究轉向自動化,有各種方法開始出現 * HAL: 把外部設備的實作重新連到已知 lib 上 * P2IM: 建模,匹配暫存器 * Laelaps, uEmu: 符號執行解出執行路徑 * 上面這些方法在使用模糊測試的時候都會遇到一些限制,因此他們提出新的自動化建模方法,可與受到引導的 fuzzer 一起使用 * 大多是對外部設備的存取都是短暫的,與 firmware 整體運作無關(檢查外部設備的狀態或配置等等) * 會影響 firmware 執行的輸入,通常大部分都沒有使用到 * 可能一次讀取 32-bits,但只用了其中幾個 bits * 每次存取造成多餘的 cost * 為了降低這種 cost,使用局部的動態符號執行(DSE)分析哪個部分的值是有意義的 * 不使用 DSE 引擎來求具體解,而是利用生成的約束條件來推斷模型 * 這些模型會用於配置模擬器,具體值則由 fuzzer 提供 * 模擬過程中,模型不會選擇路徑或偏好路徑,目標是用最少 cost 有最高的覆蓋率 * 評估表明雖然需要多 0.5%~2% 的計算時間,但消除 95.5% 的輸入 cost,和其他工具相比有 3.25 倍的覆蓋率和找到額外的 bug * 貢獻 * 提出新的建模法,保留路徑,讓 fuzzer 專注在有意義的值 * 實現 FUZZWARE,可以用與 OS 無關的方式模糊測試單片 firmware * 實驗中優於其他工作 * 發現 12 個以前未知的漏洞並回報 * https://github.com/fuzzware-fuzzer/fuzzware * 還未公布 ## Technical Background ### Monolithic Embedded Systems * 這種 firmware 可能不包含 OS,且不會有傳統 binary executables 中的 metadata ### Memory-mapped IO * 現在的 CPU 透過 MMIO 訪問外部設備,外部設備被分配到內存空間中的區域 * 例如可以透過讀取 MMIO 暫存器來得知按鈕是否被按下 * 不同暫存器代表的資訊不同、大小和讀寫操作也不同 * ![](https://i.imgur.com/BaPGaMj.png) ### Interrupts and DMA * 硬體可以透過中斷來告訴軟體發生事件 * CPU 透過 interrupt service routines(ISR) 來維護中斷事件 * CPU 可以決定中斷的優先度 * 另一個硬體與軟體溝通的方式是 DMA,他透過 MMIO 完成 * 透過 DMA,外部設備可以執行和 memory controller 溝通而不用經過 CPU * 中斷較普遍,DMA 主要用於 USB 等需要高吞吐量的設備 ### Re-Hosting Embedded Systems * Re-hosting 是不需要實體設備執行 firmware binary image 的方式 * 為了正確模擬,需要處理 MMIO 的存取 * QEMU 完全重新實現 MMIO 暫存器的行為,但需要完整的硬體文檔(資訊) * 另一種方式是用 fuzzer 處理 MMIO;只要 firmware 存取 MMIO 暫存器,就由 fuzzer 提供值回傳 * 好處是不用知道 MMIO 到底如何處理回傳 * 壞處是前面說過的,fuzzer 要提供許多不相關的輸入 ## MMIO Access Handling ### Input Overhead * 對於 MMIO 的存取,可以分為兩類 * Full input overhead: fuzzer 提供的值完全不影響 firmware 執行 * Partial input overhead: 一位或多位會影響運作邏輯 * 如果存取了 32-bits 但實際上只有 8 bits 會被使用,那就有 24-bits 的 input overhead * 範例一: * 假設要從外部設備讀取值,通常要先等待 MMIO 中某區塊出現一個特定的值,代表資料已經準備好 * 沒有建模的話 fuzzer 要找到特定值就要很久 * 接著會對 MMIO 進行寫入,代表對 GPIO 寫入以開啟指示燈 * 這個寫入對 firmware 程式不會影響,Full input overhead * 最後讀取實際上要的資料 * 因為 MMIO 暫存器是 4-bytes 寬,因此你就算只要 1 byte 也會多讀資料,Partial input overhead * 針對這個部份去限縮 fuzzer 就可以減少開銷 * 範例二: * 如果出現 switch case 的結構,MMIO 的值被當作決定路徑的變數時,如果分支不多,但依然一次寫入 4-bytes 的長度就會造成 Partial input overhead ### Previous MMIO Modeling Approaches * 目前的 MMIO 建模方式 * 完全避開 MMIO 存取 * HAL,替換成抽象層 * 建模處理 * P2IM,基於對暫存器不同的存取方式來減少輸入空間 * 符號執行來建模 * Laelaps, uEmu,把對外部設備的存取視為符號值,當需要存取時再求具體解 * 目前都有這些問題 * 需要手動的工作(HAL) * overhead * path elimination ## Design * FUZZWARE 為了分析 firmware 行為,使用 DSE 來得到硬體產出的所有可能值 * 直接用符號執行建模會導致成本太高,因此 DSE 僅用於特定存取 MMIO 的 code ### Prerequisites and Threat Model * 先決條件 * 能得到設備的 binary firmware image * 要能提供基本的 memory mapping * 威脅模型 * 攻擊者能控制給 firmware 的輸入 ### FUZZWARE's Emulator * 使用 ISA Emulator 加上覆蓋率引導的 fuzzer * 目標是消除 partial input overhead,因此引入存取模型 * 設置了 harness 可以攔截所有 MMIO 存取 * emulation run: 進行 firmware 模擬,MMIO 存取發生時,會檢查是否有為這裡建立模型 * 模糊引擎會生成一堆輸入,這些輸入會經由模型轉換為合適的大小給模擬的 firmware 使用 * 模擬結束後會把覆蓋率反饋給模糊器 * 每次看到新的 MMIO 存取,就會對 memory 做 snapshot,然後用符號執行來產生模型 * 每次重新配置模擬器就會因為新模型而減少 overhead ### Modeling Approach * 對於每個不同 PC 和存取的 MMIO 地址都會做一個模型 * 把存取前的暫存器和記憶體狀態給 DSE 建模 * 分析範圍 * 以下事情發生就停止符號執行 1. 所有 MMIO 存取的符號變數都死亡 2. 當前 function return 3. 符號被寫入全域變數或上層 stack 等等 4. 定義的資源以用完(時間、符號狀態數、DSE 步數) * 停止時會生成當前路徑的符號約束範圍,提供給模型 * 模型設計注意事項 * 同樣的輸入經過模型後給 firmware 要有一樣的結果 * 盡量保留路徑 * 錯誤處理和執行停止 * 允許執行錯誤的路徑,增加覆蓋率 ### FUZZWARE Model Definitions * 5 種模型 * Constant Model * 將常數和 MMIO 存取的值做比較,滿足條件才會繼續做 * Passthrough Model * MMIO 的值根本不影響 firmware 執行 * Bitextract Model * firmware 只使用讀取的部分 bits 時使用 * Set Model * 根據不同的值會執行不同操作時使用 * Identity Model * 所有位元都是有意義的時候使用 ### Interrupt, Timer and DMA Handling * ISA emulator 沒有中斷,因此由 FUZZWARE 觸發 * 一定 basic-block 後觸發 * FUZZWARE 可以把 buffer 定義為 MMIO 區段來支援 DMA,但沒自動化建模 ## Implementation * 實現了一個支援 ARM Cortex-M 的 prototype ### FUZZWARE's Emulator * Unicorn Engine 作為模擬器,AFL 作為模糊器 * 用 Unicorn API 來 hook MMIO 存取事件 * 擴展 Unicorn 實現中斷控制器 ### MMIO Access Modeling * 使用 angr 作為引擎 * 達到退出條件時,檢查符號和約束來選擇模型 * Constant Model * 不再引用被追蹤的變數,而是直接約束結果 * Passthrough Model * 不再引用被追蹤的變數,也不約束結果 * Bitextract Model * 上特定的 Mask 後,所有約束和符號表達都沒變 * Set Model * 不同分區有不同的約束結果 * Identity Model * 以上都不符合時 * 可能同時符合多個模型,選擇開銷減少最多的模型 * DSE 最多每個模型執行 5 分鐘、1000 個 basic-blocks 就會強制退出 ## Evaluation * 5 個評估 * 基於符號執行的建模,計算成本多高 * 因為保守的範圍界定,錯失多少優化建模的機會 * MMIO 模型適用於各種 firmware 和硬體平台嗎 * 和以前的方法比較,fizz 單片 firmware 的表現如何 * 可以發現現實世界以前未知的錯誤嗎 * 針對 19 個不同的硬體平台、77個不同的 firmware image 實驗 ### Access Modeling for Fuzzing * 在 10 個不同的板子編譯相同的應用程式 * 輸入密碼,如果對了會開啟一個漏洞 * P2IM 66 個單元測試 * 24 小時模糊測試,有用 MMIO 建模和沒有的都有做 * 40-core Intel Xeon Gold 6230 CPU @ 2.10 GHz machine running Ubuntu 18.04.4 LTS * ![](https://i.imgur.com/PwQBLdl.png) * 算出幾個字元 - 所花費的時間 * 藍色有建模、橘色沒有 * 模型生成花費的成本 * 平均而言,每個 firmware 生成 62 個模型,每個模型花費 6 秒,總花費 6.34 分鐘 * Input overhead 消除 * ![](https://i.imgur.com/otjR4me.png) * M: 減少的 overhead * F: 耗費的模糊輸入 * MMIO 模型通用性 * P2IM 的單元測試跑了 10 分鐘,有 100% 的通過率 ### Comparison with the State of the Art * 和 uEmu 和 P2IM 比較 * Dataset 使用 uEmu 的 21 個樣本 * 其中四個禁止中斷,其中一個手動定義 DMA * P2IM 跑不動 11 個樣本(和 uEmu 寫的一樣) * 跑五次的 24 小時 * ![](https://i.imgur.com/NIu8m87.png) * 程式碼覆蓋率平均比 P2IM 高 44%,比 uEmu 高 61% * uEmu 會比 P2IM 低,可能是因為無效引導消除了路徑 * 發現 3 個以前沒報告過的 bugs ### Fuzzing New Targets * 額外測試了兩個和 core network 有關的 firmware framework * 發現了 12 個錯誤並發布 CVE * ![](https://i.imgur.com/099C24R.png) ### False Positive Crash Analysis * 61 個 unique crashes 中,42 個和安全有關,16 個和初始化有關,剩下 3 個是誤報 * 誤報是因為真實的設備不會有問題(e.g. 初始化前就觸發中斷) ## Discussion * DMA * 目前沒自動化 * 在 FUZZWARE 之外的地方使用模型 * 成功移植到 avatar2 和 PANDA framework 中 * 路徑消除的優點 * 就比較不容易出錯,但如果把錯誤的路徑當成正確的反而需要人工修復 * FUZZWARE 允許卡住,透過 Timeout 和回饋模糊引擎來避免 * Implicit Peripheral Semantics * firmware 會對某些外部設備的行為有隱含的假設 ## Related Work * AFL * QEMU * HALUCINATOR * PRETENDER * P2IM * uEmu * LAELAPS ## Conclusion * 提出了對 MMIO 建模的方式,可對 monolithic firmware binary 做 fuzzing * 這種建模可以消除 fuzzing 的 overhead 並提高有效性 ###### tags: `paper`