Skip to content

Instantly share code, notes, and snippets.

@roktas
Forked from iximeow/stub.rs
Created January 30, 2022 17:44

Revisions

  1. @iximeow iximeow created this gist Jan 30, 2022.
    47 changes: 47 additions & 0 deletions stub.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    use std::io::Write;
    use std::process::Command;

    extern "C" {
    fn mprotect(addr: *const u8, len: usize, prot: u32) -> u32;
    }

    fn main() {
    let mut args = std::env::args();
    let _ = args.next();
    let fname = if let Some(n) = args.next() {
    n
    } else {
    return;
    };
    let res = Command::new("/usr/bin/nasm")
    .args(["-o", "/dev/stdout", "-f", "bin", &fname])
    .output()
    .expect("process runs");

    if res.status.success() {
    unsafe {
    let code = res.stdout.as_ptr();
    let len = res.stdout.len();
    // round down because we might be offset in the first page
    let prefix = (code as isize) & 0x0fff;

    let pages_start = code.offset(-prefix);
    let code_end = len + prefix as usize;

    // rwx
    if mprotect(pages_start, code_end, 7) != 0 {
    return;
    }

    let f: fn() -> ! = std::mem::transmute::<*const u8, fn() -> !>(code);
    f();
    }
    } else {
    let mut out = std::io::stdout();
    out.write_all(&res.stdout).unwrap();
    out.flush().unwrap();
    let mut err = std::io::stderr();
    err.write_all(&res.stderr).unwrap();
    err.flush().unwrap();
    }
    }