1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#[cfg(not(windows))]
compile_error!("this crate is only meant to be used for windows targets");

mod imp;

mod windows_prelude;
use windows_prelude::*;

/// Opens the process specified by `pid` in a manner suitable for DLL injection.
pub fn open_process(pid: DWORD) -> Result<HANDLE, DWORD> {
    let handle = unsafe {
        OpenProcess(
            PROCESS_CREATE_THREAD
                | PROCESS_QUERY_INFORMATION
                | PROCESS_VM_OPERATION
                | PROCESS_VM_WRITE
                | PROCESS_VM_READ,
            FALSE,
            pid,
        )
    };

    if handle.is_null() {
        Err(unsafe { GetLastError() })
    } else {
        Ok(handle)
    }
}

/// Injects the given DLL into the process specified by handle, optionally calling the given function in the DLL.
///
/// To skip calling an initialization function, pass `NO_INIT_FN`.
///
/// # Returns
///
/// The function returns Ok with the initialization function's return code (0 if `NO_INIT_FN` is passed)
/// If an error occurs, this function returns the error code from GetLastError.
pub fn inject_dll<P: AsRef<std::path::Path>>(
    process: HANDLE,
    dll: P,
    function: &[u8],
) -> Result<DWORD, DWORD> {
    imp::inject_dll(process, dll.as_ref(), function)
}

/// Special value that tells `inject_dll` not to call any initialization function.
/// Only the injected DLL's `DllMain` function will run.
pub const NO_INIT_FN: &[u8] = &[];