Crate dll_syringe

source ·
Expand description

A crate for DLL injection on windows.

Supported scenarios

Injector ProcessTarget ProcessSupported?
32-bit32-bitYes
32-bit64-bitNo
64-bit32-bitYes (requires feature into-x86-from-x64)
64-bit64-bitYes

Usage

Inject & Eject

This crate allows you to inject and eject a DLL into a target process. The example below will inject and then eject injection_payload.dll into the process called “ExampleProcess”.

use dll_syringe::{Syringe, process::OwnedProcess};

// find target process by name
let target_process = OwnedProcess::find_first_by_name("ExampleProcess").unwrap();

// create a new syringe for the target process
let syringe = Syringe::for_process(target_process);

// inject the payload into the target process
let injected_payload = syringe.inject("injection_payload.dll").unwrap();

// do something else

// eject the payload from the target (optional)
syringe.eject(injected_payload).unwrap();

Remote Procedure Calls (RPC)

This crate supports two mechanisms for rpc. Both only work one-way for calling exported functions in the target process and are only intended for one-time initialization usage. For extended communication a dedicated rpc library should be used.

RemotePayloadProcedureRemoteRawProcedure
Featurerpc-payloadrpc-raw
Argument and Return RequirementsSerialize + DeserializeOwnedCopy, Argument size has to be smaller than usize in target process
Function DefinitionUsing macro payload_procedure!Any extern "system" or extern "C" with #[no_mangle]

RemotePayloadProcedure

A rpc mechanism based on bincode. The target procedure must be defined using the payload_procedure! macro (requires the payload-utils feature).

The definition of an exported add function could look like this:

dll_syringe::payload_procedure! {
    fn add(a: f64, b: f64) -> f64 {
        a + b
    }
}

The code of the injector/caller could looks like this:

use dll_syringe::{Syringe, process::OwnedProcess};

// find target process by name
let target_process = OwnedProcess::find_first_by_name("ExampleProcess").unwrap();

// create a new syringe for the target process
let syringe = Syringe::for_process(target_process);

// inject the payload into the target process
let injected_payload = syringe.inject("injection_payload.dll").unwrap();

let remote_add = unsafe { syringe.get_payload_procedure::<fn(f64, f64) -> f64>(injected_payload, "add") }.unwrap().unwrap();
let result = remote_add.call(&2.0, &4.0).unwrap();
println!("{}", result); // prints 6

// eject the payload from the target (optional)
syringe.eject(injected_payload).unwrap();

RemoteRawProcedure

This mechanism is based on dynamically generated assembly code. The target procedure can be any exported function as long as it uses either the system or C calling convention. This means that even Win32 functions can be called directly.

The definition of an exported add function could look like this:

#[no_mangle]
extern "system" fn add(a: f64, b: f64) -> f64 {
    a + b
}

The code of the injector/caller could looks like this:

use dll_syringe::{Syringe, process::OwnedProcess};

// find target process by name
let target_process = OwnedProcess::find_first_by_name("ExampleProcess").unwrap();

// create a new syringe for the target process
let syringe = Syringe::for_process(target_process);

// inject the payload into the target process
let injected_payload = syringe.inject("injection_payload.dll").unwrap();

let remote_add = unsafe { syringe.get_raw_procedure::<extern "system" fn(f64, f64) -> f64>(injected_payload, "add") }.unwrap().unwrap();
let result = remote_add.call(2.0, 4.0).unwrap();
println!("{}", result); // prints 6

// eject the payload from the target (optional)
syringe.eject(injected_payload).unwrap();

Modules

  • Module containing the error enums used in this crate.
  • Module containing traits and types for working with function pointers.
  • Module containing process abstractions and utilities.
  • rpcrpc-core
    Module containing traits and structs regarding remote procedures.

Macros

Structs

  • Syringesyringe
    An injector that can inject modules (.dll’s) into a target process.