input tool + env

This commit is contained in:
Alwin Berger 2025-02-21 19:33:33 +01:00
parent 9412b44747
commit 57aaa0a96d
4 changed files with 2040 additions and 0 deletions

View File

@ -61,6 +61,7 @@
snakemake
vim
psmisc
sqlite
];
shellHook = ''
@ -73,6 +74,7 @@
# export CPU_TARGET=arm
# export CROSS_CC=arm-none-eabi-gcc
export LIBCLANG_PATH=${llvmPackages_19.libclang.lib}/lib
export BENCHDIR=bench_default
'';
};

1868
input_serde/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

21
input_serde/Cargo.toml Normal file
View File

@ -0,0 +1,21 @@
[package]
name = "input_serde"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
fret = { path = "../LibAFL/fuzzers/FRET" }
libafl = { path = "../LibAFL/libafl" }
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
hashbrown = { version = "0.14.0", features = ["serde"] } # A faster hashmap, nostd compatible
# petgraph = { version="0.6.0", features = ["serde-1"] }
ron = "0.7" # write serialized data - including hashmaps
rand = "0.5"
clap = "4.5.17"
itertools = "0.13.0"
either = { version = "1.13.0", features = ["serde"] }
postcard = { version = "1.0.10", features = [
"alloc",
], default-features = false } # no_std compatible serde serialization format

149
input_serde/src/main.rs Normal file
View File

@ -0,0 +1,149 @@
use either::Either::{self, Left, Right};
use hashbrown::HashMap;
use rand::rngs::StdRng;
use std::path::PathBuf;
use std::{env,fs};
use fret::systemstate::{ExecInterval, RTOSJob, target_os::SystemTraceData, target_os::freertos::FreeRTOSTraceMetadata, target_os::SystemState, target_os::TaskControlBlock, helpers::interrupt_times_to_input_bytes};
use libafl::inputs::multi::MultipartInput;
use libafl::inputs::{BytesInput, Input};
use std::io::Write;
use clap::Parser;
use itertools::{assert_equal, join, Itertools};
use rand::RngCore;
use libafl::inputs::HasMutatorBytes;
const MAX_NUM_INTERRUPT: usize = 128;
const NUM_INTERRUPT_SOURCES: usize = 6; // Keep in sync with qemu-libafl-bridge/hw/timer/armv7m_systick.c:319 and FreeRTOS/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/init/startup.c:216
pub const QEMU_ICOUNT_SHIFT: u32 = 5;
pub const QEMU_ISNS_PER_SEC: u32 = u32::pow(10, 9) / u32::pow(2, QEMU_ICOUNT_SHIFT);
pub const QEMU_ISNS_PER_USEC: f32 = QEMU_ISNS_PER_SEC as f32 / 1000000.0;
#[derive(Parser)]
struct Config {
/// Input Case
#[arg(short, long, value_name = "FILE")]
case: PathBuf,
/// Input format
#[arg(short, long, value_name = "FORMAT")]
input_format: Option<String>,
/// Output format
#[arg(short, long, value_name = "FORMAT", default_value = "edit")]
format: String,
}
/// Setup the interrupt inputs. Noop if interrupts are not fuzzed
fn setup_interrupt_inputs(mut input : MultipartInput<BytesInput>) -> MultipartInput<BytesInput> {
for i in 0..MAX_NUM_INTERRUPT {
let name = format!("isr_{}_times",i);
if input.parts_by_name(&name).next().is_none() {
input.add_part(name, BytesInput::new([0; MAX_NUM_INTERRUPT*4].to_vec()));
}
}
input
}
fn unfold_input(input : &MultipartInput<BytesInput>) -> HashMap<String,Either<Vec<u8>,Vec<u32>>> {
let mut res = HashMap::new();
for (name, part) in input.iter() {
if name == "bytes" {
res.insert(name.to_string(),Left(part.bytes().to_vec()));
} else {
// let times = unsafe{std::mem::transmute::<&[u8], &[u32]>(&part.bytes()[0..4*(part.bytes().len()/4)])}.to_vec();
println!("name {} len {}", name, part.bytes().len());
let mut times = part.bytes().chunks(4).filter(|x| x.len()==4).map(|x| u32::from_le_bytes(x.try_into().unwrap())).collect::<Vec<_>>();
times.sort_unstable();
res.insert(name.to_string(),Right(times));
}
}
res
}
fn fold_input(input : HashMap<String,Either<Vec<u8>,Vec<u32>>>) -> MultipartInput<BytesInput> {
let mut res = MultipartInput::new();
for (name, data) in input {
match data {
Left(x) => res.add_part(name, BytesInput::new(x)),
Right(x) => res.add_part(name, BytesInput::new(interrupt_times_to_input_bytes(&x))),
}
}
res
}
fn main() {
let conf = Config::parse();
let show_input = match conf.input_format {
Some(x) => {
match x.as_str() {
"case" => {
eprintln!("Interpreting input file as multipart input");
MultipartInput::from_file(conf.case.as_os_str()).unwrap()
},
"edit" => {
let bytes = fs::read(conf.case).expect("Can not read input file");
let input_str = String::from_utf8_lossy(&bytes);
eprintln!("Interpreting input file as custom edit input");
fold_input(ron::from_str::<HashMap<String,Either<Vec<u8>,Vec<u32>>>>(&input_str).expect("Failed to parse input"))
},
"ron" => {
let bytes = fs::read(conf.case).expect("Can not read input file");
let input_str = String::from_utf8_lossy(&bytes);
eprintln!("Interpreting input file as raw ron input");
ron::from_str::<MultipartInput<BytesInput>>(&input_str).expect("Failed to parse input")
},
"raw" => {
let bytes = fs::read(conf.case).expect("Can not read input file");
setup_interrupt_inputs(MultipartInput::from([("bytes",BytesInput::new(bytes))]))
},
x => panic!("Unknown input format: {}", x),
}
}
Option::None => match MultipartInput::from_file(conf.case.as_os_str()) {
Ok(x) => {
eprintln!("Interpreting input file as multipart input");
x
},
Err(_) => {
let bytes = fs::read(conf.case).expect("Can not read input file");
let input_str = String::from_utf8_lossy(&bytes);
match ron::from_str::<HashMap<String,Either<Vec<u8>,Vec<u32>>>>(&input_str) {
Ok(x) => {
eprintln!("Interpreting input file as custom edit input");
fold_input(x)
},
Err(_) => {
match ron::from_str::<MultipartInput<BytesInput>>(&input_str) {
Ok(x) => {
eprintln!("Interpreting input file as raw ron input");
x
},
Err(_) => {
eprintln!("Interpreting input file as raw input");
setup_interrupt_inputs(MultipartInput::from([("bytes",BytesInput::new(bytes))]))
}
}
}
}
}
}
};
// let uf = unfold_input(&show_input);
// println!("{:?}", show_input);
match conf.format.as_str() {
"edit" => {
let output = ron::to_string(&unfold_input(&show_input)).expect("Could not serialize input");
println!("{}", output);
},
"ron" => {
let output = ron::to_string(&show_input).expect("Could not serialize input");
println!("{}", output);
},
"case" => {
let output = postcard::to_allocvec(&show_input).expect("Could not serialize input");
std::io::stdout().write_all(&output).expect("Could not write output");
},
_ => panic!("Unknown format")
}
}