mirror of
https://github.com/KickedDroid/bof_oxide
synced 2026-06-06 16:04:29 +00:00
Cleanup
This commit is contained in:
-22
@@ -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"
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user