commit
8ff3e8b7cb
@ -149,6 +149,12 @@ where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
/// Returns the number of elements
|
||||
#[inline]
|
||||
fn count(&self) -> usize {
|
||||
self.entries().len()
|
||||
}
|
||||
|
||||
/// Gets the next entry
|
||||
#[inline]
|
||||
fn next(&mut self, rand: &mut R) -> Result<(&RefCell<Testcase<I>>, usize), AflError> {
|
||||
|
@ -3,18 +3,24 @@
|
||||
use core::fmt::Debug;
|
||||
use core::marker::PhantomData;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use crate::corpus::{Corpus, Testcase};
|
||||
use crate::events::EventManager;
|
||||
use crate::executors::{Executor, ExecutorsTuple, HasObservers};
|
||||
use crate::feedbacks::FeedbacksTuple;
|
||||
use crate::generators::Generator;
|
||||
use crate::inputs::bytes::BytesInput;
|
||||
use crate::inputs::Input;
|
||||
use crate::observers::ObserversTuple;
|
||||
use crate::serde_anymap::{SerdeAny, SerdeAnyMap};
|
||||
use crate::stages::StagesTuple;
|
||||
use crate::tuples::{tuple_list, tuple_list_type};
|
||||
use crate::utils::{current_milliseconds, Rand};
|
||||
|
||||
use crate::AflError;
|
||||
|
||||
pub trait StateMetadata: Debug {
|
||||
@ -44,6 +50,81 @@ where
|
||||
phantom: PhantomData<(I, R, OT)>,
|
||||
}
|
||||
|
||||
impl<R, FT, OT> State<BytesInput, R, FT, OT>
|
||||
where
|
||||
R: Rand,
|
||||
FT: FeedbacksTuple<BytesInput>,
|
||||
OT: ObserversTuple,
|
||||
{
|
||||
pub fn load_from_directory<G, C, E, ET, EM>(
|
||||
&mut self,
|
||||
corpus: &mut C,
|
||||
generator: &mut G,
|
||||
engine: &mut Engine<E, OT, ET, BytesInput>,
|
||||
manager: &mut EM,
|
||||
in_dir: &Path,
|
||||
) -> Result<(), AflError>
|
||||
where
|
||||
G: Generator<BytesInput, R>,
|
||||
C: Corpus<BytesInput, R>,
|
||||
E: Executor<BytesInput> + HasObservers<OT>,
|
||||
ET: ExecutorsTuple<BytesInput>,
|
||||
EM: EventManager<C, E, OT, FT, BytesInput, R>,
|
||||
{
|
||||
for entry in fs::read_dir(in_dir)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
let attributes = fs::metadata(&path);
|
||||
|
||||
if !attributes.is_ok() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let attr = attributes?;
|
||||
|
||||
if attr.is_file() && attr.len() > 0 {
|
||||
println!("Loading file {:?} ...", &path);
|
||||
let bytes = std::fs::read(&path)?;
|
||||
let input = BytesInput::new(bytes);
|
||||
let fitness = self.evaluate_input(&input, engine.executor_mut())?;
|
||||
if self.add_if_interesting(corpus, input, fitness)?.is_none() {
|
||||
println!("File {:?} was not interesting, skipped.", &path);
|
||||
}
|
||||
} else if attr.is_dir() {
|
||||
self.load_from_directory(corpus, generator, engine, manager, &path)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_initial_inputs<G, C, E, ET, EM>(
|
||||
&mut self,
|
||||
corpus: &mut C,
|
||||
generator: &mut G,
|
||||
engine: &mut Engine<E, OT, ET, BytesInput>,
|
||||
manager: &mut EM,
|
||||
in_dirs: &[PathBuf],
|
||||
) -> Result<(), AflError>
|
||||
where
|
||||
G: Generator<BytesInput, R>,
|
||||
C: Corpus<BytesInput, R>,
|
||||
E: Executor<BytesInput> + HasObservers<OT>,
|
||||
ET: ExecutorsTuple<BytesInput>,
|
||||
EM: EventManager<C, E, OT, FT, BytesInput, R>,
|
||||
{
|
||||
for in_dir in in_dirs {
|
||||
self.load_from_directory(corpus, generator, engine, manager, in_dir)?;
|
||||
}
|
||||
manager.log(
|
||||
0,
|
||||
format!("Loaded {} initial testcases.", corpus.count()), // get corpus count
|
||||
)?;
|
||||
manager.process(self, corpus)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, R, FT, OT> State<I, R, FT, OT>
|
||||
where
|
||||
I: Input,
|
||||
|
@ -742,7 +742,7 @@ where
|
||||
/// Else, it will act as client.
|
||||
pub fn new_on_port_std(stats: ST) -> Result<Self, AflError> {
|
||||
Ok(Self {
|
||||
llmp: llmp::LlmpConnection::on_port(port)?,
|
||||
llmp: llmp::LlmpConnection::on_port(1337)?,
|
||||
stats: stats,
|
||||
phantom: PhantomData,
|
||||
})
|
||||
|
@ -17,6 +17,7 @@ opt-level = 3
|
||||
debug = true
|
||||
|
||||
[dependencies]
|
||||
clap = "2.32.0"
|
||||
afl = { path = "../../afl/" }
|
||||
|
||||
[lib]
|
||||
|
@ -1,7 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAP_SIZE 65536
|
||||
|
||||
int orig_argc;
|
||||
char **orig_argv;
|
||||
char **orig_envp;
|
||||
|
||||
uint8_t __lafl_dummy_map[MAP_SIZE];
|
||||
|
||||
uint8_t *__lafl_edges_map = __lafl_dummy_map;
|
||||
@ -119,14 +124,28 @@ void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
|
||||
|
||||
}
|
||||
|
||||
__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
|
||||
|
||||
static void afl_libfuzzer_copy_args(int argc, char** argv, char** envp) {
|
||||
orig_argc = argc;
|
||||
orig_argv = argv;
|
||||
orig_envp = envp;
|
||||
}
|
||||
|
||||
__attribute__((section(".init_array"))) void (* p_afl_libfuzzer_copy_args)(int,char*[],char*[]) = &afl_libfuzzer_copy_args;
|
||||
|
||||
__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
|
||||
void afl_libfuzzer_main();
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int afl_libfuzzer_init() {
|
||||
|
||||
if (LLVMFuzzerInitialize)
|
||||
LLVMFuzzerInitialize(&argc, &argv);
|
||||
return LLVMFuzzerInitialize(&orig_argc, &orig_argv);
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
afl_libfuzzer_main();
|
||||
return 0;
|
||||
|
@ -1,7 +1,14 @@
|
||||
#![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;
|
||||
@ -24,6 +31,9 @@ extern "C" {
|
||||
/// int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
|
||||
fn LLVMFuzzerTestOneInput(data: *const u8, size: usize) -> i32;
|
||||
|
||||
// afl_libfuzzer_init calls LLVMFUzzerInitialize()
|
||||
fn afl_libfuzzer_init() -> i32;
|
||||
|
||||
static __lafl_edges_map: *mut u8;
|
||||
static __lafl_cmp_map: *mut u8;
|
||||
static __lafl_max_edges_size: u32;
|
||||
@ -40,14 +50,69 @@ const NAME_COV_MAP: &str = "cov_map";
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn afl_libfuzzer_main() {
|
||||
let mut rand = StdRand::new(0);
|
||||
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 statstime = 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();
|
||||
|
||||
let mut mgr = LlmpEventManager::new_on_port_std(1337, stats).unwrap();
|
||||
if mgr.is_broker() {
|
||||
println!("Doing broker things. Run this tool again to start fuzzing in a client.");
|
||||
mgr.broker_loop().unwrap();
|
||||
@ -66,16 +131,35 @@ pub extern "C" fn afl_libfuzzer_main() {
|
||||
|
||||
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");
|
||||
// Call LLVMFUzzerInitialize() if present.
|
||||
unsafe {
|
||||
if afl_libfuzzer_init() == -1 {
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||
}
|
||||
}
|
||||
|
||||
match input {
|
||||
Some(x) => state
|
||||
.load_initial_inputs(&mut corpus, &mut generator, &mut engine, &mut mgr, &x)
|
||||
.expect("Failed to load initial corpus"),
|
||||
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);
|
||||
|
@ -1,11 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
cargo build --release
|
||||
make -C runtime
|
||||
cargo build --release || exit 1
|
||||
make -C runtime || exit 1
|
||||
|
||||
./compiler -flto=thin -c test/test.c -o test_fuzz.o
|
||||
./compiler -flto=thin -fuse-ld=lld test_fuzz.o -o test_fuzz.elf
|
||||
rm -f test_fuzz.elf test_fuzz.o
|
||||
./compiler -flto=thin -c test/test.c -o test_fuzz.o || exit 1
|
||||
./compiler -flto=thin test_fuzz.o -o test_fuzz.elf || exit 1
|
||||
|
||||
RUST_BACKTRACE=1 ./test_fuzz.elf
|
||||
RUST_BACKTRACE=1 ./test_fuzz.elf &
|
||||
|
||||
test "$!" -gt 0 && {
|
||||
|
||||
usleep 250
|
||||
RUST_BACKTRACE=1 ./test_fuzz.elf -x a -x b -T5 in1 in2 &
|
||||
|
||||
}
|
||||
|
||||
sleep 10
|
||||
killall test_fuzz.elf
|
||||
|
||||
#rm ./test_fuzz.elf
|
||||
|
Loading…
x
Reference in New Issue
Block a user