Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Add IntelPT tracing to libafl_qemu systemmode with KVM #2774

Draft
wants to merge 86 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
979d14e
Decode with callback
Marcondiro Nov 13, 2024
4b59641
WIP restore intelpt module
Marcondiro Nov 13, 2024
fc100a9
Merge remote-tracking branch 'upstream/main'
Marcondiro Nov 14, 2024
731a7f5
Fix build_target if target_dir doesn't exist
Marcondiro Nov 14, 2024
5386013
WIP itelpt qemu/kvm example: bootloader
Marcondiro Nov 14, 2024
87612d7
Merge remote-tracking branch 'upstream/main'
Marcondiro Nov 18, 2024
73eb9db
Merge branch 'AFLplusplus:main' into main
Marcondiro Nov 19, 2024
f6f42c0
Merge branch 'AFLplusplus:main' into main
Marcondiro Nov 19, 2024
af20343
qemu config refactoring
rmalmain Nov 19, 2024
643c240
Merge remote-tracking branch 'upstream/main'
Marcondiro Nov 20, 2024
3eb1f45
Merge remote-tracking branch 'upstream/qemu_builder_update'
Marcondiro Nov 20, 2024
f4addef
Merge remote-tracking branch 'upstream/main'
Marcondiro Nov 21, 2024
cddc3df
Fix intel_pt_command_executor target dir
Marcondiro Nov 21, 2024
1dfc590
Merge remote-tracking branch 'upstream/main'
Marcondiro Nov 21, 2024
5fa831a
Merge branch 'main' into qemu_builder_update
rmalmain Nov 22, 2024
4867e08
Merge remote-tracking branch 'upstream/main'
Nov 22, 2024
4cef8f6
Merge remote-tracking branch 'upstream/main'
Marcondiro Nov 25, 2024
28655d8
* QEMU error refactoring*
rmalmain Nov 25, 2024
b85ab06
update test
rmalmain Nov 25, 2024
a7f6464
Merge remote-tracking branch 'upstream/qemu_builder_update'
Marcondiro Nov 25, 2024
8afc5fc
Bump libipt
Marcondiro Nov 25, 2024
01fe205
waitpid_filtered to ignore SIGWINCH
Marcondiro Nov 25, 2024
eb3c63e
Fix warnings unused manifest key: *.version
Marcondiro Nov 26, 2024
c8b28ba
Add export_raw feature to libafl_intelpt
Marcondiro Nov 26, 2024
42b8cfe
derive Debug for IntelPTHook
Marcondiro Nov 26, 2024
a029fd1
Clippy
Marcondiro Nov 26, 2024
47d2741
Light refactor of EmulatorModules
rmalmain Nov 26, 2024
bd14dae
Update target program ELF offsets
Marcondiro Nov 26, 2024
0d37b78
Merge branch 'main' into qemu_builder_update
rmalmain Nov 26, 2024
1c61b38
fmt
rmalmain Nov 26, 2024
68e7c75
Merge remote-tracking branch 'upstream/main' into better-command-exec
Marcondiro Nov 26, 2024
525fd11
* asan fixed size accesses working with generics
rmalmain Nov 26, 2024
5346f83
fmt
rmalmain Nov 26, 2024
02a2f1f
Add comment to KVM pt_mode check
Marcondiro Nov 27, 2024
5230945
Merge remote-tracking branch 'upstream/main' into better-command-exec
Marcondiro Nov 27, 2024
9a84af4
refactor
Marcondiro Nov 27, 2024
eff0733
Merge remote-tracking branch 'upstream/main'
Marcondiro Nov 27, 2024
761964e
Add intel_pt_export_raw feature in libafl
Marcondiro Nov 27, 2024
17059d7
fix fuzzers
rmalmain Nov 27, 2024
c50ba05
* refactor asan and asanguest modules to avoid custom init of QEMU an…
rmalmain Nov 27, 2024
8d8631e
fmt
rmalmain Nov 27, 2024
f2491c1
clippy
rmalmain Nov 27, 2024
a12dc91
Merge branch 'main' into qemu_builder_update
rmalmain Nov 27, 2024
76480c1
fix qemu_coverage
rmalmain Nov 27, 2024
46f0da7
fmt
rmalmain Nov 27, 2024
1f1d9af
Merge remote-tracking branch 'upstream/main'
Marcondiro Nov 28, 2024
d2affe5
Merge remote-tracking branch 'upstream/main' into better-command-exec
Marcondiro Nov 28, 2024
3464e44
forgot qemu args in launcher
rmalmain Nov 28, 2024
d7bfbe7
map_error instead of unwrap
Marcondiro Nov 28, 2024
005475b
use correct args
rmalmain Nov 28, 2024
7f6c516
Merge remote-tracking branch 'upstream/qemu_builder_update'
Marcondiro Nov 28, 2024
6bb2867
Update to new libafl_qemu
Marcondiro Nov 28, 2024
970aecc
Merge branch 'better-command-exec'
Marcondiro Nov 28, 2024
ea840cf
adapt api
rmalmain Nov 28, 2024
51d5061
borrow checker friendly join_split_trace
Marcondiro Nov 28, 2024
5785061
Merge branch 'better-command-exec'
Marcondiro Nov 28, 2024
2998445
testing stuff
rmalmain Nov 28, 2024
aadc025
Merge remote-tracking branch 'upstream/qemu_builder_update'
Marcondiro Nov 29, 2024
b28d473
Set ip_filters (also) with builder
Marcondiro Nov 29, 2024
121d5d2
Merge branch 'better-command-exec'
Marcondiro Nov 29, 2024
9222eab
Move trace to file
Marcondiro Nov 29, 2024
6979bd2
Merge branch 'better-command-exec'
Marcondiro Nov 29, 2024
53a241f
Store a pt_builder in module
Marcondiro Nov 29, 2024
7c8ded9
baby_bootloader target
Marcondiro Dec 3, 2024
570030f
Best bootloader ever
Marcondiro Dec 4, 2024
c5b3e19
Merge branch 'main' into qemu_builder_update
rmalmain Dec 5, 2024
0fe2977
new builder?
rmalmain Dec 5, 2024
b7f5240
use closure for qemu config from emulator builder.
rmalmain Dec 5, 2024
413767f
better format
rmalmain Dec 5, 2024
8b04e3f
clippy + fmt
rmalmain Dec 5, 2024
7b2c0a9
Merge remote-tracking branch 'upstream/qemu_builder_update'
Marcondiro Dec 6, 2024
576a419
Fix build target
Marcondiro Dec 6, 2024
395b643
Remove filter on speculatively exec blocks
Marcondiro Dec 6, 2024
fb036ce
Add current ip_filters getter
Marcondiro Dec 6, 2024
89a6bf8
Fix possibile infinite loop in trace decode
Marcondiro Dec 6, 2024
9102449
Merge branch 'better-command-exec'
Marcondiro Dec 13, 2024
34ecd12
HW breakpoint + snapshot
Marcondiro Dec 13, 2024
378da3f
add snapshot and exit at first objective
Marcondiro Dec 17, 2024
76b13d0
Merge remote-tracking branch 'upstream/main'
Marcondiro Dec 17, 2024
53c0299
Merge remote-tracking branch 'upstream/main'
Marcondiro Dec 18, 2024
1af867f
Merge remote-tracking branch 'upstream/main'
Marcondiro Dec 19, 2024
2bde279
prefer raw pointers to slice_from_raw_parts_mut
Marcondiro Dec 20, 2024
1e7c1a8
Add cpu option to QEMU config
Marcondiro Dec 20, 2024
7f80bc5
Add cpu option and minor improvements
Marcondiro Dec 20, 2024
6f6a2ad
fix cargo run causing recompile
Marcondiro Dec 20, 2024
1a9b4a1
Merge remote-tracking branch 'upstream/main'
Marcondiro Dec 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion fuzzers/binary_only/fuzzbench_fork_qemu/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ fn fuzz(
);

