Run cargo fmt
All checks were successful
CI / build (push) Successful in 1m31s

This commit is contained in:
David Venhoff 2025-08-06 15:29:29 +02:00
parent 27d379486b
commit 119077b190
7 changed files with 288 additions and 213 deletions

View File

@ -1,11 +1,10 @@
extern crate byteorder; extern crate byteorder;
extern crate config;
extern crate glob; extern crate glob;
extern crate nix; extern crate nix;
extern crate serde_derive; extern crate serde_derive;
extern crate snafu; extern crate snafu;
extern crate timeout_readwrite; extern crate timeout_readwrite;
extern crate config;
pub mod exitreason; pub mod exitreason;
pub use exitreason::ExitReason; pub use exitreason::ExitReason;
@ -14,4 +13,3 @@ pub use exitreason::ExitReason;
pub mod nyx; pub mod nyx;
pub use nyx::QemuProcess; pub use nyx::QemuProcess;

View File

@ -1,14 +1,12 @@
use nix::sys::mman::*; use nix::sys::mman::*;
use std::fmt;
use std::fs::File; use std::fs::File;
use std::os::unix::io::IntoRawFd; use std::os::unix::io::IntoRawFd;
use std::fmt;
//use std::sync::atomic::compiler_fence; //use std::sync::atomic::compiler_fence;
//use std::sync::atomic::Ordering; //use std::sync::atomic::Ordering;
use crate::nyx::mem_barrier::mem_barrier; use crate::nyx::mem_barrier::mem_barrier;
use derivative::Derivative; use derivative::Derivative;
/* various Nyx exec codes (aux_buffer.result.exec_result_code) */ /* various Nyx exec codes (aux_buffer.result.exec_result_code) */
@ -19,7 +17,6 @@ pub const NYX_TIMEOUT: u8 = 3;
pub const NYX_INPUT_WRITE: u8 = 4; pub const NYX_INPUT_WRITE: u8 = 4;
pub const NYX_ABORT: u8 = 5; pub const NYX_ABORT: u8 = 5;
pub const AUX_BUFFER_SIZE: usize = 4096; pub const AUX_BUFFER_SIZE: usize = 4096;
const AUX_MAGIC: u64 = 0x54502d554d4551_u64; const AUX_MAGIC: u64 = 0x54502d554d4551_u64;
@ -50,9 +47,7 @@ pub struct AuxBuffer {
} }
impl AuxBuffer { impl AuxBuffer {
pub fn new_readonly(file: File, read_only: bool, size: usize) -> Self { pub fn new_readonly(file: File, read_only: bool, size: usize) -> Self {
let mut prot = ProtFlags::PROT_READ; let mut prot = ProtFlags::PROT_READ;
if !read_only { if !read_only {
prot |= ProtFlags::PROT_WRITE; prot |= ProtFlags::PROT_WRITE;
@ -62,7 +57,15 @@ impl AuxBuffer {
let null_addr = std::num::NonZeroUsize::new(0); let null_addr = std::num::NonZeroUsize::new(0);
let aux_buffer_alloc_size = std::num::NonZeroUsize::new(size).unwrap(); let aux_buffer_alloc_size = std::num::NonZeroUsize::new(size).unwrap();
unsafe { unsafe {
let ptr = mmap(null_addr, aux_buffer_alloc_size, prot, flags, file.into_raw_fd(), 0).unwrap(); let ptr = mmap(
null_addr,
aux_buffer_alloc_size,
prot,
flags,
file.into_raw_fd(),
0,
)
.unwrap();
let header = (ptr.add(HEADER_OFFSET) as *mut auxilary_buffer_header_s) let header = (ptr.add(HEADER_OFFSET) as *mut auxilary_buffer_header_s)
.as_mut() .as_mut()
.unwrap(); .unwrap();
@ -99,19 +102,33 @@ impl AuxBuffer {
/* This is a somewhat hacky way of returning a slice of the total misc area */ /* This is a somewhat hacky way of returning a slice of the total misc area */
pub fn misc_slice(&self) -> &[u8] { pub fn misc_slice(&self) -> &[u8] {
return unsafe { std::slice::from_raw_parts(self.misc as *const auxilary_buffer_misc_s as *const u8, self.size - MISC_OFFSET) }; return unsafe {
std::slice::from_raw_parts(
self.misc as *const auxilary_buffer_misc_s as *const u8,
self.size - MISC_OFFSET,
)
};
} }
/* same... */ /* same... */
pub fn misc_data_slice(&self) -> &[u8] { pub fn misc_data_slice(&self) -> &[u8] {
return unsafe { std::slice::from_raw_parts((self.misc as *const auxilary_buffer_misc_s as *const u8).offset(std::mem::size_of::<u16>() as isize), self.size - MISC_OFFSET - std::mem::size_of::<u16>()) }; return unsafe {
std::slice::from_raw_parts(
(self.misc as *const auxilary_buffer_misc_s as *const u8)
.offset(std::mem::size_of::<u16>() as isize),
self.size - MISC_OFFSET - std::mem::size_of::<u16>(),
)
};
} }
pub fn validate_header(&self) -> Result<(), String> { pub fn validate_header(&self) -> Result<(), String> {
mem_barrier(); mem_barrier();
let mgc = self.header.magic; let mgc = self.header.magic;
if mgc != AUX_MAGIC { if mgc != AUX_MAGIC {
return Err(format!("aux buffer magic mismatch {} != {}...\n[!] Probably the AUX buffer is corrupted?!", AUX_MAGIC, mgc)); return Err(format!(
"aux buffer magic mismatch {} != {}...\n[!] Probably the AUX buffer is corrupted?!",
AUX_MAGIC, mgc
));
} }
let version = self.header.version; let version = self.header.version;
if version != QEMU_PT_VERSION { if version != QEMU_PT_VERSION {
@ -141,7 +158,6 @@ pub struct auxilary_buffer_cap_s {
pub agent_input_buffer_size: u32, /* agent requests a custom input buffer size (if the size is 0, the minimum buffer size is used) */ pub agent_input_buffer_size: u32, /* agent requests a custom input buffer size (if the size is 0, the minimum buffer size is used) */
pub agent_coverage_bitmap_size: u32, /* agent requests a custom coverage bitmap size (if the size is 0, the minimum buffer size is used) */ pub agent_coverage_bitmap_size: u32, /* agent requests a custom coverage bitmap size (if the size is 0, the minimum buffer size is used) */
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[repr(C, packed(1))] #[repr(C, packed(1))]
@ -195,7 +211,6 @@ pub struct auxilary_buffer_result_s {
pub bb_coverage: u32, pub bb_coverage: u32,
pub runtime_usec: u32, pub runtime_usec: u32,
pub runtime_sec: u32, pub runtime_sec: u32,
} }
#[repr(C, packed(1))] #[repr(C, packed(1))]

View File

@ -1,7 +1,7 @@
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[repr(C, packed(1))] #[repr(C, packed(1))]
pub struct InterpreterData { pub struct InterpreterData {
pub executed_opcode_num: u32 pub executed_opcode_num: u32,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View File

@ -12,20 +12,20 @@ use std::path::PathBuf;
extern crate config; extern crate config;
fn into_absolute_path(sharedir: &str) -> String { fn into_absolute_path(sharedir: &str) -> String {
let srcdir = PathBuf::from(&sharedir); let srcdir = PathBuf::from(&sharedir);
if srcdir.is_relative() { if srcdir.is_relative() {
return fs::canonicalize(&srcdir).unwrap().to_str().unwrap().to_string(); return fs::canonicalize(&srcdir)
} .unwrap()
else{ .to_str()
.unwrap()
.to_string();
} else {
return sharedir.to_string(); return sharedir.to_string();
} }
} }
pub fn qemu_process_new(sharedir: String, cfg: &config::Config) -> Result<QemuProcess, String> { pub fn qemu_process_new(sharedir: String, cfg: &config::Config) -> Result<QemuProcess, String> {
let qemu_params = params::QemuParams::new(into_absolute_path(&sharedir), cfg); let qemu_params = params::QemuParams::new(into_absolute_path(&sharedir), cfg);
return qemu_process::QemuProcess::new(qemu_params); return qemu_process::QemuProcess::new(qemu_params);
} }

View File

@ -1,5 +1,8 @@
use crate::{
config::{Config, FuzzRunnerConfig, QemuNyxRole},
QemuProcess,
};
use std::time::Duration; use std::time::Duration;
use crate::{config::{Config, FuzzRunnerConfig, QemuNyxRole}, QemuProcess};
pub struct QemuParams { pub struct QemuParams {
pub cmd: Vec<String>, pub cmd: Vec<String>,
@ -20,9 +23,7 @@ pub struct QemuParams {
} }
impl QemuParams { impl QemuParams {
pub fn new(sharedir: String, fuzzer_config: &Config) -> QemuParams { pub fn new(sharedir: String, fuzzer_config: &Config) -> QemuParams {
let mut cmd = vec![]; let mut cmd = vec![];
let qemu_id = fuzzer_config.runtime.worker_id(); let qemu_id = fuzzer_config.runtime.worker_id();
@ -44,12 +45,12 @@ impl QemuParams {
cmd.push("-append".to_string()); cmd.push("-append".to_string());
cmd.push("nokaslr oops=panic nopti ignore_rlimit_data".to_string()); cmd.push("nokaslr oops=panic nopti ignore_rlimit_data".to_string());
}, }
FuzzRunnerConfig::QemuSnapshot(x) => { FuzzRunnerConfig::QemuSnapshot(x) => {
cmd.push(x.qemu_binary.to_string()); cmd.push(x.qemu_binary.to_string());
cmd.push("-drive".to_string()); cmd.push("-drive".to_string());
cmd.push(format!("file={},index=0,media=disk", x.hda.to_string())); cmd.push(format!("file={},index=0,media=disk", x.hda.to_string()));
}, }
} }
/* generic QEMU-Nyx parameters */ /* generic QEMU-Nyx parameters */
@ -95,11 +96,17 @@ impl QemuParams {
cmd.push("-device".to_string()); cmd.push("-device".to_string());
let mut nyx_ops = format!("nyx,chardev=nyx_interface"); let mut nyx_ops = format!("nyx,chardev=nyx_interface");
nyx_ops += &format!(",bitmap_size={}", fuzzer_config.fuzz.bitmap_size); nyx_ops += &format!(",bitmap_size={}", fuzzer_config.fuzz.bitmap_size);
nyx_ops += &format!(",input_buffer_size={}", fuzzer_config.fuzz.input_buffer_size); nyx_ops += &format!(
",input_buffer_size={}",
fuzzer_config.fuzz.input_buffer_size
);
nyx_ops += &format!(",worker_id={}", qemu_id); nyx_ops += &format!(",worker_id={}", qemu_id);
nyx_ops += &format!(",workdir={}", workdir); nyx_ops += &format!(",workdir={}", workdir);
nyx_ops += &format!(",sharedir={}", sharedir); nyx_ops += &format!(",sharedir={}", sharedir);
nyx_ops += &format!(",aux_buffer_size={}", fuzzer_config.runtime.aux_buffer_size()); nyx_ops += &format!(
",aux_buffer_size={}",
fuzzer_config.runtime.aux_buffer_size()
);
nyx_ops += &format!(",dump_pt_trace={}", true); nyx_ops += &format!(",dump_pt_trace={}", true);
let mut i = 0; let mut i = 0;
@ -111,7 +118,10 @@ impl QemuParams {
} }
if fuzzer_config.fuzz.cow_primary_size.is_some() { if fuzzer_config.fuzz.cow_primary_size.is_some() {
nyx_ops += &format!(",cow_primary_size={}", fuzzer_config.fuzz.cow_primary_size.unwrap()); nyx_ops += &format!(
",cow_primary_size={}",
fuzzer_config.fuzz.cow_primary_size.unwrap()
);
} }
cmd.push(nyx_ops); cmd.push(nyx_ops);
@ -131,48 +141,60 @@ impl QemuParams {
if fuzzer_config.runtime.reuse_root_snapshot_path().is_some() { if fuzzer_config.runtime.reuse_root_snapshot_path().is_some() {
cmd.push("-fast_vm_reload".to_string()); cmd.push("-fast_vm_reload".to_string());
cmd.push(format!("path={},load=on", fuzzer_config.runtime.reuse_root_snapshot_path().unwrap())); cmd.push(format!(
} "path={},load=on",
else{ fuzzer_config.runtime.reuse_root_snapshot_path().unwrap()
));
} else {
match fuzzer_config.runner.clone() { match fuzzer_config.runner.clone() {
FuzzRunnerConfig::QemuKernel(_) => { FuzzRunnerConfig::QemuKernel(_) => {
match fuzzer_config.runtime.process_role() { match fuzzer_config.runtime.process_role() {
QemuNyxRole::StandAlone => { QemuNyxRole::StandAlone => {
cmd.push("-fast_vm_reload".to_string()); cmd.push("-fast_vm_reload".to_string());
cmd.push(format!("path={}/snapshot/,load=off,skip_serialization=on", workdir)); cmd.push(format!(
}, "path={}/snapshot/,load=off,skip_serialization=on",
workdir
));
}
QemuNyxRole::Parent => { QemuNyxRole::Parent => {
cmd.push("-fast_vm_reload".to_string()); cmd.push("-fast_vm_reload".to_string());
cmd.push(format!("path={}/snapshot/,load=off", workdir)); cmd.push(format!("path={}/snapshot/,load=off", workdir));
}, }
QemuNyxRole::Child => { QemuNyxRole::Child => {
cmd.push("-fast_vm_reload".to_string()); cmd.push("-fast_vm_reload".to_string());
cmd.push(format!("path={}/snapshot/,load=on", workdir)); cmd.push(format!("path={}/snapshot/,load=on", workdir));
}, }
}; };
}, }
FuzzRunnerConfig::QemuSnapshot(x) => { FuzzRunnerConfig::QemuSnapshot(x) => {
match fuzzer_config.runtime.process_role() { match fuzzer_config.runtime.process_role() {
QemuNyxRole::StandAlone => { QemuNyxRole::StandAlone => {
cmd.push("-fast_vm_reload".to_string()); cmd.push("-fast_vm_reload".to_string());
if x.presnapshot.is_empty() { if x.presnapshot.is_empty() {
cmd.push(format!("path={}/snapshot/,load=off,skip_serialization=on", workdir)); cmd.push(format!(
"path={}/snapshot/,load=off,skip_serialization=on",
workdir
));
} else { } else {
cmd.push(format!("path={}/snapshot/,load=off,pre_path={},skip_serialization=on", workdir, x.presnapshot)); cmd.push(format!(
"path={}/snapshot/,load=off,pre_path={},skip_serialization=on",
workdir, x.presnapshot
));
}
} }
},
QemuNyxRole::Parent => { QemuNyxRole::Parent => {
cmd.push("-fast_vm_reload".to_string()); cmd.push("-fast_vm_reload".to_string());
cmd.push(format!("path={}/snapshot/,load=off,pre_path={}", workdir, x.presnapshot)); cmd.push(format!(
}, "path={}/snapshot/,load=off,pre_path={}",
workdir, x.presnapshot
));
}
QemuNyxRole::Child => { QemuNyxRole::Child => {
cmd.push("-fast_vm_reload".to_string()); cmd.push("-fast_vm_reload".to_string());
cmd.push(format!("path={}/snapshot/,load=on", workdir)); cmd.push(format!("path={}/snapshot/,load=on", workdir));
}, }
}; };
}, }
} }
} }
@ -180,13 +202,12 @@ impl QemuParams {
QemuNyxRole::StandAlone | QemuNyxRole::Parent => { QemuNyxRole::StandAlone | QemuNyxRole::Parent => {
assert!(qemu_id == 0); assert!(qemu_id == 0);
QemuProcess::prepare_workdir(workdir, fuzzer_config.fuzz.seed_path.clone()); QemuProcess::prepare_workdir(workdir, fuzzer_config.fuzz.seed_path.clone());
}, }
QemuNyxRole::Child => { QemuNyxRole::Child => {
QemuProcess::wait_for_workdir(workdir); QemuProcess::wait_for_workdir(workdir);
}, }
}; };
return QemuParams { return QemuParams {
cmd, cmd,
qemu_aux_buffer_filename, qemu_aux_buffer_filename,
@ -203,8 +224,7 @@ impl QemuParams {
cow_primary_size: fuzzer_config.fuzz.cow_primary_size, cow_primary_size: fuzzer_config.fuzz.cow_primary_size,
hprintf_fd: fuzzer_config.runtime.hprintf_fd(), hprintf_fd: fuzzer_config.runtime.hprintf_fd(),
aux_buffer_size: fuzzer_config.runtime.aux_buffer_size(), aux_buffer_size: fuzzer_config.runtime.aux_buffer_size(),
time_limit: fuzzer_config.fuzz.time_limit time_limit: fuzzer_config.fuzz.time_limit,
};
} }
} }
}

View File

@ -1,20 +1,20 @@
use std::os::unix::prelude::FromRawFd; use fs4::FileExt;
use std::path::PathBuf;
use nix::sys::mman::*; use nix::sys::mman::*;
use std::fs; use std::fs;
use std::io;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use std::os::unix::fs::symlink; use std::os::unix::fs::symlink;
use std::os::unix::io::IntoRawFd;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::os::unix::io::IntoRawFd;
use std::os::unix::net::UnixStream; use std::os::unix::net::UnixStream;
use std::os::unix::prelude::FromRawFd;
use std::path::Path; use std::path::Path;
use std::path::PathBuf;
use std::process;
use std::process::Child; use std::process::Child;
use std::process::Command; use std::process::Command;
use std::{thread, time}; use std::{thread, time};
use std::process;
use fs4::FileExt;
use nix::unistd::gettid; use nix::unistd::gettid;
@ -24,16 +24,16 @@ extern crate colored; // not needed in Rust 2018
use colored::*; use colored::*;
use crate::nyx::aux_buffer::AuxBuffer; use crate::nyx::aux_buffer::AuxBuffer;
use crate::nyx::aux_buffer::{NYX_SUCCESS, NYX_CRASH, NYX_HPRINTF, NYX_TIMEOUT, NYX_ABORT, NYX_INPUT_WRITE}; use crate::nyx::aux_buffer::{
NYX_ABORT, NYX_CRASH, NYX_HPRINTF, NYX_INPUT_WRITE, NYX_SUCCESS, NYX_TIMEOUT,
};
use crate::nyx::ijon_data::{SharedFeedbackData, FeedbackBuffer}; use crate::nyx::ijon_data::{FeedbackBuffer, SharedFeedbackData};
use crate::nyx::mem_barrier::mem_barrier; use crate::nyx::mem_barrier::mem_barrier;
use crate::nyx::params::QemuParams; use crate::nyx::params::QemuParams;
pub struct QemuProcess { pub struct QemuProcess {
process: Child, process: Child,
/* ptr to the aux buffer */ /* ptr to the aux buffer */
@ -96,7 +96,6 @@ fn make_shared_ijon_data(file: File, size: usize) -> FeedbackBuffer {
} }
impl QemuProcess { impl QemuProcess {
pub fn new(params: QemuParams) -> Result<QemuProcess, String> { pub fn new(params: QemuParams) -> Result<QemuProcess, String> {
Self::prepare_redqueen_workdir(&params.workdir, params.qemu_id); Self::prepare_redqueen_workdir(&params.workdir, params.qemu_id);
@ -116,7 +115,6 @@ impl QemuProcess {
.open(&shm_work_dir_path) .open(&shm_work_dir_path)
.expect("couldn't open bitmap file"); .expect("couldn't open bitmap file");
if Path::new(&format!("{}/bitmap_{}", params.workdir, params.qemu_id)).exists() { if Path::new(&format!("{}/bitmap_{}", params.workdir, params.qemu_id)).exists() {
fs::remove_file(format!("{}/bitmap_{}", params.workdir, params.qemu_id)).unwrap(); fs::remove_file(format!("{}/bitmap_{}", params.workdir, params.qemu_id)).unwrap();
} }
@ -137,7 +135,6 @@ impl QemuProcess {
.open(&shm_work_dir_path) .open(&shm_work_dir_path)
.expect("couldn't open bitmap file"); .expect("couldn't open bitmap file");
if Path::new(&format!("{}/ijon_{}", params.workdir, params.qemu_id)).exists() { if Path::new(&format!("{}/ijon_{}", params.workdir, params.qemu_id)).exists() {
fs::remove_file(format!("{}/ijon_{}", params.workdir, params.qemu_id)).unwrap(); fs::remove_file(format!("{}/ijon_{}", params.workdir, params.qemu_id)).unwrap();
} }
@ -184,8 +181,7 @@ impl QemuProcess {
.env("DUMP_PAYLOAD_MODE", "TRUE") .env("DUMP_PAYLOAD_MODE", "TRUE")
.spawn() .spawn()
.expect("failed to execute process") .expect("failed to execute process")
} } else {
else{
Command::new(&params.cmd[0]) Command::new(&params.cmd[0])
.args(&params.cmd[1..]) .args(&params.cmd[1..])
.spawn() .spawn()
@ -195,9 +191,7 @@ impl QemuProcess {
let mut control = loop { let mut control = loop {
match UnixStream::connect(&params.control_filename) { match UnixStream::connect(&params.control_filename) {
Ok(stream) => break stream, Ok(stream) => break stream,
_ => { _ => thread::sleep(time::Duration::from_millis(1)),
thread::sleep(time::Duration::from_millis(1))
},
} }
}; };
@ -220,8 +214,8 @@ impl QemuProcess {
child.kill().unwrap(); child.kill().unwrap();
child.wait().unwrap(); child.wait().unwrap();
return Err(x); return Err(x);
}, }
Ok(_) => {}, Ok(_) => {}
} }
if params.write_protected_input_buffer { if params.write_protected_input_buffer {
if params.qemu_id == 0 { if params.qemu_id == 0 {
@ -237,15 +231,20 @@ impl QemuProcess {
}; };
loop { loop {
match aux_buffer.result.exec_result_code { match aux_buffer.result.exec_result_code {
NYX_HPRINTF => { NYX_HPRINTF => {
let len = aux_buffer.misc.len; let len = aux_buffer.misc.len;
QemuProcess::output_hprintf(&mut hprintf_file, &String::from_utf8_lossy(&aux_buffer.misc.data[0..len as usize]).yellow()); QemuProcess::output_hprintf(
}, &mut hprintf_file,
&String::from_utf8_lossy(&aux_buffer.misc.data[0..len as usize]).yellow(),
);
}
NYX_ABORT => { NYX_ABORT => {
let len = aux_buffer.misc.len; let len = aux_buffer.misc.len;
let msg = format!("agent abort() -> \n\t{}", String::from_utf8_lossy(&aux_buffer.misc.data[0..len as usize]).red()); let msg = format!(
"agent abort() -> \n\t{}",
String::from_utf8_lossy(&aux_buffer.misc.data[0..len as usize]).red()
);
/* get rid of this process */ /* get rid of this process */
child.kill().unwrap(); child.kill().unwrap();
@ -253,7 +252,7 @@ impl QemuProcess {
return Err(msg); return Err(msg);
} }
NYX_SUCCESS => {}, NYX_SUCCESS => {}
x => { x => {
panic!(" -> unkown type ? {}", x); panic!(" -> unkown type ? {}", x);
} }
@ -274,7 +273,10 @@ impl QemuProcess {
bitmap_size = aux_buffer.cap.agent_coverage_bitmap_size as usize; bitmap_size = aux_buffer.cap.agent_coverage_bitmap_size as usize;
if aux_buffer.cap.agent_coverage_bitmap_size as usize > bitmap_shared.len() { if aux_buffer.cap.agent_coverage_bitmap_size as usize > bitmap_shared.len() {
//println!("[!] libnyx: agent requests a differnt coverage bitmap size: {:x} (current: {:x})", aux_buffer.cap.agent_coverage_bitmap_size as u32, file_len); //println!("[!] libnyx: agent requests a differnt coverage bitmap size: {:x} (current: {:x})", aux_buffer.cap.agent_coverage_bitmap_size as u32, file_len);
bitmap_shared = make_shared_data(&bitmap_shm_f, aux_buffer.cap.agent_coverage_bitmap_size as usize); bitmap_shared = make_shared_data(
&bitmap_shm_f,
aux_buffer.cap.agent_coverage_bitmap_size as usize,
);
} }
} }
@ -282,7 +284,10 @@ impl QemuProcess {
if aux_buffer.cap.agent_input_buffer_size != 0 { if aux_buffer.cap.agent_input_buffer_size != 0 {
input_buffer_size = aux_buffer.cap.agent_input_buffer_size as usize; input_buffer_size = aux_buffer.cap.agent_input_buffer_size as usize;
if aux_buffer.cap.agent_input_buffer_size as usize > payload_shared.len() { if aux_buffer.cap.agent_input_buffer_size as usize > payload_shared.len() {
payload_shared = make_shared_data(&payload_shm_f, aux_buffer.cap.agent_input_buffer_size as usize); payload_shared = make_shared_data(
&payload_shm_f,
aux_buffer.cap.agent_input_buffer_size as usize,
);
} }
} }
@ -320,7 +325,7 @@ impl QemuProcess {
match hprintf_file { match hprintf_file {
Some(ref mut f) => { Some(ref mut f) => {
f.write_fmt(format_args!("{}", msg)).unwrap(); f.write_fmt(format_args!("{}", msg)).unwrap();
}, }
None => { None => {
print!("{}", msg); print!("{}", msg);
} }
@ -346,7 +351,7 @@ impl QemuProcess {
mem_barrier(); mem_barrier();
match run_qemu(&mut self.ctrl) { match run_qemu(&mut self.ctrl) {
Err(x) => return Err(x), Err(x) => return Err(x),
Ok(_) => {}, Ok(_) => {}
} }
mem_barrier(); mem_barrier();
@ -362,13 +367,12 @@ impl QemuProcess {
mem_barrier(); mem_barrier();
match run_qemu(&mut self.ctrl) { match run_qemu(&mut self.ctrl) {
Err(x) => return Err(x), Err(x) => return Err(x),
Ok(_) => {}, Ok(_) => {}
} }
mem_barrier(); mem_barrier();
continue; continue;
} } else {
else{
println!("libnyx: cannot dump missing page -> {:x}", v); println!("libnyx: cannot dump missing page -> {:x}", v);
} }
} }
@ -376,17 +380,24 @@ impl QemuProcess {
match self.aux.result.exec_result_code { match self.aux.result.exec_result_code {
NYX_HPRINTF => { NYX_HPRINTF => {
let len = self.aux.misc.len; let len = self.aux.misc.len;
QemuProcess::output_hprintf(&mut self.hprintf_file, &String::from_utf8_lossy(&self.aux.misc_data_slice()[0..len as usize]).yellow()); QemuProcess::output_hprintf(
&mut self.hprintf_file,
&String::from_utf8_lossy(&self.aux.misc_data_slice()[0..len as usize])
.yellow(),
);
continue; continue;
}, }
NYX_ABORT => { NYX_ABORT => {
let len = self.aux.misc.len; let len = self.aux.misc.len;
println!("[!] libnyx: agent abort() -> \"{}\"", String::from_utf8_lossy(&self.aux.misc_data_slice()[0..len as usize]).red()); println!(
"[!] libnyx: agent abort() -> \"{}\"",
String::from_utf8_lossy(&self.aux.misc_data_slice()[0..len as usize]).red()
);
break; break;
}, }
NYX_SUCCESS | NYX_CRASH | NYX_INPUT_WRITE | NYX_TIMEOUT => { NYX_SUCCESS | NYX_CRASH | NYX_INPUT_WRITE | NYX_TIMEOUT => {
break; break;
}, }
x => { x => {
panic!("[!] libnyx: ERROR -> unkown Nyx exec result code: {}", x); panic!("[!] libnyx: ERROR -> unkown Nyx exec result code: {}", x);
} }
@ -406,17 +417,40 @@ impl QemuProcess {
} }
fn remove_shm_work_dir(&mut self) { fn remove_shm_work_dir(&mut self) {
/* move originals into workdir (in case we need the data to debug stuff) */ /* move originals into workdir (in case we need the data to debug stuff) */
let shm_path = self.shm_work_dir.to_str().unwrap(); let shm_path = self.shm_work_dir.to_str().unwrap();
fs::remove_file(&format!("{}/bitmap_{}", &self.params.workdir, self.params.qemu_id)).unwrap(); fs::remove_file(&format!(
fs::copy(&format!("{}/bitmap", shm_path), &format!("{}/bitmap_{}", &self.params.workdir, self.params.qemu_id)).unwrap(); "{}/bitmap_{}",
&self.params.workdir, self.params.qemu_id
))
.unwrap();
fs::copy(
&format!("{}/bitmap", shm_path),
&format!("{}/bitmap_{}", &self.params.workdir, self.params.qemu_id),
)
.unwrap();
fs::remove_file(&format!("{}/payload_{}", &self.params.workdir, self.params.qemu_id)).unwrap(); fs::remove_file(&format!(
fs::copy(&format!("{}/input", shm_path), &format!("{}/payload_{}", &self.params.workdir, self.params.qemu_id)).unwrap(); "{}/payload_{}",
&self.params.workdir, self.params.qemu_id
))
.unwrap();
fs::copy(
&format!("{}/input", shm_path),
&format!("{}/payload_{}", &self.params.workdir, self.params.qemu_id),
)
.unwrap();
fs::remove_file(&format!("{}/ijon_{}", &self.params.workdir, self.params.qemu_id)).unwrap(); fs::remove_file(&format!(
fs::copy(&format!("{}/ijon", shm_path), &format!("{}/ijon_{}", &self.params.workdir, self.params.qemu_id)).unwrap(); "{}/ijon_{}",
&self.params.workdir, self.params.qemu_id
))
.unwrap();
fs::copy(
&format!("{}/ijon", shm_path),
&format!("{}/ijon_{}", &self.params.workdir, self.params.qemu_id),
)
.unwrap();
/* remove this shm directory */ /* remove this shm directory */
fs::remove_dir_all(&self.shm_work_dir).unwrap(); fs::remove_dir_all(&self.shm_work_dir).unwrap();
@ -436,7 +470,7 @@ impl QemuProcess {
"page_cache.lock", "page_cache.lock",
"page_cache.addr", "page_cache.addr",
"page_cache.addr", "page_cache.addr",
"snapshot/fast_snapshot.qemu_state" "snapshot/fast_snapshot.qemu_state",
]; ];
for file in files.iter() { for file in files.iter() {
while !Path::new(&format!("{}/{}", workdir, file)).exists() { while !Path::new(&format!("{}/{}", workdir, file)).exists() {
@ -483,18 +517,31 @@ impl QemuProcess {
.open(format!("{}/page_cache.addr", workdir)) .open(format!("{}/page_cache.addr", workdir))
.unwrap(); .unwrap();
OpenOptions::new().create(true).write(true).open(format!("{}/program", workdir)).unwrap(); OpenOptions::new()
.create(true)
.write(true)
.open(format!("{}/program", workdir))
.unwrap();
//println!("IMPORT STUFF FOR {:?}", seed_path); //println!("IMPORT STUFF FOR {:?}", seed_path);
if let Some(path) = seed_path { if let Some(path) = seed_path {
let pattern = format!("{}/*", path); let pattern = format!("{}/*", path);
//println!("IMPORT STUFF FOR {}", pattern); //println!("IMPORT STUFF FOR {}", pattern);
for (i,p) in glob::glob(&pattern).expect("couldn't glob seed pattern??").enumerate() for (i, p) in glob::glob(&pattern)
.expect("couldn't glob seed pattern??")
.enumerate()
{ {
let src = p.unwrap_or_else(|e| panic!("invalid seed path found {:?}", e)); let src = p.unwrap_or_else(|e| panic!("invalid seed path found {:?}", e));
//println!("import {} to {}/seeds/seed_{}",src.to_string_lossy(), workdir,i); //println!("import {} to {}/seeds/seed_{}",src.to_string_lossy(), workdir,i);
let dst = format!("{}/seeds/seed_{}.bin", workdir, i); let dst = format!("{}/seeds/seed_{}.bin", workdir, i);
fs::copy(&src, &dst).unwrap_or_else(|e| panic!("couldn't copy seed {} to {} {:?}",src.to_string_lossy(),dst,e)); fs::copy(&src, &dst).unwrap_or_else(|e| {
panic!(
"couldn't copy seed {} to {} {:?}",
src.to_string_lossy(),
dst,
e
)
});
} }
} }
} }
@ -511,17 +558,12 @@ impl QemuProcess {
path.push("lock"); path.push("lock");
if path.exists() { if path.exists() {
let file_lock = match OpenOptions::new().read(true).open(&path) {
let file_lock = match OpenOptions::new()
.read(true)
.open(&path){
Err(x) => { Err(x) => {
println!("Warning: {}", x); println!("Warning: {}", x);
Err(x) Err(x)
}, }
x => { x => x,
x
},
}; };
if file_lock.is_ok() { if file_lock.is_ok() {
@ -533,12 +575,12 @@ impl QemuProcess {
match fs::remove_dir_all(path) { match fs::remove_dir_all(path) {
Err(x) => { Err(x) => {
println!("Warning: {}", x); println!("Warning: {}", x);
}, }
_ => {}, _ => {}
} }
} }
}, }
Err(_) => {}, Err(_) => {}
} }
} }
} }