From 3b2b678064b4b5c121ea1f17cb35265021eaca99 Mon Sep 17 00:00:00 2001 From: chvancooten Date: Thu, 30 May 2024 18:55:59 +0200 Subject: [PATCH] Add 'bin' argument type (base64-encoded), update README, fix 'hexilify' typo --- Cargo.toml | 1 + README.md | 11 +++++++++-- src/loader/beacon_pack.rs | 12 ++++++++++++ src/main.rs | 15 +++++++++++---- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 97aa7c3..8792ab1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,3 +49,4 @@ windows-sys = { version = "0.48.0", features = [ "Win32_Security", "Win32_System_Diagnostics_Debug" ] } +base64 = "0.22.1" diff --git a/README.md b/README.md index 696b271..3dd9491 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Coffee: A COFF loader made in Rust Usage: coffee.exe [OPTIONS] --bof-path [-- ...] Arguments: - [ARGS]... Arguments to the BOF passed after the "--" delimiter, supported types are: str, wstr, int, short + [ARGS]... Arguments to the BOF passed after the "--" delimiter, supported types are: str, wstr, int, short, bin Options: -b, --bof-path Path to the Beacon Object File (BOF) @@ -31,8 +31,9 @@ Arguments for the BOF can be passed after the `--` delimiter. Each argument must - `wstr` - A wide null-terminated string - `int` - A signed 32-bit integer - `short` - A signed 16-bit integer +- `bin` - A base64-encoded binary blob -## Example +## Examples Using the `dir.x64.o` BOF from the [trustedsec/CS-Situational-Awareness-BOF](https://github.com/trustedsec/CS-Situational-Awareness-BOF) repository and passing arguments to the BOF: @@ -40,6 +41,12 @@ Using the `dir.x64.o` BOF from the [trustedsec/CS-Situational-Awareness-BOF](htt coffee.exe --bof-path .\dir.x64.o -- wstr:"C:\\Windows\\System32" ``` +Using the `ntcreatethread.x64.o` BOF from the [trustedsec/CS-Remote-OPs-BOF](https://github.com/trustedsec/CS-Remote-OPs-BOF) repository and passing a PID and the shellcode to execute as base64-encoded binary data. + +```bash +coffee.exe --bof-path .\ntcreatethread.x64.o -- int:1337 bin:/EiD5PDowAAAAEFRQVBSUVZIMdJlSItSYEiLUhhIi1IgSItyUEgPt0pKTTHJSDHArDxhfAIsIEHByQ1BAcHi7VJBUUiLUiCLQjxIAdCLgIgAAABIhcB0Z0gB0FCLSBhEi0AgSQHQ41ZI/8lBizSISAHWTTHJSDHArEHByQ1BAcE44HXxTANMJAhFOdF12FhEi0AkSQHQZkGLDEhEi0AcSQHQQYsEiEgB0EFYQVheWVpBWEFZQVpIg+wgQVL/4FhBWVpIixLpV////11IugEAAAAAAAAASI2NAQEAAEG6MYtvh//Vu+AdKgpBuqaVvZ3/1UiDxCg8BnwKgPvgdQW7RxNyb2oAWUGJ2v/VY2FsYy5leGUA +``` + ## Usage as library ```bash diff --git a/src/loader/beacon_pack.rs b/src/loader/beacon_pack.rs index b02941a..73975b4 100644 --- a/src/loader/beacon_pack.rs +++ b/src/loader/beacon_pack.rs @@ -76,6 +76,18 @@ impl BeaconPack { self.buffer.write_u16::(0).unwrap(); self.size += ((s_bytes.len() * 2) + 2) as u32 + 4; } + + /// `add_bin` adds binary data to the buffer + /// + /// # Panics + /// Panics if the buffer cannot be written as binary data + pub fn add_bin(&mut self, bin: &[u8]) { + self.buffer + .write_u32::(bin.len() as u32) + .unwrap(); + self.buffer.write_all(bin).unwrap(); + self.size += (bin.len() as u32) + 4; + } } impl Default for BeaconPack { diff --git a/src/main.rs b/src/main.rs index 905b699..a90693f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ use std::fmt::Write; use std::path::PathBuf; +use base64::{prelude::BASE64_STANDARD, Engine}; use clap::Parser; use color_eyre::Result; use tracing::{debug, info}; @@ -32,13 +33,13 @@ struct Args { #[clap(default_value = "1")] verbosity: Option, - /// Arguments to the BOF passed after the "--" delimiter, supported types are: str, wstr, int, short + /// Arguments to the BOF passed after the "--" delimiter, supported types are: str, wstr, int, short, bin #[clap(last = true)] arguments: Vec, } -/// Unhexilify a string of hexadecimal characters to pass as arguments to the BOF -fn unhexilify_args(value: &str) -> Result> { +/// Unhexlify a string of hexadecimal characters to pass as arguments to the BOF +fn unhexlify_args(value: &str) -> Result> { assert!(value.len() % 2 == 0, "Invalid argument hexadecimal string"); let bytes: Result, _> = (0..value.len()) @@ -80,6 +81,12 @@ fn hexlify_args(args: Vec) -> String { panic!("Invalid short value"); } } + "bin" => { + let bin_value = BASE64_STANDARD + .decode(argument_value) + .expect("Invalid binary value, please provide as base64"); + beacon_pack.add_bin(&bin_value); + } _ => panic!("Invalid argument type"), } } @@ -130,7 +137,7 @@ fn main() -> Result<()> { let coff_buffer = std::fs::read(&args.bof_path)?; // Unhexlify the arguments - let unhexilified = unhexilify_args(arguments.as_str())?; + let unhexilified = unhexlify_args(arguments.as_str())?; debug!("Unhexilified arguments: {:?}", unhexilified); // Execute the BOF