近年来,蓝牙设备的应用越发广泛。若蓝牙设备存在漏洞可能会导致信息泄露、经济损失等后果。而蓝牙设备的固件程序更新存在滞后的情况,有些甚至无法进行热更新。目前,针对固件蓝牙协议的漏洞挖掘工具相对缺乏。现有的固件模糊测试工具无法同时满足虚拟化、可交互、微控制器(MCU)适用,以及具备反馈与引导机制、仿真精确性和错误检测机制等需求。因此,提出了一种基于虚拟化的固件蓝牙协议栈模糊测试方案——BBFirmBTFuzz。该方案通过对多种设备进行仿真,以同时支持实时操作系统(RTOS)固件程序和无系统固件程序(bare-metal),并对蓝牙控制器进行仿真。实验结果显示,BBFirmBTFuzz 能够有效地对 Cordio 蓝牙协议栈进行模糊测试。
蓝牙作为一种广泛使用的通信协议,近年来的 数量增长迅猛。据市场调研显示,2021年,蓝牙设备的出货量达到47亿台,并预计在2026年将 超过70亿台。蓝牙设备通常部署在物理硬件,因此若存在漏洞,可能会造成信息泄露、经济损失, 甚至对人身安全造成威胁。与其他固件设备一样, 蓝牙设备的固件程序更新存在滞后性,甚至有些蓝牙设备无法进行热更新。因此,对蓝牙设备的固件程序进行软件测试显得十分必要。模糊测试技术是一种软件测试方法,与符号执行技术相比,其速度更快、开销更小,近年来成为一种流行的有效漏洞挖掘方法。模糊测试通过将随机生成的测试用例输入到程序中,监视程序的运行状态和异常情况,以便探测可能存在的程序漏洞。已经有研究证明,模糊测试技术是一种有效的方法, 并且已经成功挖掘了大量的软件漏洞。随着研究的不断深入,研究人员已将模糊测试技术应用于多种协议、多种固件的软件测试中。通过研究固件蓝牙协议栈的漏洞挖掘方法,可以更好地进行固件蓝牙协议栈的软件测试,从而保护蓝牙设备用户的信息安全甚至人身安全,减少由于漏洞带来的经济损失,维护网络空间的安全与稳定。
当前,已经有许多灰盒模糊测试工具得到了工业界和学术界的广泛认可。然而,这些研究工作并不适用于协议测试。一方面,服务端通常具有状态机模型,客户端需要向服务端发送请求以推进服务端的当前状态,否则输入会在早期被服务端丢弃,从而无法探测深层次的路径。另一方面,协议往往具有一定的语法和语义规则,仅通过字节级的变异算法会产生大量无效的输入。近年来,针对协议模糊测试的工具不断涌现, 例如AFLNET和 StateAFL。此外,还有针对特定协议开发的工具,如ICS3Fuzzer和 TCP-Fuzz]。在这些方案中,AFLNET是比较具有代表性的工具。AFLNET将消息序列作为种子文件,通过解析服务 端的响应包来提取较为粗略的服务端状态变化,并记录种子文件中各个数据包导致的服务端状态变化。通过这种方法,在客户端构建服务端的状态机变化模型,同时将种子文件拆分为M1、M2、M3等。在模糊测试过程中,AFLNET一次仅针对一个服务端 的当前状态进行测试,这种做法被证明非常有效。
对固件程序进行模糊测试时,首要任务是构建一个仿真环境。这是因为固件设备的硬件资源受限, 仅依靠固件设备进行模糊测试效率低下,并且无法实现规模化。为了建立固件程序的仿真环境,必须 考虑固件程序与外围设备的交互,主要包括中断、 直接内存访问(Direct Memory Access,DMA)和内存映射I/O(Memory-mapped I/O,MMIO)这3个方面。在这些交互中,MMIO是普遍存在的,因此实现固 件程序与 MMIO的交互是构建固件仿真环境所必须考虑的关键因素。针对固件的模糊测试方案主要包括以下几种:
这种方案的代表工作包括Avatar2 和 Inception。虽然这种方法具有一定的效果,但它存在一些问题。首先,它缺乏普适性,无法适用于所有固件设备。其次,在转发过程或在下一个模糊测试循环中重置固件设备的状态时,操作非常缓慢,从而成为模糊测试的性能瓶颈。
(2)抽象替换方案。这种方案的代表工作包括 HALucinator和 Firmadyne。该方法的核心思想是避 免固件程序对MMIO的访问,通过绕过固件程序和外围设备的交互来实现。然而,这需要大量的人工工作来绕过固件程序对MMIO的访问,因此适配性较差。
(3)全仿真的方案。这种方案通过在仿真器中重新实现硬件设备来解决固件程序和外围设备交互的问题。代表性工作有快速仿真器(Quick EMUlator,QEMU)。尽管这种方案可以精确地仿 真MMIO,但它需要对硬件文档有深入地理解,并需要人工来编写重新实现的硬件设备代码,因此工 程化程度较高,相关研究工作较少。
当前,国内外对蓝牙模糊测试的研究工作仍然相对较少,其中具有代表性的方案包括Frankenstein和Sweyntooth。Frankenstein 测试的目标是手机蓝牙模块, 其基于QEMU的虚拟化方案进行实现。该方案通过收集仿真CPU的运行信息来获得程序覆盖率。在手机蓝牙中,host位于应用处理器(Application Processor,AP)芯片上,而蓝牙的controller 位于蓝牙芯片上。Frankenstein 通过将host附着到Linux的 BlueZ 蓝牙协议栈上,支持对controller的模糊测试。
Sweyntooth 方案考虑到了通用型模糊测试工具无法有效地对蓝牙协议进行模糊测试的问题,为其 模糊测试框架添加了协议状态机,以避免产生大量无效的测试用例。除此之外,该方案针对蓝牙数据 包的模糊测试还添加了更为有效的变异算法。这些算法包括通过启发式算法变异特定的蓝牙字段,以及在错误的状态下重复测试蓝牙数据包。这些改进使得Sweyntooth 方案能够更加精准和高效地对蓝牙协议进行模糊测试。
本文研究设计并实现了一种基于虚拟化的固件蓝牙协议栈模糊测试方案,称为BBFirmBTFuzz。固件蓝牙协议栈通常用于智能家居设备,主要针对微控制器(Microcontroller Unit,MCU)固件设备。因此,仿真环境必须适用于MCU设备,而现有的基于Linux的研究方案并不能实现。本文通过使用 QEMU全仿真环境为MCU固件程序提供运行环境。相较于桌面操作系统,固件运行的硬件环境资 源有限。例如,以bare-metal模式编译的expat固 件约为100 KiB,适用于STM32XXXXXB(128KB Flash)型号的开发板;而以实时操作系统(Real-Time Operating System,RTOS)模式编译的 GATT Server (通用属性配置文件)固件约为230 KB,仅适用于 STM32XXXXXC(256KB Flash)以上型号的开发板。本文通过对多种设备的仿真,以同时支持RTOS固 件程序和bare-metal固件程序,并对蓝牙控制器进行了仿真,从而支持对固件蓝牙协议栈的模糊测试。
图1基于虚拟化的固件蓝牙协议栈模糊测试方案架构该方案的宏观结构与AFL一致,分为Fuzzer、 Forkserver 和 Target 这 3 个部分。
(1)Fuzzer:负责模糊测试的逻辑控制和测试 用例的变异。任何使用AFL设计架构的模糊测试引 擎都可以作为该框架的Fuzzer。
(3)Target:PANDA 是真正运行固件程序的 Target。它负责收集固件程序运行的边覆盖率信息, 在固件程序运行时进行错误检测,并通过仿真通用 同步异步收发器(Universal Synchronous Asynchronous Receiver Transmitter,USART)串口接收测试用例输入。为了能够对固件蓝牙协议栈进行模糊测试,同 时支持RTOS固件程序和bare-metal固件程序,固 件蓝牙协议栈虚拟化方案架构如图2所示。
图2固件蓝牙协议栈虚拟化方案架构所有的仿真设备都可以通过仿真嵌套向量中断 控制器(Nested Vectored Interrupt Controller,NVIC) 在任何时候将中断和异常传递给仿真CPU。当仿真 CPU翻译执行完当前基本块后,会处理产生的中断和异常。这个过程通常涉及压栈、执行ISR(中断 服务例程)、出栈等操作。每一个irq(中断请求) 的值对应着中断向量表中的一个中断服务例程表 项。在ARMv7-M芯片中,QEMU只启用了前16个表项(不包括保留的部分),这部分在ARMv7-M 芯片中是通用的。而后续的中断服务例程表项在不 同的硬件环境下会有所不同。因此,在实现仿真环境时,需要手动启用所需的中断服务例程表项,例 如在BBFirmBTFuzz 中需要启用EXTI0中断表项。
仿真NVIC的作用是通知仿真CPU当前产生了一个中断向量号为X的中断。仿真CPU在处理该 中断时,会根据中断向量号从保存在SRAM中的中 断向量表中取出ISR的地址,并将其赋给PC(程 序计数器)寄存器,从而完成此次中断操作。中断向量表首先保存在Flash存储空间的起始地址,在 STM32L152RE 中默认为0x08000000。在初始化阶 段,中断向量表会被复制到SRAM起始地址处,在 STM32L152RE 中默认为0x20000000。随后,在初 始化阶段,会将需要的中断服务例程注册到中断向量表中。最终,SRAM起始地址处保存着完整的中断向量表。
由于模糊测试使用的是应用程序main函数处 的快照,省去了固件程序冗长的初始化过程,因此对于目标而言,SRAM起始地址处保存着完整的中断向量表。
定时器在各种操作系统中都得到了广泛应用, 比如在执行等待秒(wait_s)、毫秒(wait_ms)、 微秒(wait_us)等操作时,即使在bare-metal模式 下,也会通过设置循环中断来实现定时器的效果。在STM32硬件环境下,当仿真CPU需要执行一个 定时任务时,会修改定时器(Timer)的预装载寄 存器,从而设置一个定时任务。当等待时间到达时, 定时器会产生一个中断,通知仿线构建最小仿真设备
本节将介绍如何构建一个最简单的板载仿真设备。实际上,构建仿真设备是一项工程性的任务, 每个仿真设备都与特定的硬件环境相关联。要实现仿真设备,通常需要参考硬件环境的用户手册和数据手册。尽管构建基本的仿真设备需要一些人工参与,但实际上并不需要太多时间。之后,可以根据需求对仿真设备进行扩展。然而,要开发一款成熟的固件模糊测试工程产品,需要适配不同的外围设备和硬件环境,就像QEMU所做的那样。这对于个人而言可能是一项不小的工作量。
板载外围设备挂载在系统总线上,外部外围设备通过串口,如USART、串行外设接口(Serial Peripheral Interface,SPI) 与 开 发 板 相 连, 例如 STM32L15XXB及以下闪存容量的开发板系统架构 如图3所示。因此,构建仿真设备时也需要将其挂 载到QEMU的系统总线上,该工作在创建仿真设备对象后完成。为仿真设备对象设置属性也应在实现 (Realized)仿真设备对象前,例如为定时器对象设置时钟频率。
外围设备与CPU之间通过MMIO交换数据, 实现MMIO功能是构建仿真设备的基础。对仿真设备而言,其需要响应仿真CPU对相应MMIO区域的访问指令,包括读操作和写操作。在QEMU中使 用一块内存区域来模拟仿真设备的各个寄存器。这 样,当仿真CPU访问相应的MMIO区域时,仿真设备通过对各个模拟寄存器进行操作来达到模拟真 实设备的效果。对于一个最简单的板载仿真设备而言,当CPU对相应的MMIO执行写操作时,仅需把源操作数的值赋给模拟寄存器,当CPU对相应 的MMIO执行读操作时,仅需把模拟寄存器的值赋给目的操作数。
除了板载外围设备,外围设备还可以通过串口, 如USART、SPI等,与开发板相连,以扩展开发板 的功能。在STM32L152RE硬件环境下,尽管没有板载蓝牙芯片,但可以通过SPI与蓝牙扩展板连接 以实现蓝牙功能。因此,本节将介绍如何通过仿真 SPI与仿真蓝牙控制器来实现仿真环境的蓝牙功能。
在仿真环境中,SPI只需关注与总线相连的部 分。在STM32L152RE硬件环境下,SPI默认配置为 全双工(full-duplex)的工作模式,这也是SPI的通常工作模式。因此,仿真SPI也需要以全双工的 模式工作。在全双工的工作模式下,SPI Master主 动触发主输出从输入(Master Out Slave In,MOSI) 接口,然后SPI Slave 触发MISO接口。不能由SPI Slave 主动触发MISO接口。因此,读和写操作是同 步完成的。具体来说,当程序只执行写操作时,只 需忽略接收到的字节;当程序只执行读操作时,只 需将空字节写入对应的MMIO中,以引发SPI Slave 的MISO传输。
本节通过对使用RTOS模式编译的GATT服务 端进行模糊测试,从性能、路径覆盖率和新增的种 子文件数这3个指标进行评估,验证BBFirmBTFuzz 的有效性。测试目标选取了Cordio蓝牙协议栈,这 是由ARM开发的专为低功耗、单模式蓝牙设备设 计的协议栈。Cordio蓝牙协议栈因代码规模小、易于使用的API接口和可移植的架构而备受青睐,是开发低功耗蓝牙产品的出色解决方案。
图4和图5分别展示了对固件蓝牙服务端进行 模糊测试过程中的路径覆盖情况与新增种子情况。由于实验以固件程序初始化后的快照作为target, 以避免冗长的初始化过程,提升模糊测试的性能, 否则,实时操作系统启动与初始化的所有路径都将 被包含在其中。因此,在0 h时所探测的路径数量 并不多,这是正常现象,因为对于GATT服务而言, 绝大多数测试用例都会在处理的早期被丢弃。从 图4和图5中可以发现,种子文件的增速和探测路 径的增速并不匹配,这是因为,在模糊测试的早期, 新增的种子文件有较大的概率因为触发新的执行逻 辑而被添加到队列中,而到了模糊测试的后期,新 增的种子文件数更可能因为其他原因被添加到队列 中,例如边执行次数的增加、稳定性(由于RTOS 是多线程的架构)的下降。
实验结果表明,BBFirmBTFuzz能够正确地对 Cordio 蓝牙协议栈进行模糊测试,其执行速度、探测路径数、种子队列长度等指标均处于正常范围。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
iPhone 16两周后亮相?苹果或9月10日举行今年最重磅新品发布会
海外网友热议WBG淘汰TES:JKL别再选女枪了!TES完全不值得信任
上海小朋友的周末好city,钓“鱼”、做饭应有尽有…让孩子们化身“厨艺小达人”
外滩妈妈们的“自留款”,超高颜值的英语故事APP,解锁分级阅读的“新玩法”