Add custom GDB commands to libafl_qemu (#671)
* Add custom GDB commands * clippy * statically linked QEMU * fix Calibrate * clippy
This commit is contained in:
parent
f7c997ec65
commit
93048f6270
@ -155,9 +155,15 @@ where
|
||||
.unwrap()
|
||||
.history_map;
|
||||
|
||||
for j in 0..map_len {
|
||||
if map_first[j] != map[j] && history_map[j] != O::Entry::max_value() {
|
||||
history_map[j] = O::Entry::max_value();
|
||||
if history_map.len() < map_len {
|
||||
history_map.resize(map_len, O::Entry::default());
|
||||
}
|
||||
|
||||
for (first, (cur, history)) in
|
||||
map_first.iter().zip(map.iter().zip(history_map.iter_mut()))
|
||||
{
|
||||
if *first != *cur && *history != O::Entry::max_value() {
|
||||
*history = O::Entry::max_value();
|
||||
unstable_entries += 1;
|
||||
};
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use which::which;
|
||||
|
||||
const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
|
||||
const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
|
||||
const QEMU_REVISION: &str = "d840462c2e4cdda4428d99cd4003ddda95c5a2dc";
|
||||
const QEMU_REVISION: &str = "6a9a929222cbc8b10adfb048aa24f73486e0a886";
|
||||
|
||||
fn build_dep_check(tools: &[&str]) {
|
||||
for tool in tools {
|
||||
@ -141,81 +141,18 @@ pub fn build() {
|
||||
let build_dir = qemu_path.join("build");
|
||||
let output_lib = build_dir.join(&format!("libqemu-{}.so", cpu_target));
|
||||
if !output_lib.is_file() {
|
||||
drop(
|
||||
/*drop(
|
||||
Command::new("make")
|
||||
.current_dir(&qemu_path)
|
||||
.arg("distclean")
|
||||
.status(),
|
||||
);
|
||||
);*/
|
||||
Command::new("./configure")
|
||||
.current_dir(&qemu_path)
|
||||
//.arg("--as-static-lib")
|
||||
.arg("--as-shared-lib")
|
||||
.arg(&format!("--target-list={}-linux-user", cpu_target))
|
||||
.args(&[
|
||||
"--audio-drv-list=",
|
||||
"--disable-blobs",
|
||||
"--disable-bochs",
|
||||
"--disable-brlapi",
|
||||
"--disable-bsd-user",
|
||||
"--disable-bzip2",
|
||||
"--disable-cap-ng",
|
||||
"--disable-cloop",
|
||||
"--disable-curl",
|
||||
"--disable-curses",
|
||||
"--disable-dmg",
|
||||
"--disable-fdt",
|
||||
"--disable-gcrypt",
|
||||
"--disable-glusterfs",
|
||||
"--disable-gnutls",
|
||||
"--disable-gtk",
|
||||
"--disable-guest-agent",
|
||||
"--disable-iconv",
|
||||
"--disable-libiscsi",
|
||||
"--disable-libnfs",
|
||||
"--disable-libssh",
|
||||
"--disable-libusb",
|
||||
"--disable-linux-aio",
|
||||
"--disable-live-block-migration",
|
||||
"--disable-lzo",
|
||||
"--disable-nettle",
|
||||
"--disable-numa",
|
||||
"--disable-opengl",
|
||||
"--disable-parallels",
|
||||
"--disable-plugins",
|
||||
"--disable-qcow1",
|
||||
"--disable-qed",
|
||||
"--disable-rbd",
|
||||
"--disable-rdma",
|
||||
"--disable-replication",
|
||||
"--disable-sdl",
|
||||
"--disable-seccomp",
|
||||
"--disable-smartcard",
|
||||
"--disable-snappy",
|
||||
"--disable-spice",
|
||||
"--disable-system",
|
||||
"--disable-tools",
|
||||
"--disable-tpm",
|
||||
"--disable-usb-redir",
|
||||
"--disable-vde",
|
||||
"--disable-vdi",
|
||||
"--disable-vhost-crypto",
|
||||
"--disable-vhost-kernel",
|
||||
"--disable-vhost-net",
|
||||
"--disable-vhost-scsi",
|
||||
"--disable-vhost-user",
|
||||
"--disable-vhost-vdpa",
|
||||
"--disable-vhost-vsock",
|
||||
"--disable-virglrenderer",
|
||||
"--disable-virtfs",
|
||||
"--disable-vnc",
|
||||
"--disable-vnc-jpeg",
|
||||
"--disable-vnc-sasl",
|
||||
"--disable-vte",
|
||||
"--disable-vvfat",
|
||||
"--disable-xen",
|
||||
"--disable-xen-pci-passthrough",
|
||||
])
|
||||
.args(&["--disable-blobs", "--disable-bsd-user", "--disable-fdt"])
|
||||
.status()
|
||||
.expect("Configure failed");
|
||||
if let Ok(j) = jobs {
|
||||
@ -235,77 +172,71 @@ pub fn build() {
|
||||
//let _ = remove_file(build_dir.join(&format!("libqemu-{}.so", cpu_target)));
|
||||
}
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
{
|
||||
let mut objects = vec![];
|
||||
for dir in &[
|
||||
build_dir.join("libcommon.fa.p"),
|
||||
build_dir.join(&format!("libqemu-{}-linux-user.fa.p", cpu_target)),
|
||||
//build_dir.join("libcommon-user.fa.p"),
|
||||
//build_dir.join("libqemuutil.a.p"),
|
||||
//build_dir.join("libqom.fa.p"),
|
||||
//build_dir.join("libhwcore.fa.p"),
|
||||
//build_dir.join("libcapstone.a.p"),
|
||||
] {
|
||||
for path in fs::read_dir(dir).unwrap() {
|
||||
let path = path.unwrap().path();
|
||||
if path.is_file() {
|
||||
if let Some(name) = path.file_name() {
|
||||
if name.to_string_lossy().starts_with("stubs") {
|
||||
continue;
|
||||
} else if let Some(ext) = path.extension() {
|
||||
if ext == "o" {
|
||||
objects.push(path);
|
||||
}
|
||||
let mut objects = vec![];
|
||||
for dir in &[
|
||||
build_dir.join("libcommon.fa.p"),
|
||||
build_dir.join(&format!("libqemu-{}-linux-user.fa.p", cpu_target)),
|
||||
//build_dir.join("libcommon-user.fa.p"),
|
||||
//build_dir.join("libqemuutil.a.p"),
|
||||
//build_dir.join("libqom.fa.p"),
|
||||
//build_dir.join("libhwcore.fa.p"),
|
||||
] {
|
||||
for path in fs::read_dir(dir).unwrap() {
|
||||
let path = path.unwrap().path();
|
||||
if path.is_file() {
|
||||
if let Some(name) = path.file_name() {
|
||||
if name.to_string_lossy().starts_with("stubs") {
|
||||
continue;
|
||||
} else if let Some(ext) = path.extension() {
|
||||
if ext == "o" {
|
||||
objects.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for obj in &objects {
|
||||
println!("cargo:rustc-cdylib-link-arg={}", obj.display());
|
||||
}
|
||||
|
||||
println!("cargo:rustc-cdylib-link-arg=-Wl,--start-group");
|
||||
|
||||
println!("cargo:rustc-cdylib-link-arg=-Wl,--whole-archive");
|
||||
println!(
|
||||
"cargo:rustc-cdylib-link-arg={}/libhwcore.fa",
|
||||
build_dir.display()
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-cdylib-link-arg={}/libqom.fa",
|
||||
build_dir.display()
|
||||
);
|
||||
println!("cargo:rustc-cdylib-link-arg=-Wl,--no-whole-archive");
|
||||
println!(
|
||||
"cargo:rustc-cdylib-link-arg={}/libcapstone.a",
|
||||
build_dir.display()
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-cdylib-link-arg={}/libqemuutil.a",
|
||||
build_dir.display()
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-cdylib-link-arg={}/libhwcore.fa",
|
||||
build_dir.display()
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-cdylib-link-arg={}/libqom.fa",
|
||||
build_dir.display()
|
||||
);
|
||||
|
||||
println!("cargo:rustc-cdylib-link-arg=-lrt");
|
||||
println!("cargo:rustc-cdylib-link-arg=-lutil");
|
||||
println!("cargo:rustc-cdylib-link-arg=-lgthread-2.0");
|
||||
println!("cargo:rustc-cdylib-link-arg=-lglib-2.0");
|
||||
println!("cargo:rustc-cdylib-link-arg=-lstdc++");
|
||||
|
||||
println!("cargo:rustc-cdylib-link-arg=-Wl,--end-group");
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "python"))]
|
||||
Command::new("ld")
|
||||
.current_dir(&out_dir_path)
|
||||
.arg("-o")
|
||||
.arg("libqemu-partially-linked.o")
|
||||
.arg("-r")
|
||||
.args(objects)
|
||||
.arg("--start-group")
|
||||
.arg("--whole-archive")
|
||||
.arg(format!("{}/libhwcore.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqom.fa", build_dir.display()))
|
||||
.arg(format!("{}/libevent-loop-base.a", build_dir.display()))
|
||||
.arg("--no-whole-archive")
|
||||
.arg(format!("{}/libqemuutil.a", build_dir.display()))
|
||||
.arg(format!("{}/libhwcore.fa", build_dir.display()))
|
||||
.arg(format!("{}/libqom.fa", build_dir.display()))
|
||||
.arg(format!(
|
||||
"--dynamic-list={}/plugins/qemu-plugins.symbols",
|
||||
qemu_path.display()
|
||||
))
|
||||
.status()
|
||||
.expect("Partial linked failure");
|
||||
|
||||
drop(
|
||||
Command::new("ar")
|
||||
.current_dir(&out_dir_path)
|
||||
.arg("crus")
|
||||
.arg("libqemu-partially-linked.a")
|
||||
.arg("libqemu-partially-linked.o")
|
||||
.status(),
|
||||
);
|
||||
|
||||
println!("cargo:rustc-link-search=native={}", out_dir);
|
||||
println!("cargo:rustc-link-lib=static=qemu-partially-linked");
|
||||
|
||||
println!("cargo:rustc-link-lib=rt");
|
||||
println!("cargo:rustc-link-lib=gmodule-2.0");
|
||||
println!("cargo:rustc-link-lib=glib-2.0");
|
||||
println!("cargo:rustc-link-lib=stdc++");
|
||||
|
||||
/* #[cfg(not(feature = "python"))]
|
||||
{
|
||||
fs::copy(
|
||||
build_dir.join(&format!("libqemu-{}.so", cpu_target)),
|
||||
@ -320,7 +251,7 @@ pub fn build() {
|
||||
println!("cargo:rustc-link-lib=qemu-{}", cpu_target);
|
||||
|
||||
println!("cargo:rustc-env=LD_LIBRARY_PATH={}", target_dir.display());
|
||||
}
|
||||
} */
|
||||
|
||||
drop(
|
||||
Command::new("make")
|
||||
@ -347,52 +278,3 @@ pub fn build() {
|
||||
.file(src_dir.join("asan-giovese.c"))
|
||||
.compile("asan_giovese");
|
||||
}
|
||||
|
||||
/*
|
||||
// Build a static library
|
||||
let mut objects = vec![];
|
||||
for dir in &[
|
||||
build_dir.join("libcommon.fa.p"),
|
||||
build_dir.join(&format!("libqemu-{}-linux-user.fa.p", cpu_target)),
|
||||
build_dir.join("libqemuutil.a.p"),
|
||||
build_dir.join("libqom.fa.p"),
|
||||
build_dir.join("libhwcore.fa.p"),
|
||||
build_dir.join("libcapstone.a.p"),
|
||||
] {
|
||||
for path in read_dir(dir).unwrap() {
|
||||
let path = path.unwrap().path();
|
||||
if path.is_file() {
|
||||
if let Some(name) = path.file_name() {
|
||||
if name.to_string_lossy().starts_with("stubs") {
|
||||
continue;
|
||||
}
|
||||
else if let Some(ext) = path.extension() {
|
||||
if ext == "o" {
|
||||
objects.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Command::new("ar")
|
||||
.current_dir(&out_dir_path)
|
||||
.arg("crus")
|
||||
.arg("libqemu-bridge.a")
|
||||
.args(&objects)
|
||||
.status()
|
||||
.expect("Ar failed");
|
||||
|
||||
println!("cargo:rustc-link-search=native={}", &out_dir);
|
||||
println!("cargo:rustc-link-lib=static=qemu-bridge");
|
||||
|
||||
println!("cargo:rustc-link-lib=rt");
|
||||
println!("cargo:rustc-link-lib=util");
|
||||
println!("cargo:rustc-link-lib=gthread-2.0");
|
||||
println!("cargo:rustc-link-lib=glib-2.0");
|
||||
println!("cargo:rustc-link-lib=stdc++");
|
||||
|
||||
}
|
||||
*/
|
||||
|
@ -3,7 +3,7 @@
|
||||
use core::{
|
||||
convert::Into,
|
||||
ffi::c_void,
|
||||
mem::{transmute, MaybeUninit},
|
||||
mem::MaybeUninit,
|
||||
ptr::{addr_of, addr_of_mut, copy_nonoverlapping, null},
|
||||
};
|
||||
use libc::c_int;
|
||||
@ -248,6 +248,12 @@ extern "C" {
|
||||
unsafe extern "C" fn(i32, u64, u64, u64, u64, u64, u64, u64, u64) -> SyscallHookResult;
|
||||
static mut libafl_post_syscall_hook:
|
||||
unsafe extern "C" fn(u64, i32, u64, u64, u64, u64, u64, u64, u64, u64) -> u64;
|
||||
|
||||
fn libafl_qemu_add_gdb_cmd(
|
||||
callback: extern "C" fn(*const u8, usize, *const ()) -> i32,
|
||||
data: *const (),
|
||||
);
|
||||
fn libafl_qemu_gdb_reply(buf: *const u8, len: usize);
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "python", pyclass(unsendable))]
|
||||
@ -309,6 +315,25 @@ impl Drop for GuestMaps {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) struct FatPtr(*const c_void, *const c_void);
|
||||
|
||||
static mut GDB_COMMANDS: Vec<FatPtr> = vec![];
|
||||
|
||||
extern "C" fn gdb_cmd(buf: *const u8, len: usize, data: *const ()) -> i32 {
|
||||
unsafe {
|
||||
let closure =
|
||||
&mut *(data as *mut std::boxed::Box<dyn for<'r> std::ops::FnMut(&'r str) -> bool>);
|
||||
let cmd = std::str::from_utf8_unchecked(std::slice::from_raw_parts(buf, len));
|
||||
if closure(cmd) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut EMULATOR_IS_INITIALIZED: bool = false;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -451,7 +476,7 @@ impl Emulator {
|
||||
|
||||
#[must_use]
|
||||
pub fn g2h<T>(&self, addr: GuestAddr) -> *mut T {
|
||||
unsafe { transmute(addr as usize + guest_base) }
|
||||
unsafe { (addr as usize + guest_base) as *mut T }
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
@ -704,12 +729,25 @@ impl Emulator {
|
||||
libafl_post_syscall_hook = hook;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_gdb_cmd(&self, callback: Box<dyn FnMut(&str) -> bool>) {
|
||||
unsafe {
|
||||
GDB_COMMANDS.push(core::mem::transmute(callback));
|
||||
libafl_qemu_add_gdb_cmd(
|
||||
gdb_cmd,
|
||||
GDB_COMMANDS.last().unwrap() as *const _ as *const (),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gdb_reply(&self, output: &str) {
|
||||
unsafe { libafl_qemu_gdb_reply(output.as_bytes().as_ptr(), output.len()) };
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
pub mod pybind {
|
||||
use super::{GuestAddr, GuestUsize, MmapPerms, SyscallHookResult};
|
||||
use core::mem::transmute;
|
||||
use pyo3::exceptions::PyValueError;
|
||||
use pyo3::{prelude::*, types::PyInt};
|
||||
use std::convert::TryFrom;
|
||||
@ -820,7 +858,7 @@ pub mod pybind {
|
||||
}
|
||||
|
||||
fn h2g(&self, addr: u64) -> GuestAddr {
|
||||
self.emu.h2g(unsafe { transmute::<_, *const u8>(addr) })
|
||||
self.emu.h2g(addr as *const u8)
|
||||
}
|
||||
|
||||
fn binary_path(&self) -> String {
|
||||
|
@ -14,15 +14,11 @@ use libafl::{executors::inprocess::inprocess_get_state, inputs::Input};
|
||||
|
||||
pub use crate::emu::SyscallHookResult;
|
||||
use crate::{
|
||||
emu::{Emulator, SKIP_EXEC_HOOK},
|
||||
emu::{Emulator, FatPtr, SKIP_EXEC_HOOK},
|
||||
helper::{QemuHelper, QemuHelperTuple},
|
||||
GuestAddr,
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
struct FatPtr(*const c_void, *const c_void);
|
||||
|
||||
// all kinds of hooks
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
enum Hook {
|
||||
|
@ -7,6 +7,8 @@
|
||||
allow(clippy::useless_conversion)
|
||||
)]
|
||||
#![allow(clippy::needless_pass_by_value)]
|
||||
// Till they fix this buggy lint in clippy
|
||||
#![allow(clippy::borrow_deref_ref)]
|
||||
|
||||
use std::env;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user