libafl bridge as Rust crate
This commit is contained in:
parent
308c6ab905
commit
5e1a634d0c
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
|
/qemu_libafl_bridge/Cargo.lock
|
||||||
|
/qemu_libafl_bridge/target/
|
||||||
/GNUmakefile
|
/GNUmakefile
|
||||||
/build/
|
/build/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
6
configure
vendored
6
configure
vendored
@ -446,6 +446,8 @@ slirp_smbd="$default_feature"
|
|||||||
malloc_trim="auto"
|
malloc_trim="auto"
|
||||||
gio="$default_feature"
|
gio="$default_feature"
|
||||||
|
|
||||||
|
libafl_bridge=""
|
||||||
|
|
||||||
# parse CC options second
|
# parse CC options second
|
||||||
for opt do
|
for opt do
|
||||||
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
|
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
|
||||||
@ -1558,6 +1560,8 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--disable-slirp-smbd) slirp_smbd=no
|
--disable-slirp-smbd) slirp_smbd=no
|
||||||
;;
|
;;
|
||||||
|
--with-libafl-bridge=*) libafl_bridge="$optarg"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "ERROR: unknown option $opt"
|
echo "ERROR: unknown option $opt"
|
||||||
echo "Try '$0 --help' for more information"
|
echo "Try '$0 --help' for more information"
|
||||||
@ -1566,6 +1570,8 @@ for opt do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
QEMU_LDFLAGS="$QEMU_LDFLAGS $libafl_bridge"
|
||||||
|
|
||||||
case $git_submodules_action in
|
case $git_submodules_action in
|
||||||
update|validate)
|
update|validate)
|
||||||
if test ! -e "$source_path/.git"; then
|
if test ! -e "$source_path/.git"; then
|
||||||
|
11
qemu_libafl_bridge/Cargo.toml
Normal file
11
qemu_libafl_bridge/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "qemu_libafl_bridge"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
num = "0.4"
|
||||||
|
num_enum = "0.5.1"
|
23
qemu_libafl_bridge/src/amd64.rs
Normal file
23
qemu_libafl_bridge/src/amd64.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
|
|
||||||
|
#[derive(IntoPrimitive, TryFromPrimitive, Clone, Copy)]
|
||||||
|
#[repr(i32)]
|
||||||
|
#[allow(clippy::pub_enum_variant_names)]
|
||||||
|
pub enum Amd64Regs {
|
||||||
|
Rax = 0,
|
||||||
|
Rcx = 1,
|
||||||
|
Rdx = 2,
|
||||||
|
Rbx = 3,
|
||||||
|
Rsp = 4,
|
||||||
|
Rbp = 5,
|
||||||
|
Rsi = 6,
|
||||||
|
Rdi = 7,
|
||||||
|
R8 = 8,
|
||||||
|
R9 = 9,
|
||||||
|
R10 = 10,
|
||||||
|
R11 = 11,
|
||||||
|
R12 = 12,
|
||||||
|
R13 = 13,
|
||||||
|
R14 = 14,
|
||||||
|
R15 = 15,
|
||||||
|
}
|
92
qemu_libafl_bridge/src/lib.rs
Normal file
92
qemu_libafl_bridge/src/lib.rs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
use core::{mem::transmute, ptr::copy_nonoverlapping};
|
||||||
|
use num::Num;
|
||||||
|
|
||||||
|
pub mod amd64;
|
||||||
|
|
||||||
|
/*
|
||||||
|
int libafl_qemu_write_reg(int reg, uint8_t* val);
|
||||||
|
int libafl_qemu_read_reg(int reg, uint8_t* val);
|
||||||
|
int libafl_qemu_num_regs(void);
|
||||||
|
int libafl_qemu_set_breakpoint(uint64_t addr);
|
||||||
|
int libafl_qemu_remove_breakpoint(uint64_t addr);
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn libafl_qemu_write_reg(reg: i32, val: *const u8) -> i32;
|
||||||
|
fn libafl_qemu_read_reg(reg: i32, val: *mut u8) -> i32;
|
||||||
|
fn libafl_qemu_num_regs() -> i32;
|
||||||
|
fn libafl_qemu_set_breakpoint(addr: u64) -> i32;
|
||||||
|
fn libafl_qemu_remove_breakpoint(addr: u64) -> i32;
|
||||||
|
fn libafl_qemu_run() -> i32;
|
||||||
|
|
||||||
|
static guest_base: isize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct QemuEmulator {}
|
||||||
|
|
||||||
|
impl QemuEmulator {
|
||||||
|
pub fn write_mem(&mut self, addr: isize, buf: &[u8]) {
|
||||||
|
let host_addr = self.g2h(addr);
|
||||||
|
unsafe { copy_nonoverlapping(buf.as_ptr() as *const u8, host_addr, buf.len()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_mem(&mut self, addr: isize, buf: &mut [u8]) {
|
||||||
|
let host_addr = self.g2h(addr);
|
||||||
|
unsafe {
|
||||||
|
copy_nonoverlapping(
|
||||||
|
host_addr as *const u8,
|
||||||
|
buf.as_mut_ptr() as *mut u8,
|
||||||
|
buf.len(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn num_regs(&self) -> i32 {
|
||||||
|
unsafe { libafl_qemu_num_regs() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_reg<T>(&mut self, reg: i32, val: T) -> Result<(), String>
|
||||||
|
where
|
||||||
|
T: Num + PartialOrd + Copy,
|
||||||
|
{
|
||||||
|
let success = unsafe { libafl_qemu_write_reg(reg, &val as *const _ as *const u8) };
|
||||||
|
if success != 0 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(format!("Failed to write to register {}", reg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_reg<T>(&mut self, reg: i32) -> Result<T, String>
|
||||||
|
where
|
||||||
|
T: Num + PartialOrd + Copy,
|
||||||
|
{
|
||||||
|
let mut val = T::zero();
|
||||||
|
let success = unsafe { libafl_qemu_read_reg(reg, &mut val as *mut _ as *mut u8) };
|
||||||
|
if success != 0 {
|
||||||
|
Ok(val)
|
||||||
|
} else {
|
||||||
|
Err(format!("Failed to read register {}", reg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_breakpoint(&mut self, addr: isize) {
|
||||||
|
unsafe { libafl_qemu_set_breakpoint(addr as u64) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_breakpoint(&mut self, addr: isize) {
|
||||||
|
unsafe { libafl_qemu_remove_breakpoint(addr as u64) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self) {
|
||||||
|
unsafe { libafl_qemu_run() };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn g2h(&self, addr: isize) -> *mut u8 {
|
||||||
|
unsafe { transmute(addr + guest_base) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn h2g(&self, addr: isize) -> *mut u8 {
|
||||||
|
unsafe { transmute(addr - guest_base) }
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user