Write, debug and execute BOFs using bof-launcher (part 1)
Our bof-launcher project allows you to write, build, debug and execute BOFs using Zig, C and/or assembly language on Windows (x86/x64) and Linux (x86/x64/ARM/AARCH64).
Prerequisites
The only dependency is Zig compiler package (version 0.13.0 is required) which can
be downloaded from here.
This package contains Zig/C/C++ compilers in one executable
and supports cross-compilation out of the box (single zig
executable can produce
binaries for any supported target).
First steps
Add zig
executable from the package to your PATH
environment variable and run:
git clone https://github.com/The-Z-Labs/bof-launcher
cd bof-launcher
zig build
The last command will build bof-luncher library, sample BOFs and example programs
for all supported platforms in ReleaseSmall configuration.
Check zig-out
directory for build artifacts.
To execute one of the included BOFs run:
(Windows)
.\zig-out\bin\integration_with_c_win_x64.exe .\zig-out\bin\test_obj0.coff.x64.o
(Linux)
./zig-out/bin/integration_with_c_lin_x64 zig-out/bin/test_obj0.elf.x64.o
You should get output similar to the below:
<bof-filename>: .\zig-out\bin\test_obj0.coff.x64.o
File size is: 7129
Running BOF from command line C application...
--- test_obj0.zig ---
Hello, go!
func() it
Writting and building your first BOFs
Using Zig:
const beacon = @import("bof_api").beacon;
pub export fn go(_: ?[*]u8, _: i32) callconv(.C) u8 {
_ = beacon.printf(0, "hello, bof!\n");
return 0;
}
Using C:
#include "beacon.h"
unsigned char go(unsigned char* arg_data, int arg_len) {
BeaconPrintf(0, "hello, bof!\n");
return 0;
}
Save above files as:
bofs/src/firstBof.zig
bofs/src/firstBofC.c
We also support writing BOFs in assembly langauge (fasm) but this is a bit more advanced topic and will be described in one of the future posts. For now, take a look at sample BOFs if you are interested:
- bofs/src/wDirectSyscall.asm
- bofs/src/lAsmTest.asm
- bofs/src/process-injection-chain/wInjectionChainStage1A.asm
To add BOFs to the build system you need to edit bofs/build.zig file.
Add below lines to the definition of bofs_my_custom
array in this file. It should look like this:
const bofs_my_custom = [_]Bof{
.{ .name = "firstBof", .formats = &.{ .elf, .coff }, .archs = &.{ .x64, .x86, .aarch64, .arm } },
.{ .name = "firstBofC", .formats = &.{ .elf, .coff }, .archs = &.{ .x64, .x86, .aarch64, .arm } },
};
This will instruct the build system to build both BOFs for all supported platforms.
From the root directory of the bof-launcher
tree run:
zig build
BOFs will show up in zig-out/bin
directory as:
firstBof.coff.x86.o
firstBof.coff.x64.o
firstBof.elf.x86.o
firstBof.elf.x64.o
firstBof.elf.arm.o
firstBof.elf.aarch64.o
firstBofC.coff.x86.o
firstBofC.coff.x64.o
firstBofC.elf.x86.o
firstBofC.elf.x64.o
firstBofC.elf.arm.o
firstBofC.elf.aarch64.o
To run your BOFs you can use integration_with_c
example program:
.\zig-out\bin\integration_with_c_win_x64.exe .\zig-out\bin\firstBof.coff.x64.o
.\zig-out\bin\integration_with_c_win_x64.exe .\zig-out\bin\firstBofC.coff.x64.o
The source code of this program shows how to use bof-launcher library C API. Take a look at: examples/integration-with-c/main.c if you are interested.
Debugging BOFs
So far we have been building BOFs in ReleaseSmall configuration which is a default mode when you run:
zig build
This is equivalent to:
zig build -Doptimize=ReleaseSmall
In this mode all the BOFs are compiled to object files (COFF or ELF) with binary size optimizations and speed optimizations enabled.
You can also build BOFs as standalone executables with full debug symbols. To do so, run:
zig build -Doptimize=Debug
You can now run any BOF directly, for example:
.\zig-out\bin\test_obj0.coff.x64.exe
You can debug your BOFs in Visual Studio, WinDbg, gdb or any other debugger.
For example, to debug in WinDbg you can use below command:
WinDbgX.exe .\zig-out\bin\helloBof.coff.x64.exe
And then, inside WinDbg:
bp go
g
To debug in Visual Studio open BOF executable (File->Open->Project/Solution…), add new Function Breakpoint (CTRL+K, B) at go()
and press F5.
If you want to debug on Linux in gdb, do:
gdb ./zig-out/bin/helloBof.elf.x64
And then inside gdb:
b go
run
Summary
This is all I wanted to show in the first part. We now know how to build the project, how to add our own custom BOFs to the build system and how to run/debug BOFs.
In the next part we will see how to pass arguments to the BOF, how to use bof-launcher library in an external project and we will also look at some unique features/extensions that bof-launcher project provides. Thanks for reading and stay tuned!