I want something like where i have an executable and I can read that executable and I am able to read and store it into some variable and than with some interaction with that variable I can run the executable.
fn main() -> io::Result<()> {
const BUFFER_SIZE: usize = 4096;
let input_path = "/home/ubuntu/Desktop/exp/target/debug/exp";
let mut file = File::open(input_path)?;
let mut contents = Vec::new();
file.read_to_end(&mut contents)?;
let bytes_to_copy = contents.len().min(BUFFER_SIZE);
unsafe {
let mem_address = libc::mmap(
ptr::null_mut(),
bytes_to_copy,
libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
);
if mem_address == libc::MAP_FAILED {
panic!("mmap failed: {}", io::Error::last_os_error());
}
ptr::copy_nonoverlapping(contents.as_ptr(), mem_address as *mut u8, bytes_to_copy);
// Ensure memory is executable
let result = libc::mprotect(
mem_address,
bytes_to_copy,
libc::PROT_READ | libc::PROT_EXEC,
);
if result != 0 {
panic!("mprotect failed: {}", io::Error::last_os_error());
}
// Cast the memory address to a function pointer and call it
let code: extern "C" fn() = std::mem::transmute(mem_address as *const ());
code();
}
Ok(())
}
So I tried this but it gives me seg fault. What am I doing wrong?
The memfd_create
+ fexecve
combo might just work for you (assuming a unix-like system): using memfd_create and fexecve to run ELF from memory