使用 KVM 对内存快照进行轻量级模糊测试
Snapchange 能够将原始内存转储和寄存器状态加载到 KVM 虚拟机(VM)中执行。在执行过程中,可以通过重置 KVM 发现的脏页或模糊器手动标记的脏页,将该虚拟机重置到初始状态。
$ cp -r -L fuzzer_template your_new_fuzzer
your_new_fuzzer/create_snapshot.sh 以获取目标快照src/fuzzer.rs 以将变异数据注入 guest VM#[derive(Default)]
pub struct TemplateFuzzer;
impl Fuzzer for TemplateFuzzer {
// The type of Input being fuzzed. Used to know how to generate and mutate useful inputs.
type Input = Vec<u8>;
// The starting address of the snapshot
const START_ADDRESS: u64 = 0x402363;
// The maximum length of mutated input to generate
const MAX_INPUT_LENGTH: usize = 100;
fn set_input(&mut self, input: &Self::Input, fuzzvm: &mut FuzzVm<Self>) -> Result<()> {
// Write the mutated input into the data buffer in the guest VM
fuzzvm.write_bytes_dirty(VirtAddr(0x402004), CR3, &input)?;
Ok(())
}
fn reset_breakpoints(&self) -> Option<&[BreakpointLookup]> {
Some(&[
// Reset when the VM hits example1!main+0x123
BreakpointLookup::SymbolOffset("example1!main", 0x123)
])
}
}
$ cargo run -r -- fuzz -c 16
本 README 中使用的术语:
Hypervisor 首先为每个请求的核心映射物理内存文件。这样,每个核心都有自己唯一的内存副本。随后,hypervisor 创建 KVM guest,并将该后备内存提供给 guest。然后使用给定的寄存器状态初始化该 guest 的寄存器状态,并启动 guest 的执行。Hypervisor 等待 guest 退出。每次退出都由 hypervisor 处理,其中一些会传递给模糊器进行目标特定的变异、修改或内省。如果退出处理程序表示 guest 应被重置,hypervisor 将退出运行循环,将 guest 重置回原始快照状态,并重新启动运行循环。
Guest 的覆盖率通过使用覆盖率断点生成。可以向 hypervisor 提供一个包含要设置断点的地址列表的单独文件。如果命中这些地址中的任何一个,该地址将被添加到覆盖率数据库,并恢复该地址的指令。这样,断点就不会再次触发。
Snapchange 利用目标特定的项目目录进行配置。输入和输出文件及目录都放置在此目录中。以下文件扩展名/目录用作输入:
.physmem - 包含原始物理内存的文件.regs - 包含 寄存器状态 的 JSON 寄存器文件.qemuregs - 来自 qemu 的 info registers 输出项目目录中文件的完整列表及其用途可在此处找到 此处
调试单步追踪的完整示例可在此处找到 此处。
ITERATION 604 0x00007ffff7ecb0d5 0x11115000 | libc-2.31.so!__GI___getpid+0x5 (0x7ffff7ecb0d5)
syscall
[0f, 05]
ITERATION 605 0xffffffff83a00000 0x11115000 | entry_SYSCALL_64+0x0 (0xffffffff83a00000)
swapgs
[0f, 01, f8]
ITERATION 606 0xffffffff83a00003 0x11115000 | entry_SYSCALL_64+0x3 (0xffffffff83a00003)
mov qword ptr gs:[0xa014], rsp
[None:0x0+0xa014=0xa014]]
RSP:0x7fffffffeb78 -> example1!main+0x19 (0x55555555514e)-> 0xff8458b48f44589
[65, 48, 89, 24, 25, 14, a0, 00, 00]
ITERATION 607 0xffffffff83a0000c 0x11115000 | entry_SYSCALL_64+0xc (0xffffffff83a0000c)
nop
[66, 90]
ITERATION 608 0xffffffff83a0000e 0x11115000 | entry_SYSCALL_64+0xe (0xffffffff83a0000e)
mov rsp, cr3
RSP:0x7fffffffeb78 -> example1!main+0x19 (0x55555555514e) -> 0xff8458b48f44589
CR3:0x11115000
[0f, 20, dc]
有关通过 VirtualBox 或 QEMU 获取快照的信息,请参见下文:
示例中包含一个 make_example.sh(如 示例 1)脚本,该脚本可从零开始构建完整快照。这些示例可用作其他目标的可重现快照模板。
make all
cargo doc --open
HACKING 提供了代码库中几个较高层次的入口点,帮助您开始理解整个系统。
有关更多信息,请参阅 CONTRIBUTING。
本项目采用 Apache-2.0 许可证。