程序环境模糊测试(EnvFuzz)
EnvFuzz (εFuzz) 是一种新型的模糊测试器,可以对几乎任何东西进行模糊测试,包括:
- 网络服务器/客户端
- 图形用户界面 (GUI) 应用程序
- 编辑器
- 编译器
- 数据库
- 任何其他Linux用户模式软件等
例如,以下演示展示了如何使用EnvFuzz对GUI应用程序进行模糊测试:
[EnvFuzz对GUI应用程序二进制文件(gnome-calculator
)进行模糊测试的演示。
首先,正常运行应用程序,并将所有环境交互(包括用户输入)记录到文件中。
接下来,对应用程序进行模糊测试,这次是通过重复播放原始记录但应用一个或多个变异。
EnvFuzz快速发现了几个崩溃,以红色突出显示。]
与仅对特定输入源进行模糊测试的现有模糊测试器(如AFL)不同,EnvFuzz对主体与其环境(ε)之间的整个交互进行模糊测试——包括所有文件(配置、缓存、资源、字体等)、套接字(会话管理器、辅助功能服务、名称服务等)、通过窗口系统的用户交互、特殊文件、设备和标准流,如下图所示:
换句话说,EnvFuzz将整个环境(ε)本身视为模糊测试目标——即所谓的程序环境模糊测试。 这甚至包括通过窗口系统的用户交互(例如,鼠标移动、按钮点击等),这些被视为与任何其他套接字或文件没有区别的输入源。 这使得EnvFuzz成为一个非常全面的模糊测试器,因为它会自动对所有输入(和输入组合)进行模糊测试,甚至包括在典型模糊测试活动中通常被忽视的不常见输入。
EnvFuzz也非常通用,旨在对现成的用户模式Linux二进制文件进行模糊测试,无需任何配置或设置。 请参见上面的演示。
EnvFuzz如何工作?
EnvFuzz基于底层的完整环境记录和重放(rr)和模糊测试基础设施。 该基础设施基于这样一个洞察:对于典型的用户模式程序,所有环境交互都通过内核-用户模式接口进行。 因此,通过记录此接口,我们也隐式地记录了程序与环境的交互,然后可以对其进行模糊测试。 基本上,EnvFuzz分两个阶段工作:
- 记录阶段正常执行程序,并将主体与其环境之间的所有交互(例如,系统调用、信号、线程切换等)记录到文件中。
- 接下来是重放与模糊测试阶段,在模糊测试循环中重复执行程序。 然而,这次原始的环境交互从记录中重放,但应用了一个或多个可能的变异。 这些变异可能会引发新的程序行为和可能的崩溃。
由于EnvFuzz在环境交互的抽象层面上工作,它可以对非常多样化的主体进行模糊测试,而无需任何特殊处理。 这使得EnvFuzz强大且易于使用。
上面的简单演示展示了EnvFuzz的使用示例:
-
第一阶段使用以下命令记录
gnome-calculator
应用程序:$ ./env-fuzz record gnome-calculator
这会创建一个
out/
子目录,记录存储在out/RECORD.pcap.gz
文件中。 -
第二阶段使用以下命令模糊测试
gnome-calculator
应用程序:$ ./env-fuzz fuzz
模糊测试器使用步骤(1.)中的原始记录作为初始种子,并重复执行程序。 模糊测试器不会精确重放原始记录,而是应用一个(或多个)变异,引发新的程序行为和可能的崩溃。
发现的崩溃存储在 out/crash/
子目录中,可以使用以下命令重放:
$ ./env-fuzz replay out/crash/SIGSEGV_XXXX_m0YYYY.patch
我们将EnvFuzz应用于各种程序,发现了几个新的错误,包括那些难以或无法用传统模糊测试器发现的错误。 有关更多信息,请参阅下面列出的预印本。
构建
要构建EnvFuzz,只需运行 build.sh
脚本。
$ ./build.sh
这仅在基于Ubuntu的系统上进行过测试。
EnvFuzz使用方法
记录:
$ ./env-fuzz record -- vim hello.txt
重放:
$ ./env-fuzz replay
模糊测试:
$ ./env-fuzz fuzz
重放崩溃:
$ ./env-fuzz replay out/crash/SIGSEGV_XXXX_mYYYYY.patch
调试崩溃:
$ ./env-fuzz replay out/crash/SIGSEGV_XXXX_mYYYYY.patch -d
EnvFuzz还支持(可选的)AFL风格的覆盖率插桩:
插桩程序二进制文件:
$ ./env-fuzz instrument program
这将生成一个插桩后的 program.rr
二进制文件,可以替代原始文件。
也可以对库代码进行插桩:
$ ./env-fuzz instrument /path/to/library.so
这将在 lib/
子目录中放置一个插桩版本的库,该目录包含在库搜索路径中。
EnvFuzz 文件
在模糊测试过程中,将生成几个文件:
out/COMMAND.cmd
:命令行out/RECORD.pcap.gz
:记录out/crash/*.patch
:崩溃补丁out/hang/*.patch
:挂起补丁out/abort/*.patch
:中止补丁out/queue/m*/*.patch
:有趣的补丁lib/
:存储修补后的libc
和插桩库的位置
注意,存储在 out/RECORD.pcap.gz
文件中的交互可以使用 Wireshark 查看。
EnvFuzz 技术信息
EnvFuzz 使用 E9Patch 静态重写 libc
中的所有 syscall
指令。
因此,每当程序调用系统调用(例如 open
、read
、write
等)时,调用将被转移到我们的记录和回放基础设施。
对于记录,该基础设施充当用户模式和内核模式之间的"中间人",所有交互都保存到文件中。
对于回放(带有模糊测试),程序会(重复)执行,但这次每个系统调用都从原始记录中"回放",可能会应用一个或多个变异。
在回放期间,系统调用几乎完全从记录中提供服务,不与内核和真实环境交互。
除了 libc
系统调用外,EnvFuzz 还有特殊方法处理 vDSO、信号、线程切换和 libc
外的系统调用指令。
EnvFuzz 不使用 ptrace。
一个问题是,在应用变异后,程序行为可能(而且会)发生偏离。 事实上,模糊测试的主要目的是诱导新的行为,以期发现新的错误。 为了处理这种情况,EnvFuzz 在变异后采用"系统调用模拟",以"宽松"的回放模式进行。 这允许仅使用原始记录来探索多样化的程序行为。 更多信息请参见下面的预印本。
EnvFuzz 状态
实现完整的环境记录和回放基础设施是出了名的具有挑战性。
例如,相关的 rr-debug
项目估计总共花费了五人年(来源)用于开发(截至 2017 年),即便如此,它也无法完美记录和回放所有程序。
我们的底层记录和回放框架开发时间远未达到这个水平,当前实现应被视为不一定适用于所有程序的"研究原型"。
尽管如此,我们"按原样"提供该系统,因为 EnvFuzz 已被证明在发现其他模糊测试器无法检测到的错误方面很有效,即使实现尚未完全完善。
我们将根据社区的兴趣程度继续开发和改进 EnvFuzz。
EnvFuzz 问题
请记住,EnvFuzz 是 alpha 质量的软件和研究原型。
请在此报告明显的错误:
通常不应报告与回放过程中意外偏离相关的问题。 话虽如此,我们非常欢迎修复偏离问题的拉取请求。
同样,不应报告与缺少 ioctl、fcntl 和 prctl 相关的问题。
相反,您应该尽可能更新相应的 .tab
文件,并考虑提交拉取请求。
致谢
本研究得到新加坡国家研究基金会和新加坡网络安全局在其国家网络安全研发计划(模糊测试 NRF-NCR25-Fuzz-0001)下的支持。本材料中表达的任何意见、发现和结论或建议均为作者的观点,不反映新加坡国家研究基金会和新加坡网络安全局的观点。
许可证
该软件已根据 GNU 公共许可证 (GPL) 第 3 版发布。
有关更多信息,请参阅 LICENSE
文件。
引用 EnvFuzz
有关更多信息,请参阅我们的研究论文:
- Ruijie Meng, Gregory J. Duck, Abhik Roychoudhury, 程序环境模糊测试, ACM SIGSAC 计算机与通信安全会议 (CCS), 2024。
如果您在科学工作中使用此代码,请按以下方式引用论文:
@inproceedings{envfuzz,
title={程序环境模糊测试},
author={Meng, Ruijie and Duck, Gregory J. and Roychoudhury, Abhik},
booktitle={第 31 届 ACM SIGSAC 计算机与通信安全会议 (CCS) 论文集},
year={2024}
}