Add redirect stdin module (#3077)
* forkserver api * poc * i'm dumb * add things * use snapshot * delete println debug * anglais * d * fixer * take care of further read * take care about u32 * aa * fix cursor * mm * pushing things temporary so i can try this path later * delete useless setter * rme * BytesConverter * now revert * clp * typo * change how input passing works * fuck * fmt * fixer * fix * lol * lol * lol * disable CI * delete assert * clp * a
This commit is contained in:
parent
30946641cd
commit
4130e3860f
@ -17,3 +17,5 @@ pub use asan::AsanModule;
|
||||
pub mod asan_guest;
|
||||
#[cfg(not(cpu_target = "hexagon"))]
|
||||
pub use asan_guest::AsanGuestModule;
|
||||
pub mod redirect_stdin;
|
||||
pub use redirect_stdin::*;
|
||||
|
149
libafl_qemu/src/modules/usermode/redirect_stdin.rs
Normal file
149
libafl_qemu/src/modules/usermode/redirect_stdin.rs
Normal file
@ -0,0 +1,149 @@
|
||||
use core::fmt::Debug;
|
||||
|
||||
use libafl_bolts::HasLen;
|
||||
use libafl_qemu_sys::GuestAddr;
|
||||
|
||||
#[cfg(not(cpu_target = "hexagon"))]
|
||||
use crate::SYS_read;
|
||||
use crate::{
|
||||
Qemu,
|
||||
emu::EmulatorModules,
|
||||
modules::{EmulatorModule, EmulatorModuleTuple},
|
||||
qemu::{Hook, SyscallHookResult},
|
||||
};
|
||||
|
||||
#[cfg(cpu_target = "hexagon")]
|
||||
/// Hexagon syscalls are not currently supported by the `syscalls` crate, so we just paste this here for now.
|
||||
/// <https://github.com/qemu/qemu/blob/11be70677c70fdccd452a3233653949b79e97908/linux-user/hexagon/syscall_nr.h#L230>
|
||||
#[expect(non_upper_case_globals)]
|
||||
const SYS_read: u8 = 63;
|
||||
|
||||
/// This module hijacks any read to buffer from stdin, and instead fill the buffer from the specified input address
|
||||
/// This is useful when your binary target reads the input from the stdin.
|
||||
/// With this you can just fuzz more like afl++
|
||||
/// You need to use this with snapshot module!
|
||||
#[derive(Debug)]
|
||||
pub struct RedirectStdinModule {
|
||||
input_addr: *const u8,
|
||||
read: usize,
|
||||
total: usize,
|
||||
}
|
||||
|
||||
impl Default for RedirectStdinModule {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl RedirectStdinModule {
|
||||
#[must_use]
|
||||
/// constuctor
|
||||
pub fn new() -> Self {
|
||||
Self::with_input_addr(core::ptr::null())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
/// Create with specified input address
|
||||
pub fn with_input_addr(addr: *const u8) -> Self {
|
||||
Self {
|
||||
input_addr: addr,
|
||||
read: 0,
|
||||
total: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tell this module where to look for the input addr
|
||||
pub fn set_input_addr(&mut self, addr: *const u8) {
|
||||
self.input_addr = addr;
|
||||
}
|
||||
|
||||
pub fn reset_input_addr(&mut self) {
|
||||
self.input_addr = core::ptr::null();
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, S> EmulatorModule<I, S> for RedirectStdinModule
|
||||
where
|
||||
I: Unpin + HasLen + Debug,
|
||||
S: Unpin,
|
||||
{
|
||||
fn first_exec<ET>(
|
||||
&mut self,
|
||||
_qemu: Qemu,
|
||||
emulator_modules: &mut EmulatorModules<ET, I, S>,
|
||||
_state: &mut S,
|
||||
) where
|
||||
ET: EmulatorModuleTuple<I, S>,
|
||||
{
|
||||
emulator_modules.pre_syscalls(Hook::Function(syscall_read_hook::<ET, I, S>));
|
||||
}
|
||||
|
||||
fn pre_exec<ET>(
|
||||
&mut self,
|
||||
_qemu: Qemu,
|
||||
_emulator_modules: &mut EmulatorModules<ET, I, S>,
|
||||
_state: &mut S,
|
||||
input: &I,
|
||||
) where
|
||||
ET: EmulatorModuleTuple<I, S>,
|
||||
{
|
||||
self.total = input.len();
|
||||
self.read = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
fn syscall_read_hook<ET, I, S>(
|
||||
_qemu: Qemu,
|
||||
emulator_modules: &mut EmulatorModules<ET, I, S>,
|
||||
_state: Option<&mut S>,
|
||||
syscall: i32,
|
||||
x0: GuestAddr,
|
||||
x1: GuestAddr,
|
||||
x2: GuestAddr,
|
||||
_x3: GuestAddr,
|
||||
_x4: GuestAddr,
|
||||
_x5: GuestAddr,
|
||||
_x6: GuestAddr,
|
||||
_x7: GuestAddr,
|
||||
) -> SyscallHookResult
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S>,
|
||||
I: Unpin + HasLen + Debug,
|
||||
S: Unpin,
|
||||
{
|
||||
let h = emulator_modules.get_mut::<RedirectStdinModule>().unwrap();
|
||||
if h.input_addr.is_null() {
|
||||
return SyscallHookResult::new(None);
|
||||
}
|
||||
if syscall == SYS_read as i32 && x0 == 0 {
|
||||
/*
|
||||
println!(
|
||||
"Is sys read {:x} {} {:x} {:x} {} {} {} {} {}",
|
||||
rip, x0, x1, x2, x3, x4, x5, x6, x7
|
||||
);
|
||||
*/
|
||||
let size = unsafe {
|
||||
let mut src = h.input_addr;
|
||||
src = src.wrapping_add(h.read);
|
||||
let dst = x1 as *mut u8;
|
||||
if h.total >= h.read {
|
||||
let size = std::cmp::min(x2, (h.total - h.read).try_into().unwrap());
|
||||
/*
|
||||
println!(
|
||||
"trying to read {} bytes copying src: {:p} {:p} size: {} h.total: {} h.read {} ",
|
||||
x2, src, dst, size, h.total, h.read
|
||||
);
|
||||
*/
|
||||
dst.copy_from(src, size as usize);
|
||||
size
|
||||
} else {
|
||||
0
|
||||
}
|
||||
};
|
||||
// println!("copied {}", size);
|
||||
h.read += size as usize;
|
||||
return SyscallHookResult::new(Some(size));
|
||||
}
|
||||
SyscallHookResult::new(None)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user