# [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 暫存器來得知按鈕是否被按下
* 不同暫存器代表的資訊不同、大小和讀寫操作也不同
* 
### 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
* 
* 算出幾個字元 - 所花費的時間
* 藍色有建模、橘色沒有
* 模型生成花費的成本
* 平均而言,每個 firmware 生成 62 個模型,每個模型花費 6 秒,總花費 6.34 分鐘
* Input overhead 消除
* 
* M: 減少的 overhead
* F: 耗費的模糊輸入
* MMIO 模型通用性
* P2IM 的單元測試跑了 10 分鐘,有 100% 的通過率
### Comparison with the State of the Art
* 和 uEmu 和 P2IM 比較
* Dataset 使用 uEmu 的 21 個樣本
* 其中四個禁止中斷,其中一個手動定義 DMA
* P2IM 跑不動 11 個樣本(和 uEmu 寫的一樣)
* 跑五次的 24 小時
* 
* 程式碼覆蓋率平均比 P2IM 高 44%,比 uEmu 高 61%
* uEmu 會比 P2IM 低,可能是因為無效引導消除了路徑
* 發現 3 個以前沒報告過的 bugs
### Fuzzing New Targets
* 額外測試了兩個和 core network 有關的 firmware framework
* 發現了 12 個錯誤並發布 CVE
* 
### 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`