fuzzer parallelization
This commit is contained in:
parent
5c5f1f77bd
commit
1713824c3b
@ -18,9 +18,11 @@ use std::{
|
|||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{
|
bolts::{
|
||||||
current_nanos, current_time,
|
current_nanos, current_time,
|
||||||
os::dup2,
|
os::{dup2,Cores},
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
tuples::{tuple_list, Merge},
|
tuples::{tuple_list, Merge},
|
||||||
|
shmem::{ShMemProvider,StdShMemProvider},
|
||||||
|
launcher::Launcher,
|
||||||
},
|
},
|
||||||
corpus::{
|
corpus::{
|
||||||
Corpus, OnDiskCorpus, PowerQueueCorpusScheduler,
|
Corpus, OnDiskCorpus, PowerQueueCorpusScheduler,
|
||||||
@ -30,7 +32,7 @@ use libafl::{
|
|||||||
feedbacks::{MapFeedbackState, MaxMapFeedback},
|
feedbacks::{MapFeedbackState, MaxMapFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::SimpleMonitor,
|
monitors::{MultiMonitor,SimpleMonitor},
|
||||||
mutators::{
|
mutators::{
|
||||||
scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations,
|
scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations,
|
||||||
StdMOptMutator, StdScheduledMutator, Tokens,
|
StdMOptMutator, StdScheduledMutator, Tokens,
|
||||||
@ -42,7 +44,8 @@ use libafl::{
|
|||||||
ShadowTracingStage, StdMutationalStage,
|
ShadowTracingStage, StdMutationalStage,
|
||||||
},
|
},
|
||||||
state::{HasCorpus, HasMetadata, StdState},
|
state::{HasCorpus, HasMetadata, StdState},
|
||||||
events::SimpleEventManager,
|
events::{SimpleEventManager,EventConfig},
|
||||||
|
generators::RandBytesGenerator,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
use libafl_qemu::{
|
use libafl_qemu::{
|
||||||
@ -61,7 +64,7 @@ use libafl_qemu::{
|
|||||||
clock::ClockFeedback,
|
clock::ClockFeedback,
|
||||||
clock::QemuClockIncreaseFeedback
|
clock::QemuClockIncreaseFeedback
|
||||||
};
|
};
|
||||||
use wcet_qemu_sys::worst::{HitFeedback,HitcountsMapObserver,HitImprovingFeedback,LenTimeMaximizerCorpusScheduler};
|
use wcet_qemu_sys::worst::{SortedFeedback,HitFeedback,HitcountsMapObserver,HitImprovingFeedback,LenTimeMaximizerCorpusScheduler};
|
||||||
|
|
||||||
|
|
||||||
/// The fuzzer main
|
/// The fuzzer main
|
||||||
@ -214,7 +217,27 @@ fn fuzz(
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
env::remove_var("LD_LIBRARY_PATH");
|
env::remove_var("LD_LIBRARY_PATH");
|
||||||
|
|
||||||
//=========== Initialize the Emulator
|
//=========== Analyze the binary to find the target function address
|
||||||
|
let mut elf_buffer = Vec::new();
|
||||||
|
let elf = EasyElf::from_file(&kernel, &mut elf_buffer)?;
|
||||||
|
|
||||||
|
let input_addr = elf
|
||||||
|
.resolve_symbol("FUZZ_INPUT", 0)
|
||||||
|
.expect("Symbol FUZZ_INPUT not found");
|
||||||
|
let input_addr = virt2phys(input_addr,&elf.goblin());
|
||||||
|
println!("FUZZ_INPUT @ {:#x}", input_addr);
|
||||||
|
let test_length_ptr = elf
|
||||||
|
.resolve_symbol("FUZZ_LENGTH", 0)
|
||||||
|
.expect("Symbol FUZZ_LENGTH not found");
|
||||||
|
let test_length_ptr = virt2phys(test_length_ptr,&elf.goblin());
|
||||||
|
println!("FUZZ_LENGTH @ {:#x}", test_length_ptr);
|
||||||
|
let check_breakpoint = elf
|
||||||
|
.resolve_symbol("trigger_Qemu_break", 0)
|
||||||
|
.expect("Symbol trigger_Qemu_break not found");
|
||||||
|
let check_breakpoint = virt2phys(check_breakpoint,&elf.goblin());
|
||||||
|
println!("Breakpoint at {:#x}", check_breakpoint);
|
||||||
|
|
||||||
|
//=========== Prepare Emulator Args
|
||||||
let args: Vec<String> = vec![
|
let args: Vec<String> = vec![
|
||||||
"qemu-system-arm",
|
"qemu-system-arm",
|
||||||
"-machine","mps2-an385",
|
"-machine","mps2-an385",
|
||||||
@ -228,36 +251,8 @@ fn fuzz(
|
|||||||
"-S"
|
"-S"
|
||||||
].iter().map(|x| x.to_string()).collect();
|
].iter().map(|x| x.to_string()).collect();
|
||||||
let env: Vec<(String, String)> = env::vars().collect();
|
let env: Vec<(String, String)> = env::vars().collect();
|
||||||
let emu = Emulator::new(&args, &env);
|
|
||||||
|
|
||||||
//=========== Analyze the binary to find the target function address
|
|
||||||
let mut elf_buffer = Vec::new();
|
|
||||||
let bin_path=kernel;
|
|
||||||
let elf = EasyElf::from_file(bin_path, &mut elf_buffer)?;
|
|
||||||
|
|
||||||
let test_one_input_ptr = elf
|
|
||||||
.resolve_symbol("FUZZ_INPUT", 0)
|
|
||||||
.expect("Symbol FUZZ_INPUT not found");
|
|
||||||
let test_one_input_ptr = virt2phys(test_one_input_ptr,&elf.goblin());
|
|
||||||
println!("FUZZ_INPUT @ {:#x}", test_one_input_ptr);
|
|
||||||
let test_length_ptr = elf
|
|
||||||
.resolve_symbol("FUZZ_LENGTH", 0)
|
|
||||||
.expect("Symbol FUZZ_LENGTH not found");
|
|
||||||
let test_length_ptr = virt2phys(test_length_ptr,&elf.goblin());
|
|
||||||
println!("FUZZ_LENGTH @ {:#x}", test_length_ptr);
|
|
||||||
let check_breakpoint = elf
|
|
||||||
.resolve_symbol("trigger_Qemu_break", 0)
|
|
||||||
.expect("Symbol trigger_Qemu_break not found");
|
|
||||||
let check_breakpoint = virt2phys(check_breakpoint,&elf.goblin());
|
|
||||||
println!("Breakpoint at {:#x}", check_breakpoint);
|
|
||||||
|
|
||||||
|
|
||||||
//====== Note the input field
|
|
||||||
let input_addr = test_one_input_ptr;
|
|
||||||
println!("Placing input at {:#x}", input_addr);
|
|
||||||
emu.set_breakpoint(check_breakpoint); // trigger_Qemu_break
|
|
||||||
|
|
||||||
//====== Setup log and stdout
|
|
||||||
let log = RefCell::new(
|
let log = RefCell::new(
|
||||||
OpenOptions::new()
|
OpenOptions::new()
|
||||||
.append(true)
|
.append(true)
|
||||||
@ -265,30 +260,18 @@ fn fuzz(
|
|||||||
.open(&logfile)?,
|
.open(&logfile)?,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(unix)]
|
let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");
|
||||||
let mut stdout_cpy = unsafe {
|
let monitor = MultiMonitor::new(|s| {
|
||||||
let new_fd = dup(io::stdout().as_raw_fd())?;
|
println!("{}",s);
|
||||||
File::from_raw_fd(new_fd)
|
writeln!(log.borrow_mut(), "{}",s).unwrap();
|
||||||
};
|
|
||||||
#[cfg(unix)]
|
|
||||||
let file_null = File::open("/dev/null")?;
|
|
||||||
|
|
||||||
//====== Create the most simple status display and managers.
|
|
||||||
|
|
||||||
// 'While the stats are state, they are usually used in the broker - which is likely never restarted
|
|
||||||
let monitor = SimpleMonitor::new(|s| {
|
|
||||||
#[cfg(unix)]
|
|
||||||
writeln!(&mut stdout_cpy, "{}", s).unwrap();
|
|
||||||
#[cfg(windows)]
|
|
||||||
println!("{}", s);
|
|
||||||
writeln!(log.borrow_mut(), "{:?} {}", current_time(), s).unwrap();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// let mut shmem_provider = StdShMemProvider::new()?;
|
//====== Child Function
|
||||||
|
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut mgr, _core_id| {
|
||||||
//====== Create the most simple status display and managers.
|
|
||||||
let mut mgr = SimpleEventManager::new(monitor);
|
|
||||||
|
|
||||||
|
//====== Set up Emu and termination-point
|
||||||
|
let emu = Emulator::new(&args, &env);
|
||||||
|
emu.set_breakpoint(check_breakpoint); // trigger_Qemu_break
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
let edges = unsafe { &mut edges::EDGES_MAP };
|
let edges = unsafe { &mut edges::EDGES_MAP };
|
||||||
let edges_counter = unsafe { &mut edges::MAX_EDGES_NUM };
|
let edges_counter = unsafe { &mut edges::MAX_EDGES_NUM };
|
||||||
@ -316,37 +299,32 @@ fn fuzz(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
let feedback = feedback_or!(
|
let feedback = feedback_or!(
|
||||||
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||||
HitImprovingFeedback::new(target_map.clone()),
|
// HitImprovingFeedback::new(target_map.clone()),
|
||||||
QemuClockIncreaseFeedback::default(),
|
QemuClockIncreaseFeedback::default(),
|
||||||
ClockFeedback::new_with_observer(&clock_observer)
|
ClockFeedback::new_with_observer(&clock_observer)
|
||||||
);
|
);
|
||||||
// let feedback = feedback_or!(
|
|
||||||
// // New maximization map feedback linked to the edges observer and the feedback state
|
|
||||||
// MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
|
||||||
// MapHitIncreaseFeedback::new(),
|
|
||||||
// // Time feedback, this one does not need a feedback state
|
|
||||||
// TimeFeedback::new_with_observer(&time_observer)
|
|
||||||
// );
|
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
let objective = HitFeedback::new(target_map,0.0);
|
// let objective = HitFeedback::new(target_map,0.0);
|
||||||
|
let objective = SortedFeedback::new();
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
let mut state = {
|
let mut state = state.unwrap_or_else(||{
|
||||||
StdState::new(
|
StdState::new(
|
||||||
// RNG
|
// RNG
|
||||||
StdRand::with_seed(current_nanos()),
|
StdRand::with_seed(current_nanos()),
|
||||||
// Corpus that will be evolved, we keep it in memory for performance
|
// Corpus that will be evolved
|
||||||
OnDiskCorpus::new(corpus_dir).unwrap(),
|
OnDiskCorpus::new(&corpus_dir).unwrap(),
|
||||||
// Corpus in which we store solutions (crashes in this example),
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(&objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// They are the data related to the feedbacks that you want to persist in the State.
|
||||||
tuple_list!(feedback_state,clock::MaxIcountMetadata::default()),
|
tuple_list!(feedback_state,clock::MaxIcountMetadata::default()),
|
||||||
)
|
)
|
||||||
};
|
});
|
||||||
|
|
||||||
let calibration = CalibrationStage::new(&mut state, &edges_observer);
|
let calibration = CalibrationStage::new(&mut state, &edges_observer);
|
||||||
|
|
||||||
@ -407,20 +385,27 @@ fn fuzz(
|
|||||||
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
|
let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer));
|
||||||
|
|
||||||
// Read tokens
|
// Read tokens
|
||||||
if let Some(tokenfile) = tokenfile {
|
if let Some(tokenfile) = &tokenfile {
|
||||||
if state.metadata().get::<Tokens>().is_none() {
|
if state.metadata().get::<Tokens>().is_none() {
|
||||||
state.add_metadata(Tokens::from_tokens_file(tokenfile)?);
|
state.add_metadata(Tokens::from_tokens_file(&tokenfile)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.corpus().count() < 1 {
|
if state.corpus().count() < 1 {
|
||||||
state
|
if _core_id == 0 && state.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()]).is_ok() {
|
||||||
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
// println!("We imported {} inputs from disk.", state.corpus().count());
|
||||||
.unwrap_or_else(|_| {
|
} else {
|
||||||
println!("Failed to load initial corpus at {:?}", &seed_dir);
|
let mut generator = RandBytesGenerator::new(32);
|
||||||
process::exit(0);
|
state
|
||||||
});
|
.generate_initial_inputs(
|
||||||
println!("We imported {} inputs from disk.", state.corpus().count());
|
&mut fuzzer,
|
||||||
|
&mut executor,
|
||||||
|
&mut generator,
|
||||||
|
&mut mgr,
|
||||||
|
8,
|
||||||
|
)
|
||||||
|
.expect("Failed to generate the initial corpus");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tracing = ShadowTracingStage::new(&mut executor);
|
let tracing = ShadowTracingStage::new(&mut executor);
|
||||||
@ -430,18 +415,13 @@ fn fuzz(
|
|||||||
|
|
||||||
// Remove target ouput (logs still survive)
|
// Remove target ouput (logs still survive)
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
let file_null = File::open("/dev/null")?;
|
||||||
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
let null_fd = file_null.as_raw_fd();
|
let null_fd = file_null.as_raw_fd();
|
||||||
dup2(null_fd, io::stdout().as_raw_fd())?;
|
dup2(null_fd, io::stdout().as_raw_fd())?;
|
||||||
dup2(null_fd, io::stderr().as_raw_fd())?;
|
dup2(null_fd, io::stderr().as_raw_fd())?;
|
||||||
}
|
}
|
||||||
// reopen file to make sure we're at the end
|
|
||||||
log.replace(
|
|
||||||
OpenOptions::new()
|
|
||||||
.append(true)
|
|
||||||
.create(true)
|
|
||||||
.open(&logfile)?,
|
|
||||||
);
|
|
||||||
|
|
||||||
fuzzer
|
fuzzer
|
||||||
.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)
|
.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)
|
||||||
@ -449,4 +429,23 @@ fn fuzz(
|
|||||||
|
|
||||||
// Never reached
|
// Never reached
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
match Launcher::builder()
|
||||||
|
.shmem_provider(shmem_provider)
|
||||||
|
.configuration(EventConfig::AlwaysUnique)
|
||||||
|
.monitor(monitor)
|
||||||
|
.run_client(&mut run_client)
|
||||||
|
.cores(&Cores::from_cmdline("all").unwrap())
|
||||||
|
// .broker_port(1337)
|
||||||
|
// .remote_broker_addr(remote_broker_addr)
|
||||||
|
//.stdout_file(Some("/dev/null"))
|
||||||
|
.build()
|
||||||
|
.launch()
|
||||||
|
{
|
||||||
|
Ok(_) | Err(Error::ShuttingDown) => (),
|
||||||
|
Err(e) => panic!("{:?}", e),
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -2219,11 +2219,12 @@ where
|
|||||||
loop {
|
loop {
|
||||||
match listener.accept() {
|
match listener.accept() {
|
||||||
ListenerStream::Tcp(mut stream, addr) => {
|
ListenerStream::Tcp(mut stream, addr) => {
|
||||||
eprintln!(
|
// For some reason stderr is not avalible in child
|
||||||
"New connection: {:?}/{:?}",
|
// eprintln!(
|
||||||
addr,
|
// "New connection: {:?}/{:?}",
|
||||||
stream.peer_addr().unwrap()
|
// addr,
|
||||||
);
|
// stream.peer_addr().unwrap()
|
||||||
|
// );
|
||||||
|
|
||||||
// Send initial information, without anyone asking.
|
// Send initial information, without anyone asking.
|
||||||
// This makes it a tiny bit easier to map the broker map for new Clients.
|
// This makes it a tiny bit easier to map the broker map for new Clients.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user