libafl_qemu cpu_target cfg (#383)
* cpu_target * report * track mmap in x64 snapshots
This commit is contained in:
parent
4d24012245
commit
fd5e793e57
@ -40,7 +40,6 @@ use libafl::{
|
|||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
use libafl_qemu::{
|
use libafl_qemu::{
|
||||||
amd64::Amd64Regs,
|
|
||||||
asan::QemuAsanHelper,
|
asan::QemuAsanHelper,
|
||||||
cmplog,
|
cmplog,
|
||||||
cmplog::{CmpLogObserver, QemuCmpLogHelper},
|
cmplog::{CmpLogObserver, QemuCmpLogHelper},
|
||||||
@ -49,7 +48,7 @@ use libafl_qemu::{
|
|||||||
elf::EasyElf,
|
elf::EasyElf,
|
||||||
emu, filter_qemu_args, init_with_asan,
|
emu, filter_qemu_args, init_with_asan,
|
||||||
snapshot::QemuSnapshotHelper,
|
snapshot::QemuSnapshotHelper,
|
||||||
MmapPerms, QemuExecutor,
|
MmapPerms, QemuExecutor, Regs,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The fuzzer main
|
/// The fuzzer main
|
||||||
@ -175,10 +174,10 @@ fn fuzz(
|
|||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Break at {:#x}",
|
"Break at {:#x}",
|
||||||
emu::read_reg::<_, u64>(Amd64Regs::Rip).unwrap()
|
emu::read_reg::<_, u64>(Regs::Rip).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let stack_ptr: u64 = emu::read_reg(Amd64Regs::Rsp).unwrap();
|
let stack_ptr: u64 = emu::read_reg(Regs::Rsp).unwrap();
|
||||||
let mut ret_addr = [0u64];
|
let mut ret_addr = [0u64];
|
||||||
emu::read_mem(stack_ptr, &mut ret_addr);
|
emu::read_mem(stack_ptr, &mut ret_addr);
|
||||||
let ret_addr = ret_addr[0];
|
let ret_addr = ret_addr[0];
|
||||||
@ -293,10 +292,10 @@ fn fuzz(
|
|||||||
|
|
||||||
emu::write_mem(input_addr, buf);
|
emu::write_mem(input_addr, buf);
|
||||||
|
|
||||||
emu::write_reg(Amd64Regs::Rdi, input_addr).unwrap();
|
emu::write_reg(Regs::Rdi, input_addr).unwrap();
|
||||||
emu::write_reg(Amd64Regs::Rsi, len).unwrap();
|
emu::write_reg(Regs::Rsi, len).unwrap();
|
||||||
emu::write_reg(Amd64Regs::Rip, test_one_input_ptr).unwrap();
|
emu::write_reg(Regs::Rip, test_one_input_ptr).unwrap();
|
||||||
emu::write_reg(Amd64Regs::Rsp, stack_ptr).unwrap();
|
emu::write_reg(Regs::Rsp, stack_ptr).unwrap();
|
||||||
|
|
||||||
emu::run();
|
emu::run();
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ fn main() {
|
|||||||
"cc".to_owned()
|
"cc".to_owned()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
println!("cargo:rustc-cfg=cpu_target=\"{}\"", cpu_target);
|
||||||
|
|
||||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
let out_dir = out_dir.to_string_lossy().to_string();
|
let out_dir = out_dir.to_string_lossy().to_string();
|
||||||
let out_dir_path = Path::new(&out_dir);
|
let out_dir_path = Path::new(&out_dir);
|
||||||
|
@ -6,7 +6,7 @@ use pyo3::prelude::*;
|
|||||||
|
|
||||||
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter)]
|
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum Aarch64Regs {
|
pub enum Regs {
|
||||||
X0 = 0,
|
X0 = 0,
|
||||||
X1 = 1,
|
X1 = 1,
|
||||||
X2 = 2,
|
X2 = 2,
|
||||||
@ -38,17 +38,20 @@ pub enum Aarch64Regs {
|
|||||||
X28 = 28,
|
X28 = 28,
|
||||||
X29 = 29,
|
X29 = 29,
|
||||||
X30 = 30,
|
X30 = 30,
|
||||||
|
Sp = 31,
|
||||||
|
Pc = 32,
|
||||||
|
Pstate = 33,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// alias registers
|
/// alias registers
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
impl Aarch64Regs {
|
impl Regs {
|
||||||
pub const Fp: Aarch64Regs = Aarch64Regs::X29;
|
pub const Fp: Regs = Regs::X29;
|
||||||
pub const Lr: Aarch64Regs = Aarch64Regs::X30;
|
pub const Lr: Regs = Regs::X30;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "python")]
|
#[cfg(feature = "python")]
|
||||||
impl IntoPy<PyObject> for Aarch64Regs {
|
impl IntoPy<PyObject> for Regs {
|
||||||
fn into_py(self, py: Python) -> PyObject {
|
fn into_py(self, py: Python) -> PyObject {
|
||||||
let n: i32 = self.into();
|
let n: i32 = self.into();
|
||||||
n.into_py(py)
|
n.into_py(py)
|
||||||
|
@ -7,7 +7,7 @@ use pyo3::prelude::*;
|
|||||||
/// Registers for the ARM instruction set.
|
/// Registers for the ARM instruction set.
|
||||||
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter)]
|
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum ArmRegs {
|
pub enum Regs {
|
||||||
R0 = 0,
|
R0 = 0,
|
||||||
R1 = 1,
|
R1 = 1,
|
||||||
R2 = 2,
|
R2 = 2,
|
||||||
@ -28,18 +28,18 @@ pub enum ArmRegs {
|
|||||||
|
|
||||||
/// alias registers
|
/// alias registers
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
impl ArmRegs {
|
impl Regs {
|
||||||
pub const Sp: ArmRegs = ArmRegs::R13;
|
pub const Sp: Regs = Regs::R13;
|
||||||
pub const Lr: ArmRegs = ArmRegs::R14;
|
pub const Lr: Regs = Regs::R14;
|
||||||
pub const Pc: ArmRegs = ArmRegs::R15;
|
pub const Pc: Regs = Regs::R15;
|
||||||
pub const Sb: ArmRegs = ArmRegs::R9;
|
pub const Sb: Regs = Regs::R9;
|
||||||
pub const Sl: ArmRegs = ArmRegs::R10;
|
pub const Sl: Regs = Regs::R10;
|
||||||
pub const Fp: ArmRegs = ArmRegs::R11;
|
pub const Fp: Regs = Regs::R11;
|
||||||
pub const Ip: ArmRegs = ArmRegs::R12;
|
pub const Ip: Regs = Regs::R12;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "python")]
|
#[cfg(feature = "python")]
|
||||||
impl IntoPy<PyObject> for ArmRegs {
|
impl IntoPy<PyObject> for Regs {
|
||||||
fn into_py(self, py: Python) -> PyObject {
|
fn into_py(self, py: Python) -> PyObject {
|
||||||
let n: i32 = self.into();
|
let n: i32 = self.into();
|
||||||
n.into_py(py)
|
n.into_py(py)
|
||||||
|
@ -1375,7 +1375,7 @@ int asan_giovese_report_and_crash(int access_type, target_ulong addr, size_t n,
|
|||||||
"==%d==ABORTING\n",
|
"==%d==ABORTING\n",
|
||||||
getpid());
|
getpid());
|
||||||
|
|
||||||
signal(SIGABRT, SIG_DFL);
|
// signal(SIGABRT, SIG_DFL);
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1491,7 +1491,7 @@ int asan_giovese_badfree(target_ulong addr, target_ulong pc) {
|
|||||||
": bad-free %s\n", printable_pc);
|
": bad-free %s\n", printable_pc);
|
||||||
|
|
||||||
fprintf(stderr, "==%d==ABORTING\n", getpid());
|
fprintf(stderr, "==%d==ABORTING\n", getpid());
|
||||||
signal(SIGABRT, SIG_DFL);
|
//signal(SIGABRT, SIG_DFL);
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
|
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
use std::{env, fs};
|
use std::{env, fs, ptr};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
emu,
|
emu,
|
||||||
emu::SyscallHookResult,
|
emu::SyscallHookResult,
|
||||||
executor::QemuExecutor,
|
executor::QemuExecutor,
|
||||||
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
|
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
|
||||||
|
Regs,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO at some point, merge parts with libafl_frida
|
// TODO at some point, merge parts with libafl_frida
|
||||||
@ -58,7 +59,7 @@ pub enum PoisonKind {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct CallContext {
|
struct CallContext {
|
||||||
pub addresses: *const u64,
|
pub addresses: *const u64,
|
||||||
pub tid: u32,
|
pub tid: i32,
|
||||||
pub size: u32,
|
pub size: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,20 +81,35 @@ extern "C" {
|
|||||||
fn asan_giovese_store2(ptr: *const u8) -> i32;
|
fn asan_giovese_store2(ptr: *const u8) -> i32;
|
||||||
fn asan_giovese_store4(ptr: *const u8) -> i32;
|
fn asan_giovese_store4(ptr: *const u8) -> i32;
|
||||||
fn asan_giovese_store8(ptr: *const u8) -> i32;
|
fn asan_giovese_store8(ptr: *const u8) -> i32;
|
||||||
// int asan_giovese_loadN(void* ptr, size_t n);
|
|
||||||
fn asan_giovese_loadN(ptr: *const u8, n: usize) -> i32;
|
fn asan_giovese_loadN(ptr: *const u8, n: usize) -> i32;
|
||||||
// int asan_giovese_storeN(void* ptr, size_t n);
|
|
||||||
fn asan_giovese_storeN(ptr: *const u8, n: usize) -> i32;
|
fn asan_giovese_storeN(ptr: *const u8, n: usize) -> i32;
|
||||||
// int asan_giovese_poison_region(void* ptr, size_t n, uint8_t poison_byte);
|
|
||||||
fn asan_giovese_poison_region(ptr: *const u8, n: usize, poison: u8) -> i32;
|
fn asan_giovese_poison_region(ptr: *const u8, n: usize, poison: u8) -> i32;
|
||||||
// int asan_giovese_unpoison_region(void* ptr, size_t n);
|
|
||||||
fn asan_giovese_unpoison_region(ptr: *const u8, n: usize) -> i32;
|
fn asan_giovese_unpoison_region(ptr: *const u8, n: usize) -> i32;
|
||||||
// struct chunk_info* asan_giovese_alloc_search(target_ulong query);
|
|
||||||
fn asan_giovese_alloc_search(query: u64) -> *mut ChunkInfo;
|
fn asan_giovese_alloc_search(query: u64) -> *mut ChunkInfo;
|
||||||
// void asan_giovese_alloc_remove(target_ulong start, target_ulong end);
|
|
||||||
fn asan_giovese_alloc_remove(start: u64, end: u64);
|
fn asan_giovese_alloc_remove(start: u64, end: u64);
|
||||||
// void asan_giovese_alloc_insert(target_ulong start, target_ulong end, struct call_context* alloc_ctx);
|
|
||||||
fn asan_giovese_alloc_insert(start: u64, end: u64, alloc_ctx: *const CallContext);
|
fn asan_giovese_alloc_insert(start: u64, end: u64, alloc_ctx: *const CallContext);
|
||||||
|
fn asan_giovese_report_and_crash(
|
||||||
|
access_type: i32,
|
||||||
|
addr: u64,
|
||||||
|
n: usize,
|
||||||
|
pc: u64,
|
||||||
|
bp: u64,
|
||||||
|
sp: u64,
|
||||||
|
);
|
||||||
|
fn asan_giovese_badfree(addr: u64, pc: u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn asan_giovese_printaddr(_addr: u64) -> *const u8 {
|
||||||
|
// Just addresses ATM
|
||||||
|
ptr::null()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn asan_giovese_populate_context(ctx: *mut CallContext, _pc: u64) {
|
||||||
|
let ctx = ctx.as_mut().unwrap();
|
||||||
|
ctx.tid = libc::gettid() as i32;
|
||||||
|
ctx.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut ASAN_INITED: bool = false;
|
static mut ASAN_INITED: bool = false;
|
||||||
@ -201,14 +217,14 @@ impl QemuAsanHelper {
|
|||||||
if let Some(ck) = ckinfo.as_mut() {
|
if let Some(ck) = ckinfo.as_mut() {
|
||||||
if ck.start != addr {
|
if ck.start != addr {
|
||||||
// Free not the start of the chunk
|
// Free not the start of the chunk
|
||||||
std::process::abort();
|
asan_giovese_badfree(addr, emu::read_reg(Regs::Pc).unwrap_or(u64::MAX));
|
||||||
}
|
}
|
||||||
let ctx: *const CallContext =
|
let ctx: *const CallContext =
|
||||||
libc::calloc(core::mem::size_of::<CallContext>(), 1) as *const _;
|
libc::calloc(core::mem::size_of::<CallContext>(), 1) as *const _;
|
||||||
ck.free_ctx = ctx;
|
ck.free_ctx = ctx;
|
||||||
} else {
|
} else {
|
||||||
// Free of wild ptr
|
// Free of wild ptr
|
||||||
std::process::abort();
|
asan_giovese_badfree(addr, emu::read_reg(Regs::Pc).unwrap_or(u64::MAX));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,62 +236,152 @@ impl QemuAsanHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_1(&mut self, addr: u64) {
|
pub fn read_1(&mut self, addr: u64) {
|
||||||
if self.enabled() && unsafe { asan_giovese_load1(emu::g2h(addr)) != 0 } {
|
unsafe {
|
||||||
std::process::abort();
|
if self.enabled() && asan_giovese_load1(emu::g2h(addr)) != 0 {
|
||||||
|
asan_giovese_report_and_crash(
|
||||||
|
0,
|
||||||
|
addr,
|
||||||
|
1,
|
||||||
|
emu::read_reg(Regs::Pc).unwrap_or(u64::MAX),
|
||||||
|
0,
|
||||||
|
emu::read_reg(Regs::Sp).unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_2(&mut self, addr: u64) {
|
pub fn read_2(&mut self, addr: u64) {
|
||||||
if self.enabled() && unsafe { asan_giovese_load2(emu::g2h(addr)) != 0 } {
|
unsafe {
|
||||||
std::process::abort();
|
if self.enabled() && asan_giovese_load2(emu::g2h(addr)) != 0 {
|
||||||
|
asan_giovese_report_and_crash(
|
||||||
|
0,
|
||||||
|
addr,
|
||||||
|
2,
|
||||||
|
emu::read_reg(Regs::Pc).unwrap_or(u64::MAX),
|
||||||
|
0,
|
||||||
|
emu::read_reg(Regs::Sp).unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_4(&mut self, addr: u64) {
|
pub fn read_4(&mut self, addr: u64) {
|
||||||
if self.enabled() && unsafe { asan_giovese_load4(emu::g2h(addr)) != 0 } {
|
unsafe {
|
||||||
std::process::abort();
|
if self.enabled() && asan_giovese_load4(emu::g2h(addr)) != 0 {
|
||||||
|
asan_giovese_report_and_crash(
|
||||||
|
0,
|
||||||
|
addr,
|
||||||
|
4,
|
||||||
|
emu::read_reg(Regs::Pc).unwrap_or(u64::MAX),
|
||||||
|
0,
|
||||||
|
emu::read_reg(Regs::Sp).unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_8(&mut self, addr: u64) {
|
pub fn read_8(&mut self, addr: u64) {
|
||||||
if self.enabled() && unsafe { asan_giovese_load8(emu::g2h(addr)) != 0 } {
|
unsafe {
|
||||||
std::process::abort();
|
if self.enabled() && asan_giovese_load8(emu::g2h(addr)) != 0 {
|
||||||
|
asan_giovese_report_and_crash(
|
||||||
|
0,
|
||||||
|
addr,
|
||||||
|
8,
|
||||||
|
emu::read_reg(Regs::Pc).unwrap_or(u64::MAX),
|
||||||
|
0,
|
||||||
|
emu::read_reg(Regs::Sp).unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_n(&mut self, addr: u64, size: usize) {
|
pub fn read_n(&mut self, addr: u64, size: usize) {
|
||||||
if self.enabled() && unsafe { asan_giovese_loadN(emu::g2h(addr), size) != 0 } {
|
unsafe {
|
||||||
std::process::abort();
|
if self.enabled() && asan_giovese_loadN(emu::g2h(addr), size) != 0 {
|
||||||
|
asan_giovese_report_and_crash(
|
||||||
|
0,
|
||||||
|
addr,
|
||||||
|
size,
|
||||||
|
emu::read_reg(Regs::Pc).unwrap_or(u64::MAX),
|
||||||
|
0,
|
||||||
|
emu::read_reg(Regs::Sp).unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_1(&mut self, addr: u64) {
|
pub fn write_1(&mut self, addr: u64) {
|
||||||
if self.enabled() && unsafe { asan_giovese_store1(emu::g2h(addr)) != 0 } {
|
unsafe {
|
||||||
std::process::abort();
|
if self.enabled() && asan_giovese_store1(emu::g2h(addr)) != 0 {
|
||||||
|
asan_giovese_report_and_crash(
|
||||||
|
1,
|
||||||
|
addr,
|
||||||
|
1,
|
||||||
|
emu::read_reg(Regs::Pc).unwrap_or(u64::MAX),
|
||||||
|
0,
|
||||||
|
emu::read_reg(Regs::Sp).unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_2(&mut self, addr: u64) {
|
pub fn write_2(&mut self, addr: u64) {
|
||||||
if self.enabled() && unsafe { asan_giovese_store2(emu::g2h(addr)) != 0 } {
|
unsafe {
|
||||||
std::process::abort();
|
if self.enabled() && asan_giovese_store2(emu::g2h(addr)) != 0 {
|
||||||
|
asan_giovese_report_and_crash(
|
||||||
|
1,
|
||||||
|
addr,
|
||||||
|
2,
|
||||||
|
emu::read_reg(Regs::Pc).unwrap_or(u64::MAX),
|
||||||
|
0,
|
||||||
|
emu::read_reg(Regs::Sp).unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_4(&mut self, addr: u64) {
|
pub fn write_4(&mut self, addr: u64) {
|
||||||
if self.enabled() && unsafe { asan_giovese_store4(emu::g2h(addr)) != 0 } {
|
unsafe {
|
||||||
std::process::abort();
|
if self.enabled() && asan_giovese_store4(emu::g2h(addr)) != 0 {
|
||||||
|
asan_giovese_report_and_crash(
|
||||||
|
1,
|
||||||
|
addr,
|
||||||
|
4,
|
||||||
|
emu::read_reg(Regs::Pc).unwrap_or(u64::MAX),
|
||||||
|
0,
|
||||||
|
emu::read_reg(Regs::Sp).unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_8(&mut self, addr: u64) {
|
pub fn write_8(&mut self, addr: u64) {
|
||||||
if self.enabled() && unsafe { asan_giovese_store8(emu::g2h(addr)) != 0 } {
|
unsafe {
|
||||||
std::process::abort();
|
if self.enabled() && asan_giovese_store8(emu::g2h(addr)) != 0 {
|
||||||
|
asan_giovese_report_and_crash(
|
||||||
|
1,
|
||||||
|
addr,
|
||||||
|
8,
|
||||||
|
emu::read_reg(Regs::Pc).unwrap_or(u64::MAX),
|
||||||
|
0,
|
||||||
|
emu::read_reg(Regs::Sp).unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_n(&mut self, addr: u64, size: usize) {
|
pub fn write_n(&mut self, addr: u64, size: usize) {
|
||||||
if self.enabled() && unsafe { asan_giovese_storeN(emu::g2h(addr), size) != 0 } {
|
unsafe {
|
||||||
std::process::abort();
|
if self.enabled() && asan_giovese_storeN(emu::g2h(addr), size) != 0 {
|
||||||
|
asan_giovese_report_and_crash(
|
||||||
|
1,
|
||||||
|
addr,
|
||||||
|
size,
|
||||||
|
emu::read_reg(Regs::Pc).unwrap_or(u64::MAX),
|
||||||
|
0,
|
||||||
|
emu::read_reg(Regs::Sp).unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use pyo3::prelude::*;
|
|||||||
|
|
||||||
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter)]
|
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum X86Regs {
|
pub enum Regs {
|
||||||
Eax = 0,
|
Eax = 0,
|
||||||
Ebx = 1,
|
Ebx = 1,
|
||||||
Ecx = 2,
|
Ecx = 2,
|
||||||
@ -21,13 +21,13 @@ pub enum X86Regs {
|
|||||||
|
|
||||||
/// alias registers
|
/// alias registers
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
impl X86Regs {
|
impl Regs {
|
||||||
pub const Sp: X86Regs = X86Regs::Esp;
|
pub const Sp: Regs = Regs::Esp;
|
||||||
pub const Pc: X86Regs = X86Regs::Eip;
|
pub const Pc: Regs = Regs::Eip;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "python")]
|
#[cfg(feature = "python")]
|
||||||
impl IntoPy<PyObject> for X86Regs {
|
impl IntoPy<PyObject> for Regs {
|
||||||
fn into_py(self, py: Python) -> PyObject {
|
fn into_py(self, py: Python) -> PyObject {
|
||||||
let n: i32 = self.into();
|
let n: i32 = self.into();
|
||||||
n.into_py(py)
|
n.into_py(py)
|
@ -1,9 +1,18 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
pub mod aarch64;
|
pub mod aarch64;
|
||||||
pub mod amd64;
|
|
||||||
pub mod arm;
|
pub mod arm;
|
||||||
pub mod x86;
|
pub mod i386;
|
||||||
|
pub mod x86_64;
|
||||||
|
|
||||||
|
#[cfg(cpu_target = "aarch64")]
|
||||||
|
pub use aarch64::*;
|
||||||
|
#[cfg(cpu_target = "arm")]
|
||||||
|
pub use arm::*;
|
||||||
|
#[cfg(cpu_target = "i386")]
|
||||||
|
pub use i386::*;
|
||||||
|
#[cfg(cpu_target = "x86_64")]
|
||||||
|
pub use x86_64::*;
|
||||||
|
|
||||||
pub mod elf;
|
pub mod elf;
|
||||||
|
|
||||||
@ -210,19 +219,12 @@ pub fn python_module(py: Python, m: &PyModule) -> PyResult<()> {
|
|||||||
emu::remove_hook(addr);
|
emu::remove_hook(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
let x86m = PyModule::new(py, "x86")?;
|
let regsm = PyModule::new(py, "regs")?;
|
||||||
for r in x86::X86Regs::iter() {
|
for r in Regs::iter() {
|
||||||
let v: i32 = r.into();
|
let v: i32 = r.into();
|
||||||
x86m.add(&format!("{:?}", r), v)?;
|
regsm.add(&format!("{:?}", r), v)?;
|
||||||
}
|
}
|
||||||
m.add_submodule(x86m)?;
|
m.add_submodule(regsm)?;
|
||||||
|
|
||||||
let amd64m = PyModule::new(py, "amd64")?;
|
|
||||||
for r in amd64::Amd64Regs::iter() {
|
|
||||||
let v: i32 = r.into();
|
|
||||||
amd64m.add(&format!("{:?}", r), v)?;
|
|
||||||
}
|
|
||||||
m.add_submodule(amd64m)?;
|
|
||||||
|
|
||||||
let mmapm = PyModule::new(py, "mmap")?;
|
let mmapm = PyModule::new(py, "mmap")?;
|
||||||
for r in emu::MmapPerms::iter() {
|
for r in emu::MmapPerms::iter() {
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
|
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[cfg(cpu_target = "x86_64")]
|
||||||
|
use crate::TARGET_NR_mmap;
|
||||||
use crate::{
|
use crate::{
|
||||||
emu,
|
emu,
|
||||||
emu::GuestMaps,
|
emu::{GuestMaps, SyscallHookResult},
|
||||||
executor::QemuExecutor,
|
executor::QemuExecutor,
|
||||||
helper::{QemuHelper, QemuHelperTuple},
|
helper::{QemuHelper, QemuHelperTuple},
|
||||||
};
|
};
|
||||||
@ -23,6 +25,7 @@ pub struct QemuSnapshotHelper {
|
|||||||
pub pages: HashMap<u64, SnapshotPageInfo>,
|
pub pages: HashMap<u64, SnapshotPageInfo>,
|
||||||
pub dirty: Vec<u64>,
|
pub dirty: Vec<u64>,
|
||||||
pub brk: u64,
|
pub brk: u64,
|
||||||
|
pub new_maps: Vec<(u64, usize)>,
|
||||||
pub empty: bool,
|
pub empty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,6 +38,7 @@ impl QemuSnapshotHelper {
|
|||||||
pages: HashMap::default(),
|
pages: HashMap::default(),
|
||||||
dirty: vec![],
|
dirty: vec![],
|
||||||
brk: 0,
|
brk: 0,
|
||||||
|
new_maps: vec![],
|
||||||
empty: true,
|
empty: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,6 +105,18 @@ impl QemuSnapshotHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
emu::set_brk(self.brk);
|
emu::set_brk(self.brk);
|
||||||
|
self.reset_maps();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_mapped(&mut self, start: u64, size: usize) {
|
||||||
|
self.new_maps.push((start, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_maps(&mut self) {
|
||||||
|
for (addr, size) in &self.new_maps {
|
||||||
|
drop(emu::unmap(*addr, *size));
|
||||||
|
}
|
||||||
|
self.new_maps.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +142,11 @@ where
|
|||||||
executor.hook_write2_execution(trace_write2_snapshot::<I, QT, S>);
|
executor.hook_write2_execution(trace_write2_snapshot::<I, QT, S>);
|
||||||
executor.hook_write1_execution(trace_write1_snapshot::<I, QT, S>);
|
executor.hook_write1_execution(trace_write1_snapshot::<I, QT, S>);
|
||||||
executor.hook_write_n_execution(trace_write_n_snapshot::<I, QT, S>);
|
executor.hook_write_n_execution(trace_write_n_snapshot::<I, QT, S>);
|
||||||
|
|
||||||
|
#[cfg(cpu_target = "x86_64")]
|
||||||
|
{
|
||||||
|
executor.hook_syscalls(trace_mmap_snapshot::<I, QT, S>);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pre_exec(&mut self, _input: &I) {
|
fn pre_exec(&mut self, _input: &I) {
|
||||||
@ -196,3 +217,30 @@ pub fn trace_write_n_snapshot<I, QT, S>(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
h.access(addr, size);
|
h.access(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(cpu_target = "x86_64")]
|
||||||
|
pub fn trace_mmap_snapshot<I, QT, S>(
|
||||||
|
helpers: &mut QT,
|
||||||
|
_state: &mut S,
|
||||||
|
sys_num: i32,
|
||||||
|
a0: u64,
|
||||||
|
a1: u64,
|
||||||
|
_a2: u64,
|
||||||
|
_a3: u64,
|
||||||
|
_a4: u64,
|
||||||
|
_a5: u64,
|
||||||
|
_a6: u64,
|
||||||
|
_a7: u64,
|
||||||
|
) -> SyscallHookResult
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
QT: QemuHelperTuple<I, S>,
|
||||||
|
{
|
||||||
|
if sys_num == TARGET_NR_mmap {
|
||||||
|
let h = helpers
|
||||||
|
.match_first_type_mut::<QemuSnapshotHelper>()
|
||||||
|
.unwrap();
|
||||||
|
h.add_mapped(a0, a1 as usize);
|
||||||
|
}
|
||||||
|
SyscallHookResult::new(None)
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@ use pyo3::prelude::*;
|
|||||||
|
|
||||||
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter)]
|
#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum Amd64Regs {
|
pub enum Regs {
|
||||||
Rax = 0,
|
Rax = 0,
|
||||||
Rbx = 1,
|
Rbx = 1,
|
||||||
Rcx = 2,
|
Rcx = 2,
|
||||||
@ -29,13 +29,13 @@ pub enum Amd64Regs {
|
|||||||
|
|
||||||
/// alias registers
|
/// alias registers
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
impl Amd64Regs {
|
impl Regs {
|
||||||
pub const Sp: Amd64Regs = Amd64Regs::Rsp;
|
pub const Sp: Regs = Regs::Rsp;
|
||||||
pub const Pc: Amd64Regs = Amd64Regs::Rip;
|
pub const Pc: Regs = Regs::Rip;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "python")]
|
#[cfg(feature = "python")]
|
||||||
impl IntoPy<PyObject> for Amd64Regs {
|
impl IntoPy<PyObject> for Regs {
|
||||||
fn into_py(self, py: Python) -> PyObject {
|
fn into_py(self, py: Python) -> PyObject {
|
||||||
let n: i32 = self.into();
|
let n: i32 = self.into();
|
||||||
n.into_py(py)
|
n.into_py(py)
|
Loading…
x
Reference in New Issue
Block a user