├── scripts ├── add.txt ├── generate_md.py ├── find-dupes.py └── test2.py ├── Gemfile ├── resources ├── image.png ├── image-1.png ├── async-bof.png ├── diataxis.png ├── load-bof.png ├── hello-bof-cs.png └── hello-args-bof.png ├── how-to ├── index.md ├── how-to-resources │ ├── ai.png │ ├── image.png │ ├── image-1.png │ ├── image-10.png │ ├── image-11.png │ ├── image-12.png │ ├── image-13.png │ ├── image-14.png │ ├── image-15.png │ ├── image-2.png │ ├── image-3.png │ ├── image-4.png │ ├── image-5.png │ ├── image-6.png │ ├── image-8.png │ ├── image-9.png │ └── c-extension.png ├── how-to-async-execute.md ├── setup-visual-studio-bof.md ├── how-to-execute-bofs-in-c2.md └── setup-vscode-bof.md ├── explanation ├── index.md ├── explanation-what-are-bofs.md ├── bof_loader_explainer.md ├── explanation-bof-args.md └── bof-internals-explained.md ├── reference ├── index.md ├── bof-training-courses.md ├── c2-framework-bof-support.md ├── reference-bof-dev.md ├── loaders-catalog.md └── bof-blogs-and-research.md ├── tutorials ├── index.md ├── tutorial-building-your-first-bof.md └── tutorial-building-your-second-bof.md ├── index.md ├── _config.yml ├── LICENSE ├── .github └── workflows │ └── jekyll-gh-pages.yml └── README.md /scripts/add.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | # the theme itself 4 | gem "just-the-docs" 5 | -------------------------------------------------------------------------------- /resources/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/resources/image.png -------------------------------------------------------------------------------- /resources/image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/resources/image-1.png -------------------------------------------------------------------------------- /resources/async-bof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/resources/async-bof.png -------------------------------------------------------------------------------- /resources/diataxis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/resources/diataxis.png -------------------------------------------------------------------------------- /resources/load-bof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/resources/load-bof.png -------------------------------------------------------------------------------- /resources/hello-bof-cs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/resources/hello-bof-cs.png -------------------------------------------------------------------------------- /how-to/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How-to 3 | nav_order: 3 # optional ordering 4 | has_children: true 5 | --- 6 | -------------------------------------------------------------------------------- /resources/hello-args-bof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/resources/hello-args-bof.png -------------------------------------------------------------------------------- /how-to/how-to-resources/ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/ai.png -------------------------------------------------------------------------------- /explanation/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Explanation 3 | nav_order: 3 # optional ordering 4 | has_children: true 5 | --- 6 | -------------------------------------------------------------------------------- /how-to/how-to-resources/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image.png -------------------------------------------------------------------------------- /reference/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Reference 3 | nav_order: 3 # optional ordering 4 | has_children: true 5 | --- 6 | -------------------------------------------------------------------------------- /tutorials/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tutorials 3 | nav_order: 3 # optional ordering 4 | has_children: true 5 | --- 6 | -------------------------------------------------------------------------------- /how-to/how-to-resources/image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-1.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-10.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-11.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-12.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-13.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-14.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-15.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-2.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-3.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-4.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-5.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-6.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-8.png -------------------------------------------------------------------------------- /how-to/how-to-resources/image-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/image-9.png -------------------------------------------------------------------------------- /how-to/how-to-resources/c-extension.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chryzsh/awesome-bof/HEAD/how-to/how-to-resources/c-extension.png -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "awesome-bof" 3 | has_children: true # tells Just-the-Docs this is the tree root 4 | nav_order: 0 5 | --- 6 | 7 | Welcome to **awesome-bof** – community-curated resources for Beacon Object 8 | Files. Use the sidebar to explore. 9 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | title: awesome-bof 2 | 3 | remote_theme: just-the-docs/just-the-docs # ← replaces `theme:` 4 | 5 | color_scheme: dark 6 | 7 | url: "https://chryzsh.github.io" 8 | 9 | baseurl: "/awesome-bof" 10 | 11 | plugins: # make sure the plugin is on 12 | - jekyll-remote-theme 13 | 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 crusher 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/jekyll-gh-pages.yml: -------------------------------------------------------------------------------- 1 | # # .github/workflows/jekyll-gh-pages.yml 2 | name: Build & deploy awesome-bof docs 3 | 4 | on: 5 | push: 6 | branches: [ "main" ] # or whatever your default branch is 7 | workflow_dispatch: # allow manual reruns 8 | 9 | permissions: 10 | contents: read 11 | pages: write 12 | id-token: write 13 | 14 | concurrency: 15 | group: "pages" 16 | cancel-in-progress: false 17 | 18 | jobs: 19 | # ---------- BUILD ---------- 20 | build: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Checkout repo 24 | uses: actions/checkout@v4 25 | 26 | # 👇 THIS action already has Ruby + Jekyll + just-the-docs pre-installed 27 | - name: Build site with Jekyll 28 | uses: actions/jekyll-build-pages@v1 29 | with: 30 | # Our docs live in the repository **root**, 31 | # so use "./" instead of the default "./docs" 32 | source: ./ 33 | destination: ./_site # leave this as-is 34 | 35 | - name: Upload artifact 36 | uses: actions/upload-pages-artifact@v3 37 | with: 38 | path: ./_site # must match “destination” above 39 | 40 | # ---------- DEPLOY ---------- 41 | deploy: 42 | needs: build 43 | runs-on: ubuntu-latest 44 | environment: 45 | name: github-pages 46 | url: ${{ steps.deployment.outputs.page_url }} 47 | steps: 48 | - name: Deploy to GitHub Pages 49 | id: deployment 50 | uses: actions/deploy-pages@v4 51 | -------------------------------------------------------------------------------- /reference/bof-training-courses.md: -------------------------------------------------------------------------------- 1 | # Reference: BOF Development Training and Courses 2 | 3 | This reference page lists available training resources and online courses that specifically cover Beacon Object File (BOF) development. 4 | 5 | --- 6 | 7 | ## 🎓 Structured trainings and courses 8 | 9 | | Course Title | Provider | Details | Publication Date | 10 | |--------------|----------|---------|------------------| 11 | | [BOF Development and Tradecraft](https://training.zeropointsecurity.co.uk/courses/bof-dev-and-tradecraft) | Zero-Point Security | Learn how to write and unit test Beacon Object Files (BOFs) | 2024-06-20 | 12 | | [Beacon Object File (BOF) Development](https://learn.trustedsec.com/courses/cd84409a-36af-4507-be2c-ca7ad1e9fd2d) | TrustedSec | A full, start-to-finish guide covering how to develop BOFs in C | 2024-12-15 | 13 | 14 | ## Other courses 15 | This repo will not maintain a list of courses or trainings that may use BOFs or show development of BOFs unless its a focus area. 16 | Some courses known to show development or BOFs or COFF loaders are: 17 | 18 | | Course Title | Provider | Details | Publication Date | 19 | |--------------|----------|---------|------------------| 20 | | [RED TEAM Operator: Malware Development Advanced - Vol.1](https://institute.sektor7.net/rto-maldev-adv1) | Sektor7 | Advanced offensive security tool development topics. Includes COFF/BOF development as part of malware tradecraft | 2023-08-28 | 21 | | [Signal Labs - Offensive Tool Development](https://signal-labs.com/trainings/offensive-tool-development/) | Signal Labs | Includes a section called "Creating Our Own COFF Loader" | 2023 | 22 | 23 | --- 24 | 25 | ## 📢 Contribution 26 | If you become aware of courses or training specifically covering BOF development, feel free to open a PR or create an issue to get it listed here. 27 | -------------------------------------------------------------------------------- /explanation/explanation-what-are-bofs.md: -------------------------------------------------------------------------------- 1 | # Explanation: What is a BOF? 2 | 3 | A **BOF** — or **Beacon Object File** — is a compiled **COFF (Common Object File Format)** file designed to be run in-memory by a post-exploitation agent like Cobalt Strike's Beacon or Havoc's Demon. BOFs are small, self-contained C programs that execute directly inside a live process, inheriting its memory, permissions, and execution context. 4 | 5 | --- 6 | 7 | ## 🧠 Key Characteristics 8 | 9 | - 🔧 **Compiled from C** using a Windows cross-compiler (e.g., MinGW) 10 | - 🧵 **Executed in-memory**, inside the agent's thread or via a job system 11 | - 🕵️‍♂️ **Stealthy** — no disk writes, no new process creation 12 | - ⚡ **Fast and lightweight**, ideal for small, purpose-built tasks 13 | 14 | --- 15 | 16 | ## 💡 What Makes BOFs Special? 17 | 18 | BOFs provide red teamers and malware developers with a way to extend C2 functionality without writing full post-exploitation modules or launching separate binaries. They enable fileless execution of complex logic using minimal memory and almost no forensic artifacts. 19 | 20 | Originally popularized in **Cobalt Strike**, BOFs have now been adopted by C2 frameworks like: 21 | - **Brute Ratel** 22 | - **Havoc** 23 | - **Sliver** 24 | - **Mythic (Xenon)** 25 | - **Meterpreter** (via extensions) 26 | 27 | Each framework has its own method of loading and executing BOFs, but the core model remains consistent. 28 | 29 | --- 30 | 31 | ## 📦 What BOFs Are Used For 32 | - Credential dumping (e.g., LSASS memory access) 33 | - Enumeration and situational awareness 34 | - Process injection and syscall execution 35 | - Evasion (e.g., AMSI bypasses, memory unhooking) 36 | - Persistence techniques 37 | 38 | --- 39 | 40 | ## ✅ Summary 41 | BOFs are a powerful, stealthy, and increasingly cross-platform way to embed post-exploitation logic into an existing C2 agent. With growing support across frameworks, they’ve become a fundamental part of modern red team operations. 42 | 43 | For how BOFs are written, parsed, and executed, check out: 44 | - [`explanation/bof-internals-explained.md`](../explanation/bof-internals-explained.md) 45 | - [`explanation/bof-argument-parsing.md`](../explanation/bof-argument-parsing.md) 46 | 47 | -------------------------------------------------------------------------------- /how-to/how-to-async-execute.md: -------------------------------------------------------------------------------- 1 | # How-To: Run BOFs asynchronously with `async-execute` in Cobalt Strike 2 | 3 | This guide will show you how to use the `async-execute` Postex DLL in Cobalt Strike to run Beacon Object Files (BOFs) asynchronously. This enables BOFs to run in their own threads without blocking the Beacon process. 4 | 5 | --- 6 | 7 | ## 🎯 Goal 8 | - Understand what the purpose of `async-execute` is 9 | - Load and run BOFs using `async-execute` 10 | - Manage and monitor asynchronous jobs 11 | 12 | --- 13 | 14 | ## 🧠 Why Use `async-execute`? 15 | Traditionally, BOFs run synchronously. They take over the Beacon thread and must finish before you can issue another command. `async-execute` allows: 16 | 17 | - Running multiple BOFs in parallel 18 | - Avoiding long delays or lock-ups in Beacon from long-running jobs 19 | - Improved operational flexibility 20 | 21 | With CS 4.11, the CS team introduced a way to run BOFs async with a moduled developed in the Postex kit. 22 | 23 | 24 | --- 25 | 26 | ## 📦 Requirements 27 | - Cobalt Strike 4.11+ 28 | - `async-execute` module (downloaded from the Postex Kit) 29 | - A compiled BOF (`.o` file) 30 | 31 | --- 32 | 33 | ## 📁 Step 1: Download and load it from the Postex Kit 34 | - Download the artifact kit (requires valid CS license) 35 | - Load the `async-execute.cna` through the Script Manager in CS 36 | - From Beacon, the `async-execute` command should be exposed: 37 | 38 | ``` 39 | help async-execute 40 | Usage: async-execute --pid --arch --mode --bof --syscall --fmt --argX 41 | ``` 42 | 43 | ## ▶️ Step 2: Run a BOF Asynchronously 44 | Execute multiple BOFs with the `async-execute` command 45 | ```powershell 46 | async-execute --arch x64 --bof first-bof.o 47 | ``` 48 | 49 | ```powershell 50 | async-execute --arch x64 --bof second-bof.o 51 | ``` 52 | 53 | Output appears in the job-specific console in the GUI. 54 | 55 | --- 56 | 57 | ## 📋 Step 3: Monitor Asynchronous Jobs 58 | Each async BOF appears as its own *job*. You can follow the BOFs in the `Right click -> Jobs ...` menu for a Beacon, or `View -> All Jobs` menu to see jobs across all beacons. 59 | 60 | ![alt text](../resources/async-bof.png) 61 | 62 | --- 63 | 64 | ## ⚠️ Limitations 65 | - `BeaconDataStore` and some internal APIs are not supported in async mode. 66 | 67 | --- 68 | 69 | ### References 70 | - [Blog post referencing Asynchronous BOFs](https://www.cobaltstrike.com/blog/cobalt-strike-411-shh-beacon-is-sleeping) 71 | - [Postex kit](https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/post-exploitation_postex-kit.htm) 72 | 73 | --- 74 | -------------------------------------------------------------------------------- /how-to/setup-visual-studio-bof.md: -------------------------------------------------------------------------------- 1 | # How-To: Setting Up Visual Studio for BOF Development 2 | 3 | This guide will show you how to configure Visual Studio (VS) for BOF (Beacon Object File) development. Visual Studio provides a powerful IDE for C/C++ with features like IntelliSense, build configuration, and debugging. 4 | 5 | --- 6 | 7 | ## 🎯 Goal 8 | - Create a Visual Studio project for BOF development 9 | - Use templates to simplify the process 10 | - Build .o (COFF) files compatible with Cobalt Strike and other C2s 11 | - Test your code outside of Beacon 12 | 13 | --- 14 | 15 | ## 🔧 Prerequisites 16 | - Visual Studio 2019 or later (Community Edition is fine) 17 | - C++ Desktop Development workload installed 18 | - Git (optional, for pulling templates) 19 | 20 | --- 21 | 22 | ## 📁 Step 1: Use the Fortra BOF Visual Studio Template 23 | Fortra provides a [Beacon Object File Visual Studio Template](https://github.com/Cobalt-Strike/bof-vs) designed to streamline the BOF development workflow. The project is preconfigured to: 24 | - Build a `.o` file when targeting for `Release` 25 | - Build a `.dll` or `.exe` for local testing when targeting for `Debug` 26 | - Include `beacon.h` 27 | 28 | Steps 29 | 30 | - Download their latest release ZIP. 31 | - Copy `bof-vs.zip` to `%USERPROFILE%\Documents\Visual Studio 2022\Templates\ProjectTemplates`. You do not need to extract it. 32 | 33 | --- 34 | 35 | ## 🛠️ Step 2: Create Your Project 36 | 37 | - Open Visual Studio. 38 | - Select `Create a new project`, search for `BOF` and you will see a BOF project template. 39 | ![alt text](../resources/image.png) 40 | 41 | --- 42 | 43 | ## ⚙️ Step 3: Explore Project Structure 44 | ![alt text](../resources/image-1.png) 45 | - `bof.c` — Your main BOF source file with the `go()` entry point. 46 | - `beacon.h` — Cobalt Strike Beacon API header. 47 | - `Makefile` - For building 48 | 49 | --- 50 | 51 | ## 🧪 Step 4: Test Locally 52 | 53 | The template allows running your BOF logic outside of Beacon: 54 | 55 | - Build the project in `x64/Debug` mode. 56 | - Start debugging in VS, or: 57 | - Run the generated `.exe` or `.dll` to simulate execution. 58 | 59 | > Great for debugging logic and argument parsing before loading into a C2. 60 | 61 | --- 62 | 63 | ## 📤 Step 5: Use the .o File in Beacon 64 | 65 | After building for `Release`, you'll find the `.o` file in your `x64/Release` directory. 66 | 67 | To execute it, in Cobalt Strike: 68 | ```powershell 69 | inline_execute mybof.o 70 | ``` 71 | 72 | --- 73 | 74 | ## ✅ Summary 75 | With the Visual Studio template from Fortra, you can: 76 | - Develop BOFs in a familiar IDE 77 | - Test code outside of C2 78 | - Export `.o` files with minimal effort 79 | 80 | --- -------------------------------------------------------------------------------- /tutorials/tutorial-building-your-first-bof.md: -------------------------------------------------------------------------------- 1 | # Tutorial: Building Your First Beacon Object File (BOF) 2 | 3 | This tutorial will walk you through creating your very first Beacon Object File (BOF), explaining the structure, build process, and how to run it in a C2 framework like Cobalt Strike. 4 | 5 | --- 6 | 7 | ## 🎯 Goal 8 | - Understand what a BOF is and why it's used 9 | - Write a simple "Hello, world" BOF 10 | - Compile it using MinGW or clang 11 | - Load it in a C2 framework (e.g. Cobalt Strike) 12 | 13 | --- 14 | 15 | ## 📦 Prerequisites 16 | 17 | - Linux, or Windows with WSL 18 | - `gcc` or `clang` (MinGW toolchain) 19 | - A C2 framework like Cobalt Strike, Sliver, or Havoc (for testing) 20 | - [beacon.h](https://github.com/Cobalt-Strike/bof_template/blob/main/beacon.h) — the header file that provides the Beacon API 21 | 22 | Install MinGW if using Linux: 23 | ```bash 24 | sudo apt install gcc-mingw-w64 -y 25 | ``` 26 | 27 | --- 28 | 29 | ## 🛠️ Step-by-Step 30 | 31 | ### 1. Download the Beacon header file 32 | Create a folder for your project 33 | 34 | ```bash 35 | mkdir hello-bof 36 | cd hello-bof 37 | ``` 38 | 39 | Download the Beacon header file 40 | ```bash 41 | wget https://github.com/Cobalt-Strike/bof_template/raw/refs/heads/main/beacon.h 42 | ``` 43 | 44 | ### 2. Create the Source File 45 | Create a file called `hello.c` with the following code: 46 | 47 | ```c 48 | #include 49 | #include "beacon.h" 50 | 51 | void go(char *args, int len) { 52 | BeaconPrintf(CALLBACK_OUTPUT, "Hello, world! This is my first BOF."); 53 | } 54 | ``` 55 | 56 | In case its not obvious, the code simply prints a hello world type message. 57 | 58 | > `go` is the entry point for all BOFs. 59 | 60 | --- 61 | 62 | ### 3. Compile the BOF 63 | Use MinGW to compile it into a `.o` COFF object: 64 | 65 | ```bash 66 | x86_64-w64-mingw32-gcc -c hello.c -o hello.o 67 | ``` 68 | 69 | > If targeting 32-bit systems: 70 | ```bash 71 | i686-w64-mingw32-gcc -c hello.c -o hello.o 72 | ``` 73 | 74 | You now have a lightweight, position-independent object file. 75 | 76 | --- 77 | 78 | ### 4. Load into Cobalt Strike (or other C2 framework you have access to) 79 | 80 | In a Cobalt Strike beacon: 81 | ```powershell 82 | inline_execute hello.o 83 | ``` 84 | 85 | ![Hello world BOF in CS Beacon](../resources/hello-bof-cs.png) 86 | 87 | Congratulations! You have made your first BOF and executed it. 88 | 89 | --- 90 | 91 | ## 🧠 Tips & Gotchas 92 | - Always use `BeaconPrintf` to output data 93 | - Do not call `printf` or other console APIs 94 | - Do not use global variables 95 | - Avoid long-running loops — BOFs should return quickly 96 | 97 | --- 98 | 99 | ## ✅ What You Learned 100 | - How BOFs work 101 | - How to write a basic one in C 102 | - How to compile it for use in a C2 103 | - Basic conventions for output and entry points 104 | 105 | --- 106 | 107 | Next up: Try the second tutorial that extends this prject with some arguments 108 | 109 | -------------------------------------------------------------------------------- /how-to/how-to-execute-bofs-in-c2.md: -------------------------------------------------------------------------------- 1 | # How-To: Run BOFs in Common C2 Frameworks 2 | 3 | This guide walks through how to execute Beacon Object Files (BOFs) across major C2 frameworks. While BOFs were originally built for Cobalt Strike, many open-source and commercial frameworks have since adopted them. Each C2 has different loading mechanisms, argument handling, and feature suppor. Always consult your C2 documentation to verify current syntax and API support. 4 | 5 | --- 6 | 7 | ## 🐝 Cobalt Strike 8 | 9 | ### 🔧 Setup 10 | - BOFs are supported natively 11 | - Requires `inline-execute` or `async-execute` 12 | 13 | ### ▶️ Run a BOF 14 | ```powershell 15 | inline-execute /path/to/bof.o "arg1 arg2" 16 | ``` 17 | 18 | ### ✅ Async Mode (v4.11+) 19 | See [How-To: Run BOFs asynchronously with `async-execute` in Cobalt Strike](../how-to/how-to-async-execute.md) 20 | 21 | --- 22 | 23 | ## 🐺 Sliver C2 24 | 25 | ### 🔧 Sliver BOF support 26 | - Sliver supports BOFs via extensions 27 | - Official extensions can be installed with `Armory` 28 | - Requires 32-bit and 64-bit `.o` files 29 | - Commands must be registered with `extension.json` 30 | 31 | ### ▶️ Run a BOF in Sliver 32 | > This article is incomplete. Refer to the documentation for details on how to execute BOFs. 33 | 34 | ### References 35 | - [Armory (Sliver Docs)](https://sliver.sh/docs?name=Armory) 36 | - [Sliver BOF (Redteaming.org)](https://www.redteaming.org/sliverbof.html) 37 | - [Feeding Sliver — Extension Guide (Medium)](https://medium.com/@l4rry/feeding-sliver-extension-guide-1c14fae42a2a) 38 | 39 | --- 40 | 41 | ## 👾 Havoc Framework 42 | 43 | ### 🔧 Setup 44 | - Havoc supports inline BOF execution 45 | - Use `.register_extension` to define commands (GUI or script) 46 | 47 | ### ▶️ Run a BOF 48 | ```bash 49 | inline-execute /path/to/bof.o "arg1 arg2" 50 | ``` 51 | 52 | --- 53 | 54 | ## 🧬 Meterpreter (Metasploit) 55 | 56 | ### 🔧 Setup 57 | - Load the `bofloader` extension 58 | - Ensure `.o` file is compatible with CS-style BOFs 59 | 60 | ### ▶️ Run a BOF 61 | Examples with and without arguments. 62 | ```bash 63 | meterpreter > load bofloader 64 | meterpreter > execute_bof /path/to/bof.o 65 | meterpreter > execute_bof --format-string Zs /path/to/bof.o c:\\ 0 66 | ``` 67 | 68 | ### References 69 | - [Operator's Guide to the Meterpreter BOFLoader](https://trustedsec.com/blog/operators-guide-to-the-meterpreter-bofloader) 70 | 71 | --- 72 | 73 | ## 🎩 Outflank OST 74 | 75 | ### 🔧 Setup 76 | - BOFs integrated as part of OST internal toolset 77 | - Can be executed with `execute_bof` 78 | - BOFs are exposed through Python scripts. 79 | - BOFs are uploaded to the implant from a browser window (not specified by path like with CS). 80 | 81 | ### ▶️ Run a BOF 82 | ```powershell 83 | execute_bof 84 | execute_bof Zz arg1 arg2 85 | ``` 86 | 87 | > No direct `inline_execute`. Uses internal resolution and configuration. 88 | 89 | --- 90 | 91 | ## 🧠 Mythic (Xenon Agent) 92 | TODO 93 | 94 | See [Forge on Github](https://github.com/MythicAgents/forge) 95 | 96 | --- 97 | 98 | ## 🦊 Brute Ratel (BRC4) 99 | TODO 100 | 101 | --- 102 | 103 | ## 🦉 Nighthawk 104 | TODO 105 | 106 | --- 107 | 108 | Want to add usage for another C2? Submit a PR! 109 | -------------------------------------------------------------------------------- /reference/c2-framework-bof-support.md: -------------------------------------------------------------------------------- 1 | # Reference: BOF Support Across C2 Frameworks 2 | 3 | This reference provides a comprehensive overview of how Beacon Object Files (BOFs) are supported across major Command and Control (C2) frameworks. It covers implementation details, compatibility, execution methods, and key differences to help red team operators understand how BOFs work in different environments. 4 | 5 | 6 | --- 7 | ## 🧭 BOF Support Overview by C2 8 | 9 | | C2 Framework | BOF Support | Platform(s) | Async Execution | Beacon API Compatibility | Argument Handling | Notes | Docs | 10 | |------------------|-------------|-------------|-----------------|--------------------------|-------------------|-------|------| 11 | | **Cobalt Strike**| ✅ Native | Windows | ✅ `async-execute` | ✅ Full API support | `BeaconDataParse` | Original BOF host. Mature and stable. | 12 | | **Sliver** | ✅ Native | Win/Linux | ❌ | ⚠️ Partial | Format string | Requires `extension.json` for BOF commands. | [Documentation](https://sliver.sh/docs?name=BOF+and+COFF+Support) 13 | | **Havoc** | ✅ Native | Windows | ❌ | ⚠️ Partial (Beacon-style) | Format string | Uses inline-execute or register command. | [Documentation](https://havocframework.com/docs/object_files) 14 | | **Meterpreter** | ✅ Native | Windows | ❌ | ⚠️ Partial | Format string | `bofloader` extension added in 2023. | [Documentation](https://docs.metasploit.com/docs/using-metasploit/advanced/meterpreter/meterpreter-executebof-command.html) 15 | | **Outflank OST** | ✅ Native | Windows | ❌ | ⚠️ Partial (custom) | Hardcoded/config | Custom loader used in enterprise red teams. | 16 | | **Brute Ratel** | ✅ Native | Windows | ✅ | ✅ Full (Beacon-style) | `BeaconDataParse` | Commercial tool with async BOF threading. | 17 | | **Nighthawk** | ✅ Native | Windows | ✅ | ✅ Full (internal runtime) | `BeaconDataParse` | High-end C2 focused on stealth and OPSEC. | 18 | | **Mythic (Xenon)**| ✅ Partial | Windows | ❌ | ⚠️ Minimal | Manual/C-style | BOF support added via `execute_bof`. | 19 | | **AdaptixC2**| ✅ Partial | Windows | ❌ | ⚠️ Minimal | Manual/C-style | BOF support added via `execute_bof`. | 20 | --- 21 | 22 | --- 23 | 24 | ## 🔍 Key Differences 25 | 26 | ### Execution Model 27 | - **Synchronous Execution**: Most frameworks (Sliver, Havoc, Meterpreter, OST, Mythic) run BOFs in the main agent thread, which blocks until completion. 28 | - **Asynchronous Execution**: Cobalt Strike (4.11+), Brute Ratel, and Nighthawk support running BOFs in separate threads, allowing the agent to remain responsive. 29 | 30 | ### API Compatibility 31 | - **Full API**: Cobalt Strike, Brute Ratel, and Nighthawk implement the complete Beacon API. 32 | - **Partial API**: Sliver, Havoc, Meterpreter, and OST implement core functions but may lack some advanced features. 33 | - **Minimal API**: Mythic (Xenon) provides basic functionality but requires more adaptation for complex BOFs. 34 | 35 | ### Argument Handling 36 | - **BeaconDataParse**: Cobalt Strike, Brute Ratel, and Nighthawk use the standard Beacon argument parsing. 37 | - **Format Strings**: Sliver, Havoc, and Meterpreter use format string-based argument parsing. 38 | - **Custom**: OST and some others use custom argument handling mechanisms. 39 | 40 | ### Platform Support 41 | - **Windows-only**: Most frameworks only support BOFs on Windows. 42 | - **Cross-platform**: Sliver stands out by supporting BOFs on both Windows and Linux. 43 | 44 | --- 45 | 46 | ## 🔗 Related Resources 47 | - [`reference/loaders-catalog.md`](./loaders-catalog.md) 48 | 49 | ## Contributions 50 | Please contribute by adding PRs to track new C2s adopting BOF support! 51 | -------------------------------------------------------------------------------- /scripts/generate_md.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | import argparse 5 | import sys 6 | from urllib.parse import urlparse 7 | 8 | def get_repo_info(repo_url): 9 | """ 10 | Fetches repository description using the GitHub API. 11 | Returns username, repo_name, description or None on error. 12 | """ 13 | parsed_url = urlparse(repo_url) 14 | if parsed_url.netloc.lower() != 'github.com': 15 | print(f"Error: URL '{repo_url}' is not a valid GitHub repository URL.", file=sys.stderr) 16 | return None, None, None 17 | 18 | path_parts = parsed_url.path.strip('/').split('/') 19 | if len(path_parts) < 2: 20 | print(f"Error: Could not parse username/repository from URL path '{parsed_url.path}'.", file=sys.stderr) 21 | return None, None, None 22 | 23 | username = path_parts[0] 24 | repo_name = path_parts[1] 25 | api_url = f"https://api.github.com/repos/{username}/{repo_name}" 26 | 27 | try: 28 | response = requests.get(api_url, timeout=10) 29 | response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx) 30 | 31 | data = response.json() 32 | description = data.get("description") # Use .get() to handle missing key safely 33 | if description is None: 34 | description = "[No description provided]" # Provide a placeholder 35 | elif not description.strip(): # Handle empty string description 36 | description = "[Description is empty]" 37 | 38 | return username, repo_name, description 39 | 40 | except requests.exceptions.Timeout: 41 | print(f"Error: Request timed out while fetching data for {repo_url}.", file=sys.stderr) 42 | return None, None, None 43 | except requests.exceptions.HTTPError as e: 44 | if response.status_code == 404: 45 | print(f"Error: Repository not found at {repo_url} (404).", file=sys.stderr) 46 | elif response.status_code == 403: 47 | print(f"Error: API rate limit likely exceeded or forbidden access (403).", file=sys.stderr) 48 | else: 49 | print(f"Error: HTTP error fetching data for {repo_url}: {e}", file=sys.stderr) 50 | return None, None, None 51 | except requests.exceptions.RequestException as e: 52 | print(f"Error: Could not connect or fetch data for {repo_url}: {e}", file=sys.stderr) 53 | return None, None, None 54 | except Exception as e: # Catch potential JSON decoding errors or others 55 | print(f"Error: An unexpected error occurred: {e}", file=sys.stderr) 56 | return None, None, None 57 | 58 | 59 | def format_markdown_row(url, username, repo_name, description): 60 | """Formats the data into the desired Markdown table row.""" 61 | stars_badge = f"![](https://img.shields.io/github/stars/{username}/{repo_name}?label=&style=flat)" 62 | commit_badge = f"![](https://img.shields.io/github/last-commit/{username}/{repo_name}?label=&style=flat)" 63 | 64 | # Ensure the original URL is used in the link 65 | markdown_link = f"[{repo_name}]({url})" 66 | 67 | # Escape pipe characters within the description if necessary (optional, but good practice) 68 | safe_description = description.replace('|', '\\|') 69 | 70 | return f"| {markdown_link} | {safe_description} | {stars_badge} | {commit_badge} |" 71 | 72 | 73 | if __name__ == "__main__": 74 | parser = argparse.ArgumentParser(description="Generate a Markdown table row for a GitHub repository.") 75 | parser.add_argument("repo_url", help="The full URL of the GitHub repository (e.g., https://github.com/user/repo)") 76 | args = parser.parse_args() 77 | 78 | repo_url = args.repo_url 79 | username, repo_name, description = get_repo_info(repo_url) 80 | 81 | if username and repo_name: # Check if we got valid data back 82 | markdown_row = format_markdown_row(repo_url, username, repo_name, description) 83 | print(markdown_row) 84 | else: 85 | # Error message was already printed to stderr by get_repo_info 86 | sys.exit(1) # Exit with a non-zero status to indicate failure -------------------------------------------------------------------------------- /reference/reference-bof-dev.md: -------------------------------------------------------------------------------- 1 | # 🛠️ Reference: Developer Tooling & Templates 2 | These are templates and tools used in BOF development. 3 | 4 | ## Templates 5 | | Tool | Description | Stars | Last commit | 6 | |------|-------------|-------|-------------| 7 | | [bof-vscode](https://github.com/brmkit/bof-vscode) | vscode development environment for Beacon Object Files (BOFs) | ![](https://img.shields.io/github/stars/brmkit/bof-vscode?label=&style=flat) | ![](https://img.shields.io/github/last-commit/brmkit/bof-vscode?label=&style=flat) | 8 | | [Beacon Object File Visual Studio Template (bof-vs)](https://github.com/Cobalt-Strike/bof-vs) | A complete Visual Studio environment for writing and debugging BOFs.
This is an official template from the Cobalt Strike team. | ![](https://img.shields.io/github/stars/Cobalt-Strike/bof-vs?label=&style=flat) | ![](https://img.shields.io/github/last-commit/Cobalt-Strike/bof-vs?label=&style=flat) 9 | | [bof_template](https://github.com/Cobalt-Strike/bof_template) | Minimal working BOF template with Beacon API use.
This is a official template from the Cobalt Strike team. | ![](https://img.shields.io/github/stars/Cobalt-Strike/bof_template?label=&style=flat) | ![](https://img.shields.io/github/last-commit/Cobalt-Strike/bof_template?label=&style=flat) 10 | | [linux_bof_template](https://github.com/outflanknl/linux_bof_template) | Boilerplate to write Linux-compatible BOFs (ELF) from Outflank. | ![](https://img.shields.io/github/stars/outflanknl/linux_bof_template?label=&style=flat) | ![](https://img.shields.io/github/last-commit/outflanknl/linux_bof_template?label=&style=flat) 11 | | [bof-vs-template](https://github.com/nccgroup/nccfsas/tree/main/Tools/bof-vs-template) | Visual Studio template for building BOFs (part of nccfsas) | ![](https://img.shields.io/github/stars/nccgroup/nccfsas?label=&style=flat) | ![](https://img.shields.io/github/last-commit/nccgroup/nccfsas?label=&style=flat) 12 | | [Visual-Studio-BOF-template](https://github.com/securifybv/Visual-Studio-BOF-template) | Visual Studio template to create Cobalt Strike BOFs | ![](https://img.shields.io/github/stars/securifybv/Visual-Studio-BOF-template?label=&style=flat) | ![](https://img.shields.io/github/last-commit/securifybv/Visual-Studio-BOF-template?label=&style=flat) 13 | 14 | ## Supporting tools 15 | | Tool | Description | Stars | Last commit | 16 | |------|-------------|-------|-------------| 17 | | [BOF_NativeAPI_Definitions-VSCode](https://github.com/EspressoCake/BOF_NativeAPI_Definitions-VSCode) | A VSCode plugin to assist with BOF development. | ![](https://img.shields.io/github/stars/EspressoCake/BOF_NativeAPI_Definitions-VSCode?label=&style=flat) | ![](https://img.shields.io/github/last-commit/EspressoCake/BOF_NativeAPI_Definitions-VSCode?label=&style=flat) | 18 | | [BOF Extension](https://www.youtube.com/watch?v=oWss4Ac9Pl8) | Video demonstrating the [BOF_NativeAPI_Definitions-VSCode](https://github.com/EspressoCake/BOF_NativeAPI_Definitions-VSCode) repo. 19 | | [BOF_Development_Docker](https://github.com/EspressoCake/BOF_Development_Docker) | A VSCode devcontainer for development of COFF files with batteries included. | ![](https://img.shields.io/github/stars/EspressoCake/BOF_Development_Docker?label=&style=flat) | ![](https://img.shields.io/github/last-commit/EspressoCake/BOF_Development_Docker?label=&style=flat) | 20 | | [BOF Patcher](https://github.com/Octoberfest7/Enumprotections_BOF?tab=readme-ov-file#compilation) | A proprietary tool to patch symbols post-compilation. Provided in the BOF Development and Tradecraft course.| ![](https://img.shields.io/github/stars/Octoberfest7/Enumprotections_BOF?label=&style=flat) | ![](https://img.shields.io/github/last-commit/Octoberfest7/Enumprotections_BOF?label=&style=flat) 21 | 22 | ## Development for other languages 23 | | [Speedloader: Rust COFF Loader Template/Library ](https://github.com/aliwioiod/speedloader) | This is a Rust template/library designed for implementing your own COFF loader.| ![](https://img.shields.io/github/stars/aliwioiod/speedloader?label=&style=flat) | ![](https://img.shields.io/github/last-commit/aliwioiod/speedloader?label=&style=flat) 24 | | [linux_bof](https://github.com/chryzsh/linux_bof) | Fork of Outflank’s Linux BOF template | ![](https://img.shields.io/github/stars/chryzsh/linux_bof?label=&style=flat) | ![](https://img.shields.io/github/last-commit/chryzsh/linux_bof?label=&style=flat) 25 | | [bof_oxide](https://github.com/KickedDroid/bof_oxide) | A POC or Template whatever for developing BOFs for Sliver, Havoc, Cobalt Strike or most COFFLoaders in Rust. | ![](https://img.shields.io/github/stars/KickedDroid/bof_oxide?label=&style=flat) | ![](https://img.shields.io/github/last-commit/KickedDroid/bof_oxide?label=&style=flat) | -------------------------------------------------------------------------------- /explanation/bof_loader_explainer.md: -------------------------------------------------------------------------------- 1 | # Explanation: BOF Loaders and Execution Engines 2 | 3 | BOF loaders are specialized programs or modules that know how to load and execute Beacon Object Files (.o files) outside or inside a C2 framework. While BOFs are most commonly used in Cobalt Strike, a growing number of loaders enable BOFs to be executed: 4 | 5 | - Outside of a Beacon context (e.g. for debugging) 6 | - Inside custom C2 agents 7 | - On Linux or cross-platform implants 8 | 9 | This article explores popular BOF loaders and execution strategies. 10 | 11 | --- 12 | 13 | ## 🧰 What is a BOF Loader? 14 | A BOF loader is a runtime or tool that: 15 | - Parses a COFF object file (.o) 16 | - Resolves external function imports (e.g. `BeaconPrintf`, `kernel32!CreateFileA`, etc.) 17 | - Allocates memory and relocates code 18 | - Calls the BOF entrypoint function (typically `go()`) 19 | 20 | --- 21 | 22 | ## 🔄 Native vs External BOF Execution 23 | 24 | | Loader Type | Description | Example | 25 | |-------------|--------------------------------------------|-------------------------| 26 | | **Internal**| Built into a C2 framework | Cobalt Strike, Sliver | 27 | | **External**| Standalone tool to test or host BOFs | COFFLoader, BOF.NET | 28 | | **Cross-Platform** | Loads ELF/COFF for Linux/Mac implants | ELFLoader, Linux BOFs | 29 | 30 | --- 31 | 32 | ## 🔧 Notable BOF Loaders 33 | 34 | ### 🐝 **Cobalt Strike (Native Loader)** 35 | - Uses a proprietary COFF parser 36 | - Maps functions via `beacon.h`-defined APIs 37 | - Supports `inline-execute` to run BOFs directly 38 | - Loads BOFs into Beacon’s memory and executes them on its thread 39 | 40 | ### 📦 **COFFLoader (TrustedSec)** 41 | - Standalone command-line tool to execute BOFs outside Cobalt Strike 42 | - Implements core Beacon APIs (output, argument parsing, memory) 43 | - Great for testing BOFs without launching a full C2 44 | - [COFFLoader on GitHub](https://github.com/trustedsec/COFFLoader) 45 | 46 | ### 🧪 **BOF.NET** 47 | - Allows writing BOFs in C#/.NET 48 | - Embeds a .NET runtime inside a native BOF loader 49 | - Supports a `BeaconObject` interface that gets called like a normal BOF 50 | - [BOF.NET on GitHub](https://github.com/CCob/BOF.NET) 51 | 52 | ### 🐧 **ELFLoader (TrustedSec)** 53 | - Linux-native loader for `.o` (ELF) files 54 | - Useful for testing Linux-based BOFs 55 | - Dynamically links symbols via libc 56 | - Compatible with x86 and x86_64 Linux 57 | - [ELFLoader on GitHub](https://github.com/trustedsec/ELFLoader) 58 | 59 | ### 🧬 **bof-launcher and cli4bofs (Z-Labs)** 60 | - Allows writing BOFs in C and [Zig](https://ziglang.org/) 61 | - Supports Windows COFF (x86_64, x86) and Linux ELF (x86_64, x86, arm, aarch64) 62 | - Provides reusable library with simple [C API for launching BOFs](https://github.com/The-Z-Labs/bof-launcher/blob/main/bof-launcher/src/bof_launcher_api.h) 63 | - cli4bofs is standalone command-line tool for launching, injecting and organizing BOFs outside Cobalt Strike 64 | - Supports `exec` and `inject` commands to run/inject BOFs directly 65 | - [bof-launcher on GitHub](https://github.com/The-Z-Labs/bof-launcher) 66 | - [cli4bofs on GitHub](https://github.com/The-Z-Labs/cli4bofs) 67 | 68 | ### 🧬 **Custom Agent Loaders (e.g., Xenon, Havoc, Brute Ratel)** 69 | - Many modern C2s implement their own BOF loaders: 70 | - **Xenon** (Mythic) — parses and executes `.o` files directly 71 | - **Havoc** — parses and executes `.o` files directly 72 | - **Brute Ratel** — ships with its own loader 73 | - **Outflank C2** — ships with its own loader 74 | - Most follow the CS convention of looking for `go(char*, int)` 75 | 76 | --- 77 | 78 | ## Developing your own loader 79 | It is possible to write your own loader. Some guidance has been written on this specifically, please refer to: 80 | - [Reference: BOF Loaders Catalog](../reference/loaders-catalog.md) for some reference projects, and 81 | - [Reference: Blog Posts and Research on BOF Development](../reference/loaders-catalog.md) which contains articles on BOF and COFF loader development. 82 | - [Reference: BOF Development Training and Courses](../reference/bof-training-courses.md) which lists some training courses that involve loader development. 83 | 84 | ## 🧠 Takeaways 85 | - BOF loaders are key to portability and flexibility 86 | - COFFLoader and ELFLoader are ideal for testing BOFs outside of C2 87 | - C2s implement their own BOF engines — be aware of differences in APIs and argument handling 88 | - BOF.NET introduces a high-level approach for .NET developers 89 | 90 | --- 91 | 92 | ## 🔗 Related articles 93 | - [`how-to/setup-visual-studio-for-bof-development.md`](../how-to/setup-visual-studio-bof.md) 94 | - [`reference/loaders-catalog.md`](../reference/loaders-catalog.md) 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # awesome-bof 2 | > 🧠 The ultimate, community-curated resource for Beacon Object Files (BOFs) — tutorials, how-tos, deep dives, and reference materials. 3 | 4 | ## 🎯 Goals 5 | **Be the go-to source for everything related to BOFs** 6 | - Help both Red and Blue Teams understand the mechanics of BOFs 7 | - Make BOF development, testing and execution even more accessible 8 | - Find public BOF projects, tools, loaders, research and training 9 | 10 | --- 11 | 12 | ### 🧪 Tutorials — *Learning by Doing* 13 | - [Building Your First BOF](./tutorials/tutorial-building-your-first-bof.md) 14 | - [Building Your Second BOF](./tutorials/tutorial-building-your-second-bof.md) 15 | 16 | ### 🛠️ How-To Guides — *Solving Specific Tasks* 17 | - [Set Up Visual Studio for BOF Development](./how-to/setup-visual-studio-bof.md) 18 | - [Set Up VSCode for BOF Development](./how-to/setup-vscode-bof.md) 19 | - [Execute BOFs in C2 frameworks](./how-to/how-to-execute-bofs-in-c2.md) 20 | - [Running BOFs Asynchronously in Cobalt Strike](./how-to/how-to-async-execute.md) 21 | 22 | ### 📖 Explanation — *Understanding Concepts* 23 | - [What are BOFs?](./explanation/explanation-what-are-bofs.md) 24 | - [C2 Framework BOF Support](./reference/c2-framework-bof-support.md) 25 | - [BOF Internals: Structure, API, Lifecycle](./explanation/bof-internals-explained.md) 26 | - [BOF Loaders and Execution Engines](./explanation/bof_loader_explainer.md) 27 | 28 | ### 🧾 Reference — *Reliable Information Lookups* 29 | - [Public BOF Repositories Catalog](./reference/bofs-catalog.md) 30 | - [BOF and COFF loaders](./reference/loaders-catalog.md) 31 | - [C2 Framework BOF Support](./reference/c2-framework-bof-support.md) 32 | - [Developer Tooling & Templates](./reference/reference-bof-dev.md) 33 | - [Blog Posts and Research on BOF Development](./reference/bof-blogs-and-research.md) 34 | - [BOF Training Courses](./reference/bof-training-courses.md) 35 | 36 | --- 37 | 38 | ## Community todo list 39 | These are articles where changes are appropriate, or not yet written. Hopefully the community would like to contribute to this project by tackling any of these or other ideas for the project. 40 | 41 | ### Change ideas 42 | - Continue expanding the [Public BOF Repositories Catalog](./reference/bofs-catalog.md) with new BOFs coming out 43 | - Expand the [Public BOF Repositories Catalog](./reference/bofs-catalog.md) with Sliver extensions and BOFs written for Havoc 44 | - Expand [Execute BOFs in C2 frameworks](./how-to/how-to-execute-bofs-in-c2.md) with more detail for each C2 framework 45 | 46 | ### New article ideas 47 | - Explanation article about BOF detection strategies 48 | - How-to article demonstrating how to detect BOF execution 49 | - How-to article on intermediate level BOF development 50 | - How-to article on advanced BOF development 51 | - How-to article on writing aggressor scripts for BOF support in CS 52 | - How-to article on writing scripts for BOF support in Sliver and Havoc 53 | - How-to article for developing and running BOF.NET BOFs 54 | 55 | ## 🤝 Contributing 56 | Want to update a reference page with new BOFs? Or write a new article? Or make changes? 57 | - Open a pull request 58 | - Follow the structure of the article in the relevant folder (`tutorials/`, `how-to/`, etc.) 59 | - Include links, descriptions, and credit where due 60 | - Or, submit an issue with whatever you would like to see changed 61 | 62 | This repo thrives on contributions from both red and blue teams in the community. I hope we can apply the structure I have created to add new information as it appears. The entire project is written in markdown, making it easy for anyone to fork, modify and submit pull requests or issues. 63 | 64 | *Note*: I have used AI to help me write and structure some the articles. I have reviewed all the information, but if mistakes have snuck in, its probably this human's fault, rather than AI slop. Again however, issues and pull requests are very welcome to correct any wrong information. 65 | 66 | --- 67 | 68 | ## About Diátaxis 69 | This project follow the approach of the [Diátaxis](https://diataxis.fr/) documentation framework. Diátaxis identifies four distinct needs, and four corresponding forms of documentation - tutorials, how-to guides, technical reference and explanation. All articles in this repository if therefore organised around the structures of those needs. This ensures high-quality, easy to discover and use documentation. 70 | 71 | ![Diátaxis framework](./resources/diataxis.png) 72 | 73 | --- 74 | 75 | ## Credit 76 | - All the awesome BOF and loader developers that publish their BOFs on Github 77 | - The Cobalt Strike team for pushing the direction of BOF development since 2020 78 | - TrustedSec for all their awesome blog posts, BOF collections and training 79 | - Zero-point for their awesome course on BOF development 80 | -------------------------------------------------------------------------------- /explanation/explanation-bof-args.md: -------------------------------------------------------------------------------- 1 | # Explanation: BOF Arguments and Argument Parsing 2 | 3 | Beacon Object Files (BOFs) often require input from the operator — such as hostnames, usernames, file paths, or raw data — to operate effectively. However, because BOFs are small, position-independent C object files with no standard input or command-line environment, they rely on custom argument-passing mechanisms implemented by the C2 framework. 4 | 5 | This article explains how arguments are passed into BOFs, how they are parsed inside different C2 frameworks, and provides a reference for Cobalt Strike’s argument format specifiers. If you are looking for how to execute BOFs in different C2 frameworks, see [How-To: Run BOFs in Common C2 Frameworks](../how-to/how-to-execute-bofs-in-c2.md). 6 | 7 | --- 8 | 9 | ## 🧠 Core Concept 10 | 11 | A BOF has one required entrypoint: 12 | ```c 13 | void go(char *args, int length); 14 | ``` 15 | 16 | - `args`: a pointer to the raw argument data buffer 17 | - `length`: the size of the data buffer in bytes 18 | 19 | The actual format and encoding of `args` varies depending on the C2 framework. 20 | 21 | --- 22 | 23 | ## 🐝 Cobalt Strike Argument Parsing 24 | 25 | Cobalt Strike offers a full API for structured argument parsing through the `BeaconDataParse` family of functions. This allows complex argument formats including integers, strings, blobs, and even nested data. 26 | 27 | ### General principles 28 | - Args are packed in binary format using bof_pack function 29 | - Args are unpacked via functions (eg BeaconDataParse and BeaconDataExtract) exported by beacon.h 30 | - Args are unpacked in the same order they were packed 31 | 32 | ### ✅ Example 33 | This is a simple example just to demonstrate arg parsing. 34 | ```c 35 | #include "beacon.h" 36 | 37 | void go(char *args, int len) { 38 | datap parser; 39 | BeaconDataParse(&parser, args, len); 40 | 41 | char *host = BeaconDataExtract(&parser, NULL); 42 | int port = BeaconDataInt(&parser); 43 | 44 | BeaconPrintf(CALLBACK_OUTPUT, "Host: %s, Port: %d", host, port); 45 | } 46 | ``` 47 | 48 | ### 💡 Usage in Aggressor Script 49 | Pay attention to the `bof_pack` function. 50 | 51 | ```aggressor 52 | # Register a new Beacon command called 'connect_test' 53 | beacon_command_register( 54 | "connect_test", 55 | "Test BOF with hostname and port arguments", 56 | "Usage: connect_test [hostname] [port]" 57 | ); 58 | 59 | # Define the alias that will be called when the command is used 60 | alias connect_test { 61 | # $1 = Beacon ID 62 | # $2 = hostname argument 63 | # $3 = port argument 64 | 65 | # Validate arguments 66 | if ($2 eq "" || $3 eq "") { 67 | berror($1, "Please provide both hostname and port arguments"); 68 | return; 69 | } 70 | 71 | # Parse port as integer 72 | local('$port'); 73 | $port = int($3); 74 | 75 | # Pack arguments using format specifiers: 76 | # - 'Z' for null-terminated string (hostname) 77 | # - 'i' for 4-byte integer (port) 78 | $args = bof_pack($1, "Zi", $2, $port); 79 | 80 | # Log what we're doing 81 | blog($1, "Executing connect_test BOF with Host: $2, Port: $port"); 82 | 83 | # Execute the BOF with our packed arguments 84 | # Assuming the BOF file is in the same directory as the script 85 | beacon_inline_execute($1, script_resource("connect_test.o"), $args); 86 | } 87 | 88 | ``` 89 | 90 | ### Usage from Beacon 91 | ```powershell 92 | inline-execute bof.o example.com 8080 93 | ``` 94 | Cobalt Strike internally packs these arguments into a buffer using its scripting language. 95 | 96 | --- 97 | 98 | ## 🔤 Format Specifiers for Argument Packing 99 | 100 | When using Aggressor Script or a compatible scripting interface to invoke BOFs, arguments are packed into a binary blob using format strings. 101 | 102 | | Specifier | Meaning | C Type | 103 | |-----------|----------------------------------|------------------------| 104 | | `Z` | Null-terminated string | `char *` | 105 | | `z` | Binary blob (length-prefixed) | `char *, int` | 106 | | `i` | 4-byte integer | `int` | 107 | | `b` | Boolean (1-byte integer) | `char` or `int` | 108 | | `r` | Raw buffer (returns length too) | `char *, int` | 109 | 110 | > These format specifiers tell the loader how to serialize and pass values to the BOF. 111 | 112 | --- 113 | 114 | 115 | ## ⚠️ Pitfalls 116 | 117 | - 🧨 **No bounds checking**: If you parse arguments manually, always validate input length. 118 | - 🧵 **Thread-safety**: Do not store parsed args in static/global memory. 119 | - 🧪 **Test with malformed input**: Make your BOFs resilient to invalid arg formats. 120 | - 🧱 **Avoid assumptions**: Not every C2 packs arguments the same way — always test per framework. 121 | 122 | --- 123 | 124 | ## 🧪 Testing Argument Parsing 125 | 126 | Use standalone loaders like [`COFFLoader`](https://github.com/trustedsec/COFFLoader). 127 | 128 | --- 129 | -------------------------------------------------------------------------------- /explanation/bof-internals-explained.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "BOF Internals – How Beacon Object Files Work" 3 | parent: "Explanation" 4 | grand_parent: "awesome-bof" 5 | nav_order: 2 6 | # ⚠️ remove inline comments after the values; YAML stops reading at the # 7 | --- 8 | 9 | # Explanation: BOF Internals – How Beacon Object Files Work 10 | 11 | Beacon Object Files (BOFs) are small compiled C programs designed to run directly within the memory space of a C2 agent (like Cobalt Strike’s Beacon). This execution model allows stealthy, fast, and fileless tasking of post-exploitation actions without creating new processes or touching disk. 12 | 13 | This article explains the internal structure, lifecycle, memory model, and API integration of a typical BOF. 14 | 15 | --- 16 | 17 | ## 🧱 1. BOF Structure Overview 18 | 19 | - **Format:** COFF (Common Object File Format) 20 | - **Compiled From:** C source code using `gcc`/`clang` (typically MinGW for Windows) 21 | - **Entrypoint:** `void go(char *args, int len)` 22 | - **Output API:** `BeaconPrintf(CALLBACK_OUTPUT, "message")` 23 | 24 | BOFs are not executables — they lack a PE header and are never intended to run as standalone binaries. Instead, they are loaded into a running process (e.g. Beacon) and executed in-memory. 25 | 26 | --- 27 | 28 | ## 🧬 2. Lifecycle of a BOF 29 | 30 | 1. **Authoring:** Write a small C function that uses Beacon APIs (e.g. for printing or parsing arguments). 31 | 2. **Compilation:** Compile to `.o` (COFF object file) using `-c` flag: 32 | ```bash 33 | x86_64-w64-mingw32-gcc -c mybof.c -o mybof.o 34 | ``` 35 | 3. **Loading:** The C2 (e.g. Cobalt Strike) injects the object file into memory and parses the COFF format. 36 | 4. **Linking/Resolution:** The loader resolves any function symbols (e.g. `BeaconPrintf`, `memcpy`, etc.). 37 | 5. **Execution:** The C2 calls the `go()` function and passes argument data. 38 | 6. **Output Handling:** BOFs must output data using Beacon API functions — no `printf()` or `stdout`. 39 | 7. **Cleanup:** Memory is optionally freed. Some C2s auto-clean the job after BOF finishes. 40 | 41 | --- 42 | 43 | ## 🧠 3. Function Naming and Dynamic Linking 44 | 45 | All external function calls must be **statically declared** using special macros or headers (e.g. `beacon.h`). C2 frameworks typically do one of the following: 46 | 47 | - **Match symbol names:** Expect functions like `BeaconPrintf` to exist in the `.o` file 48 | - **Patch symbol table:** New reesarch reveals it is possible rewrite symbols after compilation (e.g. using `objcopy` techniques), see [Writing Beacon Object Files Without DFR](https://blog.cybershenanigans.space/posts/writing-bofs-without-dfr/) 49 | - **Manual linking:** In some frameworks (like Sliver or Mythic), function pointers are passed manually 50 | 51 | --- 52 | 53 | ## 🧵 4. Threading and Execution Context 54 | 55 | - **Cobalt Strike (Sync):** BOF runs inline on the Beacon thread 56 | - **Cobalt Strike (Async):** Using `async-execute`, each BOF runs in a new thread 57 | - **Sliver / Havoc / Meterpreter:** BOFs typically run synchronously 58 | - **Memory Space:** BOFs inherit Beacon’s context — same PID, token, architecture, etc. 59 | - **Stack Constraints:** Keep memory use minimal; avoid recursion and large stack frames 60 | 61 | --- 62 | 63 | ## 📦 5. Argument Handling 64 | 65 | ### Cobalt Strike: 66 | ```c 67 | datap parser; 68 | BeaconDataParse(&parser, args, len); 69 | char *input = BeaconDataExtract(&parser, NULL); 70 | ``` 71 | 72 | ### Sliver, Meterpreter, Havoc: 73 | - Arguments passed as a format string (e.g. `"arg1 arg2"`) and parsed manually 74 | 75 | --- 76 | 77 | ## 🔐 6. Beacon APIs Used in BOFs 78 | 79 | | Function | Purpose | 80 | |----------|---------| 81 | | `BeaconPrintf()` | Send output back to C2 GUI or job window | 82 | | `BeaconDataParse()` | Parse incoming arguments | 83 | | `BeaconFormat/Output()` | Build dynamic output buffers | 84 | | `BeaconUseToken()` | Set token for impersonation | 85 | | `BeaconGetSpawnTo()` | Retrieve configured sacrificial process | 86 | 87 | Note: Not all C2s implement all Beacon APIs. Some, like async loaders, may not support certain calls. 88 | 89 | --- 90 | 91 | ## ⚠️ 7. Common Pitfalls 92 | 93 | - ❌ Using `printf`, `malloc`, or globals 94 | - ❌ Expecting console or stdin/stdout access 95 | - ❌ Writing large or long-running loops (blocks the agent thread) 96 | - ❌ Assuming BOFs are DLLs — they’re not 97 | 98 | --- 99 | 100 | ## ✅ 8. Best Practices 101 | 102 | - Keep BOFs small and purpose-built 103 | - Always test outside C2 with loaders like `COFFLoader` 104 | - Use `BeaconPrintf` for all output 105 | - Test 32-bit and 64-bit variants 106 | - Avoid using C++ STL or exceptions 107 | 108 | --- 109 | 110 | ## 🧠 Summary 111 | BOFs are minimalistic, thread-safe C routines compiled as COFF files. They rely on the C2's loader to inject, resolve, and execute them. When written properly, they provide low-overhead, high-stealth capabilities for red team operations — especially when combined with async execution and direct syscalls. 112 | 113 | For examples and loaders, see: 114 | - [`reference/bofs-catalog.md`](../reference/bofs-catalog.md) 115 | - [`reference/loaders-catalog.md`](../reference/loaders-catalog.md) 116 | 117 | -------------------------------------------------------------------------------- /how-to/setup-vscode-bof.md: -------------------------------------------------------------------------------- 1 | # How-To: Set Up VSCode for BOF Development 2 | 3 | This guide will show you how to configure VSCode (not Visual Studio) for BOF (Beacon Object File) development. This is useful if you are developing in VSCode on Linux System as opposed to using Visual Studio on Windows. 4 | 5 | > VSCode stands for Visual Studio Code. To not making this any more confusing than necessary, this article will refer to it as VSCode. 6 | 7 | --- 8 | 9 | ## 🎯 Goal 10 | - Install the required extensions in VSCode 11 | - Install BOF definitions that assist with BOF development 12 | - Use templates to simplify the process 13 | 14 | --- 15 | 16 | ## 🔧 Prerequisites 17 | - VSCode installed on a Linux system 18 | - This could work on Windows too, but the guide is tested on Linux only 19 | 20 | --- 21 | 22 | 23 | ### The problems we face 24 | Once you start developing BOFs in VSCode you will notice that the formatter goes wild because you are not writing proper C and are doing all kinds of shenanings it does not expect. 25 | 26 | ![alt text](./how-to-resources/image-5.png) 27 | 28 | Another challenge is that you constantly have to look up API docs, their prototypes and figure out their implementations, and make sure its all correct. It can sometimes feel like using laptop that has the screen facing in the wrong direction. (thanks AI!) 29 | 30 | ![ai](./how-to-resources/ai.png) 31 | 32 | This article aims to introduce some VSCode configuration and tools that alleviate some of these challenges. 33 | 34 | ## Step 1: Install the C/C++ extension 35 | Install the [C/C++ Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools). You can do this with Ctrl+Shift+X and search for it. 36 | 37 | ![C/C++ Extension](./how-to-resources/c-extension.png) 38 | 39 | ## Step 2: Configure the compiler path for the extension 40 | Configure the path of the C/C++ extensions' Compiler Path arguments to be representative of your MingW/etc, path. 41 | You can look this up by running: 42 | 43 | `which x86_64-w64-mingw32-gcc` 44 | 45 | which should return something like: 46 | 47 | `/usr/bin/x86_64-w64-mingw32-gcc` 48 | 49 | To configure it, press Ctrl+Shift+P and search for "C/C++: Select a Configuration" 50 | 51 | ![alt text](./how-to-resources/image-4.png) 52 | 53 | From that manu, set the "Compiler path" to the path of the compiler identified in the previous step. 54 | 55 | ![alt text](./how-to-resources/image-3.png) 56 | 57 | ## Step 3: Install supplementary extensions 58 | The project [BOF_NativeAPI_Definitions-VSCode](https://github.com/EspressoCake/BOF_NativeAPI_Definitions-VSCode) provides two VSCode extensions to assist with BOF development. We will get to what they do and how they work in a second. 59 | 60 | Download the VSIX files from the Releases section on the Github repository. 61 | 62 | Press Ctrl+Shfit+P and search for "Install from VSIX" an 63 | ![alt text](./how-to-resources/image.png) 64 | 65 | After this, select the vsix file and press Install. Repeat the process for both vsix files. 66 | ![alt text](./how-to-resources/image-2.png) 67 | 68 | 69 | ### Step 4: Confirm that there are no more errors 70 | After installing you should not have a ton of red squiggly lines complaining about regular things like including `windows.h` in your C files. This is a good sign. This is primarily resolved by pointing the C/C++ extension to the cross-compiler. 71 | 72 | ![alt text](./how-to-resources/image-6.png) 73 | 74 | ## Step 3 Confirm BOF definitions and prototypes work 75 | The developer of these extensions included a [video](https://www.youtube.com/watch?v=oWss4Ac9Pl8) that demonstrates how this is supposed to be used. The guide below more or less re-iterates what is in the video. 76 | 77 | ### Step 3a: BOF definitions 78 | The first extension, according to the developer, does the following: 79 | 80 | > - Highlighted text representing a known Win32 API function is queried to identify the correct DLL it originates from 81 | > - If successful, the DFR syntax for the function is displayed as a notification window 82 | > - If successful, the relevant header file to include is displayed as a notification window 83 | 84 | To verify you have these features installed and working, do the following: 85 | 86 | Highlight a function call, for example `CreateFileA` and select "Peek -> Peek definition" 87 | 88 | ![alt text](./how-to-resources/image-12.png) 89 | 90 | When you peek the definition, you can copy it to the C file. 91 | 92 | ![alt text](./how-to-resources/image-13.png) 93 | 94 | Highlight the definition function name, press Ctrl+Shift+P and search for "Obtain External Definition". 95 | 96 | ![alt text](./how-to-resources/image-14.png) 97 | 98 | Once you click it, you will see a VSCode notification with the correct DFR syntax and header file to include is shown. 99 | 100 | ![alt text](./how-to-resources/image-15.png) 101 | 102 | You can then insert the header in your code, and update the DFR syntax with the DLL name. 103 | 104 | ### Step 3b: BOF prototypes 105 | The second extension, according to the developer, does the following: 106 | 107 | > Serves as a series of VSCode snippets in which: 108 | > 109 | > - NT/ZW functions prototypes are handled via bp_ prefixed strings 110 | > - NT/ZW functions implementations are handled via bf_ prefixed strings 111 | > - All implementations have sane default values to assist development 112 | 113 | To verify this functionality, start typing `bp_` and you should see prototypes for a range of functions. 114 | When selecting an entry, this should auto-insert the full prototype. 115 | 116 | ![alt text](./how-to-resources/image-9.png) 117 | 118 | ![alt text](./how-to-resources/image-10.png) 119 | 120 | Similarly, when inside a function, you will see the same dropdown menu. But when selecting an entry, they will auto-expand to implementations instead of prototypes. 121 | 122 | ![alt text](./how-to-resources/image-11.png) 123 | ![alt text](./how-to-resources/image-8.png)) 124 | 125 | --- 126 | 127 | ## ✅ Summary 128 | With these extensions, you get: 129 | - Better formatting and error reporting when developing BOFs 130 | - Great ergonomics and lookups of prototypes and implementations 131 | - Easy lookup of API functions and DFR syntax. 132 | 133 | --- -------------------------------------------------------------------------------- /scripts/find-dupes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import re 5 | import argparse 6 | from collections import defaultdict 7 | import sys 8 | 9 | # Regex to find a Markdown link: [text](url) and capture the url 10 | MARKDOWN_LINK_PATTERN = re.compile(r'\[.*?\]\(([^)]+)\)') 11 | 12 | # Regex to match a GitHub repo URL and capture the username/repo part 13 | # Ensures it starts with http/https and github.com 14 | GITHUB_REPO_PATTERN = re.compile(r'^https?://github\.com/([\w._-]+/[\w._-]+)') 15 | 16 | def find_markdown_files(root_dir): 17 | """Recursively finds all '.md' files in the given directory.""" 18 | markdown_files = [] 19 | for dirpath, _, filenames in os.walk(root_dir): 20 | for filename in filenames: 21 | if filename.lower().endswith(".md"): 22 | markdown_files.append(os.path.join(dirpath, filename)) 23 | return markdown_files 24 | 25 | def extract_repo_references(filepath): 26 | """ 27 | Extracts 'username/repo' references ONLY from the primary Markdown link 28 | (expected in the first data column of a table row) in a file. 29 | """ 30 | references = [] 31 | file_name = os.path.basename(filepath) 32 | try: 33 | with open(filepath, 'r', encoding='utf-8', errors='ignore') as f: 34 | for line_num, line in enumerate(f, 1): 35 | stripped_line = line.strip() 36 | # Check if the line looks like a table row 37 | if not stripped_line.startswith('|') or not stripped_line.endswith('|'): 38 | continue 39 | 40 | parts = stripped_line.split('|') 41 | # Need at least 4 parts for "| Col1 | Col2 | ... |" structure 42 | # parts[0] is empty, parts[1] is Col1 content, parts[2] is Col2 content etc. parts[-1] is empty 43 | if len(parts) < 4: 44 | continue 45 | 46 | # Target the content of the first data column (between the first two pipes) 47 | first_col_content = parts[1].strip() 48 | 49 | # Find the first Markdown link within this first column's content 50 | link_match = MARKDOWN_LINK_PATTERN.search(first_col_content) 51 | if not link_match: 52 | continue # No markdown link found in the first column 53 | 54 | # Extract the URL from the link 55 | url = link_match.group(1).strip() 56 | 57 | # Check if this URL is specifically a GitHub repo URL 58 | repo_match = GITHUB_REPO_PATTERN.match(url) # Use match() for start-of-string check 59 | if repo_match: 60 | # Extract the username/repo part 61 | repo_path = repo_match.group(1) 62 | # Clean potential trailing characters (though less likely with stricter regex) 63 | repo_path = repo_path.rstrip('./') 64 | normalized_repo = repo_path.lower() 65 | 66 | # Store the reference details 67 | references.append({ 68 | "repo": normalized_repo, 69 | "file_path": filepath, 70 | "file_name": file_name, 71 | "line": line_num, 72 | "content": stripped_line # Store original stripped line content 73 | }) 74 | 75 | except IOError as e: 76 | print(f"Error reading file {filepath}: {e}", file=sys.stderr) 77 | except Exception as e: 78 | print(f"An unexpected error occurred processing {filepath}: {e}", file=sys.stderr) 79 | return references 80 | 81 | def main(): 82 | parser = argparse.ArgumentParser( 83 | description="Find duplicate table entries based on the primary GitHub link in the first column within the *same* Markdown file." 84 | ) 85 | parser.add_argument( 86 | "root_dir", 87 | help="The root directory to search for Markdown files recursively." 88 | ) 89 | args = parser.parse_args() 90 | 91 | if not os.path.isdir(args.root_dir): 92 | print(f"Error: Directory not found: {args.root_dir}", file=sys.stderr) 93 | sys.exit(1) 94 | 95 | print(f"Scanning for Markdown files in '{args.root_dir}'...") 96 | markdown_files = find_markdown_files(args.root_dir) 97 | 98 | if not markdown_files: 99 | print("No Markdown files found.") 100 | sys.exit(0) 101 | 102 | print(f"Found {len(markdown_files)} Markdown files. Extracting primary table link references...") 103 | 104 | # Store all valid references found 105 | all_references_list = [] 106 | total_refs_found = 0 107 | 108 | for md_file in markdown_files: 109 | refs_in_file = extract_repo_references(md_file) 110 | all_references_list.extend(refs_in_file) 111 | total_refs_found += len(refs_in_file) 112 | 113 | print(f"Found {total_refs_found} primary GitHub link references in table rows.") 114 | print("-" * 30) 115 | 116 | # Group references by (normalized_repo, file_name) 117 | grouped_references = defaultdict(list) 118 | for ref in all_references_list: 119 | key = (ref['repo'], ref['file_name']) 120 | grouped_references[key].append(ref) 121 | 122 | # --- Reporting Duplicates Found WITHIN the SAME FILE based on Primary Link --- 123 | duplicates_found_overall = False 124 | # Sort keys for consistent output (by repo, then filename) 125 | sorted_keys = sorted(grouped_references.keys()) 126 | 127 | for key in sorted_keys: 128 | locations = grouped_references[key] 129 | if len(locations) > 1: # Found duplicates of this primary repo link within this specific file 130 | repo, file_name = key 131 | if not duplicates_found_overall: 132 | print("Duplicate Primary Link References Found (within the same file):") 133 | duplicates_found_overall = True 134 | 135 | print(f"\nRepository: {repo} (Found {len(locations)} times as primary link in File: {file_name})") 136 | # Sort locations within the file by line number 137 | sorted_locations = sorted(locations, key=lambda x: x['line']) 138 | for loc in sorted_locations: 139 | # Use file_path for the full path display 140 | print(f" - Path: {loc['file_path']}, Line: {loc['line']}") 141 | print(f" Content: {loc['content']}") 142 | 143 | if not duplicates_found_overall: 144 | print("No duplicate primary link references found within the same file.") 145 | 146 | if __name__ == "__main__": 147 | main() -------------------------------------------------------------------------------- /tutorials/tutorial-building-your-second-bof.md: -------------------------------------------------------------------------------- 1 | # Tutorial: Building Your First Argument‑Accepting BOF and Aggressor Script 2 | 3 | This tutorial will walk you through creating a Beacon Object File (BOF) with arguments, explaining the structure, build process, and how to run it in a C2 framework like Cobalt Strike. 4 | 5 | > If you have never made a BOF before, you might want to try out the first tutorial [Tutorial: Building Your First Beacon Object File (BOF)](../tutorials/tutorial-building-your-first-bof.md) before you try this one. 6 | 7 | ## About this tutorial 8 | 9 | This tutorial extends the basic “Hello, world” BOF to: 10 | 11 | 1. **Accept and parse arguments** (string & integer) in your BOF 12 | 2. **Register a custom Beacon command** via an Aggressor script 13 | 14 | Ultimately, its a pointless BOF from an operational perspective. It just serves as a typical programming example to teach the basics. 15 | 16 | *Note*: This is almost identical to the article from the CS documentation found in [Aggressor Script and BOFs](https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/beacon-object-files_with-aggressor-script.htm) 17 | 18 | --- 19 | 20 | ## 🎯 Goals 21 | - Learn how to pass and parse simple arguments in your BOF 22 | - Create an Aggressor (`.cna`) script that: 23 | - Registers a new Beacon command 24 | - Loads your BOF once and caches it 25 | - Builds and passes the argument buffer to the BOF 26 | 27 | --- 28 | 29 | ## 📦 Prerequisites 30 | - Linux or Windows+WSL 31 | - gcc‑mingw‑w64 (or clang) 32 | - Cobalt Strike (or Sliver/Havoc) 33 | - [`beacon.h`](https://github.com/Cobalt-Strike/bof_template/blob/main/beacon.h) 34 | 35 | --- 36 | ## 0. Preparations 37 | Create a folder for your project 38 | 39 | ```bash 40 | mkdir hello-args-bof 41 | cd hello-args-bof 42 | ``` 43 | 44 | Download the Beacon header file 45 | ```bash 46 | wget https://github.com/Cobalt-Strike/bof_template/raw/refs/heads/main/beacon.h 47 | ``` 48 | 49 | 50 | ## 1. Create the source file 51 | Create a new file: `hello_args.c` 52 | 53 | ```c 54 | /* 55 | * Compile with: 56 | * x86_64-w64-mingw32-gcc -c hello.c -o hello.x64.o 57 | * i686-w64-mingw32-gcc -c hello.c -o hello.x86.o 58 | */ 59 | 60 | #include 61 | #include 62 | #include 63 | #include "beacon.h" 64 | 65 | void go(char* args, int length) { 66 | datap parser; 67 | char* str_arg; 68 | int num_arg; 69 | 70 | BeaconDataParse(&parser, args, length); 71 | str_arg = BeaconDataExtract(&parser, NULL); 72 | num_arg = BeaconDataInt(&parser); 73 | 74 | BeaconPrintf(CALLBACK_OUTPUT, "Message is %s with %d arg", str_arg, num_arg); 75 | } 76 | ``` 77 | 78 | 1. `BeaconDataParse` initializes the parser. 79 | 2. `BeaconDataExtract` pulls out the next string. 80 | 3. `BeaconDataInt` pulls out the integer. 81 | 82 | --- 83 | 84 | ## 2. Compile the BOF 85 | 86 | In the previous tutorial, we compiled our BOFs using the command line, like this: 87 | ```bash 88 | # 64‑bit target 89 | x86_64-w64-mingw32-gcc -c hello_args.c -o hello_args.x64.o 90 | 91 | # 32‑bit target (if needed) 92 | i686-w64-mingw32-gcc -c hello_args.c -o hello_args.x86.o 93 | ``` 94 | 95 | We can also write a makefile with compiling instructions for both architectures 96 | 97 | Create a new file called: `Makefile` 98 | ```make 99 | BOFNAME := hello_args 100 | CC_x64 := x86_64-w64-mingw32-gcc 101 | CC_x86 := i686-w64-mingw32-gcc 102 | 103 | .PHONY: all clean x86 x64 104 | 105 | all: x86 x64 106 | 107 | x86: 108 | $(CC_x86) -Os -c hello_args.c -o $(BOFNAME).x86.o 109 | 110 | x64: 111 | $(CC_x64) -Os -c hello_args.c -o $(BOFNAME).x64.o 112 | 113 | clean: 114 | @rm -f $(BOFNAME).*.o 115 | ``` 116 | 117 | Run `make` to compile. This will now output compiled BOF o-files for both architectures. 118 | 119 | --- 120 | 121 | ## 3. Aggressor Script 122 | To avoid having to write `inline-execute` with the full Beacon path every time, we can develop a so-called aggressor script in the Sleep programming language. 123 | 124 | Create the file: `hello_args.cna` 125 | 126 | ```sleep 127 | # 128 | # Usage (within beacon console): hello_args "" 129 | # Example: 130 | # beacon> hello_args "Fire in the hole" 31415 131 | # 132 | alias hello_args { 133 | # Declare local variables actually used 134 | local('$bid $barch $handle $data $args $msg $num'); 135 | 136 | # Arguments are passed from beacon_command_register: 137 | # $1 = beacon_id 138 | # $2 = message 139 | # $3 = number 140 | 141 | # 1) Check argument count (beacon ID is implicit $1) 142 | if (size(@_) != 3) 143 | { 144 | berror($1, "Usage: hello_args \"\" "); 145 | berror($1, beacon_command_detail("hello_args")); 146 | return; 147 | } 148 | 149 | # 2) Assign arguments 150 | $bid = $1; 151 | $msg = $2; 152 | $num = $3; 153 | 154 | # 3) Load the correct BOF based on beacon architecture 155 | $barch = barch($bid); 156 | $bof_filename = "hello_args." . $barch . ".o"; 157 | $handle = openf( script_resource($bof_filename) ); 158 | $data = readb( $handle, -1 ); 159 | closef( $handle ); 160 | 161 | # 4) Pack the arguments: (string, integer) 162 | $args = bof_pack($bid, "zi", $msg, $num); 163 | 164 | # 5) Execute the BOF 165 | btask($bid, "Tasked beacon to run hello_args BOF"); 166 | # Entry point is "demo" from your C code 167 | beacon_inline_execute( $bid, $data, "demo", $args ); 168 | } 169 | 170 | # Register the command so it's available in the beacon console 171 | beacon_command_register( 172 | "hello_args", 173 | "Run the hello_args BOF example.", 174 | " 175 | Synopsis: hello_args \"\" 176 | 177 | Runs a sample BOF that takes a string and an integer argument. 178 | 179 | Arguments: 180 | - The message to pass to the BOF (enclose in quotes if it has spaces). 181 | - The number to pass to the BOF. 182 | 183 | Example: 184 | hello_args \"Sending data\" 12345 185 | " 186 | ); 187 | ``` 188 | The script does the following: 189 | - Determines the architecture of the beacon (x64/x86) 190 | - Loads the compiled `hello_args.x64.o` or the equivivalent for x86 from disk 191 | - Packs the arguments using `bof_pack` with the correct formats: `z` for string and `i` for integer 192 | - Run the bof with args using `beacon_inline_execute` 193 | - Register the `hello_args` with usage information in beacon 194 | 195 | --- 196 | 197 | ## 4. Load & Test 198 | 199 | From Cobalt Strike 200 | Open the Script Manager and Load your CNA script. 201 | 202 | ![](../resources/load-bof.png) 203 | 204 | 3. In a Beacon on a target, run: 205 | 206 | ``` 207 | hello_args "hello" 123 208 | ``` 209 | And you should see output like this 210 | 211 | ![alt text](../resources/hello-args-bof.png) 212 | 213 | --- 214 | 215 | ## 🧠 Tips & Gotchas 216 | - **Validate** argument count before parsing. 217 | - The **order** of `BeaconDataExtract` / `BeaconDataInt` calls matter. 218 | - Use `static` in Aggressor to avoid re‑reading the BOF file on each run. 219 | - For complex data (buffers, blobs), explore `BeaconDataPtr`. 220 | 221 | --- 222 | 223 | ## ✅ Summary 224 | - You’ve parsed string & integer arguments in your BOF. 225 | - You built a friendly Beacon command in Aggressor to wrap your BOF. 226 | - You now have a repeatable workflow for argument‑driven BOFs! 227 | 228 | ``` 229 | -------------------------------------------------------------------------------- /reference/loaders-catalog.md: -------------------------------------------------------------------------------- 1 | # Reference: BOF Loaders Catalog 2 | 3 | This catalog summarizes known BOF (Beacon Object File) loaders and runtimes. These tools help you execute, test, or embed `.o` object files in a variety of contexts — including inside and outside of C2 frameworks, across different platforms, and with different levels of API emulation. Each loader has its own API quirks and execution model. Always test your BOF in the target C2 to ensure compatibility. 4 | 5 | --- 6 | 7 | ## 🧰 Native Loaders (within C2 frameworks) 8 | 9 | | Loader | C2 Framework | Platform | Async Support | Description | 10 | |--------|--------------|----------|---------------|-------------| 11 | | Cobalt Strike | Cobalt Strike (v4.1+) | Windows | ✅ via `async-execute` | Originator of BOFs with full API support and extensive documentation | 12 | | Sliver | Sliver | Win/Linux | ❌ | Uses `bof upload` and `bof execute` commands with `extension.json` for registration | 13 | | Havoc | Havoc (Demon agent) | Windows | ❌ | Supports inline execution and script-based BOF registration | 14 | | Meterpreter | Metasploit | Windows | ❌ | Requires `bofloader` extension with limited Beacon API compatibility | 15 | | OST (Outflank) | Outflank C2 | Windows | ✅ | Integrated BOF loader with support for "async BOFs" | 16 | | Brute Ratel | Brute Ratel | Windows | ✅ | Implements high-fidelity BOF support with asynchronous execution | 17 | | Nighthawk | Nighthawk | Windows | ✅ | Private commercial C2 with high-performance BOF runtime | 18 | | Mythic (Xenon) | Mythic | Windows | ❌ | Xenon agent supports `.o` execution via `execute_bof` command | 19 | 20 | --- 21 | 22 | ## 🧪 Standalone Loaders (Local Testing & Debugging) 23 | 24 | | Tool | Language | Description | Stars | Last commit | 25 | |------|-----------|-------------|-------|-------------| 26 | | [async_bof](https://github.com/9Insomnie/async_bof) [translated version](https://github-com.translate.goog/9Insomnie/async_bof?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en-US&_x_tr_pto=wapp) | 异步Beacon Object Files概念的实现。它提供了一个框架,用于运行可以检测事件并报告回Cobalt Strike团队服务器的异步监控任务。 | ![](https://img.shields.io/github/stars/9Insomnie/async_bof?label=&style=flat) | ![](https://img.shields.io/github/last-commit/9Insomnie/async_bof?label=&style=flat) | 27 | | [COFFLoader](https://github.com/trustedsec/COFFLoader) | C | CLI tool to run `.o` files outside Cobalt Strike for testing and development | ![](https://img.shields.io/github/stars/trustedsec/COFFLoader?label=&style=flat) | ![](https://img.shields.io/github/last-commit/trustedsec/COFFLoader?label=&style=flat) 28 | | [BOF.NET](https://github.com/CCob/BOF.NET) | C# / Native | Embeds .NET runtime within BOFs to enable managed code execution | ![](https://img.shields.io/github/stars/CCob/BOF.NET?label=&style=flat) | ![](https://img.shields.io/github/last-commit/CCob/BOF.NET?label=&style=flat) 29 | | [InlineExecuteEx](https://github.com/0xTriboulet/InlineExecuteEx) | A BOF that's a BOF Loader. Implements COFFLoader in Cobalt Strike | ![](https://img.shields.io/github/stars/0xTriboulet/InlineExecuteEx?label=&style=flat) | ![](https://img.shields.io/github/last-commit/0xTriboulet/InlineExecuteEx?label=&style=flat) 30 | | [BOF-PE](https://github.com/NetSPI/BOF-PE) | C / C++ | Portable Executable format for BOFs with extended capabilities and improved compatibility | ![](https://img.shields.io/github/stars/NetSPI/BOF-PE?label=&style=flat) | ![](https://img.shields.io/github/last-commit/NetSPI/BOF-PE?label=&style=flat) 31 | | [ELFLoader](https://github.com/trustedsec/ELFLoader) | C | Runs ELF `.o` files in-memory using libc/dlsym for Linux/macOS testing | ![](https://img.shields.io/github/stars/trustedsec/ELFLoader?label=&style=flat) | ![](https://img.shields.io/github/last-commit/trustedsec/ELFLoader?label=&style=flat) 32 | | [Coffee](https://github.com/hakaioffsec/coffee) | Rust | Coffee is a custom implementation of the original Cobalt Strike's beacon_inline_execute. It is written in Rust and supports most of the features of the Cobalt Strike compatibility layer.| ![](https://img.shields.io/github/stars/hakaioffsec/coffee?label=&style=flat) | ![](https://img.shields.io/github/last-commit/hakaioffsec/coffee?label=&style=flat) 33 | | [CoffeeLdr](https://github.com/Cracked5pider/CoffeeLdr) | C | CoffeeLdr is a loader for so called Beacon Object Files. | ![](https://img.shields.io/github/stars/Cracked5pider/CoffeeLdr?label=&style=flat) | ![](https://img.shields.io/github/last-commit/Cracked5pider/CoffeeLdr?label=&style=flat) 34 | | [ldr](https://github.com/yamakadi/ldr) | Rust | Unsuccessful attempt at a Rust BOF/COFF loader.| ![](https://img.shields.io/github/stars/yamakadi/ldr?label=&style=flat) | ![](https://img.shields.io/github/last-commit/yamakadi/ldr?label=&style=flat) 35 | | [COFF-Loader](https://github.com/Ap3x/COFF-Loader) | C++ | This is a reimplementation of TrustedSec COFF Loader.| ![](https://img.shields.io/github/stars/Ap3x/COFF-Loader?label=&style=flat) | ![](https://img.shields.io/github/last-commit/Ap3x/COFF-Loader?label=&style=flat) 36 | | [Invoke-Bof](https://github.com/airbus-cert/Invoke-Bof) | PowerShell | A PowerShell script to run BOFs. | ![](https://img.shields.io/github/stars/airbus-cert/Invoke-Bof?label=&style=flat) | ![](https://img.shields.io/github/last-commit/airbus-cert/Invoke-Bof?label=&style=flat) 37 | | [pybof](https://github.com/rkbennett/pybof) | Python | Python based BOF loader | ![](https://img.shields.io/github/stars/rkbennett/pybof?label=&style=flat) | ![](https://img.shields.io/github/last-commit/rkbennett/pybof?label=&style=flat) 38 | | [python-bof-runner](https://github.com/naksyn/python-bof-runner) | Python | Python-based BOF runner using inline shellcode injection | ![](https://img.shields.io/github/stars/naksyn/python-bof-runner?label=&style=flat) | ![](https://img.shields.io/github/last-commit/naksyn/python-bof-runner?label=&style=flat) 39 | | [RunOF](https://github.com/nettitude/RunOF) | .NET | Running BOFs in .NET | ![](https://img.shields.io/github/stars/nettitude/RunOF?label=&style=flat) | ![](https://img.shields.io/github/last-commit/nettitude/RunOF?label=&style=flat) 40 | | [NiCOFF](https://github.com/frkngksl/NiCOFF) | Nim | COFF and BOF file loader written in Nim.| ![](https://img.shields.io/github/stars/frkngksl/NiCOFF?label=&style=flat) | ![](https://img.shields.io/github/last-commit/frkngksl/NiCOFF?label=&style=flat) 41 | | [COFFLoader2](https://github.com/Yaxser/COFFLoader2) | C | Rewrite of the TrustedSec COFF loader.| ![](https://img.shields.io/github/stars/Yaxser/COFFLoader2?label=&style=flat) | ![](https://img.shields.io/github/last-commit/Yaxser/COFFLoader2?label=&style=flat) 42 | | [Jormungandr](https://github.com/Idov31/Jormungandr) | C++ | a kernel implementation of a COFF loader. | ![](https://img.shields.io/github/stars/Idov31/Jormungandr?label=&style=flat) | ![](https://img.shields.io/github/last-commit/Idov31/Jormungandr?label=&style=flat) 43 | | [bof-launcher](https://github.com/The-Z-Labs/bof-launcher) | Zig and C | Beacon Object File (BOF) launcher - library for executing BOF files in C/C++/Zig applications.| ![](https://img.shields.io/github/stars/The-Z-Labs/bof-launcher?label=&style=flat) | ![](https://img.shields.io/github/last-commit/The-Z-Labs/bof-launcher?label=&style=flat) 44 | | [CS2BR BOF](https://github.com/NVISOsecurity/cs2br-bof) | C | CS2BR implements a compatibility-layer that make CS BOFs use the BRC4 API. | ![](https://img.shields.io/github/stars/NVISOsecurity/cs2br-bof?label=&style=flat) | ![](https://img.shields.io/github/last-commit/NVISOsecurity/cs2br-bof?label=&style=flat) 45 | | [nim-lazy-bof](https://github.com/zimnyaa/nim-lazy-bof) | Nim | Nim port of Sliver's BOF loader | ![](https://img.shields.io/github/stars/zimnyaa/nim-lazy-bof?label=&style=flat) | ![](https://img.shields.io/github/last-commit/zimnyaa/nim-lazy-bof?label=&style=flat) 46 | | [coff_loader](https://github.com/soheil-01/coff_loader) | Zig | Experimental COFF loader for Cobalt Strike BOFs | ![](https://img.shields.io/github/stars/soheil-01/coff_loader?label=&style=flat) | ![](https://img.shields.io/github/last-commit/soheil-01/coff_loader?label=&style=flat) 47 | | [BOF2shellcode](https://github.com/FalconForceTeam/BOF2shellcode) | Convert BOFs into raw shellcode || ![](https://img.shields.io/github/stars/FalconForceTeam/BOF2shellcode?label=&style=flat) | ![](https://img.shields.io/github/last-commit/FalconForceTeam/BOF2shellcode?label=&style=flat) 48 | | [warlock](https://github.com/cyberphor/warlock) | C | Beacon Object File (BOF) generator, client, and loader.| ![](https://img.shields.io/github/stars/cyberphor/warlock?label=&style=flat) | ![](https://img.shields.io/github/last-commit/cyberphor/warlock?label=&style=flat) 49 | | [GoBofRunner](https://github.com/parzel/GoBofRunner) | Go | Beacon Object File (BOF) Runner written in Go with partial support of Cobalt Strike BeaconAPI| ![](https://img.shields.io/github/stars/parzel/GoBofRunner?label=&style=flat) | ![](https://img.shields.io/github/last-commit/Real-Cryillic/GOFFER?label=&style=flat) 50 | | [GOFFER](https://github.com/Real-Cryillic/GOFFER) | Go | Beacon Object File loaderin Go.| ![](https://img.shields.io/github/stars/Real-Cryillic/GOFFER?label=&style=flat) | ![](https://img.shields.io/github/last-commit/Real-Cryillic/GOFFER?label=&style=flat) 51 | | [bof-loader](https://github.com/cirosec/bof-loader) | C++ | Beacon Object File (BOF) Runtime/Loader| ![](https://img.shields.io/github/stars/cirosec/bof-loader?label=&style=flat) | ![](https://img.shields.io/github/last-commit/cirosec/bof-loader?label=&style=flat) 52 | | [BOF-Exec](https://github.com/nseckt/BOF-Exec) | C++ | A small tool that loads and executes a Beacon Object File (BOF) and optionally passes arguments to it.| ![](https://img.shields.io/github/stars/nseckt/BOF-Exec?label=&style=flat) | ![](https://img.shields.io/github/last-commit/nseckt/BOF-Exec?label=&style=flat) 53 | | [blacksandbeacon](https://github.com/grisuno/blacksandbeacon) | C | Black Sand Beacon — a lightweight, memory-resident micro beacon or implant for the LazyOwn RedTeam Framework — is the first offensive platform to deliver true native BOF (Beacon Object File) support for Linux. Inspired by the Windows-based Black Basalt Beacon, it enables red teams to write position-independent, fileless post-exploitation modules | ![](https://img.shields.io/github/stars/grisuno/blacksandbeacon?label=&style=flat) | ![](https://img.shields.io/github/last-commit/grisuno/blacksandbeacon?label=&style=flat) | 54 | 55 | --- 56 | 57 | ## 📚 Contribution 58 | Want to add another loader or tool? Open a PR! 59 | -------------------------------------------------------------------------------- /scripts/test2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import re 4 | import requests 5 | import time 6 | import argparse 7 | from urllib.parse import urlparse, urljoin 8 | import os 9 | import sys 10 | 11 | # --- Configuration --- 12 | REQUEST_DELAY_SECONDS = 0.5 13 | 14 | # --- Functions --- (Keep functions as they are, no changes needed here) 15 | def extract_repo_urls(markdown_content): 16 | urls = re.findall(r"^\s*\|\s*\[.*?\]\((https?://github\.com/[^/]+/[^)]+)\)", markdown_content, re.MULTILINE) 17 | return list(set(urls)) 18 | # ... (keep get_repo_base_info, get_raw_file_url, fetch_readme_content, extract_potential_bofs) ... 19 | def get_repo_base_info(repo_url): 20 | parsed_url = urlparse(repo_url); 21 | if parsed_url.netloc.lower() != 'github.com': return None, None, None 22 | path_parts = parsed_url.path.strip('/').split('/'); 23 | if len(path_parts) < 2: return None, None, None 24 | user = path_parts[0]; repo = path_parts[1]; base_url = f"https://github.com/{user}/{repo}" 25 | return user, repo, base_url 26 | def get_raw_file_url(user, repo, file_path, branch): 27 | return f"https://raw.githubusercontent.com/{user}/{repo}/{branch}/{file_path.lstrip('/')}" 28 | def fetch_readme_content(repo_url): 29 | user, repo, base_url = get_repo_base_info(repo_url); 30 | if not user: return None, None 31 | headers = {'Accept': 'text/plain'}; content = None; found_branch = None; 32 | for branch in ['main', 'master']: 33 | readme_path = 'README.md'; raw_url = get_raw_file_url(user, repo, readme_path, branch); 34 | try: 35 | response = requests.get(raw_url, headers=headers, timeout=15); 36 | if response.status_code == 200: content = response.text; found_branch = branch; break; 37 | elif response.status_code != 404: print(f"[!] Warning: Fetch '{branch}' for {repo_url}: Status {response.status_code}", file=sys.stderr) 38 | except requests.exceptions.Timeout: print(f"[!] Warning: Timeout fetch '{branch}' for {repo_url}", file=sys.stderr) 39 | except requests.exceptions.RequestException as e: print(f"[!] Warning: Network error fetch '{branch}' for {repo_url}: {e}", file=sys.stderr) 40 | if content is None and branch == 'main': time.sleep(REQUEST_DELAY_SECONDS / 2) 41 | return content, found_branch 42 | def extract_potential_bofs(readme_content, repo_url=None, user=None, repo=None, branch=None): 43 | if not readme_content: return [] 44 | found_bofs = set(); 45 | # 1: Backticks 46 | for name in re.findall(r"`([a-zA-Z0-9_.-]+\.(?:c|o)|[a-zA-Z0-9_.-]{3,35})`", readme_content): 47 | if len(name) > 2 and name.lower() not in ['bof','c','o','cs','cpp','dll','exe','aggressor','output','input','cmd','ps']: found_bofs.add(name.strip('.')) 48 | # 2: Bold 49 | for name in re.findall(r"\*\*([a-zA-Z0-9_.-]+\.(?:c|o)|[a-zA-Z0-9_.-]{3,35})\*\*", readme_content): 50 | if len(name) > 2 and name.lower() not in ['bof','c','o','cs','cpp','dll','exe','aggressor','output','input','cmd','ps']: found_bofs.add(name.strip('.')) 51 | # 3: List items 52 | for line in readme_content.splitlines(): 53 | m = re.match(r"^\s*(?:[-*]|\d+\.)\s+[`\*]*([a-zA-Z0-9_.-]+\.(?:c|o)|[a-zA-Z0-9_.-]{3,35})[`\*]*[\s:–-]", line) 54 | if m and m.group(1) and len(m.group(1)) > 2 and m.group(1).lower() not in ['bof','c','o','cs','cpp','dll','exe','aggressor','usage','example','note','output','input','cmd','ps']: found_bofs.add(m.group(1).strip('.')) 55 | # 4: Filenames .c/.o 56 | for name in re.findall(r'([a-zA-Z0-9_-]+\.(?:c|o))\b', readme_content): 57 | if name.lower() not in ['beacon.c','beacon.h','example.c','main.c','common.c','common.h']: found_bofs.add(name.strip()) 58 | # 5: Numbered headings 59 | for m in re.finditer(r"^\s*#+\s*\d+\s*\)\s*(.*)", readme_content, re.M|re.I): 60 | name = m.group(1).strip(); name = re.sub(r'\[.*?\].*$', '', name).strip(); name = re.sub(r'[:–-].*$', '', name).strip() 61 | if 2 < len(name) < 50 and re.match(r'^[a-zA-Z0-9\s_/().-]+$', name) and name.lower() not in ['usage','compilation','instructions','features','acknowledgement','acknowledgments','example','introduction','overview','note','notes','why are you doing this','did you write this from the ground up','note on quality','can i/we reach you','can i/we help you','requirements','setup']: found_bofs.add(name.strip('.')) 62 | # 6: Table first column 63 | header_pattern = re.compile(r"Commands?|Project|Name", re.I); separator_pattern = re.compile(r"^\s*\|?\s*--+.*") 64 | for line in readme_content.splitlines(): 65 | if separator_pattern.match(line): continue 66 | m = re.match(r"^\s*\|\s*([^|]+?)\s*\|", line) 67 | if m: 68 | name = m.group(1).strip(); name = re.sub(r'\[([^\]]+)\]\(.*?\)', r'\1', name).strip(); name = name.replace('`', '').replace('*', '').strip() 69 | if name and 2 < len(name) < 50 and not header_pattern.search(name) and name.lower() not in ['bof','c','o','cs','cpp','dll','exe','aggressor','usage','example','note','output','input','cmd','ps']: found_bofs.add(name.strip('.')) 70 | # 7: Sub-projects/Dirs (README links) 71 | for m in re.finditer(r"\[[^\]]+\]\(((?!https?://)[^)]*?)/README\.md\)", readme_content): 72 | dir_name = m.group(1).strip(); 73 | if dir_name and '/' not in dir_name and 2 < len(dir_name) < 30: found_bofs.add(dir_name) 74 | # 7b: Sub-projects/Dirs (H2 Headings) 75 | for m in re.finditer(r"^\s*##\s+([a-zA-Z0-9_-]+)", readme_content, re.M): 76 | h_name = m.group(1).strip(); 77 | if 2 < len(h_name) < 30 and h_name.lower() not in ['usage','compilation','features','references','notes','acknowledgement','acknowledgments','installation','setup','examples','commands','modules']: found_bofs.add(h_name) 78 | # Final Filtering 79 | bof_list = sorted(list(found_bofs), key=str.lower); 80 | common_words_to_filter = {'the','and','for','with','using','via','from','this','that','bof','file','object','beacon','cobalt','strike','command','output','input','example','description','parameter','argument','arguments','function','feature','module','script','tool','utility','windows','linux','api','net','system','process','thread','memory','injection','payload','bypass','lateral','movement','privilege','escalation','collection','various','general','purpose','command','control','active','directory','kerberos','number','string','value','path','name','project','usage','notes','note','references','commands'}; 81 | bof_list = [b for b in bof_list if b.lower() not in common_words_to_filter and len(b.split()) < 5 and not re.match(r'^\d+$', b) and not (b.startswith('.') or b.endswith('.')) and len(b) > 2] 82 | return bof_list 83 | 84 | # --- Main Execution --- 85 | if __name__ == "__main__": 86 | parser = argparse.ArgumentParser(description="Extract potential BOF names from READMEs linked in a Markdown file.") 87 | parser.add_argument("markdown_file", help="Path to the input Markdown file containing the table of repositories.") 88 | args = parser.parse_args() 89 | 90 | if not os.path.exists(args.markdown_file): print(f"[!] Error: Input file not found: {args.markdown_file}", file=sys.stderr); exit(1) 91 | 92 | print(f"[*] Reading input file: {args.markdown_file}") 93 | try: 94 | with open(args.markdown_file, 'r', encoding='utf-8') as f: markdown_content = f.read() 95 | except Exception as e: print(f"[!] Error reading file: {e}", file=sys.stderr); exit(1) 96 | 97 | repo_urls = extract_repo_urls(markdown_content) 98 | print(f"[*] Found {len(repo_urls)} unique repository URLs in the table.") 99 | 100 | results = {} 101 | print("[*] Processing repositories...") 102 | for i, url in enumerate(repo_urls, 1): 103 | user, repo, base_url = get_repo_base_info(url) 104 | if not user: print(f"[-] Skipping invalid URL: {url}"); results[url] = []; continue 105 | readme_content, found_branch = fetch_readme_content(url) 106 | if readme_content and found_branch: results[url] = extract_potential_bofs(readme_content, url, user, repo, found_branch) 107 | else: results[url] = [] 108 | if i < len(repo_urls): time.sleep(REQUEST_DELAY_SECONDS) 109 | print("[*] Finished processing repositories.") 110 | 111 | # --- Optional: Print final results dictionary for debugging --- 112 | # print("\nDEBUG: Final Results Dictionary:", file=sys.stderr) 113 | # import json 114 | # print(json.dumps(results, indent=2), file=sys.stderr) 115 | # print("-" * 60, file=sys.stderr) # Separator for debug output 116 | 117 | print("\n" + "=" * 60) 118 | print(" FINAL RESULTS SUMMARY - UPDATED MARKDOWN SNIPPET") 119 | print("=" * 60) 120 | print("[*] (Review and manually integrate into your main README file)\n") 121 | 122 | original_lines = markdown_content.splitlines() 123 | header_printed = False 124 | separator_printed = False 125 | header_pattern_check = re.compile(r"^\s*\|\s*Project\s*\|", re.IGNORECASE) 126 | separator_pattern_check = re.compile(r"^\s*\|\s*-+.*") 127 | 128 | # --- FINAL OUTPUT LOOP - REVISED REGEX --- 129 | for line_num, line in enumerate(original_lines, 1): 130 | line_stripped = line.strip() 131 | # print(f"DEBUG Line {line_num}: Processing: '{line_stripped}'", file=sys.stderr) # Optional debug 132 | 133 | if not line_stripped: print(line); continue 134 | 135 | # Handle Header 136 | if not header_printed and header_pattern_check.match(line): 137 | print(f"| Project | Description | Includes | Stars | Last commit |") 138 | header_printed = True; continue 139 | 140 | # Handle Separator 141 | if not separator_printed and separator_pattern_check.match(line): 142 | print(f"|---------|-------------|----------|-------|-------------|") 143 | separator_printed = True; continue 144 | 145 | # Process potential data rows 146 | if line_stripped.startswith('|') and line_stripped.endswith('|'): 147 | # Try to extract URL from this line 148 | match_url = re.search(r"\(https?://github\.com/([^/]+/[^)]+?)\)", line) 149 | current_line_url_full = None 150 | if match_url: 151 | url_path = match_url.group(1).strip('/') 152 | current_line_url_full = f"https://github.com/{url_path}" 153 | 154 | if current_line_url_full: 155 | bofs_str = "" 156 | if current_line_url_full in results: 157 | bofs = results[current_line_url_full] 158 | bofs_str = ", ".join(f"`{b}`" for b in bofs) if bofs else "" 159 | 160 | # --- USE NEW REGEX TO CAPTURE ALL 5 CELLS --- 161 | # Regex: | cell1 | cell2 | cell3 | cell4 | cell5 | 162 | # (Proj) (Desc) (Empty) (Stars) (Commit) 163 | row_match = re.match(r"^\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*$", line_stripped) 164 | 165 | if row_match: 166 | proj_cell = row_match.group(1).strip() 167 | desc_cell = row_match.group(2).strip() 168 | # empty_cell = row_match.group(3).strip() # We don't need this one 169 | stars_cell = row_match.group(4).strip() 170 | commit_cell = row_match.group(5).strip() 171 | 172 | # Print the reconstructed line inserting bofs_str correctly 173 | print(f"| {proj_cell} | {desc_cell} | {bofs_str} | {stars_cell} | {commit_cell} |") 174 | continue # Successfully processed this row 175 | 176 | else: 177 | # Fallback if the NEW regex fails (should be less likely now) 178 | print(f"DEBUG Line {line_num}: Row regex FAILED.", file=sys.stderr) 179 | print(line + f" ") 180 | continue 181 | else: 182 | # Looked like data row but no URL extracted 183 | print(line) 184 | continue 185 | 186 | # Print non-table lines as is 187 | print(line) 188 | 189 | 190 | print("\n" + "=" * 60) 191 | print("[*] Processing Complete.") -------------------------------------------------------------------------------- /reference/bof-blogs-and-research.md: -------------------------------------------------------------------------------- 1 | # Reference: Blog Posts and Research on BOF Development 2 | 3 | This page catalogs key blog posts, whitepapers, and research articles related to Beacon Object Files (BOFs). These resources span introductory guides, advanced development tips, C2 integration techniques, stealth improvements, and detection engineering — all curated for offensive security professionals and researchers. 4 | 5 | --- 6 | 7 | ## 📘 Beginner-Friendly Introductions 8 | 9 | | Title | Author | Details | Date | 10 | |-------|--------|---------|------------------| 11 | | [A Developer's Introduction to Beacon Object Files](https://www.trustedsec.com/blog/a-developers-introduction-to-beacon-object-files/) | Christopher Paschen (TrustedSec) | Comprehensive introduction to BOF concepts and development | 2023-11-15 | 12 | | [BOFs for Script Kiddies](https://trustedsec.com/blog/bofs-for-script-kiddies) | TrustedSec | An introduction to what BOFs are | 2023-02-16 | 13 | | [Beacon Object Files](https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/beacon-object-files_main.htm) | Fortra (Official docs) | Official documentation on BOF implementation and usage | 2023-08-20 | 14 | | [Beginner introduction to CobaltStrike BOF development](https://ph3n1x.com/posts/beginner-introduction-to-cobaltstrike-bof-development/) | ph3n1x | Step-by-step guide for beginners to create their first BOF | 2025-05-03 | 15 | | [Introduction to BOF, Beacon Object Files not Buffer OverFlows](https://blog.shashwatshah.me/2023/03/26/Bofs_Part-1.html) | 0xEr3bus | Beginner-friendly blog explaining BOFs and writing custom process injector and remote Etw patching. | 2023-03-26 | 16 | | [Developing Cobalt Strike BOFs with Visual Studio](https://www.securify.nl/en/blog/creating-cobalt-strike-bofs-with-visual-studio/) | Yasse Alhzami | 2021-11-16 | Simple tutorial to develop BOFs with VS. 17 | 18 | --- 19 | 20 | ## 🧪 Videos, Guides and Demos 21 | 22 | | Title | Author/Org | Details | Date | 23 | |-------|------------|---------|------------------| 24 | | [Introduction to Beacon Object Files in Red-Teaming Operations](https://www.youtube.com/watch?v=jlLPKGDtsWY) | Rafael Felix | EKO2023 Conference Presentation on BOF usage in red team ops | 2024-11-24 | 25 | | [RTO: Malware Development Advanced - CaFeBiBa - Coff Object Parser](https://www.youtube.com/watch?v=GSdGnIu6CII) | Sektor7 | RED TEAM Operator course teaser on COFF parsing | 2022-12-23 | 26 | | [Situational Awareness Beacon Object Files](https://www.youtube.com/watch?v=G_E6ggLNtbY) | TrustedSec | Demo of BOFs for host and network reconnaissance | 2022-09-30 | 27 | | [Cobalt Strike: Beacon Object Files (NoteThief Demo)](https://www.youtube.com/watch?v=ksCVx9PbkZE) | Kandy Phan | Demo of grabbing unsaved Notepad contents with a BOF | 2022-05-14 | 28 | | [Building Your TTP Arsenal: What Are BOFs?](https://www.youtube.com/watch?v=3yEZVBZsQzU) | TrustedSec | Introduction to BOF concepts and tactical usage | 2021-03-15 | 29 | | [CredBandit - Part 1 - Tool Review](https://www.youtube.com/watch?v=WV34uVMxKZk) | ACCESS GRANTED (Joe Vest) | Review of in-memory minidump BOF for credential harvesting | 2021-07-15 | 30 | | [Universal Unhooking as a Beacon Object File](https://www.youtube.com/watch?v=y6hE0rF99EU) | Cobalt Strike Archive | Demo of Cylance's Universal Unhooking capability as BOF | 2021-01-13 | 31 | | [CVE-2020-0796 (SMBGhost) as a Beacon Object File](https://www.youtube.com/watch?v=HrYtctprUUc) | Cobalt Strike Archive | Demonstration of SMBGhost vulnerability exploitation via BOF | 2020-09-17 | 32 | | [CVE-2020-1472 Zerologon as a Beacon Object File](https://www.youtube.com/watch?v=zGf1Rat3rEk) | Cobalt Strike Archive | Demonstration of Zerologon attack chain with Cobalt Strike | 2020-09-17 | 33 | | [Beacon Object Files - Luser Demo](https://youtu.be/gfYswA_Ronw) | Cobalt Strike Archive | Basic demonstration of BOF usage and implementation | 2020-06-19 | 34 | | [Cobalt Strike BOF: Enum_filter_driver](https://www.youtube.com/watch?v=MvRY0qS8XFk) | TrustedSec | Demo of the enum_filter_driver BOF | 2021-05-06 35 | | [Building Your TTP Arsenal Video Series: Identifying Risks (BOF)](https://youtu.be/M6Y5Q8OVkSo) | TrustedSec | Demo of multiple BOFs addressing opsec | 2021-04-15 36 | | [Advanced Audit Settings](https://www.youtube.com/watch?app=desktop&v=zeuiCrUPMAs) | TrustedSec | Covers the importance of enumerating Advanced Audit Settings using BOFs | 2021-05-28 37 | | [LastPass in Memory Exposure](https://www.youtube.com/watch?app=desktop&v=9hC15PzcQgc) | TrustedSec | Dump lastpass using BOF demo | 2022-10-24 38 | | [How to Dump LSASS.exe Process Memory with Nanodump BOF - Windows Defender Bypass](https://www.youtube.com/watch?v=jwETspKR6JU) | Gemini Cyber Security | Dumping lsass with nanodump demo | 2023-08-18 39 | 40 | --- 41 | 42 | ## 🧰 BOF Development and Tooling 43 | 44 | | Title | Author | Details | Date | 45 | |-------|-------|---------|------------------| 46 | | [Async BOFs – “Wake Me Up, Before You Go Go”](https://www.outflank.nl/blog/2025/07/16/async-bofs-wake-me-up-before-you-go-go/) | Dima van de Wouw (Outflank) | Discussing the journey into Async BOFs | 2025-07-16 | 47 | | [BOF Linting for Accelerated Development](https://www.outflank.nl/blog/2025/06/30/bof-linting-for-accelerated-development/?trk=feed_main-feed-card_feed-article-content) | Cedric Van Bockhaven (Outflank) | Description of a BOF linting tool to address some of the common pitfalls of BOF development. | 2025-06-30 | 48 | | [Beacon Object Files – Five Years On…](https://aff-wg.org/2025/06/26/beacon-object-files-five-years-on/) | Raphael Mudge | History of Beacon Object Files and add some insight to the questions and discourse around them today.| 2025-06-26 | 49 | | [f Our Beacon Object Files (BOFs)](https://www.netspi.com/blog/technical-blog/adversary-simulation/the-future-of-beacon-object-files/) | Ceri Coburn (NetSPI) | Advanced BOF format for extended capabilities | 2025-03-19 | 50 | | [Writing Beacon Object Files Without DFR](https://blog.cybershenanigans.space/posts/writing-bofs-without-dfr/) | Matt Ehrnschwender | Techniques for BOF development without Dynamic Function Resolution | 2024-11-18 | 51 | | [An Operators Guide to BeaconkObject Files](https://maldev.nl/posts/operator-guide-bof/) | notb9 | Demonstrating BOF use with the Invoke-Bof project | 2024-11-01 52 | | [Simplifying BOF Development with Visual Studio](https://www.cobaltstrike.com/blog/simplifying-bof-development) | Fortra | Using Visual Studio for streamlined BOF development | 2023-08-10 | 53 | | [Changes in the Beacon Object File Landscape](https://trustedsec.com/blog/changes-in-the-beacon-object-file-landscape) | Christopher Paschen (TrustedSec) | Discussion on the current state of BOFs as per the time of writing. | 2023-03-28 54 | | [Writing BOFs: Flexible, Stealthy, and Compatible](https://www.cobaltstrike.com/blog/writing-beacon-object-files-flexible-stealthy-and-compatible) | Core Labs (Fortra) | Best practices for creating effective and stealthy BOFs | 2021-12-20 | 55 | | [Process Injection via custom Beacon Object Files Part 2](https://cerbersec.com/2021/08/26/beacon-object-files-part-2.html) | Cerbersec | Implementing the [CobaltWhispers](https://github.com/NVISOsecurity/CobaltWhispers) BOF | 2022-08-21 56 | | [Process Injection via custom Beacon Object Files Part 1](https://cerbersec.com/2021/08/26/beacon-object-files-part-1.html) | Cerbersec | Implementing the [CobaltWhispers](https://github.com/NVISOsecurity/CobaltWhispers) BOF | 2022-08-21 57 | | [CredBandit (In memory BOF MiniDump) - Tool review - Part 1](https://www.cobaltstrike.com/blog/credbandit-a-review-of-a-tool-developed-built-by-the-cobalt-strike-user-community)| Joe Vest | Demonstrating the [CredBandit](https://github.com/xforcered/CredBandit) BOF | 2021-07-13 | 58 | | [Creating the WhereAmI Cobalt Strike BOF ](https://0xboku.com/2021/08/19/Bof-WhereAmI.html) | boku7 | This is a walkthrough of creating the Cobalt Strike Beacon Object File (BOF) “Where Am I?” | 2021-08-19 | 59 | | [Exploiting (D)COM in C; CobaltStrike BOF as PoC.](https://yaxser.github.io/CobaltStrike-BOF/) | Yaxser | Explaining the DCOM lateral movement BOF | 2020 | 60 | --- 61 | | [Exploring WinRM plugins for lateral movement](https://falconforce.nl/exploring-winrm-plugins-for-lateral-movement/) | FalconForce | Exploring WinRM plugins for lateral movement | 2025-01-20 62 | 63 | ## 🔬 Advanced Techniques and Stealth 64 | 65 | | Title | Author | Details | Date | 66 | |-------|--------|---------|------------------| 67 | | [Cobalt Strike 4.11: Shhhhhh, Beacon is Sleeping....](https://www.cobaltstrike.com/blog/cobalt-strike-411-shh-beacon-is-sleeping) | William Burgess (Fortra) | Introduction to asynchronous BOF execution capabilities | 2025-04-15 | 68 | | [Cobalt Strike 4.10: Through the BeaconGate](https://www.cobaltstrike.com/blog/cobalt-strike-410-through-the-beacongate) | William Burgess (Fortra) | Introducing custom Sleepmask BOFs and other BOF updates | 2024-07-16 | 69 | | [BOFRyptor: Encrypting Your Beacon During BOF Execution to Avoid Memory Scanners](https://www.securify.nl/en/blog/bofryptor-encrypting-your-beacon-during-bof-execution-to-avoid-memory-scanners/) | Yasser Alhazmi | BOFRyptor, a BOF that will encrypt the beacon during execution to avoid memory scanners. | 2024-10-09 | 70 | | [Your BOFs Are Gross, Put on a Mask](https://www.ibm.com/think/x-force/how-to-hide-beacon-during-bof-execution) | Joshua Magri (IBM X-Force Red) | Techniques for hiding Beacon during BOF execution. See [BOFMask on Github](https://github.com/passthehashbrowns/BOFMask) | 2023-05-30 | 71 | | [Using RPC in BOFs](https://www.trustedsec.com/blog/using-rpc-in-bofs) | Christopher Paschen (TrustedSec) | Demonstration of using RPC in BOFs | 2023-03-28 | 72 | | [No Consolation – Reflective PE Loader as a BOF](https://www.coresecurity.com/core-labs/articles/running-pes-inline-without-console) | Fortra | Loading PE files as BOFs without console artifacts | 2023-02-15 | 73 | | [FalconFriday: Direct System Calls and Cobalt Strike BOFs](https://falconforce.nl/falconfriday-direct-system-calls-and-cobalt-strike-bofs-0xff14/) | FalconForce | Analysis of direct syscall techniques in BOFs | 2022-11-04 | 74 | | [Direct Syscalls in Beacon Object Files](https://www.outflank.nl/blog/2020/12/26/direct-syscalls-in-beacon-object-files/) | Cornelis de Plaa (Outflank) | Implementation of direct syscalls in BOFs to evade EDR hooks | 2020-12-10 | 75 | | [BOF2shellcode — a tutorial converting a stand-alone BOF loader into shellcode](https://falconforce.nl/bof2shellcode-a-tutorial-converting-a-stand-alone-bof-loader-into-shellcode/) | FalconForce | Converting BOFs to shellcode | 2021 76 | | [Introducing the Mutator Kit: Creating Object File Monstrosities with Sleep Mask and LLVM](https://www.cobaltstrike.com/blog/introducing-the-mutator-kit-creating-object-file-monstrosities-with-sleep-mask-and-llvm) | William Burgess (Fortra) | Mutator kit to compile BOFs | 2024 77 | | [ 78 | Cobalt Strike 4.9: Take Me To Your Loader](https://www.cobaltstrike.com/blog/cobalt-strike-49-take-me-to-your-loader) | Greg Darwin (Fortra) | Storing BOFs in beacon data store | 2023 79 | 80 | --- 81 | 82 | ## Loaders 83 | | Title | Author | Details | Date | 84 | |-------|--------|---------|------------------| 85 | | [CoffLoader ](https://otterhacker.github.io/Malware/CoffLoader.html) | An introduction to writing a COFF loader | otterhacker | 2025 | 86 | | [Introducing Goffloader: A Pure Go Implementation of an In-Memory COFFLoader and PE Loader](https://www.praetorian.com/blog/introducing-goffloader-a-pure-go-implementation-of-an-in-memory-coffloader-and-pe-loader/)| Michael Weber (Praetorian) | Go implementation of an in-memory COFFLoader and PE loader. | 2024-09-02 | 87 | | [Operator's Guide to the Meterpreter BOFLoader](https://trustedsec.com/blog/operators-guide-to-the-meterpreter-bofloader)| Kevin Clark (TrustedSec) | Demonstrate uses of the Meterpreter BOFLoader. | 2023-01-24 | 88 | | [Coffee: A COFF loader made in Rust](https://hakaisecurity.io/coffee-a-coff-loader-made-in-rust/research-blog/) | Rafael "biscoito" Felix | Demo of a COFF loader made in Rust | 2023-06-22| 89 | | [Introducing RunOF - Arbitrary BOF tool ](https://www.lrqa.com/en/cyber-labs/introducing-runof-arbitrary-bof-tool/) | Joel Snape | A .NET based BOF loader | 2022-03-02 90 | | [Malware development part 8 - COFF injection and in-memory execution](https://0xpat.github.io/Malware_development_part_8/) | Explanation of COFF injection | 0xpat | 2021-03-16 | 91 | | [Invoke-Bof](https://skyblue.team/posts/invoke-bof/) | Sky Blueteam | A PowerShell based BOF loader | 2021-12-09 92 | | [COFFLoader: Building your own in memory loader or how to run BOFs](https://trustedsec.com/blog/coffloader-building-your-own-in-memory-loader-or-how-to-run-bofs)| Kevin Haubris (TrustedSec) | Building a BOF loader | 2021-02-22 | 93 | | [Running Cobalt Strike BOFs from Python ](https://www.naksyn.com/injection/2022/02/16/running-cobalt-strike-bofs-from-python.html) | Naksyn | Demonstrating python-bof-runner | 2022-02-16 | 94 | 95 | --- 96 | 97 | ## Linux and ELF loading 98 | | Title | Author | Details | Date | 99 | |-------|--------|---------|------------------| 100 | | [Write, debug and execute BOFs with bof-launcher (part 2)](https://blog.z-labs.eu/2025/01/15/write-debug-and-execute-bofs-part2.html) | Z-Labs | Developing BOFs in Zig with the bof-launcher project | 2025-01-15 101 | | [Write, debug and execute BOFs with bof-launcher (part 1)](https://blog.z-labs.eu/2024/12/02/write-debug-and-execute-bofs-part1.html) | Z-Labs | Developing BOFs in Zig with the bof-launcher project | 2024-12-02 102 | | [Executing Cobalt Strike's BOFs on ARM-based Linux devices](https://blog.z-labs.eu/2024/05/10/bofs-on-arm-based-devices.html) | Z-Labs | Demonstrating running BOFs on Linux ARM-based devices. | 2024-05-10 103 | | [Running BOFs with 'bof-launcher' library](https://blog.z-labs.eu/2024/02/08/bof-launcher.html) | Z-Labs | An open-source library for loading, relocating and launching Cobalt Strike’s BOFs on Windows and UNIX/Linux systems. | 2024-02-08 104 | [ELFLoader: Another In Memory Loader Post](https://trustedsec.com/blog/elfloader-another-in-memory-loader-post) | Kevin Haubris | Demonstrating a Linux based BOF loader | 2022-05-04 | 105 | 106 | --- 107 | 108 | ## 🌐 Cross-C2 Usage and Integration 109 | 110 | | Title | Author | Details | Date | 111 | |-------|--------|---------|------------------| 112 | | [Let's write a Beacon Object File for Havoc C2 - Part 1/5](https://www.100daysofredteam.com/p/lets-write-a-beacon-object-file-for-havoc-c2-part-1) | Uday Mittal | First part of 5-part series on BOF development for Havoc C2 | 2025-02-27 | 113 | | [Creating a simple beacon object file for Havoc C2](https://www.100daysofredteam.com/p/creating-a-simple-beacon-object-file-for-havoc-c2) | Uday Mittal | Tutorial for creating basic BOFs for Havoc C2 framework | 2025-02-23 | 114 | | [Enhancing C2 agent via Beacon Object Files](https://www.100daysofredteam.com/p/enhancing-c2-agent-via-beacon-object-files-bof) | Uday Mittal | Using BOFs to extend C2 agent capabilities | 2025-01-10 | 115 | | [Sliver BOF](https://www.redteaming.org/sliverbof.html) | RedTeaming.org | Demo of BOF in Sliver C2 | 2023-10-18 | 116 | | [Introducing CS2BR pt. III – Knees deep in Binary](https://blog.nviso.eu/2023/10/26/introducing-cs2br-pt-iii-knees-deep-in-binary/) | Nviso | Running CS BOFs in Brute Ratel | 2023-10-26 117 | | [Introducing CS2BR pt. II – One tool to port them all](https://blog.nviso.eu/2023/07/17/introducing-cs2br-pt-ii-one-tool-to-port-them-all/) | Nviso | Running CS BOFs in Brute Ratel | 2023-07-17 118 | | [Introducing CS2BR pt. I – How we enabled Brute Ratel Badgers to run Cobalt Strike BOFs](https://blog.nviso.eu/2023/05/15/introducing-cs2br-pt-i-how-we-enabled-brute-ratel-badgers-to-run-cobalt-strike-bofs/) | Nviso | Running CS BOFs in Brute Ratel | 2023-05-15 119 | | [BOFs in Mythic with Xenon Agent](https://github.com/MythicAgents/xenon) | Mythic Contributors | BOF implementation for the Mythic C2 framework | 2023-04-30 | 120 | | [Learning Sliver C2 (12) - Extensions](https://dominicbreuker.com/post/learning_sliver_c2_12_extensions/) | dominicbreuker.com | | 2023-03-23 | 121 | | [Meterpreter & Beacon Object Files (BOF)](https://moulinette.org/posts/msf-bof/) | moulinette.org | French article on using BOFs in MSF | 2023-05-29 122 | 123 | --- 124 | 125 | ## 🛡️ Detection, Defense & Simulation 126 | 127 | | Title | Author | Details | Date | 128 | |-------|--------|---------|------------------| 129 | | [Detonating Beacons to Illuminate Detection Gaps](https://www.elastic.co/security-labs/detonating-beacons-to-illuminate-detection-gaps) | Elastic Security Labs | Analysis of BOF detection techniques and evasion methods | 2025-01 | 130 | | [FalconFriday — Direct system calls and Cobalt Strike BOFs — 0xFF14](https://falconforce.nl/falconfriday-direct-system-calls-and-cobalt-strike-bofs-0xff14/) | FalconForce | Deep-dive into how direct system calls could be detected based on some example Cobalt Strike BOFs | 2021-07-21 | 131 | --- 132 | 133 | ## 📚 Contributing 134 | 135 | If you know of a blog post, paper, or project that should be listed here, feel free to open a pull request! 136 | --------------------------------------------------------------------------------