论文地址:
http://s3.eurecom.fr/docs/dsn20_corteggiani.pdf
硬件快照
主要是使用Verilog和FPGA中进行仿真
- 基于虚拟机
- 可收集硬件状态
- 使用Verilog或者FPGA实现
现有方法总结
- 虚拟机自检工具,可提供完整的可见性和可控性,但是难以自动化与外设交互,并支持有限的外设
- 硬件外设交互,经常的问题就是外设交互,嵌入式设备往往需要与外设交互
- 模拟硬件外设设备,当外设不可访问的时候,需要mock外设驱动,缺点是容易出错,且模拟起来复杂
- 半实物的方案:输入及输出转发给真实的设备,缺点是使得完全快照不能实现
- 系统快照:复制事件以进行更详细的分析,还可以提高分析性能
总体来说,硬件快照是一种能够记录当前状态的机制,并结合符号执行方法,在FPGA和HDL模拟器上实现的能够快速评估硬件产品的设计
主要贡献
- 支持硬件和固件分析的协同测试框架
- 一种保存或恢复嵌入式系统状态的新方法,包括硬件外设和固件程序,并能够插入自检机制
- 多目标支持硬件仿真
相关工作
- 完全的仿真。QEMU+S2E,用c编写行为模型来模拟外设,优势在于提供完整的可见性、控制和确保符号执行期间的一致性,从而能够并发地和详细的探索多个执行路径
- 部分仿真。将硬件交互重定向到实际设备,不能确保硬件和软件的一致性,缺乏对实际设备的控制和可见性,可能导致误报
- 自动化托管。与底层交互的近似,可能导致误报
- 模拟。硬件模拟器HDL,好处就是可保证一致性,但是比较慢,HDL+FPGA,可见性有限,且慢
这里讲了3种方法
- 天真一致性的方法,重启之后要重新开始
- 天真不一致的方法,虽然没重启,但是硬件执行流程,两次不一致
- 硬件快照,在软件执行流程前进行硬件快照,第二次操作的时候,重新载入硬件快照,这样可以保证一致性,并且节约时间(不需要重启,一旦重启,执行流程就要重新走一遍)
文章里主要强调的是有效和一致性,这也是硬件快照解决的问题,因为在符号执行的过程中,已经覆盖过的分支,按理来说再测试的时候,是不需要再走一边了,如A-B,B有问题,A没问题,那么重启之后,从B直接开始则是最有效的,而如果有了硬件快照,在A执行完之后便保存了硬件和软件的快照,则可在执行B前恢复快照,这样就提高了执行效率
设计思路
测试系统的多路径,减少系统重启时间,需要完全可控和完全可见的快照机制,包括三部分执行:
- 外围设备快照机制(硬件快照的核心部分)
- 可选择的符号虚拟机。将固件程序的指令转发到固件外设,基于KLEE符号执行,提供接口来编写断言
- 快照控制器。能够生成固件和硬件的快照,这些快照可以用来给测试者分析
整体的架构图如下所示:
核心组件是外围硬件设备快照机制:
- 拥有自检机制,自检机制关注可控性和可见性,可控性指的是随时可对外设进行控制,可见性指的是可随时查看外设的状态。结合这两种能力,自检机制随时检查外设,保存或恢复快照,外设使用Verilog进行建模模拟,这样可以获取硬件的寄存器的值
仿真目标
论文里描述,硬件模拟器虽然能够执行HDL语言,也是比较适合作为硬件快照的仿真平台,但是在针对复杂系统时,会非常缓慢,因此文章里,只对外设进行HDL仿真,而实际固件还是在符号执行虚拟机里运行,所以在Overview的图里,作者是使用FPGA+HDL语言,模拟了一个硬件总线,因此符号执行虚拟机可以通过模拟的硬件总线,来控制硬件,使用的工具是Verilator,并提供AXI4-Lite总线的模拟
FPGA目标
作者并没有直接在FPGA中获取硬件状态,因为FPGA对调试相关对支持并不好,作者做的是在HDL中埋点(扫描链),扫描链保存了寄存器的状态,并通过scan_enable信号激活,将寄存器的信息状态信息通过总线来传输到Scan IP部分,这样形成硬件快照
B. 选择符号执行虚拟机
作者通过USB 3.0以及AXI 总线事件,这样可以供符号执行虚拟机来调用,实际上就是自己编写了一个符号执行虚拟机控制硬件的usb驱动程序
C. 快照控制器
负责保存/还原快照,使用CRIU 一个Linux用户空间的框架,可以检查并还原进程,内部硬件管理模块,管理硬件快照,一旦启动会暂停硬件执行,并将快照保存在SRAM里,这样的好处就是可以快速启动和恢复快照
这里作者其实是在FPGA上配置了一个SRAM,用于保存和读取快照,而快照管理器,扫描链的源地址是模拟器保存的硬件状态,然后保存到SRAP上
架构和实践
硬件快照实践
A.1是硬件模拟器,A.2是模拟总线,给外部提供RPC接口调用,这可以模拟简单的硬件,对于复杂的硬件太慢了
B.1和B.2,则是对复杂硬件的模拟,其实就是在FPGA上执行,但是在生成HDL的时候,会进行硬件语言插桩,定期返回硬件寄存器的状态用于生成硬件快照
符号执行虚拟机
扩展了INCEPTION的符号执行虚拟机
软件状态:三元组,某一时间的S(sw) {PC,F,G},PC—程序指针,F栈帧,G全局变量和堆
硬件状态:三元组,某一时间的S(hw),所有硬件寄存器的值
这里AS 所有的状态,初始化是init,也就是程序的入口,当AS不为空,会调用SelectNextState选择下一个状态,为S,这个时候调用两个函数:
- UpdateState:建立硬件快照
- RestoreStare:恢复进程
这里作者的思路就是,在每个状态执行的时候,先保存一下之前的状态(快照),这样每个状态都可被记录,即使当前状态出现问题,我们可以立马恢复到其之前的状态
评价体系
- 保存和恢复快照的时间
- 快照对固件分析的有效性?执行速度和分析的一致性
实验对象:
- SHA256 外设(基于Verilog的)
- AES Counter Mode
- PIC
- TIMER 外设(基于Verilog的)
测试方法:
- 硬件目标开始运行
- 控制程序运行(CRIU,通过USB,测试保存每个外设状态的时间以及恢复时间)
分析结果:
scan chain方法比CRIU 仿真器以及FPGA自身的回读都要快
最终在PIC上进行了测试,具备发现bug的能力
限制
- 基于FPGA的仿真的局限性。侧重数字功能,而不是模拟功能
- 异步逻辑。被测设计可能与无法检测的电路相互作用
结论
- 介绍了硬件快照的概念
- 硬件快照通过插入scan chain的方式来使得硬件状态保持可见性和一致性
- 硬件快照由于保存了硬件的状态,因此不需要重启以及重放,有利于协同分析,github开源:https://github.com/hardsnap/
文章总结
作者解决的问题:
- 硬件测试,不可见性以及不一致性
作者的方法: - 简单的硬件:直接使用硬件模拟器,虚拟化了硬件总线,这样控制器可通过IPC的方式,定时获取硬件快照
- 复杂的硬件:使用HDL语言,并采用scan chain的方式插桩,通过总线IPC的方式进行激活,将每一步的硬件快照都保存在SRAM里
硬件快照如果随时可获得,我们便可以拿来进行分析,有助于我们的FUZZ,因此该文章主要的思路还是对硬件进行仿真,使用仿真器或FPGA实际运行,所谓的硬件快照是一种状态的保存,在每执行一步的时候,都将相关PC、寄存器、栈帧进行保存,最终达到监控与分析的目的,因此借鉴意义:
- 驱动还是要自己写,作者这里统一了下,即通过usb来控制通信,通过总线的形式,将消息传递给相关硬件,但是对于不同硬件具体消息还是需要做各种适配
- 硬件模拟,使用HDL进行仿真,实际的硬件适配成本会比较多
所以如果实际做的话,可以使用HDL+自己写驱动的形式去实践,HDL模拟实际的硬件行为,总体成本还是非常高