# [Efficient Greybox Fuzzing of Applications in Linux-Based IoT Devices via Enhanced User-Mode Emulation](https://dl.acm.org/doi/abs/10.1145/3533767.3534414)
## Abstract
* 灰盒 Fuzzing 是漏洞挖掘的主流方法,但因 IoT 的環境依賴性而無法對其使用
* 先前的工作利用 full-system 模擬來克服,缺點是巨大的 overhead
* FirmAFL 結合 full-system 模擬與 user-mode 來加速
* 本文認為目前 user-mode 的模擬並不完整
* 提出 EQUAFL,自動用 user-mode 模擬嵌入式應用程式
* 先用 system-mode 模擬,抓出會讓程式 crash 的關鍵,再將環境改至 user-mode
* user-mode 可回放系統的網路行為
* 在 70 個網路應用程式下評估 EQUAFL,與最先進的其他 fuzz 工具比較
* 比 AFL-QEMU 快 26 倍、Firm-AFL 快 14 倍
* 發現 6 個 CVEs
## Introduction
* 現今 IoT 開發注重功能而非安全,造成系統中存在漏洞
* Mirai
* 灰盒 Fuzzing 常被用來測試程式,蒐集 PUT(program under test) 的回饋資訊
* 但因缺乏系統與硬體支援,無法直接用於嵌入式設備
* 利用模擬解決
* 模擬有 user-mode 與 full-system
* 雖然前者 cost 低,但缺乏 system calls 與 execution context
* 大多使用後者執行
* 先前的工作 Firm-AFL 利用切換 user-mode 與 full-system 加速
* 有 system call 跑 full-system
* 沒 system call 跑 user-mode
* 當 PUT 有一堆 system call 的時候,加速很少
* 希望完全在 user-mode 之下執行
* 提出 EQUAFL,利用強化的 user-mode 模擬跑灰盒 Fuzzing
* Linux-based
* 強化的 user-mode 指自動化設定執行環境,讓 system call 直接傳到 host 端
* EQUAFL 使用觀察重放策略
1. 在 full-system 模擬 PUT,觀察設定啟動變數、設定文件、設定網路等關鍵行為
2. 重放觀察到的行為去建立環境
* 動態產生設定文件和網路互動是最難的部分
* 在 70 個真實世界的 IoT Linux-based 應用程式評估
* 比 AFL-QEMU 的 full-system 模擬快 26 倍
* 比 Firm-AFL 快 14 倍
* 在 18 個設備上發現 10 個未知漏洞,包含 6 個 CVEs
* 貢獻總結
* 提出 EQUAFL,自動建立執行 user-mode 環境來高效 fuzz
* 基於 AFL 和 QEMU 實作 EQUAFL
* 在 70 個應用程式下評估,發現 6 個 CVEs
* [Open-Source](https://github.com/zyw-200/EQUAFL)
## Background
### Emulation-Based Fuzzing
* QEMU 是常用的模擬器
* Full-system 模擬 kernel, drivers 和 應用程式
* User-mode 模擬將應用程式的 system calls 委託給 host
* 快速、高效
* 缺乏兼容性,當 host 不支援該 system calls 就會失敗
* AFL 支援利用 QEMU 作為模擬引擎去對 PUT 做覆蓋率導向的灰盒 fuzz
#### AFL + QEMU user-mode emulation
* 預設之下,AFL 用 QEMU user-mode 模擬
* 直接將執行的 system calls 傳給 host
* 可能會因 host 與 PUT 相容性問題而失敗
* ex: 執行 D-Link TRENDNet TEW-634GRU series 的 sbin/httpd,會因 "/var/run/httpd.pid: No such file or directory" 而失敗
* 常見失敗的原因
* 錯誤的啟動變數
* 因錯誤或是缺乏啟動變數而在開始就停止
* 缺乏動態產生的文件
* IoT 在開機過程常常會產生文件,缺乏這些文件會使 PUT 很早就停止
* 不一致的 NVRAM 設定
* IoT 設備中的 NVRAM 資料與 host 有衝突時會導致錯誤
* 不一致的網路行為
* 許多 PUT 需要透過網路與 user 互動,當 host 無法提供合適的網路時會就失敗
* 不一致的程式資源限制
* 某些情況下 host 的限制比韌體高得多,導致效率受限
* 缺乏硬體
* 某些情況下 PUT 需要特定的硬體來執行,缺乏硬體可能導致錯誤
* 總結來說,AFL + QEMU user-mode 會因為許多兼容性問題導致錯誤,可以透過 full-system 模擬來避免
#### AFL + QEMU full-system emulation
* AFL 加上 full-system 模擬的 QEMU 能 fuzzing 整個 firmware image + application
* 但整個 fuzzing 的速度會大幅下降
#### AFL + QEMU hybrid emulation
* 為了解決上述問題,Firm-AFL 嘗試結合兩者
* 在 user-mode 下執行 code,並將 system calls 導向到 full-system 中
* 當程式頻繁地出現 system call 時,效率依舊低下
* Firm-AFL 仍然有進步空間
### Terminology
* Guest/Host Machine
* 在 full-system 模擬中,guest 指包含韌體的虛擬機器、host 指跑著 OS 的那台實體機器
* host 用模擬器執行 guest
* Page Global Directory
* PGD 指程式執行時的 top physical page frame
* 因為每個程式的 PGD 的開頭是唯一的,可用於識別 user-space 中的程式
## Overview
* 在 user-mode 下 fuzzing 很快但是容易失敗、在 full-system 下 fuzzing 容易成功但是缺乏效率
* 希望有 full-system 的成功率但越快越好
* 提出 EQUAFL(AFL-based Enhanced QEMU User-mode emulation)
* ![](https://i.imgur.com/sh74iyt.png)
* 主要兩步驟
* observation
* replay
* observation 階段會用 full-system 模擬,紀錄
* launch variables
* file generation
* NVRAM related operation
* network interaction
* process resource limits
* replay 階段利用蒐集到的資訊部屬設定在 host 上或是在 user-mode 重跑攔截到的 system-call
* 調整 PUT 的 lifecycle 和 fuzzing 的 entry point,可從網路層做 fuzzing
## Approaches
### Launch Variables Settlement
* 啟動變數是 PUT 在模擬系統中啟動的參數和環境變數
* PUT 表示為 $P^{*1}$、程式名、參數和環境變數表示為 $p^{name}$, $p^{vars}$ 和 $p^{envs}$
* 這些資訊會用很多種方式存在韌體中,例如配置文件、hard-encoded 在執行檔或是由父 process 傳遞,因此無法用靜態方式提取
* 直接用 full-system 模擬取得
#### Observation
* 偵測 kernel function 的 do_execve 來得到程序的 pname pvars penvs
* 三種 function call 會能計算這些地址
* 接著找到 QEMU 中最靠近這些指令的 Basic block
* 最後在 full-system 模擬時存下這些 block 的值
#### Replay
* 經過 Observation 後,我們得到一個集合的 pname pvars penvs(每個 process 就有一組)
* 將 pname 設為想要測試的目標 process,並將 pvars penvs 設為對應的 pairs,進行 user-mode 模擬
### Filesystem State Synchronization
* 模擬時通常會掛載一個 filesystem,並在初始化時不斷改變它
* 沒有正確的 filesystem 導致 PUT 在 user-mode 執行錯誤
* observe-replay 觀察與文件相關的 system call,並在 host 執行
* 問題是在 host 上 replay 時可能會出現未知的值,例如下圖
* ![](https://i.imgur.com/uJYCze2.png)
* 提出 process-aware observation 的方法去 mapping 這些映射
#### Accurate Process Identification
* guest 中需要做 process collection 和 process inference(收集和推斷)
* 收集利用檢查 fork 和 execve 來檢測新的 process
* 從 task_struct 得到 PGD, PID, PPID 等資訊
#### Process-aware Observation
* 蒐集到 process 後,進一步蒐集他們的 system call
* 過濾不影響文件的,剩餘的分為兩種
* 直接處理路徑,如 mkdir 等
* 處理 file desciptor(fd),如 open
* 將 Process, fd_guest, fd_host 的關係建立起來後即可在 host 上重新執行
#### Replay
* ![](https://i.imgur.com/aKdP7Pe.png)
* id_sys: 重放的 system call
* p*: 目前的 process
* obj_arg: id_sys 的主要參數(檔案路徑或是 fd)
* other_args: id_sys 其他的參數
* RDIR: host 上韌體的 filesystem 的路徑
### NVRAM Configuration
* Firmadyne 中,使用一般文件紀錄 NVRAM 的配置
* 因為前面已經實現 filesysyem 的同步,所以 NVRAM 的配置也已經在 host 上存在
* 利用 LD_PRELOAD 使用自訂的 library 執行 PUT
### Network Behavior
* 網路行為會受到外界互動的影響
* 為了模擬網路行為,觀察與網路有關的 system call 並建立狀態機
* 在 full-system 模擬中監控 socket,並利用 type 參數識別是否與網路有關
* 網路互動的狀態機模型如下
* ![](https://i.imgur.com/HntnNd6.png)
* 感覺 Fuzzing 的地方是 read/recv/recvfrom 那
### Process Resource Limits
* RLIMIT_NOFILE 是 PUT 可以打開的 fd 最大值
* 太大會降低 PUT 執行速度
* 通常 host 會超大,所以要重設
* 利用 Linux 中的 setrlimit 和 getrlimit system call 來取得這些值
## Implementation
### Emulation
#### Observation
* 首先 EQUAFL 利用 FIRMADYNE 執行 PUT 和 full-system 模擬
* full-system 模擬用於紀錄所有 system call 執行的參數和 return 值
#### Replay
* launch variables, filesystem state synchronization, NVRAM configuration 這三點,EQUAFL 直接在 host 上部屬一樣的資源
* launch variables 利用 IDA Pro 實現
* filesystem state synchronization 透過 Binwalk 解包韌體
* 利用 chroot 將提取的 filesystem 當作根目錄,相對路徑才不會錯誤
### Fuzzing
* 將接收網路輸入的 system call 當作入口點
* 輸入會進入到網路的內存區
* 檢測 read, recv, recvfrom 等等
## Evaluation
* 實現基於 QEMU 的 EQUAFL
* 有對 full-system 和 user-mode 修改
* 修改 AFL 更改 afl-fuzz 接受的參數,正確加載目標的參數和環境變數
* 評估三點
* Compatibility 兼容性
* Efficiency 效率
* Vulnerability discovery 漏洞發現
### Experiments Setup Benchmarks
* 兩個數據集
* nbench 和 lmbench
* 70 個來自 D-Link, TRENDnet, NETGEAR 的韌體
* 在 AFL-Full 和 Firm-AFL 都能成功模擬和測試
* ![](https://i.imgur.com/W3dULJs.png)
* 三個比較對象
* AFL-User
* 預設的 AFL QEMU mode
* AFL-Full
* 將AFL 和 QEMU 的 full-system 模擬結合
* 利用 DECAF 中的 VMI 來監控目標 process
* Firm-AFL
* 交替切換 full-system 和 user-mode
* AFL 有使用字典和種子
* 字典來自目標程式的靜態分析
* 種子是一個正常的網路請求
* 兼容性和效率評估的環境
* 12-core Intel(R) Xeon(R) E5-1650 v3 3.50GHz CPU
* Ubuntu 18.04.5 LTS
* 15.6GB RAM
* 漏洞發現評估的環境
* 18-core Intel(R) Xeon(R) CPU E5-2699 v3 2.30GHz CPU
* Ubuntu 18.04.5 LTS
* 188GB RAM
* 為了降低 Fuzz 的隨機性,每個實驗跑五次
### Compatibility
* AFL-Full 和 Firm-AFL 都可以成功
* ![](https://i.imgur.com/kTveQF9.png)
* CRA: 用初始的種子就 crash
* HAN: 用初始的種子就 hang
* ERR: 目標可以由 fuzzer 啟動,但有錯誤(例如找不到文件等)
* SUCC: 成功
* EQUAFL 成功了 66 個,而 AFL-User 全失敗
* ![](https://i.imgur.com/nPkxz9w.png)
* 與 full-system 的 system call 相似性,不同的部分大多是因為 process 通訊的差異造成
### Efficiency
* 兩種評估
* 與 AFL-Full 和 Firm-AFL 比較吞吐量
* EQUAFL 和 User-mode 比較 cost
* 因為 User-mode 很多跑不起來,用第一個資料集來評估
* 吞吐量
* 收集 1188 個種子,計算平均執行時間(跑 5 次)
* 平均執行時間的倒數為平均吞吐量
* ![](https://i.imgur.com/nDFUyAm.png)
* 比 Full 快 26 倍、比 Firm 快 14 倍
* cost
* ![](https://i.imgur.com/0bJuG2R.png)
* ![](https://i.imgur.com/0Li4yb5.png)
* 基本上沒有額外 cost
### Vulnerability Discovery
* ![](https://i.imgur.com/ixwa9zu.png)
* 找到 10 個漏洞
* 9 個使用 NULL 指標
* 1 個整數 overflow
* 其中 6 個得到 CVE
* ![](https://i.imgur.com/ykkdKCp.png)
* 24 小時內 unique 漏洞數
* 最快發現漏洞
## Threats to Validity
* 外部設備目前只支援 NVRAM
* 與其它 process 互動的部分可能會出錯
* 多個程式交互的漏洞無法發掘
## Related Work
* Static analysis
* PIE
* Firmalice
* DTaint
* Karonte
* SaTC
* Dynamic analysis
* Avatar
* Firmadyne
* FirmAE
* Fuzzing
* IOTFUZZER
* boofuzz
* Firmcorn
* FirmFuzz
* EM-Fuzz
## Conclusion
* 提出 EQUAFL,為 Linux-based 韌體的網路應用程式 Fuzzing 的框架
* 透過增強的 User-mode 避免 full-system 的 cost
* 發現 10 個漏洞,包含 6 個 CVE
---
* [EQUAFL 網頁](https://sites.google.com/view/equafl/home?authuser=0)
###### tags: `paper`