1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use core::{convert::Into, mem::transmute, ptr::copy_nonoverlapping};
use num::Num;
use std::{slice::from_raw_parts, str::from_utf8_unchecked};
pub mod amd64;
pub mod x86;
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;
fn strlen(s: *const u8) -> usize;
static exec_path: *const u8;
static guest_base: isize;
}
pub struct QemuEmulator {}
impl QemuEmulator {
pub fn write_mem<T>(&mut self, addr: isize, buf: &[T]) {
let host_addr = self.g2h(addr);
unsafe { copy_nonoverlapping(buf.as_ptr() as *const _ as *const u8, host_addr, buf.len()) }
}
pub fn read_mem<T>(&mut self, addr: isize, buf: &mut [T]) {
let host_addr = self.g2h(addr);
unsafe {
copy_nonoverlapping(
host_addr as *const u8,
buf.as_mut_ptr() as *mut _ as *mut u8,
buf.len(),
)
}
}
pub fn num_regs(&self) -> i32 {
unsafe { libafl_qemu_num_regs() }
}
pub fn write_reg<R, T>(&mut self, reg: R, val: T) -> Result<(), String>
where
T: Num + PartialOrd + Copy,
R: Into<i32>,
{
let reg = reg.into();
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<R, T>(&mut self, reg: R) -> Result<T, String>
where
T: Num + PartialOrd + Copy,
R: Into<i32>,
{
let reg = reg.into();
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) }
}
pub fn exec_path(&self) -> &str {
unsafe { from_utf8_unchecked(from_raw_parts(exec_path, strlen(exec_path))) }
}
pub fn new() -> Self {
Self {}
}
}