From 8272e640be0f2c42b647202ba17fea7a2e022a80 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Thu, 17 Dec 2020 14:27:11 +0100 Subject: [PATCH] qemufuzzer skeleton --- fuzzers/qemufuzzer/Cargo.toml | 23 +++++++ fuzzers/qemufuzzer/src/lib.rs | 99 ++++++++++++++++++++++++++++++ fuzzers/qemufuzzer/src/regs.rs | 107 +++++++++++++++++++++++++++++++++ fuzzers/qemufuzzer/test.sh | 11 ++++ fuzzers/qemufuzzer/test/test.c | 43 +++++++++++++ 5 files changed, 283 insertions(+) create mode 100644 fuzzers/qemufuzzer/Cargo.toml create mode 100644 fuzzers/qemufuzzer/src/lib.rs create mode 100644 fuzzers/qemufuzzer/src/regs.rs create mode 100755 fuzzers/qemufuzzer/test.sh create mode 100755 fuzzers/qemufuzzer/test/test.c diff --git a/fuzzers/qemufuzzer/Cargo.toml b/fuzzers/qemufuzzer/Cargo.toml new file mode 100644 index 0000000000..b9f8e8c9b9 --- /dev/null +++ b/fuzzers/qemufuzzer/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "qemufuzzer" +version = "0.1.0" +authors = ["Andrea Fioraldi "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +default = ["std"] +std = [] + +[profile.release] +lto = true +codegen-units = 1 +opt-level = 3 +debug = true + +[dependencies] +afl = { path = "../../afl/" } + +[lib] +crate-type = ["staticlib", "cdylib"] diff --git a/fuzzers/qemufuzzer/src/lib.rs b/fuzzers/qemufuzzer/src/lib.rs new file mode 100644 index 0000000000..38f83b434a --- /dev/null +++ b/fuzzers/qemufuzzer/src/lib.rs @@ -0,0 +1,99 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; + +use afl::corpus::InMemoryCorpus; +use afl::engines::Engine; +use afl::engines::Fuzzer; +use afl::engines::State; +use afl::engines::StdFuzzer; +use afl::events::{SimpleStats, LlmpEventManager}; +use afl::executors::inmemory::InMemoryExecutor; +use afl::executors::{Executor, ExitKind}; +use afl::feedbacks::MaxMapFeedback; +use afl::generators::RandPrintablesGenerator; +use afl::mutators::scheduled::HavocBytesMutator; +use afl::mutators::HasMaxSize; +use afl::observers::StdMapObserver; +use afl::stages::mutational::StdMutationalStage; +use afl::tuples::tuple_list; +use afl::utils::StdRand; + +use core::cmp::min; + +mod regs; +use regs::*; + +const FUZZ_MAP_SIZE: usize = 1048576; + +type TargetULong = u64; + +extern "C" { + fn fuzz_run_target(regs: *const x86_64_regs); + fn fuzz_write_mem(addr: TargetULong, buf: *const u8, size: usize); + // fn fuzz_read_mem(addr: TargetULong, buf: *const u8, size: usize); + + static fuzz_start_regs: x86_64_regs; + static mut fuzz_hitcounts_map: [u8; FUZZ_MAP_SIZE]; + static mut fuzz_edges_id: usize; +} + +fn harness(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { + unsafe { + let mut regs = fuzz_start_regs.clone(); + let len = min(buf.len(), 4096); + regs.rsi = len as u64; + fuzz_write_mem(regs.rdi, buf.as_ptr(), len); + fuzz_run_target(®s); + } + ExitKind::Ok +} + +const NAME_COV_MAP: &str = "cov_map"; + +#[no_mangle] +pub extern "C" fn fuzz_main_loop() { + let mut rand = StdRand::new(0); + + let mut corpus = InMemoryCorpus::new(); + let mut generator = RandPrintablesGenerator::new(32); + + let stats = SimpleStats::new(|s| println!("{}", s)); + let mut mgr = LlmpEventManager::new_on_port(1337, stats).unwrap(); + if mgr.is_broker() { + println!("Doing broker things."); + mgr.broker_loop().unwrap(); + } + println!("We're a client, let's fuzz :)"); + + let edges_observer = StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { fuzz_hitcounts_map.as_mut_ptr() }, unsafe { fuzz_edges_id }); + let edges_feedback = MaxMapFeedback::new_with_observer(&NAME_COV_MAP, &edges_observer); + + let executor = InMemoryExecutor::new("QEMUFuzzer", harness, tuple_list!(edges_observer)); + let mut state = State::new(tuple_list!(edges_feedback)); + + let mut engine = Engine::new(executor); + + state + .generate_initial_inputs( + &mut rand, + &mut corpus, + &mut generator, + &mut engine, + &mut mgr, + 4, + ) + .expect("Failed to load initial inputs"); + + let mut mutator = HavocBytesMutator::new_default(); + mutator.set_max_size(4096); + + let stage = StdMutationalStage::new(mutator); + let mut fuzzer = StdFuzzer::new(tuple_list!(stage)); + + fuzzer + .fuzz_loop(&mut rand, &mut state, &mut corpus, &mut engine, &mut mgr) + .expect("Fuzzer fatal error"); + #[cfg(feature = "std")] + println!("OK"); +} diff --git a/fuzzers/qemufuzzer/src/regs.rs b/fuzzers/qemufuzzer/src/regs.rs new file mode 100644 index 0000000000..bf6fe27bec --- /dev/null +++ b/fuzzers/qemufuzzer/src/regs.rs @@ -0,0 +1,107 @@ +/* Generated by hand by Fioraldi bindgen */ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct x86_regs { + pub eax: u32, + pub ebx: u32, + pub ecx: u32, + pub edx: u32, + pub edi: u32, + pub esi: u32, + pub ebp: u32, + pub eip: u32, + pub esp: u32, + pub eflags: u32, + pub xmm_regs: [[u8; 8usize]; 16usize], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct x86_64_regs { + pub rax: u64, + pub rbx: u64, + pub rcx: u64, + pub rdx: u64, + pub rdi: u64, + pub rsi: u64, + pub rbp: u64, + pub r8: u64, + pub r9: u64, + pub r10: u64, + pub r11: u64, + pub r12: u64, + pub r13: u64, + pub r14: u64, + pub r15: u64, + pub rip: u64, + pub rsp: u64, + pub rflags: u64, + pub zmm_regs: [[u8; 32usize]; 64usize], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct arm_regs { + pub r0: u32, + pub r1: u32, + pub r2: u32, + pub r3: u32, + pub r4: u32, + pub r5: u32, + pub r6: u32, + pub r7: u32, + pub r8: u32, + pub r9: u32, + pub r10: u32, + pub r11: u32, + pub r12: u32, + pub r13: u32, + pub r14: u32, + pub r15: u32, + pub cpsr: u32, + pub vfp_zregs: [[u8; 32usize]; 16usize], + pub vfp_xregs: [u32; 16usize], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct arm64_regs { + pub x0: u64, + pub x1: u64, + pub x2: u64, + pub x3: u64, + pub x4: u64, + pub x5: u64, + pub x6: u64, + pub x7: u64, + pub x8: u64, + pub x9: u64, + pub x10: u64, + pub x11: u64, + pub x12: u64, + pub x13: u64, + pub x14: u64, + pub x15: u64, + pub x16: u64, + pub x17: u64, + pub x18: u64, + pub x19: u64, + pub x20: u64, + pub x21: u64, + pub x22: u64, + pub x23: u64, + pub x24: u64, + pub x25: u64, + pub x26: u64, + pub x27: u64, + pub x28: u64, + pub x29: u64, + pub x30: u64, + pub x31: u64, + pub pc: u64, + pub cpsr: u32, + pub vfp_zregs: [[u8; 32usize]; 256usize], + pub vfp_pregs: [[u8; 17usize]; 32usize], + pub vfp_xregs: [u32; 16usize], +} diff --git a/fuzzers/qemufuzzer/test.sh b/fuzzers/qemufuzzer/test.sh new file mode 100755 index 0000000000..bb7c64cbdb --- /dev/null +++ b/fuzzers/qemufuzzer/test.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +cargo build --release + +cd qemu +git pull + +./build_qemu_fuzz.sh ../target/release/libqemufuzzer.a + +cp build/qemu-x86_64 ../qemu_fuzz + diff --git a/fuzzers/qemufuzzer/test/test.c b/fuzzers/qemufuzzer/test/test.c new file mode 100755 index 0000000000..04d002b2ae --- /dev/null +++ b/fuzzers/qemufuzzer/test/test.c @@ -0,0 +1,43 @@ +#include +#include + +int target_func(const uint8_t *buf, size_t size) { + + /*printf("BUF (%ld): ", size); + for (int i = 0; i < size; i++) { + printf("%02X", buf[i]); + } + printf("\n");*/ + + if (size == 0) return 0; + + switch (buf[0]) { + + case 1: + if (buf[1] == 0x44) { + //__builtin_trap(); + return 8; + } + + break; + case 0xff: + if (buf[2] == 0xff) { + if (buf[1] == 0x44) { + //*(char *)(0xdeadbeef) = 1; + return 9; + } + } + + break; + default: + break; + + } + + return 1; + +} + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return target_func(Data, Size); +}