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()
|
.unwrap()
|
||||||
.history_map;
|
.history_map;
|
||||||
|
|
||||||
for j in 0..map_len {
|
if history_map.len() < map_len {
|
||||||
if map_first[j] != map[j] && history_map[j] != O::Entry::max_value() {
|
history_map.resize(map_len, O::Entry::default());
|
||||||
history_map[j] = O::Entry::max_value();
|
}
|
||||||
|
|
||||||
|
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;
|
unstable_entries += 1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use which::which;
|
|||||||
|
|
||||||
const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
|
const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
|
||||||
const QEMU_DIRNAME: &str = "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]) {
|
fn build_dep_check(tools: &[&str]) {
|
||||||
for tool in tools {
|
for tool in tools {
|
||||||
@ -141,81 +141,18 @@ pub fn build() {
|
|||||||
let build_dir = qemu_path.join("build");
|
let build_dir = qemu_path.join("build");
|
||||||
let output_lib = build_dir.join(&format!("libqemu-{}.so", cpu_target));
|
let output_lib = build_dir.join(&format!("libqemu-{}.so", cpu_target));
|
||||||
if !output_lib.is_file() {
|
if !output_lib.is_file() {
|
||||||
drop(
|
/*drop(
|
||||||
Command::new("make")
|
Command::new("make")
|
||||||
.current_dir(&qemu_path)
|
.current_dir(&qemu_path)
|
||||||
.arg("distclean")
|
.arg("distclean")
|
||||||
.status(),
|
.status(),
|
||||||
);
|
);*/
|
||||||
Command::new("./configure")
|
Command::new("./configure")
|
||||||
.current_dir(&qemu_path)
|
.current_dir(&qemu_path)
|
||||||
//.arg("--as-static-lib")
|
//.arg("--as-static-lib")
|
||||||
.arg("--as-shared-lib")
|
.arg("--as-shared-lib")
|
||||||
.arg(&format!("--target-list={}-linux-user", cpu_target))
|
.arg(&format!("--target-list={}-linux-user", cpu_target))
|
||||||
.args(&[
|
.args(&["--disable-blobs", "--disable-bsd-user", "--disable-fdt"])
|
||||||
"--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",
|
|
||||||
])
|
|
||||||
.status()
|
.status()
|
||||||
.expect("Configure failed");
|
.expect("Configure failed");
|
||||||
if let Ok(j) = jobs {
|
if let Ok(j) = jobs {
|
||||||
@ -235,77 +172,71 @@ pub fn build() {
|
|||||||
//let _ = remove_file(build_dir.join(&format!("libqemu-{}.so", cpu_target)));
|
//let _ = remove_file(build_dir.join(&format!("libqemu-{}.so", cpu_target)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "python")]
|
let mut objects = vec![];
|
||||||
{
|
for dir in &[
|
||||||
let mut objects = vec![];
|
build_dir.join("libcommon.fa.p"),
|
||||||
for dir in &[
|
build_dir.join(&format!("libqemu-{}-linux-user.fa.p", cpu_target)),
|
||||||
build_dir.join("libcommon.fa.p"),
|
//build_dir.join("libcommon-user.fa.p"),
|
||||||
build_dir.join(&format!("libqemu-{}-linux-user.fa.p", cpu_target)),
|
//build_dir.join("libqemuutil.a.p"),
|
||||||
//build_dir.join("libcommon-user.fa.p"),
|
//build_dir.join("libqom.fa.p"),
|
||||||
//build_dir.join("libqemuutil.a.p"),
|
//build_dir.join("libhwcore.fa.p"),
|
||||||
//build_dir.join("libqom.fa.p"),
|
] {
|
||||||
//build_dir.join("libhwcore.fa.p"),
|
for path in fs::read_dir(dir).unwrap() {
|
||||||
//build_dir.join("libcapstone.a.p"),
|
let path = path.unwrap().path();
|
||||||
] {
|
if path.is_file() {
|
||||||
for path in fs::read_dir(dir).unwrap() {
|
if let Some(name) = path.file_name() {
|
||||||
let path = path.unwrap().path();
|
if name.to_string_lossy().starts_with("stubs") {
|
||||||
if path.is_file() {
|
continue;
|
||||||
if let Some(name) = path.file_name() {
|
} else if let Some(ext) = path.extension() {
|
||||||
if name.to_string_lossy().starts_with("stubs") {
|
if ext == "o" {
|
||||||
continue;
|
objects.push(path);
|
||||||
} 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(
|
fs::copy(
|
||||||
build_dir.join(&format!("libqemu-{}.so", cpu_target)),
|
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-link-lib=qemu-{}", cpu_target);
|
||||||
|
|
||||||
println!("cargo:rustc-env=LD_LIBRARY_PATH={}", target_dir.display());
|
println!("cargo:rustc-env=LD_LIBRARY_PATH={}", target_dir.display());
|
||||||
}
|
} */
|
||||||
|
|
||||||
drop(
|
drop(
|
||||||
Command::new("make")
|
Command::new("make")
|
||||||
@ -347,52 +278,3 @@ pub fn build() {
|
|||||||
.file(src_dir.join("asan-giovese.c"))
|
.file(src_dir.join("asan-giovese.c"))
|
||||||
.compile("asan_giovese");
|
.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::{
|
use core::{
|
||||||
convert::Into,
|
convert::Into,
|
||||||
ffi::c_void,
|
ffi::c_void,
|
||||||
mem::{transmute, MaybeUninit},
|
mem::MaybeUninit,
|
||||||
ptr::{addr_of, addr_of_mut, copy_nonoverlapping, null},
|
ptr::{addr_of, addr_of_mut, copy_nonoverlapping, null},
|
||||||
};
|
};
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
@ -248,6 +248,12 @@ extern "C" {
|
|||||||
unsafe extern "C" fn(i32, u64, u64, u64, u64, u64, u64, u64, u64) -> SyscallHookResult;
|
unsafe extern "C" fn(i32, u64, u64, u64, u64, u64, u64, u64, u64) -> SyscallHookResult;
|
||||||
static mut libafl_post_syscall_hook:
|
static mut libafl_post_syscall_hook:
|
||||||
unsafe extern "C" fn(u64, i32, u64, u64, u64, u64, u64, u64, u64, u64) -> u64;
|
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))]
|
#[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;
|
static mut EMULATOR_IS_INITIALIZED: bool = false;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -451,7 +476,7 @@ impl Emulator {
|
|||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn g2h<T>(&self, addr: GuestAddr) -> *mut T {
|
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]
|
#[must_use]
|
||||||
@ -704,12 +729,25 @@ impl Emulator {
|
|||||||
libafl_post_syscall_hook = hook;
|
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")]
|
#[cfg(feature = "python")]
|
||||||
pub mod pybind {
|
pub mod pybind {
|
||||||
use super::{GuestAddr, GuestUsize, MmapPerms, SyscallHookResult};
|
use super::{GuestAddr, GuestUsize, MmapPerms, SyscallHookResult};
|
||||||
use core::mem::transmute;
|
|
||||||
use pyo3::exceptions::PyValueError;
|
use pyo3::exceptions::PyValueError;
|
||||||
use pyo3::{prelude::*, types::PyInt};
|
use pyo3::{prelude::*, types::PyInt};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@ -820,7 +858,7 @@ pub mod pybind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn h2g(&self, addr: u64) -> GuestAddr {
|
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 {
|
fn binary_path(&self) -> String {
|
||||||
|
@ -14,15 +14,11 @@ use libafl::{executors::inprocess::inprocess_get_state, inputs::Input};
|
|||||||
|
|
||||||
pub use crate::emu::SyscallHookResult;
|
pub use crate::emu::SyscallHookResult;
|
||||||
use crate::{
|
use crate::{
|
||||||
emu::{Emulator, SKIP_EXEC_HOOK},
|
emu::{Emulator, FatPtr, SKIP_EXEC_HOOK},
|
||||||
helper::{QemuHelper, QemuHelperTuple},
|
helper::{QemuHelper, QemuHelperTuple},
|
||||||
GuestAddr,
|
GuestAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
||||||
struct FatPtr(*const c_void, *const c_void);
|
|
||||||
|
|
||||||
// all kinds of hooks
|
// all kinds of hooks
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
enum Hook {
|
enum Hook {
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
allow(clippy::useless_conversion)
|
allow(clippy::useless_conversion)
|
||||||
)]
|
)]
|
||||||
#![allow(clippy::needless_pass_by_value)]
|
#![allow(clippy::needless_pass_by_value)]
|
||||||
|
// Till they fix this buggy lint in clippy
|
||||||
|
#![allow(clippy::borrow_deref_ref)]
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user