Skip to content

Instantly share code, notes, and snippets.

@sum-catnip
Created February 18, 2020 16:41
Show Gist options
  • Save sum-catnip/00491d030f69918e96369ce900b24d52 to your computer and use it in GitHub Desktop.
Save sum-catnip/00491d030f69918e96369ce900b24d52 to your computer and use it in GitHub Desktop.

Revisions

  1. sum-catnip created this gist Feb 18, 2020.
    81 changes: 81 additions & 0 deletions inject.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    use std::io;
    use std::ptr;
    use std::mem;
    use std::io::Error;
    use std::io::ErrorKind;
    use std::path::Path;
    use std::ffi::CString;

    use winapi::um::winnt::HANDLE;
    use winapi::um::memoryapi as wmem;
    use winapi::um::processthreadsapi as wproc;
    use winapi::um::handleapi as whandle;
    use winapi::um::libloaderapi as wload;
    use winapi::um::winnt::{
    MEM_RESERVE,
    MEM_COMMIT,
    PAGE_EXECUTE_READWRITE
    };

    use log::debug;
    use widestring::WideCString;

    macro_rules! werr {
    ($cond:expr) => {
    if $cond {
    let e = io::Error::last_os_error();
    log::error!("windows error: {:?}", e);
    return Err(e);
    }
    };
    }

    pub fn inject(proc: HANDLE, dll: &Path) -> io::Result<()> {
    let full_path = dll.canonicalize()?;
    let full_path = full_path.as_os_str();
    let full_path = WideCString::from_str(full_path)
    .map_err(|e| Error::new(ErrorKind::InvalidInput,
    format!("invalid dll path: {:?}", e)))?;

    let path_len = (full_path.len() * 2) +1;
    // allocate space for the path inside target proc
    let dll_addr = unsafe {
    wmem::VirtualAllocEx(proc,
    ptr::null_mut(),
    path_len,
    MEM_RESERVE | MEM_COMMIT,
    PAGE_EXECUTE_READWRITE)
    };

    werr!(dll_addr.is_null());
    debug!("allocated remote memory @ {:?}", dll_addr);

    let res = unsafe {
    // write dll inside target process
    wmem::WriteProcessMemory(proc,
    dll_addr,
    full_path.as_ptr() as *mut _,
    path_len,
    ptr::null_mut())
    };

    werr!(res == 0);

    let krnl = CString::new("kernel32.dll").unwrap();
    let krnl = unsafe { wload::GetModuleHandleA(krnl.as_ptr()) };
    let loadlib = CString::new("LoadLibraryW").unwrap();
    let loadlib = unsafe { wload::GetProcAddress(krnl, loadlib.as_ptr()) };
    debug!("found LoadLibraryW for injection @ {:?}", loadlib);

    let hthread = unsafe {
    wproc::CreateRemoteThread(proc, ptr::null_mut(), 0,
    Some(mem::transmute(loadlib)),
    dll_addr, 0, ptr::null_mut())
    };

    werr!(hthread.is_null());
    debug!("spawned remote thread @ {:?}", hthread);
    unsafe { whandle::CloseHandle(hthread); }

    Ok(())
    }