This commit is contained in:
Kicked Droid
2025-08-20 18:06:28 -05:00
parent 154ce6cd54
commit 8662dd2239
9 changed files with 121 additions and 603 deletions
-22
View File
@@ -1,22 +0,0 @@
[package]
name = "bof_oxide"
version = "0.1.0"
edition = "2024"
[dependencies]
[features]
default = ["data", "format"]
data = []
format = []
process_injection = []
[profile.release]
strip = true
opt-level = "z"
lto = true
panic = "abort"
+20 -9
View File
@@ -1,19 +1,30 @@
# bof_oxide
A POC or Template whatever for developing BOFs for Sliver, Havoc, Cobalt Strike or most COFFLoaders.
A POC or Template whatever for developing BOFs for Sliver, Havoc, Cobalt Strike or most COFFLoaders.
Goals:
- Less Volitile BOFs
- Make Debugging BOFs less of a pain.
- Better Error Handling
- Better Error Handling
<<<<<<< Updated upstream
This project was fun but ran into limitations with what I wanted. I learned a lot of lessons of which I will write a post about soon. Until then check out my repository loadstar.
=======
This project has been fun.
### Build
```
just bof
```
>>>>>>> Stashed changes
# Usage Example
```rust
pub fn rust_bof(beacon: &mut Beacon, data: &mut Data) {
let str_arg = data.extract_str();
if str_arg.is_null() {
beacon.output(
@@ -23,9 +34,9 @@ pub fn rust_bof(beacon: &mut Beacon, data: &mut Data) {
return;
}
data.free();
beacon.printf("Hello %s from rust-bof\0", str_arg);
beacon.output(
BeaconOutputType::Standard,
"[+] Rust BOF Completed successfully",
@@ -55,10 +66,10 @@ Running in Sliver
### How it works
This is just a wrapper around the existing Beacon Fns provided. The difference is we pass the function pointers to a Rust wrapper.
This is just a wrapper around the existing Beacon Fns provided. The difference is we pass the function pointers to a Rust wrapper.
```
C -> Rust -> BeaconApi
C -> Rust -> BeaconApi
```
The bof entry point is still `go` and it's still handled in C.
@@ -135,10 +146,10 @@ AUX scnlen 0x1d nreloc 0 nlnno 0
[ 22](sec 0)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000000 __imp_BeaconFormatAlloc
```
---
### References
### References
Header file `beacon.h` from https://github.com/Cobalt-Strike/bof_template/blob/main/beacon.h
### FAFO License
This is striclty for educational and research purposes. I'm not responsible for any use of this, by any means. Use at you're own risk and find out. NOTE: This probs will get you picked up immediately so good luck.
This is striclty for educational and research purposes. I'm not responsible for any use of this, by any means. Use at you're own risk and find out. NOTE: This probs will get you picked up immediately so good luck.
-27
View File
@@ -1,27 +0,0 @@
#!/bin/bash
rm -rf objects/ ;
mkdir objects ;
RUSTFLAGS="-C target-cpu=x86-64 -C target-feature=+crt-static -C link-arg=-nostartfiles -C link-arg=-nodefaultlibs -C link-arg=-Wl,--gc-sections";
cargo rustc -- --target x86_64-pc-windows-gnu \
-C opt-level=z \
-C panic=abort \
-C debuginfo=0 \
-C strip=symbols \
-C codegen-units=1 \
-C embed-bitcode=no \
--emit=obj -o objects/rust_part.o ;
x86_64-w64-mingw32-gcc -c -DOUTPUT -DFORMAT $C_FEATURES src/entry.c -o objects/c_part.o ;
x86_64-w64-mingw32-ld -r objects/rust_part-*.o objects/c_part.o -o objects/combined.o ;
x86_64-w64-mingw32-objcopy \
--remove-section=.drectve \
--strip-symbol=@feat.00 \
--remove-section=.data \
--remove-section=.bss \
--strip-symbol=rust_begin_unwind \
--strip-debug \
objects/combined.o \
bof_oxide.o
+35
View File
@@ -0,0 +1,35 @@
rust:
RUSTFLAGS="-C target-cpu=x86-64 -C target-feature=+crt-static -C link-arg=-nostartfiles -C link-arg=-nodefaultlibs -C link-arg=-Wl,--gc-sections" \
rustc --target x86_64-pc-windows-gnu \
--cfg 'feature="data"' \
--cfg 'feature="out"' \
-C opt-level=z \
-C panic=abort \
-C debuginfo=0 \
-C strip=symbols \
-C codegen-units=1 \
-C embed-bitcode=no \
--emit=obj \
src/lib.rs -o objects/rust_part.o
c:
x86_64-w64-mingw32-gcc -c src/entry.c -o objects/c_part.o
view-bof:
objdump -t bof.o
ld:
x86_64-w64-mingw32-ld -r objects/rust_part.o objects/c_part.o -o objects/combined.o
copy: ld
x86_64-w64-mingw32-objcopy \
--remove-section=.drectve \
--strip-symbol=@feat.00 \
--remove-section=.bss \
--strip-symbol=rust_begin_unwind \
--strip-debug \
objects/combined.o \
bof.o
bof: rust c copy view-bof
+2 -292
View File
@@ -1,5 +1,3 @@
#ifndef _BEACON_H_
#define _BEACON_H_
#include <windows.h>
#ifdef __cplusplus
@@ -31,7 +29,7 @@ typedef struct {
} formatp;
#ifdef FORMAT
DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz);
DECLSPEC_IMPORT void BeaconFormatReset(formatp * format);
DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, const char * text, int len);
@@ -39,7 +37,6 @@ DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, const char * fmt, .
DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size);
DECLSPEC_IMPORT void BeaconFormatFree(formatp * format);
DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value);
#endif
/* Output Functions */
#define CALLBACK_OUTPUT 0x0
@@ -49,10 +46,9 @@ DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value);
#define CALLBACK_CUSTOM 0x1000
#define CALLBACK_CUSTOM_LAST 0x13ff
#ifdef OUTPUT
DECLSPEC_IMPORT void BeaconOutput(int type, const char * data, int len);
DECLSPEC_IMPORT void BeaconPrintf(int type, const char * fmt, ...);
#endif
#ifdef PROCESS_INJECTION
/* Spawn+Inject Functions */
@@ -74,289 +70,3 @@ DECLSPEC_IMPORT BOOL BeaconIsAdmin();
/* Utility Functions */
DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max);
/* Beacon Information */
/*
* ptr - pointer to the base address of the allocated memory.
* size - the number of bytes allocated for the ptr.
*/
typedef struct {
char * ptr;
size_t size;
} HEAP_RECORD;
#define MASK_SIZE 13
/* Information the user can set in the USER_DATA via a UDRL */
typedef enum {
PURPOSE_EMPTY,
PURPOSE_GENERIC_BUFFER,
PURPOSE_BEACON_MEMORY,
PURPOSE_SLEEPMASK_MEMORY,
PURPOSE_BOF_MEMORY,
PURPOSE_USER_DEFINED_MEMORY = 1000
} ALLOCATED_MEMORY_PURPOSE;
typedef enum {
LABEL_EMPTY,
LABEL_BUFFER,
LABEL_PEHEADER,
LABEL_TEXT,
LABEL_RDATA,
LABEL_DATA,
LABEL_PDATA,
LABEL_RELOC,
LABEL_USER_DEFINED = 1000
} ALLOCATED_MEMORY_LABEL;
typedef enum {
METHOD_UNKNOWN,
METHOD_VIRTUALALLOC,
METHOD_HEAPALLOC,
METHOD_MODULESTOMP,
METHOD_NTMAPVIEW,
METHOD_USER_DEFINED = 1000,
} ALLOCATED_MEMORY_ALLOCATION_METHOD;
/**
* This structure allows the user to provide additional information
* about the allocated heap for cleanup. It is mandatory to provide
* the HeapHandle but the DestroyHeap Boolean can be used to indicate
* whether the clean up code should destroy the heap or simply free the pages.
* This is useful in situations where a loader allocates memory in the
* processes current heap.
*/
typedef struct _HEAPALLOC_INFO {
PVOID HeapHandle;
BOOL DestroyHeap;
} HEAPALLOC_INFO, *PHEAPALLOC_INFO;
typedef struct _MODULESTOMP_INFO {
HMODULE ModuleHandle;
} MODULESTOMP_INFO, *PMODULESTOMP_INFO;
typedef union _ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION {
HEAPALLOC_INFO HeapAllocInfo;
MODULESTOMP_INFO ModuleStompInfo;
PVOID Custom;
} ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION, *PALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION;
typedef struct _ALLOCATED_MEMORY_CLEANUP_INFORMATION {
BOOL Cleanup;
ALLOCATED_MEMORY_ALLOCATION_METHOD AllocationMethod;
ALLOCATED_MEMORY_ADDITIONAL_CLEANUP_INFORMATION AdditionalCleanupInformation;
} ALLOCATED_MEMORY_CLEANUP_INFORMATION, *PALLOCATED_MEMORY_CLEANUP_INFORMATION;
typedef struct _ALLOCATED_MEMORY_SECTION {
ALLOCATED_MEMORY_LABEL Label; // A label to simplify Sleepmask development
PVOID BaseAddress; // Pointer to virtual address of section
SIZE_T VirtualSize; // Virtual size of the section
DWORD CurrentProtect; // Current memory protection of the section
DWORD PreviousProtect; // The previous memory protection of the section (prior to masking/unmasking)
BOOL MaskSection; // A boolean to indicate whether the section should be masked
} ALLOCATED_MEMORY_SECTION, *PALLOCATED_MEMORY_SECTION;
typedef struct _ALLOCATED_MEMORY_REGION {
ALLOCATED_MEMORY_PURPOSE Purpose; // A label to indicate the purpose of the allocated memory
PVOID AllocationBase; // The base address of the allocated memory block
SIZE_T RegionSize; // The size of the allocated memory block
DWORD Type; // The type of memory allocated
ALLOCATED_MEMORY_SECTION Sections[8]; // An array of section information structures
ALLOCATED_MEMORY_CLEANUP_INFORMATION CleanupInformation; // Information required to cleanup the allocation
} ALLOCATED_MEMORY_REGION, *PALLOCATED_MEMORY_REGION;
typedef struct {
ALLOCATED_MEMORY_REGION AllocatedMemoryRegions[6];
} ALLOCATED_MEMORY, *PALLOCATED_MEMORY;
/*
* version - The version of the beacon dll was added for release 4.10
* version format: 0xMMmmPP, where MM = Major, mm = Minor, and PP = Patch
* e.g. 0x040900 -> CS 4.9
* 0x041000 -> CS 4.10
*
* sleep_mask_ptr - pointer to the sleep mask base address
* sleep_mask_text_size - the sleep mask text section size
* sleep_mask_total_size - the sleep mask total memory size
*
* beacon_ptr - pointer to beacon's base address
* The stage.obfuscate flag affects this value when using CS default loader.
* true: beacon_ptr = allocated_buffer - 0x1000 (Not a valid address)
* false: beacon_ptr = allocated_buffer (A valid address)
* For a UDRL the beacon_ptr will be set to the 1st argument to DllMain
* when the 2nd argument is set to DLL_PROCESS_ATTACH.
* heap_records - list of memory addresses on the heap beacon wants to mask.
* The list is terminated by the HEAP_RECORD.ptr set to NULL.
* mask - the mask that beacon randomly generated to apply
*
* Added in version 4.10
* allocatedMemory - An ALLOCATED_MEMORY structure that can be set in the USER_DATA
* via a UDRL.
*/
typedef struct {
unsigned int version;
char * sleep_mask_ptr;
DWORD sleep_mask_text_size;
DWORD sleep_mask_total_size;
char * beacon_ptr;
HEAP_RECORD * heap_records;
char mask[MASK_SIZE];
ALLOCATED_MEMORY allocatedMemory;
} BEACON_INFO, *PBEACON_INFO;
DECLSPEC_IMPORT BOOL BeaconInformation(PBEACON_INFO info);
/* Key/Value store functions
* These functions are used to associate a key to a memory address and save
* that information into beacon. These memory addresses can then be
* retrieved in a subsequent execution of a BOF.
*
* key - the key will be converted to a hash which is used to locate the
* memory address.
*
* ptr - a memory address to save.
*
* Considerations:
* - The contents at the memory address is not masked by beacon.
* - The contents at the memory address is not released by beacon.
*
*/
DECLSPEC_IMPORT BOOL BeaconAddValue(const char * key, void * ptr);
DECLSPEC_IMPORT void * BeaconGetValue(const char * key);
DECLSPEC_IMPORT BOOL BeaconRemoveValue(const char * key);
/* Beacon Data Store functions
* These functions are used to access items in Beacon's Data Store.
* BeaconDataStoreGetItem returns NULL if the index does not exist.
*
* The contents are masked by default, and BOFs must unprotect the entry
* before accessing the data buffer. BOFs must also protect the entry
* after the data is not used anymore.
*
*/
#define DATA_STORE_TYPE_EMPTY 0
#define DATA_STORE_TYPE_GENERAL_FILE 1
typedef struct {
int type;
DWORD64 hash;
BOOL masked;
char* buffer;
size_t length;
} DATA_STORE_OBJECT, *PDATA_STORE_OBJECT;
DECLSPEC_IMPORT PDATA_STORE_OBJECT BeaconDataStoreGetItem(size_t index);
DECLSPEC_IMPORT void BeaconDataStoreProtectItem(size_t index);
DECLSPEC_IMPORT void BeaconDataStoreUnprotectItem(size_t index);
DECLSPEC_IMPORT size_t BeaconDataStoreMaxEntries();
/* Beacon User Data functions */
DECLSPEC_IMPORT char * BeaconGetCustomUserData();
/* Beacon System call */
/* Syscalls API */
typedef struct
{
PVOID fnAddr;
PVOID jmpAddr;
DWORD sysnum;
} SYSCALL_API_ENTRY, *PSYSCALL_API_ENTRY;
typedef struct
{
SYSCALL_API_ENTRY ntAllocateVirtualMemory;
SYSCALL_API_ENTRY ntProtectVirtualMemory;
SYSCALL_API_ENTRY ntFreeVirtualMemory;
SYSCALL_API_ENTRY ntGetContextThread;
SYSCALL_API_ENTRY ntSetContextThread;
SYSCALL_API_ENTRY ntResumeThread;
SYSCALL_API_ENTRY ntCreateThreadEx;
SYSCALL_API_ENTRY ntOpenProcess;
SYSCALL_API_ENTRY ntOpenThread;
SYSCALL_API_ENTRY ntClose;
SYSCALL_API_ENTRY ntCreateSection;
SYSCALL_API_ENTRY ntMapViewOfSection;
SYSCALL_API_ENTRY ntUnmapViewOfSection;
SYSCALL_API_ENTRY ntQueryVirtualMemory;
SYSCALL_API_ENTRY ntDuplicateObject;
SYSCALL_API_ENTRY ntReadVirtualMemory;
SYSCALL_API_ENTRY ntWriteVirtualMemory;
SYSCALL_API_ENTRY ntReadFile;
SYSCALL_API_ENTRY ntWriteFile;
SYSCALL_API_ENTRY ntCreateFile;
} SYSCALL_API, *PSYSCALL_API;
/* Additional Run Time Library (RTL) addresses used to support system calls.
* If they are not set then system calls that require them will fall back
* to the Standard Windows API.
*
* Required to support the following system calls:
* ntCreateFile
*/
#ifdef RTL
typedef struct
{
PVOID rtlDosPathNameToNtPathNameUWithStatusAddr;
PVOID rtlFreeHeapAddr;
PVOID rtlGetProcessHeapAddr;
} RTL_API, *PRTL_API;
typedef struct
{
PSYSCALL_API syscalls;
PRTL_API rtls;
} BEACON_SYSCALLS, *PBEACON_SYSCALLS;
DECLSPEC_IMPORT BOOL BeaconGetSyscallInformation(PBEACON_SYSCALLS info, BOOL resolveIfNotInitialized);
/* Beacon System call functions which will use the current system call method */
DECLSPEC_IMPORT LPVOID BeaconVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
DECLSPEC_IMPORT LPVOID BeaconVirtualAllocEx(HANDLE processHandle, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
DECLSPEC_IMPORT BOOL BeaconVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
DECLSPEC_IMPORT BOOL BeaconVirtualProtectEx(HANDLE processHandle, LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
DECLSPEC_IMPORT BOOL BeaconVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
DECLSPEC_IMPORT BOOL BeaconGetThreadContext(HANDLE threadHandle, PCONTEXT threadContext);
DECLSPEC_IMPORT BOOL BeaconSetThreadContext(HANDLE threadHandle, PCONTEXT threadContext);
DECLSPEC_IMPORT DWORD BeaconResumeThread(HANDLE threadHandle);
DECLSPEC_IMPORT HANDLE BeaconOpenProcess(DWORD desiredAccess, BOOL inheritHandle, DWORD processId);
DECLSPEC_IMPORT HANDLE BeaconOpenThread(DWORD desiredAccess, BOOL inheritHandle, DWORD threadId);
DECLSPEC_IMPORT BOOL BeaconCloseHandle(HANDLE object);
DECLSPEC_IMPORT BOOL BeaconUnmapViewOfFile(LPCVOID baseAddress);
DECLSPEC_IMPORT SIZE_T BeaconVirtualQuery(LPCVOID address, PMEMORY_BASIC_INFORMATION buffer, SIZE_T length);
DECLSPEC_IMPORT BOOL BeaconDuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions);
DECLSPEC_IMPORT BOOL BeaconReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead);
DECLSPEC_IMPORT BOOL BeaconWriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten);
#endif
#ifdef BEACON_GATE_API
/* Beacon Gate APIs */
DECLSPEC_IMPORT VOID BeaconDisableBeaconGate();
DECLSPEC_IMPORT VOID BeaconEnableBeaconGate();
#endif
/* Beacon User Data
*
* version format: 0xMMmmPP, where MM = Major, mm = Minor, and PP = Patch
* e.g. 0x040900 -> CS 4.9
* 0x041000 -> CS 4.10
*/
#ifdef BEACON_USER_DATA
#define DLL_BEACON_USER_DATA 0x0d
#define BEACON_USER_DATA_CUSTOM_SIZE 32
typedef struct
{
unsigned int version;
PSYSCALL_API syscalls;
char custom[BEACON_USER_DATA_CUSTOM_SIZE];
PRTL_API rtls;
PALLOCATED_MEMORY allocatedMemory;
} USER_DATA, * PUSER_DATA;
#endif
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // _BEACON_H_
+52 -125
View File
@@ -1,85 +1,53 @@
use crate::FormatP;
use core::ffi::{c_char, c_int, c_uint, c_void};
// Beacon Fn types
pub type BeaconOutputFn = unsafe extern "C" fn(c_int, *const c_char, c_int);
pub type BeaconPrintfFn = unsafe extern "C" fn(c_int, *const c_char, ...);
use core::ffi::{c_char, c_int, c_short, c_void};
pub type BeaconOutputFn = extern "C" fn(i32, *const c_char, i32);
pub type BeaconPrintfFn = extern "C" fn(i32, *const c_char, *mut c_char);
#[cfg(feature = "format")]
pub type BeaconFormatAllocFn = unsafe extern "C" fn(*mut FormatP, c_int);
#[cfg(feature = "format")]
pub type BeaconFormatFreeFn = unsafe extern "C" fn(*mut FormatP);
// Windows-specific types
#[cfg(feature = "process_injection")]
type HANDLE = *mut c_void;
#[cfg(feature = "process_injection")]
type BOOL = c_int;
#[cfg(feature = "process_injection")]
type DWORD = c_uint;
#[cfg(feature = "process_injection")]
#[repr(C)]
pub struct PROCESS_INFORMATION {
h_process: HANDLE,
h_thread: HANDLE,
process_id: DWORD,
thread_id: DWORD,
}
#[cfg(feature = "process_injection")]
pub struct BeaconInjectionFunctions {
pub get_spawn_to: BeaconGetSpawnToFn,
pub inject_process: BeaconInjectProcessFn,
pub inject_temporary_process: BeaconInjectTemporaryProcessFn,
pub cleanup_process: BeaconCleanupProcessFn,
}
// Function types for process injection
#[cfg(feature = "process_injection")]
pub type BeaconGetSpawnToFn = unsafe extern "C" fn(BOOL, *mut c_char, c_int);
#[cfg(feature = "process_injection")]
pub type BeaconInjectProcessFn =
unsafe extern "C" fn(HANDLE, c_int, *mut c_char, c_int, c_int, *mut c_char, c_int);
#[cfg(feature = "process_injection")]
pub type BeaconInjectTemporaryProcessFn =
unsafe extern "C" fn(*mut PROCESS_INFORMATION, *mut c_char, c_int, c_int, *mut c_char, c_int);
#[cfg(feature = "process_injection")]
pub type BeaconCleanupProcessFn = unsafe extern "C" fn(*mut PROCESS_INFORMATION);
// Beacon data parsing function types
#[cfg(feature = "data")]
pub type BeaconDataParseFn = unsafe extern "C" fn(*mut DataP, *mut c_char, c_int);
#[cfg(feature = "data")]
pub type BeaconDataIntFn = unsafe extern "C" fn(*mut DataP) -> c_int;
#[cfg(feature = "data")]
pub type BeaconDataShortFn = unsafe extern "C" fn(*mut DataP) -> i16;
#[cfg(feature = "data")]
pub type BeaconDataLengthFn = unsafe extern "C" fn(*mut DataP) -> c_int;
#[cfg(feature = "data")]
pub type BeaconDataExtractFn = unsafe extern "C" fn(*mut DataP, *mut c_int) -> *mut c_char;
#[cfg(feature = "data")]
// Add these to your Beacon struct
pub struct BeaconDataFunctions {
pub parse: BeaconDataParseFn,
pub get_int: BeaconDataIntFn,
pub get_short: BeaconDataShortFn,
pub get_length: BeaconDataLengthFn,
pub extract: BeaconDataExtractFn,
}
pub struct Beacon {
output: BeaconOutputFn,
pub printf: BeaconPrintfFn,
#[cfg(feature = "process_injection")]
pub injection: BeaconInjectionFunctions,
pub format: FormatP,
pub data: DataP,
pub output_addr: BeaconOutputFn,
pub printf_addr: BeaconPrintfFn,
pub args: *const c_char,
pub alen: c_int,
}
impl Beacon {
pub fn new(output: BeaconOutputFn, printf: BeaconPrintfFn, args: *const c_char, alen: c_int) -> Self {
let mut beacon = Beacon {
format: FormatP::new(),
data: DataP::new(),
output_addr: output,
printf_addr: printf,
args,
alen,
};
return beacon;
}
pub fn output(&mut self, data: &str) {
unsafe {(self.output_addr)(0, data.as_ptr() as *const c_char, data.len() as i32)};
}
}
#[repr(C)]
pub enum BeaconOutputType {
Standard = 0x0,
Oem = 0x1e,
Utf8 = 0x20,
Error = 0x0d,
#[repr(C, align(8))]
pub struct FormatP {
pub original: *mut c_char,
pub buffer: *mut c_char,
pub length: c_int,
pub size: c_int,
}
impl FormatP {
pub fn new() -> Self {
FormatP {
original: core::ptr::null_mut(),
buffer: core::ptr::null_mut(),
length: 0,
size: 0,
}
}
}
#[repr(C)]
@@ -90,54 +58,13 @@ pub struct DataP {
pub size: c_int,
}
impl Beacon {
pub fn new(
output: BeaconOutputFn,
printf: BeaconPrintfFn,
#[cfg(feature = "process_injection")] get_spawn_to: BeaconGetSpawnToFn,
#[cfg(feature = "process_injection")] inject_process: BeaconInjectProcessFn,
#[cfg(feature = "process_injection")]
inject_temporary_process: BeaconInjectTemporaryProcessFn,
#[cfg(feature = "process_injection")] cleanup_process: BeaconCleanupProcessFn,
// Arguments from Beacon
args: *mut c_char,
alen: c_int,
) -> Self {
let mut beacon = Self {
output,
printf,
#[cfg(feature = "process_injection")]
injection: BeaconInjectionFunctions {
get_spawn_to,
inject_process,
inject_temporary_process,
cleanup_process,
},
};
beacon
}
pub fn output(&self, out_type: BeaconOutputType, msg: &str) {
unsafe {
(self.output)(
out_type as c_int,
msg.as_ptr() as *const c_char,
msg.len() as c_int,
);
}
}
pub fn printf(&mut self, mut msg: &str, arg: *const c_char) {
unsafe {
(self.printf)(0, msg.as_ptr() as *const c_char, arg);
}
}
pub fn print(&mut self, mut msg: &str) {
unsafe {
(self.printf)(0, msg.as_ptr() as *const c_char);
impl DataP {
pub fn new() -> Self {
DataP {
original: core::ptr::null_mut(),
buffer: core::ptr::null_mut(),
length: 0,
size: 0,
}
}
}
+2 -33
View File
@@ -7,49 +7,18 @@ extern void initialize(
void (*beacon_output)(int, const char *, int),
void (*beacon_printf)(int, const char * fmt, ...),
#endif
void (*beacon_format_alloc)(formatp*, int),
void (*beacon_format_free)(formatp*),
#ifdef PROCESS_INJECTION
void (*beacon_get_spawn_to)(BOOL, char*, int),
void (*beacon_inject_process)(HANDLE, int, char*, int, int, char*, int),
void (*beacon_inject_temporary_process)(PROCESS_INFORMATION*, char*, int, int, char*, int),
void (*beacon_cleanup_process)(PROCESS_INFORMATION*),
#endif
void (*beacon_data_parse)(datap*, char*, int),
int (*beacon_data_int)(datap*),
short (*beacon_data_short)(datap*),
int (*beacon_data_length)(datap*),
char* (*beacon_data_extract)(datap*, int*),
char* args,
char* args,
int alen
);
void go(char* args, int alen) {
// Pass the fn pointers to the rust wrapper
initialize(
BeaconOutput,
BeaconOutput,
BeaconPrintf,
BeaconFormatAlloc,
BeaconFormatFree,
#ifdef PROCESS_INJECTION
BeaconGetSpawnTo,
BeaconInjectProcess,
BeaconInjectTemporaryProcess,
BeaconCleanupProcess,
#endif
BeaconDataParse,
BeaconDataInt,
BeaconDataShort,
BeaconDataLength,
BeaconDataExtract,
args,
alen
);
+7 -69
View File
@@ -2,89 +2,27 @@
#![no_std]
#![allow(non_upper_case_globals)]
mod rust_bof;
use core::ffi::{c_char, c_int};
use rust_bof::rust_bof;
mod beacon;
mod data;
use beacon::*;
use data::Data;
#[repr(C, align(8))]
pub struct FormatP {
original: *mut c_char,
buffer: *mut c_char,
length: c_int,
size: c_int,
}
use rust_bof::rust_bof;
use beacon::{BeaconOutputFn, BeaconPrintfFn, Beacon};
use core::ffi::{c_char, c_int};
// This is the Entrypoint for the Rust portion
// Initialize and call rust_bof
#[unsafe(no_mangle)]
pub unsafe extern "C" fn initialize(
beacon_output: BeaconOutputFn,
beacon_printf: BeaconPrintfFn,
#[cfg(feature = "format")] beacon_format_alloc: BeaconFormatAllocFn,
#[cfg(feature = "format")] beacon_format_free: BeaconFormatFreeFn,
#[cfg(feature = "process_injection")] get_spawn_to: BeaconGetSpawnToFn,
#[cfg(feature = "process_injection")] inject_process: BeaconInjectProcessFn,
#[cfg(feature = "process_injection")] inject_temporary_process: BeaconInjectTemporaryProcessFn,
#[cfg(feature = "process_injection")] cleanup_process: BeaconCleanupProcessFn,
#[cfg(feature = "data")] beacon_data_parse: BeaconDataParseFn,
#[cfg(feature = "data")] beacon_data_int: BeaconDataIntFn,
#[cfg(feature = "data")] beacon_data_short: BeaconDataShortFn,
#[cfg(feature = "data")] beacon_data_length: BeaconDataLengthFn,
#[cfg(feature = "data")] beacon_data_extract: BeaconDataExtractFn,
// Arguments from Beacon
args: *mut c_char,
alen: c_int,
) {
#[cfg(feature = "data")]
let data = BeaconDataFunctions {
parse: beacon_data_parse,
get_int: beacon_data_int,
get_short: beacon_data_short,
get_length: beacon_data_length,
extract: beacon_data_extract,
};
// Pass the fn pointers to the Beacon wrapper
let mut beacon = Beacon::new(
beacon_output,
beacon_printf,
#[cfg(feature = "process_injection")]
get_spawn_to,
#[cfg(feature = "process_injection")]
inject_process,
#[cfg(feature = "process_injection")]
inject_temporary_process,
#[cfg(feature = "process_injection")]
cleanup_process,
args,
alen,
);
#[cfg(feature = "data")]
let mut data = Data::new(
beacon_format_alloc,
beacon_format_free,
beacon_data_parse,
beacon_data_int,
beacon_data_short,
beacon_data_length,
beacon_data_extract,
args,
alen,
);
// Call rust_bof
rust_bof(&mut beacon,&mut data);
drop(beacon);
let beacon = Beacon::new(beacon_output, beacon_printf, args, alen);
rust_bof(beacon);
}
#[panic_handler]
#[unsafe(no_mangle)]
fn panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}
}
+3 -26
View File
@@ -1,29 +1,6 @@
use crate::data::Data;
use crate::{beacon, Beacon};
use beacon::BeaconOutputType;
use core::arch::asm;
use crate::Beacon;
// This will be the main file we edit to write out BOFs.
pub fn rust_bof(beacon: &mut Beacon, data: &mut Data) {
let str_arg = data.extract_str();
if str_arg.is_null() {
beacon.output(
BeaconOutputType::Error,
"[!] Str_arg argument is required\n",
);
return;
}
beacon.printf("Hello %s from rust-bof\0", str_arg);
data.free();
beacon.output(
BeaconOutputType::Standard,
"[+] Rust BOF Completed successfully",
);
pub fn rust_bof(mut beacon: Beacon) {
beacon.output("HELLOOOOOOOO");
}