#coff #loader #redteam #windows

nightly coffeeldr

A COFF (Common Object File Format) loader written in Rust

17 releases

Uses new Rust 2024

0.3.4 Dec 1, 2025
0.3.3 Nov 15, 2025
0.3.2 Oct 15, 2025
0.3.0 Jul 16, 2025
0.1.2 Oct 8, 2024

#125 in Security

MIT/Apache

87KB
1.5K SLoC

coffeeldr

Rust crate docs License Actions status

A modern and lightweight COFF (Common Object File Format) loader for Windows written in Rust, designed to run COFF files on Windows. It supports both 32-bit and 64-bit architectures and allows you to load and execute COFF files from files or memory buffers with Rust’s safety and performance guarantees.

Features

  • ✅ Supports #[no_std] environments (with alloc).
  • ✅ Load COFF files from disk or in-memory buffers.
  • ✅ Load COFF files with module stomping.
  • ✅ Compatible with x64 and x86 architectures.
  • ✅ Memory management: Automatically adjusts memory protections to ensure execution (read, write, execute permissions).
  • ✅ Dynamic relocation handling.
  • ✅ Fully written in Rust with safety and performance in mind.
  • ✅ Easy CLI integration with flexible input handling.

Getting started

Add coffeeldr to your project by updating your Cargo.toml:

cargo add coffeeldr

Usage

Loading from File

To load a COFF file from the filesystem:

use coffeeldr::CoffeeLdr;

let mut loader = CoffeeLdr::new("path/to/coff_file.o");
match loader {
    Ok(ldr) => {
        println!("COFF successfully loaded from file!");
        // Execute the entry point or manipulate the COFF as needed
    },
    Err(e) => println!("Error loading COFF: {:?}", e),
}

Loading from Buffer

To load a COFF from an in-memory buffer:

let coff_data = include_bytes!("path/to/coff_file.o");
let mut loader = CoffeeLdr::new(coff_data);
match loader {
    Ok(ldr) => {
        println!("COFF successfully loaded from buffer!");
        // Execute the entry point or manipulate the COFF as needed
    },
    Err(e) => println!("Error loading COFF: {:?}", e),
}

Executing a COFF File

Once the COFF file is loaded, you can execute it by specifying the entry point:

let mut coffee = CoffeeLdr::new("path/to/coff_file.o").unwrap();
coffee.run("entry_point_function_name", None, None).unwrap();

Using Module Stomping

Module stomping replaces the .text section of a loaded module with the COFF code.

let mut coffee = CoffeeLdr::new("path/to/coff_file.o")?
    .with_module_stomping("xpsservices.dll"); // specify the module to stomp

coffee.run("go", None, None)?;

CLI

coffeeldr also provides a convenient CLI tool for interacting with COFF files directly from the command line.

Example Command:

coffee.exe --bof path/to/coff_file.o --entrypoint go

Input Processing in CLI

These are the types of parameters that the tool accepts for processing:

  • /short:<value>: Adds a short (i16) value.
  • /int:<value>: Adds an integer (i32) value.
  • /str:<value>: Adds a string.
  • /wstr:<value>: Adds a wide string.
  • /bin:<base64-data>: Adds binary data decoded from base64.

Example command using ntcreatethread.o:

coffee.exe --bof ntcreatethread.o -e go /int:4732 /bin:Y29mZmVlbGRy..

Another example using dir.o:

coffee.exe --bof dir.o -e go /str:C:\

Using Module Stomping via CLI

When using the --stomping <module> flag, coffeeldr will identify the .text section of the specified module and overwrite its contents with the loaded COFF payload

coffee.exe --bof whoami.o -e go --stomping xpsservices.dll

CLI Help

A COFF (Common Object File Format) loader written in Rust

Usage: coffee.exe [OPTIONS] --bof <BOF> [INPUTS]...

Arguments:
  [INPUTS]...  Multiple arguments in the format `/short:<value>`, `/int:<value>`, `/str:<value>`, `/wstr:<value>`, `/bin:<base64-data>`

Options:
  -b, --bof <BOF>                The command to be executed
  -e, --entrypoint <ENTRYPOINT>  Entrypoint to use in the execution [default: go]
      --stomping <STOMPING>      Enables module stomping (e.g., --stomping xpsservices.dll)
  -v, --verbose...               Verbose mode (-v, -vv, -vvv, etc.)
  -h, --help                     Print help

References

I want to express my gratitude to these projects that inspired me to create coffeeldr and contribute with some features:

License

coffeeldr is licensed under either of

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in coffeeldr by you, as defined in the Apache-2.0 license, shall be dually licensed as above, without any additional terms or conditions.

Dependencies

~1–14MB
~121K SLoC