pub struct Executor<L: Loader, LD, GD> {Show 16 fields
pub vcpu: Vcpu,
pub pma: Option<PhysMemAllocator>,
pub vma: VirtMem,
pub loader: L,
pub loader_copy: Option<L>,
pub hooks: Hooks<LD, GD>,
pub ldata: LD,
pub gdata: Arc<RwLock<GD>>,
pub cdata: Coverage,
pub bdata: Backtrace,
pub global_coverage: GlobalCoverage,
pub config: Config<LD, GD>,
pub symbols: Symbols,
pub registers_snapshot: Vec<u64>,
pub sys_registers_snapshot: Vec<u64>,
pub fp_registers_snapshot: Vec<i8x16>,
}
Expand description
Component handling everything related to executing code by the hypervisor.
Role of the Executor in the Fuzzer
The Executor
is the component that interacts directly with the hypervisor to make it
execute our code. It can allocate memory, place hooks, gather coverage or backtrace
information, etc.
While this component is used primarily by the fuzzer, it can be instanciated independently. This is especially useful when harnessing or tracing the target, because it gives us complete control over the program during its lifetime.
Different types of hooks can be placed by the executor using the following methods:
Executor::add_function_hook
Executor::add_instruction_hook
Executor::add_custom_hook
Executor::add_exit_hook
Note: for more information about hooking mechanisms in general, you can refer to
crate::hooks::Hooks
.
Warning: when using an executor you must first instanciate one (and only one per process)
VirtualMachine
object, otherwise it will
return an error.
Example
use hyperpom::applevisor as av;
use hyperpom::config::Config;
use hyperpom::core::HyperPom;
use hyperpom::loader::Loader;
#[derive(Clone)]
pub struct GlobalData(u32);
#[derive(Clone)]
pub struct LocalData(u32);
#[derive(Clone)]
pub struct DummyLoader;
impl Loader for DummyLoader {
// [...]
}
// The first step is to instanciate the virtual machine object.
let _vm = av::VirtualMachine::new();
// We instanciate a global data object.
let gdata = GlobalData(0);
// We instanciate a local data object.
let ldata = LocalData(0);
// `loader` contains the methods that will load and map the program from the file `binary`.
let loader = DummyLoader::new("./binary");
// We create a configuration for the fuzzer.
let config = Config::builder(0x10000000, "/tmp/hyperpom/", "/tmp/corpus/")
.seed(0xdeadbeef)
.timeout(std::time::Duration::new(60, 0))
.iterations(Some(1))
.build();
// Creates an instance of the fuzzer.
let mut executor =
hp::core::Executor::<DummyLoader, LocalData, GlobalData>::new(config, loader, ldata, gdata)
.expect("could not create the executor");
// Initializes the executor.
executor.init()?;
// Runs the target without a testcase.
executor.run(None).expect("execution failed");
// Prints the number of paths covered
println!("{} paths covered", executor.cdata.set.len());
Fields
vcpu: Vcpu
The underlying applevisor::Vcpu
instance.
pma: Option<PhysMemAllocator>
A shared reference to the global physical memory allocator.
vma: VirtMem
The virtual address spaces and their snapshots.
loader: L
The loader instance passed by the user.
loader_copy: Option<L>
HACK: a copy of the loader to call trait methods while passing the Executor object’s to them without triggering any borrowing error.
hooks: Hooks<LD, GD>
The hooks applied to the target.
ldata: LD
Data local to the fuzzer.
gdata: Arc<RwLock<GD>>
A shared reference to the global data.
cdata: Coverage
Coverage data for the current iteration.
bdata: Backtrace
Backtrace data for the current iteration.
global_coverage: GlobalCoverage
A shared reference to the global coverage data.
config: Config<LD, GD>
A copy of the configuration passed by the user.
symbols: Symbols
The list of symbols for the target.
registers_snapshot: Vec<u64>
General purpose registers snapshot.
sys_registers_snapshot: Vec<u64>
System registers snapshot.
fp_registers_snapshot: Vec<i8x16>
Floating point registers snapshot.
Implementations
sourceimpl<L: Loader + Loader<LD = LD> + Loader<GD = GD>, LD: Clone, GD: Clone> Executor<L, LD, GD>
impl<L: Loader + Loader<LD = LD> + Loader<GD = GD>, LD: Clone, GD: Clone> Executor<L, LD, GD>
sourcepub fn new(
config: ConfigData<LD, GD>,
loader: L,
ldata: LD,
gdata: GD
) -> Result<Self>
pub fn new(
config: ConfigData<LD, GD>,
loader: L,
ldata: LD,
gdata: GD
) -> Result<Self>
Creates a new executor instance that can be run outside of Hyperpom.
sourcepub fn init(&mut self) -> Result<()>
pub fn init(&mut self) -> Result<()>
The executor initialization function. This function must be called before running the executor since it is responsible for:
- calling
Loader::map
; - applying hooks;
- initializing the cache maintenance handlers;
- taking snapshots.
sourcepub fn add_custom_hook(&mut self, addr: u64, hook: HookFn<LD, GD>)
pub fn add_custom_hook(&mut self, addr: u64, hook: HookFn<LD, GD>)
Adds a user-defined hook at addr
.
See Hooks
for more information about hooking in general.
sourcepub fn add_function_hook(
&mut self,
name: &str,
hook: HookFn<LD, GD>
) -> Result<()>
pub fn add_function_hook(
&mut self,
name: &str,
hook: HookFn<LD, GD>
) -> Result<()>
Adds a user-defined hook on the function named name
.
See Hooks
for more information about hooking in general.
sourcepub fn add_instruction_hook(
&mut self,
pattern: &str,
hook: HookFn<LD, GD>
) -> Result<()>
pub fn add_instruction_hook(
&mut self,
pattern: &str,
hook: HookFn<LD, GD>
) -> Result<()>
Adds a user-defined hook on all the instructions that match pattern
.
See Hooks
for more information about hooking in general.
sourcepub fn remove_custom_hook(&mut self, addr: u64)
pub fn remove_custom_hook(&mut self, addr: u64)
Removes a user-defined hook at addr
.
See Hooks
for more information about hooking in general.
sourcepub fn add_exit_hook(&mut self, addr: u64)
pub fn add_exit_hook(&mut self, addr: u64)
Adds an exit hook at addr
.
See Hooks
for more information about hooking in general.
sourcepub fn remove_exit_hook(&mut self, addr: u64)
pub fn remove_exit_hook(&mut self, addr: u64)
Removes an exit hook at addr
.
See Hooks
for more information about hooking in general.
sourcepub fn vcpu_run(&mut self) -> Result<ExitKind>
pub fn vcpu_run(&mut self) -> Result<ExitKind>
Function that starts the Vcpu and handles any exception that occurs.
sourcepub fn run(&mut self, testcase: Option<&Testcase>) -> Result<ExitKind>
pub fn run(&mut self, testcase: Option<&Testcase>) -> Result<ExitKind>
Loads a testcase in memory before running it.
sourcepub fn restore_snapshot(&mut self, snapshot_action: SnapshotAction) -> Result<()>
pub fn restore_snapshot(&mut self, snapshot_action: SnapshotAction) -> Result<()>
Restores the current address space from a snapshot or switch to another address space
depending on the action specified by snapshot_action
. Also restores the registers and
flush the TLB as well as the instruction caches.
sourcepub fn save_registers(&mut self) -> Result<()>
pub fn save_registers(&mut self) -> Result<()>
Takes a snapshot of the general purpose registers.
sourcepub fn restore_registers(&self) -> Result<()>
pub fn restore_registers(&self) -> Result<()>
Restores the Vcpu general purpose registers from a snapshot.
sourcepub fn save_sys_registers(&mut self) -> Result<()>
pub fn save_sys_registers(&mut self) -> Result<()>
Takes a snapshot of the system registers.
sourcepub fn restore_sys_registers(&self) -> Result<()>
pub fn restore_sys_registers(&self) -> Result<()>
Restores the Vcpu system registers from a snapshot.
sourcepub fn save_fp_registers(&mut self) -> Result<()>
pub fn save_fp_registers(&mut self) -> Result<()>
Takes a snapshot of the floating point registers.
sourcepub fn restore_fp_registers(&self) -> Result<()>
pub fn restore_fp_registers(&self) -> Result<()>
Restores the Vcpu floating point registers from a snapshot.