BOF and Extensions

Beacon Object Files

BOF is just a block of position-independent code that receives pointers to some Beacon internal APIs. BOFs are single-file C programs that call Win32 APIs and limited Beacon APIs.

AdaptixC2 expects that your BOFs are single-threaded programs that run for a short period of time. BOFs will block other agent tasks and functionality from executing. BOFs execute inside of your agent. If a BOF crashes, you will lose access. Write your BOFs carefully.

Description of BOF for agents

Beacon BOFsGopher BOFs

Extensions

How to execute AxScript

The extension file is an AxScript that must start with a global definition of the metadata variable that has the following properties: .

  • name - extension name,

  • description - extension description

  • store - determines whether the extension should be stored in the database (default: true).

var metadata = {
    name: "Elevation-BOF",
    description: "BOFs for context elevation",
    store: true
};

// AxScript code
// ...

Typically, extensions register new commands to call already registered commands. An example of defining a shell command that calls the command ps run -o .... See more details here.

let cmd_shell = ax.create_command("shell", "Execute command via cmd.exe", "shell whoami /all");
cmd_shell.addArgString("cmd_params", true);
cmd_shell.setPreHook(function (id, cmdline, parsed_json, ...parsed_lines) {
    let new_cmd = "ps run -o C:\\Windows\\System32\\cmd.exe /c " + parsed_json["cmd_params"];
    ax.execute_alias(id, cmdline, new_cmd);
});

AxScript and BOFs

You'll likely want to use AxScript to run your finalized BOF implementations within AdaptixC2. A BOF is a good place to implement a lateral movement technique, an escalation of privilege tool, or a new reconnaissance capability.

Each agent has its own command to execute BOF. For example, for a beacon agent it is execute bof. Here is a script to run a screenshot_bof BOF:

var cmd_screenshot = ax.create_command("screenshot_bof", "Alternative screenshot capability that does not do fork n run by @codex_tf2", "screenshot -n screen1 -p 812");
cmd_screenshot.addArgFlagString("-n", "note", "Screenshot caption", "ScreenshotBOF");
cmd_screenshot.addArgFlagInt("-p", "pid", "PID of the application whose window screenshot will be taken. If 0, then a full-screen screenshot", 0);
cmd_screenshot.setPreHook(function (id, cmdline, parsed_json, ...parsed_lines) {
    let note = parsed_json["note"];
    let pid  = parsed_json["pid"];

    let bof_params = ax.bof_pack("cstr,int", [note, pid]);
    let bof_path = ax.script_dir() + "_bin/Screenshot." + ax.arch(id) + ".o";

    ax.execute_alias(id, cmdline, `execute bof ${bof_path} ${bof_params}`, "Task: Screenshot BOF");
});

First, the script gets the note and pid values. The next step is to pack our arguments. The bof_pack function packs arguments in a way that is compatible with Beacon's internal data parser API. This script uses execute_alias to run BOF with its arguments.

Last updated