关于kvm-fuzz
kvm-fuzz是一款功能强大的模糊测试工具,该工具能够利用KVM技术对闭源用户空间x86_64二进制文件执行模糊测试。
KVM介绍
虚拟化是云计算的基础,一种资源管理技术,是将计算机的各种实体资源(CPU、内存、磁盘空间、网络适配器等)做虚拟化、将虚拟化后的整体做为一个可供分割且组合的操作系统。
服务器虚拟化是云计算最核心的技术,而KVM是当前最主流的开源的服务器虚拟化技术。KVM 全称是 Kernel-Based Virtual Machine,基于Linux内核的虚拟化技术。KVM基于Linux内核实现,属于半虚拟化的Hypervisor。KVM有一个内核模块叫 kvm.ko,只用于管理虚拟 CPU 和内存,而Qemu则协助提供IO设备半虚拟化,用于虚拟磁盘IO和网络IO等。不过IO设备的虚拟化方向都是往直接透传到宿主机的方向走,比如vhost-net,直接在硬件或内核级别支持。一个 KVM虚机在宿主机中其实是一个qemu-kvm进程。而每个虚机中的vCPU则为宿主机中的一个线程。
工具要求
Zig 0.12.0
libdwarf
libelf
libssl
Python 3
angr
工具安装
首先,我们需要使用下列命令安装并配置好该工具所需的依赖组件和环境工具:
sudo apt install libdwarf-dev libelf-dev libssl-dev sudo apt install python3 python3 -m pip install angr
为了使用Intel PT执行基于覆盖率的模糊测试,我们还需要自行安装好libxdc和kAFL。
接下来,广大研究人员可以直接使用下列命令将该项目源码克隆至本地:
git clone https://github.com/klecko/kvm-fuzz.git
然后切换到项目目录中,运行下列命令构建内核和虚拟机管理程序:
cd kvm-fuzz zig build
系统调用测试由一个二进制文件组成,它使用不同的系统调用并检查其是否正确。为了构建和运行该文件,我们可以使用提以下脚本:
./scripts/run_tests_on_linux.sh ./scripts/run_tests_on_kvm-fuzz.sh
执行之后,我们将能够看到如下所示的你诶容:
[KERNEL] =============================================================================== [KERNEL] All tests passed (2378 assertions in 44 test cases) [KERNEL] Run ended with reason Exit
工具帮助信息
kvm-fuzz: fuzz x86_64 closed-source applications with hardware acceleration Usage: kvm-fuzz [ options ] -- /path/to/fuzzed_binary [ args ] Available options: --minimize-corpus 设置语料库最小化模式 --minimize-crashes 设置碰撞最小化模式 -j, --jobs n 要使用的线程数(默认值:8) -m, --memory arg 虚拟机内存限制(默认值:8M) -t, --timeout ms 每次运行的超时时间(毫秒),0表示没有超时(默认值:2) -k, --kernel path 内核路径(默认值:./zig out/bin/kernel) -i, --input dir 输入文件夹(初始语料库)(默认值:./in) -o, --output dir 输出文件夹(语料库、崩溃等)(默认值:./out) -f, --file path 目标的内存加载文件,一次设置一个文件,例如-f file1 -f file2 -s, --single-run [=path] 执行一次任务,可以选择指定输入文件 -T, --tracing type 启用系统调用追踪,类型可以是内核或用户 --tracing-unit unit 追踪单元,它可以是指令或循环(默认循环) -h, --help 打印工具帮助信息
工具使用
现在,我们使用ls源码作为种子,来对readelf执行模糊测试。运行kvm-fuzz并为虚拟机设置 16 MB 内存和 5 毫秒的超时时间:
$ zig build -Dcoverage=none $ rm in/1 $ cp /bin/ls in/ $ zig-out/bin/kvm-fuzz -m 16M -t 5 -- /bin/readelf -a input Number of threads: 8 Total files read: 1 Max mutated input size: 1421440 Ready to run! [KERNEL] [default] [info] hello from zig [KERNEL] [user] [info] Jumping to user at 0x400000001100 with rsp 0x7ffffffffe70! [...] Performing first runs... Set corpus mode: Normal. Output directories will be ./out/corpus and ./out/crashes. Seed corpus coverage: 0 Creating threads... [1.000] cases: 6265, mips: 10807.154, fcps: 6264.102, cov: 0, corpus: 1/138.812KB, unique crashes: 0 (total: 0), timeouts: 3, no new cov for: 1.000 vm exits: 1.000 (hc: 1.000, cov: 0.000, debug: 0.000), reset pages: 137.765 run: 0.864, reset: 0.045, mut: 0.081, set_input: 0.011, report_cov: 0.000 kvm: 0.863, hc: 0.000, update_cov: 0.000, mut1: 0.007, mut2: 0.075 [2.000] cases: 12907, mips: 11112.763, fcps: 6640.934, cov: 0, corpus: 1/138.812KB, unique crashes: 0 (total: 0), timeouts: 3, no new cov for: 2.000 vm exits: 1.000 (hc: 1.000, cov: 0.000, debug: 0.000), reset pages: 137.109 run: 0.866, reset: 0.044, mut: 0.079, set_input: 0.011, report_cov: 0.000 kvm: 0.865, hc: 0.000, update_cov: 0.000, mut1: 0.007, mut2: 0.072 [3.000] cases: 19397, mips: 11125.964, fcps: 6489.186, cov: 0, corpus: 1/138.812KB, unique crashes: 0 (total: 0), timeouts: 4, no new cov for: 3.000 vm exits: 1.000 (hc: 1.000, cov: 0.000, debug: 0.000), reset pages: 137.286 run: 0.865, reset: 0.044, mut: 0.080, set_input: 0.011, report_cov: 0.000 kvm: 0.865, hc: 0.000, update_cov: 0.000, mut1: 0.007, mut2: 0.074
输出数据中包括一些有用的统计数据,例如用例总数、指令数量、模糊测试数量、语料库大小和时间数据等。
使用基于断点的覆盖率模式执行模糊测试:
$ zig build -Drelease-fast $ zig-out/bin/kvm-fuzz -m 16M -t 5 -- /bin/readelf -a input [...] [3.001] cases: 35001, mips: 11669.951, fcps: 11765.726, cov: 2684, corpus: 143/28689.814KB, unique crashes: 0 (total: 0), timeouts: 4, no new cov for: 0.000 vm exits: 1.031 (hc: 1.000, cov: 0.000, debug: 0.031), reset pages: 150.626 run: 0.541, reset: 0.161, mut: 0.242, set_input: 0.055, report_cov: 0.001 kvm: 0.540, hc: 0.000, update_cov: 0.000, mut1: 0.091, mut2: 0.150
我们可以看到我们花了 24% 的时间来改变输入。为了提高模糊测试速度,我们可以使用较小的种子来减少这一时间,将其设置为单个种子并再次运行:
$ rm in/* $ cp /bin/parallel in $ zig-out/bin/kvm-fuzz -m 16M -t 5 -- /bin/readelf -a input [...] [3.001] cases: 88147, mips: 16667.261, fcps: 31502.726, cov: 3030, corpus: 238/5874.473KB, unique crashes: 0 (total: 0), timeouts: 4, no new cov for: 0.000 vm exits: 1.014 (hc: 1.000, cov: 0.000, debug: 0.014), reset pages: 94.269 run: 0.838, reset: 0.102, mut: 0.052, set_input: 0.007, report_cov: 0.001 kvm: 0.837, hc: 0.000, update_cov: 0.000, mut1: 0.010, mut2: 0.041
性能对比
项目地址
kvm-fuzz:【GitHub传送门】
参考资料
https://github.com/klecko/libxdc
https://github.com/IntelLabs/kAFL
https://github.com/nyx-fuzz/KVM-Nyx
https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md