Enhancing C2 agent via Beacon Object Files (BOF)
Learn what are Beacon Object Files (BOF) and how they can be used to extend a C2 agent's functionality.
In 2020, a new feature was introduced, as part of Cobalt Strike 4.1 release, to extend a C2 agent’s (aka beacon) built-in functionality. Through this feature, red team operators can write code in C and customize or extend beacon’s functionality as per their requirements. This feature was termed as Beacon Object File (BOF).
A BOF is a lightweight, modular piece of compiled code designed to be executed in memory by a C2 agent. BOFs are written in C and compiled as position-independent code (PIC), enabling operations like privilege escalation, credential dumping, or enumeration to run stealthily within the memory of a target system. They’re small, efficient, harder to detect and leave minimal forensic evidence.
Position-independent code (PIC) is a way of writing computer programs so they can run from any location in a computer's memory without needing to know exactly where they are stored. Allow me to explain this through an analogy.
Let’s say you are describing a recipe for making a cake and need to mention the location of flour. Instead of saying, “Go to the second shelf of the pantry,” you say, “Look in the place where the flour is stored.” No matter how the pantry is organized, it will always work because it doesn’t rely on fixed location of the flour.
Beacon Object Files can call Win32 APIs and have access to some internal Beacon APIs (e.g., for output, token impersonation, etc.). Also, while originally introduced for Cobalt Strike, they can be used with other C2 software (e.g. Sliver) as well.
BOFs provide following advantage:
They run directly within the Beacon process which helps in avoiding the OPSEC-expensive fork&run pattern of process creation and injection used by other tools like PowerShell and Reflective DLLs.
They are tiny in comparison to alternatives—e.g., a BOF for a UAC bypass is <3KB, versus 100KB+ for a Reflective DLL, making them ideal for bandwidth-constrained environments like DNS.
They are simple to create using a Win32 C compiler, requiring minimal setup or project configuration.
They do come with certain disadvantages as well:
They are single-file C programs limited to Win32 APIs, Beacon APIs, and custom-written functions. Standard libraries (e.g., libc) and many common functions like
strlen
orstrcmp
are not available to them.BOFs run inside the Beacon agent, so a crash can cause the loss of access to the agent and can cause great disappointment.
They are single-threaded so they block other Beacon tasks while running, making them unsuitable for asynchronous or long-running operations.
They are not suitable for large projects as they cannot support linking with external functionality or handling complex, large-scale projects.
Red Team Notes
- Beacon Object Files (BOFs) are position independent compiled code files that can be linked to a C2 agent to extend or customize it's functionality.
- BOFs are light-weight, stealthy and easy to create. However, they do come with certain drawbacks such as blocking the C2 agent during execution, risk of crashing the C2 agent and cannot be used for implementing larger functionality.
Follow my journey of 100 Days of Red Team on WhatsApp or Discord.
If you want to dive deep into the technical details of how BOFs works and how to create one, below is the demo of Beacon Object Files by, Raphael Mudge (creator of Cobalt Strike):
Other resources: