add AFL++ support and other improvements
This commit is contained in:
parent
1927a0ab83
commit
a199ed31e7
@ -18,6 +18,12 @@ fn into_absolute_path(path_to_sharedir: &str, path_to_file: String) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||||
|
pub struct IptFilter {
|
||||||
|
pub a: u64,
|
||||||
|
pub b: u64,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct QemuKernelConfig {
|
pub struct QemuKernelConfig {
|
||||||
pub qemu_binary: String,
|
pub qemu_binary: String,
|
||||||
@ -132,6 +138,7 @@ pub struct FuzzerConfig {
|
|||||||
pub exit_after_first_crash: bool,
|
pub exit_after_first_crash: bool,
|
||||||
pub write_protected_input_buffer: bool,
|
pub write_protected_input_buffer: bool,
|
||||||
pub cow_primary_size: Option<u64>,
|
pub cow_primary_size: Option<u64>,
|
||||||
|
pub ipt_filters: [IptFilter;4],
|
||||||
}
|
}
|
||||||
impl FuzzerConfig{
|
impl FuzzerConfig{
|
||||||
pub fn new_from_loader(sharedir: &str, default: FuzzerConfigLoader, config: FuzzerConfigLoader) -> Self {
|
pub fn new_from_loader(sharedir: &str, default: FuzzerConfigLoader, config: FuzzerConfigLoader) -> Self {
|
||||||
@ -161,6 +168,12 @@ impl FuzzerConfig{
|
|||||||
exit_after_first_crash: config.exit_after_first_crash.unwrap_or(default.exit_after_first_crash.unwrap_or(false)),
|
exit_after_first_crash: config.exit_after_first_crash.unwrap_or(default.exit_after_first_crash.unwrap_or(false)),
|
||||||
write_protected_input_buffer: config.write_protected_input_buffer,
|
write_protected_input_buffer: config.write_protected_input_buffer,
|
||||||
cow_primary_size: if config.cow_primary_size != 0 { Some( config.cow_primary_size as u64) } else { None },
|
cow_primary_size: if config.cow_primary_size != 0 { Some( config.cow_primary_size as u64) } else { None },
|
||||||
|
ipt_filters: [
|
||||||
|
config.ip0,
|
||||||
|
config.ip1,
|
||||||
|
config.ip2,
|
||||||
|
config.ip3,
|
||||||
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,18 +192,38 @@ impl Config{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_sharedir(sharedir: &str) -> Self {
|
pub fn new_from_sharedir(sharedir: &str) -> Result<Self, String> {
|
||||||
let path_to_config = format!("{}/config.ron", sharedir);
|
let path_to_config = format!("{}/config.ron", sharedir);
|
||||||
let cfg_file = File::open(&path_to_config).expect("could not open config file");
|
|
||||||
let mut cfg: ConfigLoader = ron::de::from_reader(cfg_file).unwrap();
|
|
||||||
|
|
||||||
let default_path = into_absolute_path(sharedir, cfg.include_default_config_path.unwrap());
|
let cfg_file = match File::open(&path_to_config){
|
||||||
|
Ok(x) => {x},
|
||||||
|
Err(_) => return Err(format!("file or folder not found ({})!", path_to_config)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cfg: ConfigLoader = match ron::de::from_reader(cfg_file){
|
||||||
|
Ok(x) => {x},
|
||||||
|
Err(x) => return Err(format!("invalid configuration ({})!", x)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let include_default_config_path = match cfg.include_default_config_path{
|
||||||
|
Some(x) => {x},
|
||||||
|
None => return Err(format!("no path to default configuration given!")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let default_path = into_absolute_path(sharedir, include_default_config_path);
|
||||||
let default_config_folder = Path::new(&default_path).parent().unwrap().to_str().unwrap();
|
let default_config_folder = Path::new(&default_path).parent().unwrap().to_str().unwrap();
|
||||||
cfg.include_default_config_path = Some(default_path.clone());
|
cfg.include_default_config_path = Some(default_path.clone());
|
||||||
|
|
||||||
let default_file = File::open(cfg.include_default_config_path.as_ref().expect("no default config given")).expect("could not open config file");
|
let default_file = match File::open(default_path.clone()){
|
||||||
let default: ConfigLoader = ron::de::from_reader(default_file).unwrap();
|
Ok(x) => x,
|
||||||
|
Err(_) => return Err(format!("default config not found ({})!", default_path)),
|
||||||
|
};
|
||||||
|
|
||||||
Self::new_from_loader(&sharedir, &default_config_folder, default, cfg)
|
let default: ConfigLoader = match ron::de::from_reader(default_file){
|
||||||
|
Ok(x) => {x},
|
||||||
|
Err(x) => return Err(format!("invalid default configuration ({})!", x)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self::new_from_loader(&sharedir, &default_config_folder, default, cfg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,15 @@ pub struct FuzzerConfigLoader {
|
|||||||
#[serde(default = "default_cow_primary_size")]
|
#[serde(default = "default_cow_primary_size")]
|
||||||
pub cow_primary_size: u64,
|
pub cow_primary_size: u64,
|
||||||
|
|
||||||
|
#[serde(default = "default_ipt_filter")]
|
||||||
|
pub ip0: IptFilter,
|
||||||
|
#[serde(default = "default_ipt_filter")]
|
||||||
|
pub ip1: IptFilter,
|
||||||
|
#[serde(default = "default_ipt_filter")]
|
||||||
|
pub ip2: IptFilter,
|
||||||
|
#[serde(default = "default_ipt_filter")]
|
||||||
|
pub ip3: IptFilter,
|
||||||
|
|
||||||
pub workdir_path: Option<String>,
|
pub workdir_path: Option<String>,
|
||||||
pub bitmap_size: Option<usize>,
|
pub bitmap_size: Option<usize>,
|
||||||
pub mem_limit: Option<usize>,
|
pub mem_limit: Option<usize>,
|
||||||
@ -65,6 +74,13 @@ fn default_cow_primary_size() -> u64 {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_ipt_filter() -> IptFilter {
|
||||||
|
IptFilter{
|
||||||
|
a: 0,
|
||||||
|
b: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub struct ConfigLoader {
|
pub struct ConfigLoader {
|
||||||
pub include_default_config_path: Option<String>,
|
pub include_default_config_path: Option<String>,
|
||||||
|
@ -146,8 +146,11 @@ impl FuzzRunner for ForkServer {
|
|||||||
*/
|
*/
|
||||||
impl FuzzRunner for QemuProcess {
|
impl FuzzRunner for QemuProcess {
|
||||||
fn run_test(&mut self) -> Result<TestInfo, Box<dyn Error>> {
|
fn run_test(&mut self) -> Result<TestInfo, Box<dyn Error>> {
|
||||||
self.send_payload();
|
self.send_payload().unwrap();
|
||||||
let ops_used = self.feedback_data.shared.interpreter.executed_opcode_num;
|
let ops_used = self.feedback_data.shared.interpreter.executed_opcode_num;
|
||||||
|
if self.aux.result.abort != 0 {
|
||||||
|
panic!("Abort called!\n");
|
||||||
|
}
|
||||||
if self.aux.result.crash_found != 0 {
|
if self.aux.result.crash_found != 0 {
|
||||||
return Ok(TestInfo {ops_used, exitreason: ExitReason::Crash(self.aux.misc.as_slice().to_vec())});
|
return Ok(TestInfo {ops_used, exitreason: ExitReason::Crash(self.aux.misc.as_slice().to_vec())});
|
||||||
}
|
}
|
||||||
@ -169,7 +172,7 @@ impl FuzzRunner for QemuProcess {
|
|||||||
|
|
||||||
fn run_create_snapshot(&mut self) -> bool{
|
fn run_create_snapshot(&mut self) -> bool{
|
||||||
assert_eq!(self.aux.result.tmp_snapshot_created,0);
|
assert_eq!(self.aux.result.tmp_snapshot_created,0);
|
||||||
self.send_payload();
|
self.send_payload().unwrap();
|
||||||
return self.aux.result.tmp_snapshot_created == 1;
|
return self.aux.result.tmp_snapshot_created == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +180,7 @@ impl FuzzRunner for QemuProcess {
|
|||||||
if self.aux.result.tmp_snapshot_created != 0 {
|
if self.aux.result.tmp_snapshot_created != 0 {
|
||||||
self.aux.config.changed = 1;
|
self.aux.config.changed = 1;
|
||||||
self.aux.config.discard_tmp_snapshot = 1;
|
self.aux.config.discard_tmp_snapshot = 1;
|
||||||
self.send_payload();
|
self.send_payload().unwrap();
|
||||||
if self.aux.result.tmp_snapshot_created != 0 {
|
if self.aux.result.tmp_snapshot_created != 0 {
|
||||||
println!("AUX BUFFER {:#?}",self.aux);
|
println!("AUX BUFFER {:#?}",self.aux);
|
||||||
}
|
}
|
||||||
@ -190,7 +193,7 @@ impl FuzzRunner for QemuProcess {
|
|||||||
fn run_redqueen(&mut self) -> Result<RedqueenInfo, Box<dyn Error>> {
|
fn run_redqueen(&mut self) -> Result<RedqueenInfo, Box<dyn Error>> {
|
||||||
self.aux.config.changed = 1;
|
self.aux.config.changed = 1;
|
||||||
self.aux.config.redqueen_mode=1;
|
self.aux.config.redqueen_mode=1;
|
||||||
self.send_payload();
|
self.send_payload().unwrap();
|
||||||
self.aux.config.changed = 1;
|
self.aux.config.changed = 1;
|
||||||
self.aux.config.redqueen_mode=0;
|
self.aux.config.redqueen_mode=0;
|
||||||
let rq_file = format!("{}/redqueen_workdir_{}/redqueen_results.txt",self.params.workdir,self.params.qemu_id);
|
let rq_file = format!("{}/redqueen_workdir_{}/redqueen_results.txt",self.params.workdir,self.params.qemu_id);
|
||||||
@ -201,7 +204,7 @@ impl FuzzRunner for QemuProcess {
|
|||||||
//println!("TRACE!!!!");
|
//println!("TRACE!!!!");
|
||||||
self.aux.config.trace_mode=1;
|
self.aux.config.trace_mode=1;
|
||||||
self.aux.config.changed = 1;
|
self.aux.config.changed = 1;
|
||||||
self.send_payload();
|
self.send_payload().unwrap();
|
||||||
self.aux.config.changed = 1;
|
self.aux.config.changed = 1;
|
||||||
self.aux.config.trace_mode=0;
|
self.aux.config.trace_mode=0;
|
||||||
return Ok(CFGInfo {});
|
return Ok(CFGInfo {});
|
||||||
|
@ -17,7 +17,8 @@ use derivative::Derivative;
|
|||||||
const AUX_BUFFER_SIZE: usize = 4096;
|
const AUX_BUFFER_SIZE: usize = 4096;
|
||||||
|
|
||||||
const AUX_MAGIC: u64 = 0x54502d554d4551_u64;
|
const AUX_MAGIC: u64 = 0x54502d554d4551_u64;
|
||||||
const QEMU_PT_VERSION: u16 = 1; /* let's start at 1 for the initial version using the aux buffer */
|
const QEMU_PT_VERSION: u16 = 2; /* let's start at 1 for the initial version using the aux buffer */
|
||||||
|
const QEMU_PT_HASH: u16 = 82;
|
||||||
|
|
||||||
const HEADER_SIZE: usize = 128;
|
const HEADER_SIZE: usize = 128;
|
||||||
const CAP_SIZE: usize = 256;
|
const CAP_SIZE: usize = 256;
|
||||||
@ -82,14 +83,21 @@ impl AuxBuffer {
|
|||||||
return AuxBuffer::new_readonly(file, false);
|
return AuxBuffer::new_readonly(file, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validate_header(&self) {
|
pub fn validate_header(&self) -> Result<(), String> {
|
||||||
mem_barrier();
|
mem_barrier();
|
||||||
let mgc = self.header.magic;
|
let mgc = self.header.magic;
|
||||||
assert_eq!(mgc, AUX_MAGIC);
|
if mgc != AUX_MAGIC {
|
||||||
|
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;
|
||||||
assert_eq!(version, QEMU_PT_VERSION);
|
if version != QEMU_PT_VERSION {
|
||||||
|
return Err(format!("aux buffer version mismatch {} != {}...\n[!] You are probably using either an outdated version of libnyx or QEMU-Nyx...", QEMU_PT_VERSION, version));
|
||||||
|
}
|
||||||
let hash = self.header.hash;
|
let hash = self.header.hash;
|
||||||
assert_eq!(hash, 81);
|
if hash != QEMU_PT_HASH {
|
||||||
|
return Err(format!("aux buffer hash mismatch {} != {}...\n[!] You are probably using either an outdated version of libnyx or QEMU-Nyx...", QEMU_PT_HASH, hash));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@ -176,7 +184,7 @@ pub struct auxilary_buffer_result_s {
|
|||||||
pub dirty_pages: u32,
|
pub dirty_pages: u32,
|
||||||
pub pt_trace_size: u32,
|
pub pt_trace_size: u32,
|
||||||
pub payload_write_attempt_found: u8,
|
pub payload_write_attempt_found: u8,
|
||||||
|
pub abort: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C, packed(1))]
|
#[repr(C, packed(1))]
|
||||||
|
@ -24,7 +24,7 @@ fn into_absolute_path(sharedir: &str) -> String{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn qemu_process_new_from_kernel(sharedir: String, cfg: &QemuKernelConfig, fuzz_cfg: &FuzzerConfig) -> qemu_process::QemuProcess {
|
pub fn qemu_process_new_from_kernel(sharedir: String, cfg: &QemuKernelConfig, fuzz_cfg: &FuzzerConfig) -> Result<QemuProcess, String> {
|
||||||
let params = params::KernelVmParams {
|
let params = params::KernelVmParams {
|
||||||
qemu_binary: cfg.qemu_binary.to_string(),
|
qemu_binary: cfg.qemu_binary.to_string(),
|
||||||
kernel: cfg.kernel.to_string(),
|
kernel: cfg.kernel.to_string(),
|
||||||
@ -39,6 +39,7 @@ pub fn qemu_process_new_from_kernel(sharedir: String, cfg: &QemuKernelConfig, fu
|
|||||||
},
|
},
|
||||||
write_protected_input_buffer: fuzz_cfg.write_protected_input_buffer,
|
write_protected_input_buffer: fuzz_cfg.write_protected_input_buffer,
|
||||||
cow_primary_size: fuzz_cfg.cow_primary_size,
|
cow_primary_size: fuzz_cfg.cow_primary_size,
|
||||||
|
ipt_filters: fuzz_cfg.ipt_filters,
|
||||||
};
|
};
|
||||||
let qemu_id = fuzz_cfg.thread_id;
|
let qemu_id = fuzz_cfg.thread_id;
|
||||||
let qemu_params = params::QemuParams::new_from_kernel(&fuzz_cfg.workdir_path, qemu_id, ¶ms, fuzz_cfg.threads > 1);
|
let qemu_params = params::QemuParams::new_from_kernel(&fuzz_cfg.workdir_path, qemu_id, ¶ms, fuzz_cfg.threads > 1);
|
||||||
@ -51,7 +52,7 @@ pub fn qemu_process_new_from_kernel(sharedir: String, cfg: &QemuKernelConfig, fu
|
|||||||
return qemu_process::QemuProcess::new(qemu_params);
|
return qemu_process::QemuProcess::new(qemu_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn qemu_process_new_from_snapshot(sharedir: String, cfg: &QemuSnapshotConfig, fuzz_cfg: &FuzzerConfig) -> qemu_process::QemuProcess {
|
pub fn qemu_process_new_from_snapshot(sharedir: String, cfg: &QemuSnapshotConfig, fuzz_cfg: &FuzzerConfig) -> Result<QemuProcess, String> {
|
||||||
|
|
||||||
let snapshot_path = match &cfg.snapshot_path{
|
let snapshot_path = match &cfg.snapshot_path{
|
||||||
SnapshotPath::Create(_x) => panic!(),
|
SnapshotPath::Create(_x) => panic!(),
|
||||||
@ -80,6 +81,7 @@ pub fn qemu_process_new_from_snapshot(sharedir: String, cfg: &QemuSnapshotConfig
|
|||||||
},
|
},
|
||||||
write_protected_input_buffer: fuzz_cfg.write_protected_input_buffer,
|
write_protected_input_buffer: fuzz_cfg.write_protected_input_buffer,
|
||||||
cow_primary_size: fuzz_cfg.cow_primary_size,
|
cow_primary_size: fuzz_cfg.cow_primary_size,
|
||||||
|
ipt_filters: fuzz_cfg.ipt_filters,
|
||||||
};
|
};
|
||||||
let qemu_id = fuzz_cfg.thread_id;
|
let qemu_id = fuzz_cfg.thread_id;
|
||||||
let qemu_params = params::QemuParams::new_from_snapshot(&fuzz_cfg.workdir_path, qemu_id, fuzz_cfg.cpu_pin_start_at, ¶ms, fuzz_cfg.threads > 1);
|
let qemu_params = params::QemuParams::new_from_snapshot(&fuzz_cfg.workdir_path, qemu_id, fuzz_cfg.cpu_pin_start_at, ¶ms, fuzz_cfg.threads > 1);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use crate::config::SnapshotPath;
|
use crate::config::SnapshotPath;
|
||||||
|
use crate::config::IptFilter;
|
||||||
|
|
||||||
pub struct KernelVmParams {
|
pub struct KernelVmParams {
|
||||||
pub qemu_binary: String,
|
pub qemu_binary: String,
|
||||||
@ -13,6 +14,7 @@ pub struct KernelVmParams {
|
|||||||
pub dump_python_code_for_inputs: bool,
|
pub dump_python_code_for_inputs: bool,
|
||||||
pub write_protected_input_buffer: bool,
|
pub write_protected_input_buffer: bool,
|
||||||
pub cow_primary_size: Option<u64>,
|
pub cow_primary_size: Option<u64>,
|
||||||
|
pub ipt_filters: [IptFilter; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SnapshotVmParams{
|
pub struct SnapshotVmParams{
|
||||||
@ -28,6 +30,8 @@ pub struct SnapshotVmParams{
|
|||||||
pub dump_python_code_for_inputs: bool,
|
pub dump_python_code_for_inputs: bool,
|
||||||
pub write_protected_input_buffer: bool,
|
pub write_protected_input_buffer: bool,
|
||||||
pub cow_primary_size: Option<u64>,
|
pub cow_primary_size: Option<u64>,
|
||||||
|
pub ipt_filters: [IptFilter; 4],
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct QemuParams {
|
pub struct QemuParams {
|
||||||
@ -50,7 +54,6 @@ pub struct QemuParams {
|
|||||||
impl QemuParams {
|
impl QemuParams {
|
||||||
pub fn new_from_snapshot(workdir: &str, qemu_id: usize, cpu: usize, params: &SnapshotVmParams, create_snapshot_file: bool) -> QemuParams{
|
pub fn new_from_snapshot(workdir: &str, qemu_id: usize, cpu: usize, params: &SnapshotVmParams, create_snapshot_file: bool) -> QemuParams{
|
||||||
|
|
||||||
assert!(!(!create_snapshot_file && qemu_id == 1));
|
|
||||||
let project_name = Path::new(workdir)
|
let project_name = Path::new(workdir)
|
||||||
.file_name()
|
.file_name()
|
||||||
.expect("Couldn't get project name from workdir!")
|
.expect("Couldn't get project name from workdir!")
|
||||||
@ -112,13 +115,19 @@ impl QemuParams {
|
|||||||
nyx_ops += &format!(",workdir={}", workdir);
|
nyx_ops += &format!(",workdir={}", workdir);
|
||||||
nyx_ops += &format!(",sharedir={}", params.sharedir);
|
nyx_ops += &format!(",sharedir={}", params.sharedir);
|
||||||
|
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
for filter in params.ipt_filters{
|
||||||
|
if filter.a != 0 && filter.b != 0 {
|
||||||
|
nyx_ops += &format!(",ip{}_a={},ip{}_b={}", i, filter.a, i, filter.b);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if params.cow_primary_size.is_some(){
|
if params.cow_primary_size.is_some(){
|
||||||
nyx_ops += &format!(",cow_primary_size={}", params.cow_primary_size.unwrap());
|
nyx_ops += &format!(",cow_primary_size={}", params.cow_primary_size.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
//nyx_ops += &format!(",ip0_a=0x1000,ip0_b=0x7ffffffff000");
|
|
||||||
//nyx_ops += &format!(",ip0_a=ffff800000000000,ip0_b=ffffffffffffffff");
|
|
||||||
|
|
||||||
cmd.push(nyx_ops);
|
cmd.push(nyx_ops);
|
||||||
|
|
||||||
cmd.push("-machine".to_string());
|
cmd.push("-machine".to_string());
|
||||||
@ -171,7 +180,6 @@ impl QemuParams {
|
|||||||
pub fn new_from_kernel(workdir: &str, qemu_id: usize, params: &KernelVmParams, create_snapshot_file: bool) -> QemuParams {
|
pub fn new_from_kernel(workdir: &str, qemu_id: usize, params: &KernelVmParams, create_snapshot_file: bool) -> QemuParams {
|
||||||
//prepare_working_dir(workdir)
|
//prepare_working_dir(workdir)
|
||||||
|
|
||||||
assert!(!(!create_snapshot_file && qemu_id == 1));
|
|
||||||
let project_name = Path::new(workdir)
|
let project_name = Path::new(workdir)
|
||||||
.file_name()
|
.file_name()
|
||||||
.expect("Couldn't get project name from workdir!")
|
.expect("Couldn't get project name from workdir!")
|
||||||
@ -236,13 +244,18 @@ impl QemuParams {
|
|||||||
nyx_ops += &format!(",workdir={}", workdir);
|
nyx_ops += &format!(",workdir={}", workdir);
|
||||||
nyx_ops += &format!(",sharedir={}", params.sharedir);
|
nyx_ops += &format!(",sharedir={}", params.sharedir);
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
for filter in params.ipt_filters{
|
||||||
|
if filter.a != 0 && filter.b != 0 {
|
||||||
|
nyx_ops += &format!(",ip{}_a={:x},ip{}_b={:x}", i, filter.a, i, filter.b);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if params.cow_primary_size.is_some(){
|
if params.cow_primary_size.is_some(){
|
||||||
nyx_ops += &format!(",cow_primary_size={}", params.cow_primary_size.unwrap());
|
nyx_ops += &format!(",cow_primary_size={}", params.cow_primary_size.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
//nyx_ops += &format!(",ip0_a=0x1000,ip0_b=0x7ffffffff000");
|
|
||||||
//nyx_ops += &format!(",ip0_a=ffff800000000000,ip0_b=ffffffffffffffff");
|
|
||||||
|
|
||||||
cmd.push(nyx_ops);
|
cmd.push(nyx_ops);
|
||||||
|
|
||||||
cmd.push("-machine".to_string());
|
cmd.push("-machine".to_string());
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use core::ffi::c_void;
|
use core::ffi::c_void;
|
||||||
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::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::os::unix::fs::symlink;
|
use std::os::unix::fs::symlink;
|
||||||
@ -31,21 +32,23 @@ pub struct QemuProcess {
|
|||||||
pub bitmap: &'static mut [u8],
|
pub bitmap: &'static mut [u8],
|
||||||
pub payload: &'static mut [u8],
|
pub payload: &'static mut [u8],
|
||||||
pub params: QemuParams,
|
pub params: QemuParams,
|
||||||
hprintf_log: File,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_qemu(ctrl: &mut UnixStream) {
|
fn execute_qemu(ctrl: &mut UnixStream) -> io::Result<()>{
|
||||||
ctrl.write_all(&[120_u8]).unwrap();
|
ctrl.write_all(&[120_u8])?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_qemu(ctrl: &mut UnixStream) {
|
fn wait_qemu(ctrl: &mut UnixStream) -> io::Result<()>{
|
||||||
let mut buf = [0];
|
let mut buf = [0];
|
||||||
ctrl.read_exact(&mut buf).unwrap();
|
ctrl.read_exact(&mut buf)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_qemu(ctrl: &mut UnixStream) {
|
fn run_qemu(ctrl: &mut UnixStream) -> io::Result<()>{
|
||||||
execute_qemu(ctrl);
|
execute_qemu(ctrl)?;
|
||||||
wait_qemu(ctrl);
|
wait_qemu(ctrl)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_shared_data(file: File, size: usize) -> &'static mut [u8] {
|
fn make_shared_data(file: File, size: usize) -> &'static mut [u8] {
|
||||||
@ -69,7 +72,7 @@ fn make_shared_ijon_data(file: File, size: usize) -> FeedbackBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl QemuProcess {
|
impl QemuProcess {
|
||||||
pub fn new(params: QemuParams) -> QemuProcess {
|
pub fn new(params: QemuParams) -> Result<QemuProcess, String> {
|
||||||
Self::prepare_redqueen_workdir(¶ms.workdir, params.qemu_id);
|
Self::prepare_redqueen_workdir(¶ms.workdir, params.qemu_id);
|
||||||
|
|
||||||
if params.qemu_id == 0{
|
if params.qemu_id == 0{
|
||||||
@ -89,11 +92,20 @@ impl QemuProcess {
|
|||||||
.open(¶ms.payload_filename)
|
.open(¶ms.payload_filename)
|
||||||
.expect("couldn't open payload file");
|
.expect("couldn't open payload file");
|
||||||
|
|
||||||
|
if Path::new(&format!("{}/bitmap_{}", params.workdir, params.qemu_id)).exists(){
|
||||||
|
fs::remove_file(format!("{}/bitmap_{}", params.workdir, params.qemu_id)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
symlink(
|
symlink(
|
||||||
¶ms.bitmap_filename,
|
¶ms.bitmap_filename,
|
||||||
format!("{}/bitmap_{}", params.workdir, params.qemu_id),
|
format!("{}/bitmap_{}", params.workdir, params.qemu_id),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
if Path::new(&format!("{}/payload_{}", params.workdir, params.qemu_id)).exists(){
|
||||||
|
fs::remove_file(format!("{}/payload_{}", params.workdir, params.qemu_id)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
symlink(
|
symlink(
|
||||||
¶ms.payload_filename,
|
¶ms.payload_filename,
|
||||||
format!("{}/payload_{}", params.workdir, params.qemu_id),
|
format!("{}/payload_{}", params.workdir, params.qemu_id),
|
||||||
@ -123,7 +135,7 @@ impl QemuProcess {
|
|||||||
thread::sleep(time::Duration::from_millis(200*params.qemu_id as u64));
|
thread::sleep(time::Duration::from_millis(200*params.qemu_id as u64));
|
||||||
|
|
||||||
|
|
||||||
let child = if params.dump_python_code_for_inputs{
|
let mut child = if params.dump_python_code_for_inputs{
|
||||||
Command::new(¶ms.cmd[0])
|
Command::new(¶ms.cmd[0])
|
||||||
.args(¶ms.cmd[1..])
|
.args(¶ms.cmd[1..])
|
||||||
.env("DUMP_PAYLOAD_MODE", "TRUE")
|
.env("DUMP_PAYLOAD_MODE", "TRUE")
|
||||||
@ -159,7 +171,9 @@ impl QemuProcess {
|
|||||||
|
|
||||||
// dry_run
|
// dry_run
|
||||||
//println!("TRHEAD {} run QEMU initial",params.qemu_id);
|
//println!("TRHEAD {} run QEMU initial",params.qemu_id);
|
||||||
run_qemu(&mut control);
|
if run_qemu(&mut control).is_err() {
|
||||||
|
return Err(format!("cannot launch QEMU-Nyx..."));
|
||||||
|
}
|
||||||
|
|
||||||
let aux_shm_f = OpenOptions::new()
|
let aux_shm_f = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
@ -175,7 +189,14 @@ impl QemuProcess {
|
|||||||
.expect("couldn't open aux buffer file");
|
.expect("couldn't open aux buffer file");
|
||||||
let mut aux_buffer = AuxBuffer::new(aux_shm_f);
|
let mut aux_buffer = AuxBuffer::new(aux_shm_f);
|
||||||
|
|
||||||
aux_buffer.validate_header();
|
match aux_buffer.validate_header(){
|
||||||
|
Err(x) => {
|
||||||
|
child.kill().unwrap();
|
||||||
|
child.wait().unwrap();
|
||||||
|
return Err(x);
|
||||||
|
},
|
||||||
|
Ok(_) => {},
|
||||||
|
}
|
||||||
if params.write_protected_input_buffer{
|
if params.write_protected_input_buffer{
|
||||||
if params.qemu_id == 0 {
|
if params.qemu_id == 0 {
|
||||||
println!("[!] libnyx: input buffer is write protected");
|
println!("[!] libnyx: input buffer is write protected");
|
||||||
@ -185,22 +206,30 @@ impl QemuProcess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
if aux_buffer.result.abort == 1 {
|
||||||
|
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());
|
||||||
|
|
||||||
|
/* get rid of this process */
|
||||||
|
child.kill().unwrap();
|
||||||
|
child.wait().unwrap();
|
||||||
|
|
||||||
|
return Err(msg);
|
||||||
|
}
|
||||||
|
|
||||||
if aux_buffer.result.hprintf == 1 {
|
if aux_buffer.result.hprintf == 1 {
|
||||||
let len = aux_buffer.misc.len;
|
let len = aux_buffer.misc.len;
|
||||||
print!("{}", String::from_utf8_lossy(&aux_buffer.misc.data[0..len as usize]).yellow());
|
print!("{}", String::from_utf8_lossy(&aux_buffer.misc.data[0..len as usize]).yellow());
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
//println!("QEMU NOT READY");
|
|
||||||
}
|
|
||||||
|
|
||||||
if aux_buffer.result.state == 3 {
|
if aux_buffer.result.state == 3 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//println!("QEMU NOT READY");
|
if run_qemu(&mut control).is_err(){
|
||||||
//println!("TRHEAD {} run QEMU NOT READY",params.qemu_id);
|
return Err(format!("failed to establish fuzzing loop..."));
|
||||||
run_qemu(&mut control);
|
}
|
||||||
|
//run_qemu(&mut control).unwrap();
|
||||||
}
|
}
|
||||||
//println!("QEMU READY");
|
|
||||||
println!("[!] libnyx: qemu #{} is ready:", params.qemu_id);
|
println!("[!] libnyx: qemu #{} is ready:", params.qemu_id);
|
||||||
|
|
||||||
aux_buffer.config.reload_mode = 1;
|
aux_buffer.config.reload_mode = 1;
|
||||||
@ -208,16 +237,7 @@ impl QemuProcess {
|
|||||||
aux_buffer.config.timeout_usec = 500_000;
|
aux_buffer.config.timeout_usec = 500_000;
|
||||||
aux_buffer.config.changed = 1;
|
aux_buffer.config.changed = 1;
|
||||||
|
|
||||||
//run_qemu(&mut control);
|
return Ok(QemuProcess {
|
||||||
//run_qemu(&mut control);
|
|
||||||
|
|
||||||
let mut option = OpenOptions::new();
|
|
||||||
option.read(true);
|
|
||||||
option.write(true);
|
|
||||||
option.create(true);
|
|
||||||
let hprintf_log = option.open(format!("{}/hprintf_log_{}", params.workdir, params.qemu_id)).unwrap();
|
|
||||||
|
|
||||||
return QemuProcess {
|
|
||||||
process: child,
|
process: child,
|
||||||
aux: aux_buffer,
|
aux: aux_buffer,
|
||||||
feedback_data: ijon_shared,
|
feedback_data: ijon_shared,
|
||||||
@ -225,49 +245,32 @@ impl QemuProcess {
|
|||||||
bitmap: bitmap_shared,
|
bitmap: bitmap_shared,
|
||||||
payload: payload_shared,
|
payload: payload_shared,
|
||||||
params,
|
params,
|
||||||
hprintf_log,
|
});
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn send_payload(&mut self) {
|
pub fn send_payload(&mut self) -> io::Result<()>{
|
||||||
let mut old_address: u64 = 0;
|
let mut old_address: u64 = 0;
|
||||||
//use rand::Rng;
|
|
||||||
//println!("RUN INPUT");
|
|
||||||
//std::thread::sleep(std::time::Duration::from_secs(1));
|
|
||||||
//let time = std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH).unwrap().as_nanos();
|
|
||||||
//self.hprintf_log.write_all(&format!("===({})===\n", time).as_bytes()).unwrap();
|
|
||||||
loop {
|
loop {
|
||||||
mem_barrier();
|
mem_barrier();
|
||||||
run_qemu(&mut self.ctrl);
|
match run_qemu(&mut self.ctrl) {
|
||||||
|
Err(x) => return Err(x),
|
||||||
|
Ok(_) => {},
|
||||||
|
}
|
||||||
mem_barrier();
|
mem_barrier();
|
||||||
|
|
||||||
if self.aux.result.hprintf != 0 {
|
if self.aux.result.hprintf == 1 {
|
||||||
self.hprintf_log.write_all(&format!("{}\n", self.aux.misc.as_string()).as_bytes()).unwrap();
|
|
||||||
//println!("HPRINTF {}", self.aux.misc.as_string());
|
|
||||||
let len = self.aux.misc.len;
|
let len = self.aux.misc.len;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print!("{}", String::from_utf8_lossy(&self.aux.misc.data[0..len as usize]).yellow());
|
print!("{}", String::from_utf8_lossy(&self.aux.misc.data[0..len as usize]).yellow());
|
||||||
//print!("{}", "".clear());
|
|
||||||
println!("TEST\n");
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//println!("pt trace size {:x} bytes",self.aux.result.pt_trace_size);
|
|
||||||
//println!("{:} dirty pages",self.aux.result.dirty_pages);
|
if self.aux.result.abort == 1 {
|
||||||
//println!("interpreter ran {} ops",self.feedback_data.shared.interpreter.executed_opcode_num);
|
let len = self.aux.misc.len;
|
||||||
//let max_v = 0;
|
println!("[!] libnyx: agent abort() -> \"{}\"", String::from_utf8_lossy(&self.aux.misc.data[0..len as usize]).red());
|
||||||
//let max_i = 0;
|
break;
|
||||||
//for (i,v) in self.feedback_data.shared.ijon.max_data.iter().enumerate(){
|
}
|
||||||
// if *v > max_v{
|
|
||||||
// max_v=*v;
|
|
||||||
// max_i=i;
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//println!("found IJON MAX: {}\t{:x}",max_i,max_v);
|
|
||||||
|
|
||||||
if self.aux.result.success != 0 || self.aux.result.crash_found != 0 || self.aux.result.asan_found != 0 || self.aux.result.payload_write_attempt_found != 0 {
|
if self.aux.result.success != 0 || self.aux.result.crash_found != 0 || self.aux.result.asan_found != 0 || self.aux.result.payload_write_attempt_found != 0 {
|
||||||
break;
|
break;
|
||||||
@ -284,15 +287,8 @@ impl QemuProcess {
|
|||||||
self.aux.config.page_dump_mode = 1;
|
self.aux.config.page_dump_mode = 1;
|
||||||
self.aux.config.changed = 1;
|
self.aux.config.changed = 1;
|
||||||
}
|
}
|
||||||
//else {
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//std::thread::sleep(std::time::Duration::from_secs(1));
|
Ok(())
|
||||||
//if self.aux.result.tmp_snapshot_created != 0 {
|
|
||||||
// //println!("created snapshot!!!!!!\n");
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_timeout(&mut self, timeout: std::time::Duration){
|
pub fn set_timeout(&mut self, timeout: std::time::Duration){
|
||||||
@ -306,11 +302,26 @@ impl QemuProcess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn shutdown(&mut self) {
|
pub fn shutdown(&mut self) {
|
||||||
println!("Let's kill QEMU!");
|
println!("[!] libnyx: sending SIGKILL to QEMU-Nyx process...");
|
||||||
self.process.kill().unwrap();
|
self.process.kill().unwrap();
|
||||||
self.wait();
|
self.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn wait_for_workdir(workdir: &str){
|
||||||
|
println!("[!] libnyx: waiting for workdir to be created by parent process...");
|
||||||
|
|
||||||
|
let files = vec![
|
||||||
|
"page_cache.lock",
|
||||||
|
"page_cache.addr",
|
||||||
|
"page_cache.addr",
|
||||||
|
];
|
||||||
|
for file in files.iter() {
|
||||||
|
while !Path::new(&format!("{}/{}", workdir, file)).exists(){
|
||||||
|
thread::sleep(time::Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn prepare_workdir(workdir: &str, seed_path: Option<String>) {
|
pub fn prepare_workdir(workdir: &str, seed_path: Option<String>) {
|
||||||
Self::clear_workdir(workdir);
|
Self::clear_workdir(workdir);
|
||||||
let folders = vec![
|
let folders = vec![
|
||||||
|
@ -16,11 +16,13 @@ pub enum NyxReturnValue {
|
|||||||
Asan,
|
Asan,
|
||||||
Timout,
|
Timout,
|
||||||
InvalidWriteToPayload,
|
InvalidWriteToPayload,
|
||||||
Error
|
Error,
|
||||||
|
IoError, // QEMU process has died for some reason
|
||||||
|
Abort, // Abort hypercall called
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn nyx_new(sharedir: *const c_char, workdir: *const c_char, worker_id: u32, create_snapshot: bool) -> * mut QemuProcess {
|
pub extern "C" fn nyx_new(sharedir: *const c_char, workdir: *const c_char, worker_id: u32, cpu_id: u32, create_snapshot: bool) -> * mut QemuProcess {
|
||||||
let sharedir_c_str = unsafe {
|
let sharedir_c_str = unsafe {
|
||||||
assert!(!sharedir.is_null());
|
assert!(!sharedir.is_null());
|
||||||
CStr::from_ptr(sharedir)
|
CStr::from_ptr(sharedir)
|
||||||
@ -35,18 +37,20 @@ pub extern "C" fn nyx_new(sharedir: *const c_char, workdir: *const c_char, worke
|
|||||||
let sharedir_r_str = sharedir_c_str.to_str().unwrap();
|
let sharedir_r_str = sharedir_c_str.to_str().unwrap();
|
||||||
let workdir_r_str = workdir_c_str.to_str().unwrap();
|
let workdir_r_str = workdir_c_str.to_str().unwrap();
|
||||||
|
|
||||||
println!("r_str: {}", sharedir_r_str);
|
let cfg: Config = match Config::new_from_sharedir(&sharedir_r_str){
|
||||||
let cfg: Config = Config::new_from_sharedir(&sharedir_r_str);
|
Ok(x) => x,
|
||||||
println!("config {}", cfg.fuzz.bitmap_size);
|
Err(msg) => {
|
||||||
|
println!("[!] libnyx config reader error: {}", msg);
|
||||||
|
return std::ptr::null_mut() as *mut QemuProcess;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut config = cfg.fuzz;
|
let mut config = cfg.fuzz;
|
||||||
let runner_cfg = cfg.runner;
|
let runner_cfg = cfg.runner;
|
||||||
|
|
||||||
|
|
||||||
/* todo: add sanity check */
|
/* todo: add sanity check */
|
||||||
config.cpu_pin_start_at = worker_id as usize;
|
config.cpu_pin_start_at = cpu_id as usize;
|
||||||
|
|
||||||
config.thread_id = worker_id as usize;
|
config.thread_id = worker_id as usize;
|
||||||
config.threads = if create_snapshot { 2 as usize } else { 1 as usize };
|
config.threads = if create_snapshot { 2 as usize } else { 1 as usize };
|
||||||
@ -59,16 +63,25 @@ pub extern "C" fn nyx_new(sharedir: *const c_char, workdir: *const c_char, worke
|
|||||||
if worker_id == 0 {
|
if worker_id == 0 {
|
||||||
QemuProcess::prepare_workdir(&config.workdir_path, config.seed_path.clone());
|
QemuProcess::prepare_workdir(&config.workdir_path, config.seed_path.clone());
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
QemuProcess::wait_for_workdir(&config.workdir_path);
|
||||||
|
}
|
||||||
|
|
||||||
match runner_cfg.clone() {
|
let runner = match runner_cfg.clone() {
|
||||||
FuzzRunnerConfig::QemuSnapshot(cfg) => {
|
FuzzRunnerConfig::QemuSnapshot(cfg) => {
|
||||||
let runner = qemu_process_new_from_snapshot(sdir.to_string(), &cfg, &config);
|
qemu_process_new_from_snapshot(sdir.to_string(), &cfg, &config)
|
||||||
return Box::into_raw(Box::new(runner));
|
},
|
||||||
}
|
|
||||||
FuzzRunnerConfig::QemuKernel(cfg) => {
|
FuzzRunnerConfig::QemuKernel(cfg) => {
|
||||||
let runner = qemu_process_new_from_kernel(sdir.to_string(), &cfg, &config);
|
qemu_process_new_from_kernel(sdir.to_string(), &cfg, &config)
|
||||||
return Box::into_raw(Box::new(runner));
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match runner {
|
||||||
|
Ok(x) => Box::into_raw(Box::new(x)),
|
||||||
|
Err(msg) => {
|
||||||
|
println!("[!] libnyx failed to initialize QEMU-Nyx: {}", msg);
|
||||||
|
std::ptr::null_mut() as *mut QemuProcess
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +117,15 @@ pub extern "C" fn nyx_get_bitmap_buffer(qemu_process: * mut QemuProcess) -> *mut
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn nyx_get_bitmap_buffer_size(qemu_process: * mut QemuProcess) -> usize {
|
||||||
|
unsafe{
|
||||||
|
assert!(!qemu_process.is_null());
|
||||||
|
assert!((qemu_process as usize) % std::mem::align_of::<QemuProcess>() == 0);
|
||||||
|
return (*qemu_process).bitmap.len();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn nyx_shutdown(qemu_process: * mut QemuProcess) {
|
pub extern "C" fn nyx_shutdown(qemu_process: * mut QemuProcess) {
|
||||||
unsafe{
|
unsafe{
|
||||||
@ -152,8 +174,12 @@ pub extern "C" fn nyx_exec(qemu_process: * mut QemuProcess) -> NyxReturnValue {
|
|||||||
assert!(!qemu_process.is_null());
|
assert!(!qemu_process.is_null());
|
||||||
assert!((qemu_process as usize) % std::mem::align_of::<QemuProcess>() == 0);
|
assert!((qemu_process as usize) % std::mem::align_of::<QemuProcess>() == 0);
|
||||||
|
|
||||||
(*qemu_process).send_payload();
|
match (*qemu_process).send_payload(){
|
||||||
|
Err(_) => return NyxReturnValue::IoError,
|
||||||
|
Ok(_) => {
|
||||||
|
if (*qemu_process).aux.result.abort != 0 {
|
||||||
|
return NyxReturnValue::Abort;
|
||||||
|
}
|
||||||
if (*qemu_process).aux.result.crash_found != 0 {
|
if (*qemu_process).aux.result.crash_found != 0 {
|
||||||
return NyxReturnValue::Crash;
|
return NyxReturnValue::Crash;
|
||||||
}
|
}
|
||||||
@ -169,10 +195,11 @@ pub extern "C" fn nyx_exec(qemu_process: * mut QemuProcess) -> NyxReturnValue {
|
|||||||
if (*qemu_process).aux.result.success != 0 {
|
if (*qemu_process).aux.result.success != 0 {
|
||||||
return NyxReturnValue::Normal;
|
return NyxReturnValue::Normal;
|
||||||
}
|
}
|
||||||
println!("unknown exeuction result!!");
|
|
||||||
return NyxReturnValue::Error;
|
return NyxReturnValue::Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn nyx_set_afl_input(qemu_process: * mut QemuProcess, buffer: *mut u8, size: u32) {
|
pub extern "C" fn nyx_set_afl_input(qemu_process: * mut QemuProcess, buffer: *mut u8, size: u32) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user