LibAFL QEMU: A Library for Fuzzing-oriented Emulation EURECOM 2024
Romain Malmain, Andrea Fioraldi, Aurelien Francillon
论文笔记、部分代码实现分析
当主机和目标体系结构相似时,虚拟化这样的硬件辅助方法在获得接近本机的性能方面特别有效。然而,这种技术不能用于模拟外来的体系结构。它还限制了我们在运行时对目标的控制,因为管理程序在执行自省之前必须等待虚拟机停止。
<aside> 💡 但是 Nyx 团队一直在做基于硬件虚拟化的研究,并且 KVM 在速度提升上的效果也是有目共睹的。所以支持 Fuzz 的时候开启相关的硬件虚拟化,也是很有潜力的研究方向[Google Code Summer 2024]。
</aside>
所以本文选择以软件模拟作为研究方向,软件模拟当前可以分为:
所以从这些可扩展性和易用性方面来考虑,本文关注于 DBT。
尽管QEMU可以通过利用KVM来利用硬件辅助的虚拟化,但我们将只关注仿真。仿真依赖于 QEMU 的 TCG 模型,大致分两个步骤完成:
TCG的编译单元是一个翻译块 (TB),在大多数现代编译器中相当于一 Basic Block。QEMU具有多层 TB 缓存,广泛用于大幅提高性能。因此,如果尚未缓存,则会动态生成TB。QEMU还尽可能将TB链接在一起以加快执行速度,并在必须执行进一步翻译时链接回模拟器。QEMU还允许在目标仿真期间直接执行任何C代码,称为辅助函数。
这个背景知识与 AFL++ 中关于 QemuAFL TB Chain 的优化相关
- AFL 中的 qemuafl 在 TCG engine 执行一次 execute(TB) 前回调 afl_maybe_log(),如果开启了 TB chain 则一次对 execute(TB) 的调用会连续执行多个 TB,丢失部分 Block 的覆盖信息。AFL++ 中将 afl_maybe_log() 以 helper 的形式 inline 到了每个 TB 的头部,就又可以开启 TB chain 的优化了。
- ForkServer 的执行形式会导致子进程的 TB cache 丢失,qemuafl 中实现了 TB cache 同步机制,在 TB Translate 完毕时将结果同步到 forkserver 父进程,那么下次 fork() 出的子进程也会带有该 TB cache,不用再 Translate 一次。
APPENDIX: TCG control flow