libafl package

This commit is contained in:
Andrea Fioraldi 2021-02-15 16:54:33 +01:00
parent b368819108
commit e99c2daa41
50 changed files with 22 additions and 327 deletions

View File

@ -1,6 +0,0 @@
[workspace]
members = [
"afl",
"fuzzers/libfuzzer_libpng",
]

View File

@ -1,11 +1,9 @@
[package]
name = "libfuzzer_dummy"
version = "0.1.0"
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>"]
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
edition = "2018"
[workspace]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
@ -23,13 +21,10 @@ cc = { version = "1.0", features = ["parallel"] }
num_cpus = "1.0"
[dependencies]
clap = "2.32.0"
serde = { version = "1.0", default-features = false, features = ["alloc"] }
postcard = { version = "0.5.1", features = ["alloc"] }
afl = { path = "../../afl/" }
libafl = { path = "../../libafl/" }
[[bin]]
name = "libfuzzer"
name = "libfuzzer_dummy"
path = "./src/mod.rs"
test = false
bench = false

View File

@ -4,7 +4,7 @@
use std::{path::PathBuf};
use std::io::{self, BufRead};
use afl::{
use libafl::{
bolts::{tuples::tuple_list, shmem::UnixShMem},
corpus::{Corpus, InMemoryCorpus},
events::setup_restarting_mgr,
@ -23,8 +23,8 @@ use afl::{
/// The name of the coverage map observer, to find it again in the observer list
const NAME_COV_MAP: &str = "cov_map";
static mut __lafl_edges_map: [u8; 32] = [0; 32];
static __lafl_max_edges_size: u32 = 32;
static mut EDGES_MAP: [u8; 32] = [0; 32];
static EDGES_SIZE: u32 = 32;
/// The wrapped harness function, calling out to the llvm-style libfuzzer harness
fn harness<E, I>(_executor: &E, buf: &[u8]) -> ExitKind
@ -35,11 +35,11 @@ where
//println!("{:?}", buf);
unsafe {
__lafl_edges_map[0] = 1;
EDGES_MAP[0] = 1;
if buf.len() > 0 && buf[0] == 'a' as u8 {
__lafl_edges_map[2] = 1;
EDGES_MAP[2] = 1;
if buf.len() > 1 && buf[1] == 'b' as u8 {
__lafl_edges_map[3] = 1;
EDGES_MAP[3] = 1;
//std::process::abort();
}
}
@ -67,7 +67,7 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), Error> {
setup_restarting_mgr::<_, _, _, _, _, _, UnixShMem, _>(stats, broker_port).expect("Failed to setup the restarter".into());
let edges_observer =
StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { &mut __lafl_edges_map[0] as *mut u8 }, __lafl_max_edges_size as usize);
StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { &mut EDGES_MAP[0] as *mut u8 }, EDGES_SIZE as usize);
let mut state = match state_opt {
Some(s) => s,

View File

@ -1,7 +1,7 @@
[package]
name = "libfuzzer"
name = "libfuzzer_libpng"
version = "0.1.0"
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>"]
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
edition = "2018"
build = "build.rs"
@ -22,14 +22,10 @@ cc = { version = "1.0", features = ["parallel"] }
num_cpus = "1.0"
[dependencies]
clap = "2.32.0"
serde = { version = "1.0", default-features = false, features = ["alloc"] }
postcard = { version = "0.5.1", features = ["alloc"] }
afl = { path = "../../afl/" }
# libc = "0.2"
libafl = { path = "../../libafl/" }
[[bin]]
name = "libfuzzer"
name = "libfuzzer_libpng"
path = "./src/mod.rs"
test = false
bench = false

View File

@ -3,7 +3,7 @@
use std::{env, path::PathBuf};
use afl::{
use libafl::{
bolts::{serdeany::RegistryBuilder, shmem::UnixShMem, tuples::tuple_list},
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
events::setup_restarting_mgr,
@ -16,7 +16,7 @@ use afl::{
stages::mutational::StdMutationalStage,
state::{HasCorpus, HasMetadata, State},
stats::SimpleStats,
utils::StdRand,
utils::{current_nanos, StdRand},
Error, Fuzzer, StdFuzzer,
};
@ -69,7 +69,7 @@ pub fn main() {
/// The actual fuzzer
fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) -> Result<(), Error> {
let mut rand = StdRand::new(afl::utils::current_nanos());
let mut rand = StdRand::new(current_nanos());
// 'While the stats are state, they are usually used in the broker - which is likely never restarted
let stats = SimpleStats::new(|s| println!("{}", s));

View File

@ -1,32 +0,0 @@
[package]
name = "libfuzzer"
version = "0.1.0"
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>"]
edition = "2018"
build = "build.rs"
# 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
[build-dependencies]
cc = { version = "1.0", features = ["parallel"] }
num_cpus = "1.0"
[dependencies]
clap = "2.32.0"
afl = { path = "../../afl/", features = ["std", "runtime"] }
[[bin]]
name = "libfuzzer"
path = "./src/mod.rs"
test = false
bench = false

View File

@ -1,32 +0,0 @@
// build.rs
use std::env;
use std::path::Path;
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let _cwd = env::current_dir().unwrap().to_string_lossy().to_string();
let out_dir = out_dir.to_string_lossy().to_string();
let _out_dir_path = Path::new(&out_dir);
println!("cargo:rerun-if-changed=../libfuzzer_runtime/rt.c",);
println!("cargo:rerun-if-changed=./test/test.c");
// We need clang for pc-guard support
std::env::set_var("CC", "clang");
/*
cc::Build::new()
.file("../libfuzzer_runtime/rt.c")
.compile("libfuzzer-sys-rt");
*/
cc::Build::new()
.file("./test/test.c")
.flag("-fsanitize-coverage=trace-pc-guard")
.compile("libfuzzer-sys-target");
println!("cargo:rustc-link-search=native={}", &out_dir);
println!("cargo:rerun-if-changed=build.rs");
}

View File

@ -1 +0,0 @@
a

View File

@ -1 +0,0 @@
a

View File

@ -1,163 +0,0 @@
#![cfg_attr(not(feature = "std"), no_std)]
#[macro_use]
extern crate clap;
extern crate alloc;
use clap::{App, Arg};
use std::env;
use std::path::PathBuf;
use afl::corpus::Corpus;
use afl::corpus::InMemoryCorpus;
use afl::engines::Engine;
use afl::engines::Fuzzer;
use afl::engines::State;
use afl::engines::StdFuzzer;
use afl::events::{LlmpEventManager, SimpleStats};
use afl::executors::inmemory::InProcessExecutor;
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;
extern "C" {
/// int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
fn LLVMFuzzerTestOneInput(data: *const u8, size: usize) -> i32;
static __lafl_edges_map: *mut u8;
static __lafl_cmp_map: *mut u8;
static __lafl_max_edges_size: u32;
}
fn harness<I>(_executor: &dyn Executor<I>, buf: &[u8]) -> ExitKind {
unsafe {
LLVMFuzzerTestOneInput(buf.as_ptr(), buf.len());
}
ExitKind::Ok
}
const NAME_COV_MAP: &str = "cov_map";
pub fn main() {
let matches = App::new("libAFLrs fuzzer harness")
.about("libAFLrs fuzzer harness help options.")
.arg(
Arg::with_name("port")
.short("p")
.value_name("PORT")
.takes_value(true)
.help("Broker TCP port to use."),
)
.arg(
Arg::with_name("dictionary")
.short("x")
.value_name("DICTIONARY")
.takes_value(true)
.multiple(true)
.help("Dictionary file to use, can be specified multiple times."),
)
.arg(
Arg::with_name("statstime")
.short("T")
.value_name("STATSTIME")
.takes_value(true)
.help("How often to print statistics in seconds [default: 5, disable: 0]"),
)
.arg(Arg::with_name("workdir")
.help("Where to write the corpus, also reads the data on start. If more than one is supplied the first will be the work directory, all others will just be initially read from.")
.multiple(true)
.value_name("WORKDIR")
)
.get_matches();
let _ = value_t!(matches, "statstime", u32).unwrap_or(5);
let broker_port = value_t!(matches, "port", u16).unwrap_or(1337);
let workdir = if matches.is_present("workdir") {
matches.value_of("workdir").unwrap().to_string()
} else {
env::current_dir().unwrap().to_string_lossy().to_string()
};
let mut dictionary: Option<Vec<PathBuf>> = None;
if matches.is_present("dictionary") {
dictionary = Some(values_t!(matches, "dictionary", PathBuf).unwrap_or_else(|e| e.exit()));
}
let mut input: Option<Vec<PathBuf>> = None;
if matches.is_present("workdir") {
input = Some(values_t!(matches, "workdir", PathBuf).unwrap_or_else(|e| e.exit()));
}
if dictionary != None || input != None {
println!("Information: the first process started is the broker and only processes the \'-p PORT\' option if present.");
}
println!("Workdir: {:?}", workdir);
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_std(broker_port, stats).unwrap();
if mgr.is_broker() {
println!("Doing broker things. Run this tool again to start fuzzing in a client.");
mgr.broker_loop().unwrap();
}
println!("We're a client, let's fuzz :)");
let edges_observer =
StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { __lafl_edges_map }, unsafe {
__lafl_max_edges_size as usize
});
let edges_feedback = MaxMapFeedback::new_with_observer(&NAME_COV_MAP, &edges_observer);
let executor = InProcessExecutor::new("Libfuzzer", harness, tuple_list!(edges_observer));
let mut state = State::new(tuple_list!(edges_feedback));
let mut engine = Engine::new(executor);
match input {
Some(x) => state
.load_initial_inputs(&mut corpus, &mut generator, &mut engine, &mut mgr, &x)
.expect(&format!("Failed to load initial corpus at {:?}", &x)),
None => (),
}
if corpus.count() < 1 {
println!("Generating random inputs");
state
.generate_initial_inputs(
&mut rand,
&mut corpus,
&mut generator,
&mut engine,
&mut mgr,
4,
)
.expect("Failed to generate initial inputs");
}
println!("We have {} inputs.", corpus.count());
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");
}

View File

@ -1,18 +0,0 @@
#!/bin/sh
cargo build --release || exit 1
cp ./target/release/libfuzzer ./.libfuzzer_test.elf
RUST_BACKTRACE=full taskset -c 0 ./.libfuzzer_test.elf &
test "$!" -gt 0 && {
usleep 250
RUST_BACKTRACE=full taskset -c 1 ./.libfuzzer_test.elf -x a -x b -T5 in1 in2 &
}
sleep 15
echo "[+] Done"
killall .libfuzzer_test.elf
rm -rf ./.libfuzzer_test.elf

View File

@ -1,43 +0,0 @@
#include <stdio.h>
#include <stdint.h>
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);
}

View File

@ -1,7 +1,7 @@
[package]
name = "afl"
name = "libafl"
version = "0.1.0"
authors = ["Dominik Maier <domenukk@gmail.com>"]
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -6,7 +6,7 @@ use std::hash::Hasher;
use xxhash_rust::const_xxh3;
use xxhash_rust::xxh3;
use afl::utils::{Rand, StdRand};
use libafl::utils::{Rand, StdRand};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
fn criterion_benchmark(c: &mut Criterion) {

View File

@ -1,6 +1,6 @@
//! Compare the speed of rand implementations
use afl::utils::{
use libafl::utils::{
Lehmer64Rand, Rand, RomuDuoJrRand, RomuTrioRand, XorShift64Rand, Xoshiro256StarRand,
};
use criterion::{black_box, criterion_group, criterion_main, Criterion};

View File

@ -6,7 +6,7 @@ extern crate alloc;
use core::{convert::TryInto, time::Duration};
use std::{thread, time};
use afl::{
use libafl::{
bolts::{llmp, shmem::UnixShMem},
Error,
};