let emulator = Emulator::empty()
.qemu_cli(args)
.qemu_config(|_| args)
.modules(emulator_modules)
.build()?;

Expand Down
51 changes: 27 additions & 24 deletions fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ use libafl_qemu::{
GuestReg,
//snapshot::QemuSnapshotHelper,
MmapPerms,
Qemu,
QemuExecutor,
QemuExitError,
QemuExitReason,
Expand Down Expand Up @@ -175,7 +174,33 @@ fn fuzz(
env::remove_var("LD_LIBRARY_PATH");

let args: Vec<String> = env::args().collect();
let qemu = Qemu::init(&args).expect("QEMU init failed");

// Create an observation channel using the coverage map
let mut edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges",
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_ALLOCATED_SIZE),
&raw mut MAX_EDGES_FOUND,
))
.track_indices()
};

let modules = tuple_list!(
StdEdgeCoverageModule::builder()
.map_observer(edges_observer.as_mut())
.build()
.unwrap(),
CmpLogModule::default(),
// QemuAsanHelper::default(asan),
//QemuSnapshotHelper::new()
);

let emulator = Emulator::empty()
.qemu_args(|_| args)
.modules(modules)
.build()?;
let qemu = emulator.qemu();
// let qemu = Qemu::init(&args).expect("QEMU init failed");
// let (emu, asan) = init_with_asan(&mut args, &mut env).unwrap();

let mut elf_buffer = Vec::new();
Expand Down Expand Up @@ -255,16 +280,6 @@ fn fuzz(
},
};

// Create an observation channel using the coverage map
let mut edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges",
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_ALLOCATED_SIZE),
&raw mut MAX_EDGES_FOUND,
))
.track_indices()
};

// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");

Expand Down Expand Up @@ -364,18 +379,6 @@ fn fuzz(
ExitKind::Ok
};

let modules = tuple_list!(
StdEdgeCoverageModule::builder()
.map_observer(edges_observer.as_mut())
.build()
.unwrap(),
CmpLogModule::default(),
// QemuAsanHelper::default(asan),
//QemuSnapshotHelper::new()
);

let emulator = Emulator::empty().qemu(qemu).modules(modules).build()?;

// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
let executor = QemuExecutor::new(
emulator,
Expand Down
3 changes: 1 addition & 2 deletions fuzzers/binary_only/intel_pt_command_executor/Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ script = "sudo setcap cap_ipc_lock,cap_sys_ptrace,cap_sys_admin,cap_syslog=ep ${
dependencies = ["build_fuzzer"]

[tasks.run]
command = "cargo"
args = ["run", "--profile", "${CARGO_MAKE_CARGO_PROFILE}"]
command = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/${PROFILE_DIR}/${CARGO_MAKE_CRATE_NAME}"
dependencies = ["build", "setcap"]

[tasks.default]
Expand Down
51 changes: 27 additions & 24 deletions fuzzers/binary_only/qemu_cmin/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ use libafl_bolts::{
};
use libafl_qemu::{
elf::EasyElf, modules::edges::StdEdgeCoverageChildModule, ArchExtras, CallingConvention,
Emulator, GuestAddr, GuestReg, MmapPerms, Qemu, QemuExitError, QemuExitReason,
QemuForkExecutor, QemuShutdownCause, Regs,
Emulator, GuestAddr, GuestReg, MmapPerms, QemuExitError, QemuExitReason, QemuForkExecutor,
QemuShutdownCause, Regs,
};
use libafl_targets::{EDGES_MAP_DEFAULT_SIZE, EDGES_MAP_PTR};

Expand Down Expand Up @@ -113,7 +113,31 @@ pub fn fuzz() -> Result<(), Error> {
log::debug!("ARGS: {:#?}", options.args);

env::remove_var("LD_LIBRARY_PATH");
let qemu = Qemu::init(&options.args).unwrap();

let mut shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");

let mut edges_shmem = shmem_provider.new_shmem(EDGES_MAP_DEFAULT_SIZE).unwrap();
let edges = edges_shmem.as_slice_mut();
unsafe { EDGES_MAP_PTR = edges.as_mut_ptr() };

let mut edges_observer = unsafe {
HitcountsMapObserver::new(ConstMapObserver::from_mut_ptr(
"edges",
NonNull::new(edges.as_mut_ptr())
.expect("The edge map pointer is null.")
.cast::<[u8; EDGES_MAP_DEFAULT_SIZE]>(),
))
};

let modules = tuple_list!(StdEdgeCoverageChildModule::builder()
.const_map_observer(edges_observer.as_mut())
.build()?);

let emulator = Emulator::empty()
.qemu_config(|_| options.args)
.modules(modules)
.build()?;
let qemu = emulator.qemu();

let mut elf_buffer = Vec::new();
let elf = EasyElf::from_file(qemu.binary_path(), &mut elf_buffer).unwrap();
Expand All @@ -139,8 +163,6 @@ pub fn fuzz() -> Result<(), Error> {

let stack_ptr: GuestAddr = qemu.read_reg(Regs::Sp).unwrap();

let mut shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");

let monitor = SimpleMonitor::with_user_monitor(|s| {
println!("{s}");
});
Expand All @@ -157,19 +179,6 @@ pub fn fuzz() -> Result<(), Error> {
},
};

let mut edges_shmem = shmem_provider.new_shmem(EDGES_MAP_DEFAULT_SIZE).unwrap();
let edges = edges_shmem.as_slice_mut();
unsafe { EDGES_MAP_PTR = edges.as_mut_ptr() };

let mut edges_observer = unsafe {
HitcountsMapObserver::new(ConstMapObserver::from_mut_ptr(
"edges",
NonNull::new(edges.as_mut_ptr())
.expect("The edge map pointer is null.")
.cast::<[u8; EDGES_MAP_DEFAULT_SIZE]>(),
))
};

let mut feedback = MaxMapFeedback::new(&edges_observer);

#[allow(clippy::let_unit_value)]
Expand Down Expand Up @@ -223,12 +232,6 @@ pub fn fuzz() -> Result<(), Error> {
ExitKind::Ok
};

let modules = tuple_list!(StdEdgeCoverageChildModule::builder()
.const_map_observer(edges_observer.as_mut())
.build()?);

let emulator = Emulator::empty().qemu(qemu).modules(modules).build()?;

let mut executor = QemuForkExecutor::new(
emulator,
&mut harness,
Expand Down
147 changes: 74 additions & 73 deletions fuzzers/binary_only/qemu_coverage/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use libafl_bolts::{
use libafl_qemu::{
elf::EasyElf,
modules::{drcov::DrCovModule, StdAddressFilter},
ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, Qemu, QemuExecutor,
ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, QemuExecutor,
QemuExitReason, QemuRWError, QemuShutdownCause, Regs,
};

Expand Down Expand Up @@ -123,80 +123,93 @@ pub fn fuzz() {

env::remove_var("LD_LIBRARY_PATH");

let qemu = Qemu::init(&options.args).unwrap();

let mut elf_buffer = Vec::new();
let elf = EasyElf::from_file(qemu.binary_path(), &mut elf_buffer).unwrap();

let test_one_input_ptr = elf
.resolve_symbol("LLVMFuzzerTestOneInput", qemu.load_addr())
.expect("Symbol LLVMFuzzerTestOneInput not found");
log::debug!("LLVMFuzzerTestOneInput @ {test_one_input_ptr:#x}");
let mut run_client = |state: Option<_>,
mut mgr: LlmpRestartingEventManager<_, _, _>,
client_description: ClientDescription| {
let mut cov_path = options.coverage_path.clone();

qemu.entry_break(test_one_input_ptr);
let emulator_modules = tuple_list!(DrCovModule::builder()
.filter(StdAddressFilter::default())
.filename(cov_path.clone())
.full_trace(false)
.build());

for m in qemu.mappings() {
log::debug!(
"Mapping: 0x{:016x}-0x{:016x}, {}",
m.start(),
m.end(),
m.path().unwrap_or(&"<EMPTY>".to_string())
);
}
let emulator = Emulator::empty()
.qemu_config(|_| options.args.clone())
.modules(emulator_modules)
.build()
.expect("QEMU initialization failed");
let qemu = emulator.qemu();

let mut elf_buffer = Vec::new();
let elf = EasyElf::from_file(qemu.binary_path(), &mut elf_buffer).unwrap();

let test_one_input_ptr = elf
.resolve_symbol("LLVMFuzzerTestOneInput", qemu.load_addr())
.expect("Symbol LLVMFuzzerTestOneInput not found");
log::debug!("LLVMFuzzerTestOneInput @ {test_one_input_ptr:#x}");

qemu.entry_break(test_one_input_ptr);

for m in qemu.mappings() {
log::debug!(
"Mapping: 0x{:016x}-0x{:016x}, {}",
m.start(),
m.end(),
m.path().unwrap_or(&"<EMPTY>".to_string())
);
}

let pc: GuestReg = qemu.read_reg(Regs::Pc).unwrap();
log::debug!("Break at {pc:#x}");
let pc: GuestReg = qemu.read_reg(Regs::Pc).unwrap();
log::debug!("Break at {pc:#x}");

let ret_addr: GuestAddr = qemu.read_return_address().unwrap();
log::debug!("Return address = {ret_addr:#x}");
let ret_addr: GuestAddr = qemu.read_return_address().unwrap();
log::debug!("Return address = {ret_addr:#x}");

qemu.set_breakpoint(ret_addr);
qemu.set_breakpoint(ret_addr);

let input_addr = qemu
.map_private(0, MAX_INPUT_SIZE, MmapPerms::ReadWrite)
.unwrap();
log::debug!("Placing input at {input_addr:#x}");
let input_addr = qemu
.map_private(0, MAX_INPUT_SIZE, MmapPerms::ReadWrite)
.unwrap();
log::debug!("Placing input at {input_addr:#x}");

let stack_ptr: GuestAddr = qemu.read_reg(Regs::Sp).unwrap();
let stack_ptr: GuestAddr = qemu.read_reg(Regs::Sp).unwrap();

let reset = |buf: &[u8], len: GuestReg| -> Result<(), QemuRWError> {
unsafe {
let _ = qemu.write_mem(input_addr, buf);
qemu.write_reg(Regs::Pc, test_one_input_ptr)?;
qemu.write_reg(Regs::Sp, stack_ptr)?;
qemu.write_return_address(ret_addr)?;
qemu.write_function_argument(CallingConvention::Cdecl, 0, input_addr)?;
qemu.write_function_argument(CallingConvention::Cdecl, 1, len)?;
let reset = |buf: &[u8], len: GuestReg| -> Result<(), QemuRWError> {
unsafe {
let _ = qemu.write_mem(input_addr, buf);
qemu.write_reg(Regs::Pc, test_one_input_ptr)?;
qemu.write_reg(Regs::Sp, stack_ptr)?;
qemu.write_return_address(ret_addr)?;
qemu.write_function_argument(CallingConvention::Cdecl, 0, input_addr)?;
qemu.write_function_argument(CallingConvention::Cdecl, 1, len)?;

match qemu.run() {
Ok(QemuExitReason::Breakpoint(_)) => {}
Ok(QemuExitReason::End(QemuShutdownCause::HostSignal(Signal::SigInterrupt))) => {
process::exit(0)
match qemu.run() {
Ok(QemuExitReason::Breakpoint(_)) => {}
Ok(QemuExitReason::End(QemuShutdownCause::HostSignal(
Signal::SigInterrupt,
))) => process::exit(0),
_ => panic!("Unexpected QEMU exit."),
}
_ => panic!("Unexpected QEMU exit."),
}

Ok(())
}
};

let mut harness =
|_emulator: &mut Emulator<_, _, _, _, _>, _state: &mut _, input: &BytesInput| {
let target = input.target_bytes();
let mut buf = target.as_slice();
let mut len = buf.len();
if len > MAX_INPUT_SIZE {
buf = &buf[0..MAX_INPUT_SIZE];
len = MAX_INPUT_SIZE;
Ok(())
}
let len = len as GuestReg;
reset(buf, len).unwrap();
ExitKind::Ok
};

let mut run_client = |state: Option<_>,
mut mgr: LlmpRestartingEventManager<_, _, _>,
client_description: ClientDescription| {
let mut harness =
|_emulator: &mut Emulator<_, _, _, _, _>, _state: &mut _, input: &BytesInput| {
let target = input.target_bytes();
let mut buf = target.as_slice();
let mut len = buf.len();
if len > MAX_INPUT_SIZE {
buf = &buf[0..MAX_INPUT_SIZE];
len = MAX_INPUT_SIZE;
}
let len = len as GuestReg;
reset(buf, len).unwrap();
ExitKind::Ok
};

let core_id = client_description.core_id();
let core_idx = options
.cores
Expand Down Expand Up @@ -234,23 +247,11 @@ pub fn fuzz() {
let scheduler = QueueScheduler::new();
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);

let mut cov_path = options.coverage_path.clone();
let coverage_name = cov_path.file_stem().unwrap().to_str().unwrap();
let coverage_extension = cov_path.extension().unwrap_or_default().to_str().unwrap();
let core = core_id.0;
cov_path.set_file_name(format!("{coverage_name}-{core:03}.{coverage_extension}"));

let emulator_modules = tuple_list!(DrCovModule::builder()
.filter(StdAddressFilter::default())
.filename(cov_path)
.full_trace(false)
.build());

let emulator = Emulator::empty()
.qemu(qemu)
.modules(emulator_modules)
.build()?;

let mut executor = QemuExecutor::new(
emulator,
&mut harness,
Expand Down
Loading
Loading