CS 4.1 BOF开发

  1. BOF介绍
  2. BOF是如何执行的
  3. BOF缺陷
  4. 准备环境
  5. 前置知识
  6. 参考链接

BOF介绍

信标对象文件 (BOF) 是一个已编译的 C 程序,按照约定编写,允许它在信标进程中执行并使用内部信标 API。BOF 是一种使用新的后开发功能快速扩展 Beacon 代理的方法。

BOF是如何执行的

对于 Beacon 来说,BOF 只是一个位置无关的代码块,它接收指向某些 Beacon 内部 API 的指针。
对于 Cobalt Strike 而言,BOF 是由 C 编译器生成的目标文件。Cobalt Strike 解析此文件并充当其内容的链接器和加载器。这种方法允许您编写与位置无关的代码,用于 Beacon,而无需繁琐的体操来管理字符串和动态调用 Win32 API。

BOF缺陷

  1. BOF 是调用 Win32 API 和有限 Beacon API 的单文件 C 程序。不要期望使用此机制链接其他功能或构建大型项目。
  2. Cobalt Strike 不会将您的 BOF 链接到 libc。这意味着您仅限于编译器内部函数(例如,Visual Studio 上的 __stosb for memset)、公开的 Beacon 内部 API、Win32 API 以及您编写的函数。您可能无法通过 BOF 使用许多常用函数(例如 strlen、stcmp 等)。
  3. BOF 在您的 Beacon 代理内部执行。如果 BOF 崩溃,有可能导致Beacon崩溃
  4. Cobalt Strike 期望您的 BOF 是短时间运行的单线程程序。BOF 将阻止其他 Beacon 任务和功能的执行。异步或长时间运行的任务没有 BOF
    模式。如果要构建长时间运行的功能,请考虑在牺牲进程内运行的反射 DLL。

编译的方式

要使用 Visual Studio 编译它:
cl.exe /c /GS- hello.c /Fohello.o

要使用 x86 MinGW 编译它:
i686-w64-mingw32-gcc -c hello.c -o hello.o

要使用 x64 MinGW 编译它:
x86_64-w64-mingw32-gcc -c hello.c -o hello.o

x64 beacon对应加载x64 gcc编译的bof文件,x86 beacon对应加载x86 gcc编译的bof文件

准备环境

* cs 4.1或者以上的版本
* 从官方下载beacon.h -> https://www.cobaltstrike.com/downloads/beacon.h

前置知识

cna主要使用的几个函数和过程:
先了解几个函数:

* bof_pack - 打包参数传入到BOF里的函数
* beacon_inline_execute - 调用BOF里面的函数

bof_pack
$1 - Beacon ID
$2 - 打包数据的格式化字符串 -> (例如Socket里的Packet操作)

此函数将其参数打包成一个二进制结构,以便与&beacon_inline_execute一起使用。此处的格式字符串选项对应于 BOF 文件可用的 BeaconData* C API。该 API 根据它可以打包的每种类型的要求处理数据和提示的转换。

文档链接:https://www.cobaltstrike.com/aggressor-script/functions.html#bof_pack

beacon_inline_execute
$1 - Beacon ID
$2 - 读取了BOF文件的数据
$3 - 要调用的函数名称
$4 - 要传递给BOF文件的打包参数

执行信标对象文件

文档链接:https://www.cobaltstrike.com/aggressor-script/functions.html#beacon_inline_execute

BOF文件示例(有参数调用,无Windows API调用):

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


void demo(char * args, int length) {
    datap  parser; #参数结构定义
    char * str_arg;
    int    num_arg;


    BeaconDataParse(&parser, args, length); #准备数据解析器以从指定缓冲区中提取参数
    str_arg = BeaconDataExtract(&parser, NULL); #参数解析赋值于str_arg对应bof_pack函数参数2里的格式化字符串z
    num_arg = BeaconDataInt(&parser); #参数解析赋值于num_arg对应bof_pack函数参数2里的格式化字符串i


    BeaconPrintf(CALLBACK_OUTPUT, "Message is %s with %d arg", str_arg, num_arg);
}

cna文件示例:
cna调用BOF文件函数过程:

* 先读取bof文件内容
* 调用的函数是否需要参数
* 调用函数入口点
alias hello {
    btask($1, script_resource("demo.o"));

    $handle = openf(script_resource("demo.o")); #读取BOF文件
    $data   = readb($handle, -1); #读取BOF文件内容
    closef($handle);


    $args = bof_pack($1, "zi", "Raiden Mei Birthday", 413); #参数打包

    btask($1, "Running Hello BOF");

    beacon_inline_execute($1, $data, "demo", $args); #调用BOF文件入口点
}

效果如下:

调用Windows API
下载https://github.com/dtmsecurity/bof_helper,执行输入API转换获取BOF里的格式
(自己测试的时候获取失败了,不过看了一下人手转BOF格式也可以)

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*);

例如CreateProcessA

BOOL CreateProcessA(
  LPCSTR                lpApplicationName,
  LPSTR                 lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL                  bInheritHandles,
  DWORD                 dwCreationFlags,
  LPVOID                lpEnvironment,
  LPCSTR                lpCurrentDirectory,
  LPSTARTUPINFOA        lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);

到了BOF就变成这样
DECLSPEC_IMPORT WINBASEAPI <类型> <API类型> DLL名$<从DLL里面导出的API名称>

DECLSPEC_IMPORT WINBASEAPI BOOL WINAPI KERNEL32$CreateProcessA(
  LPCSTR                lpApplicationName,
  LPSTR                 lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL                  bInheritHandles,
  DWORD                 dwCreationFlags,
  LPVOID                lpEnvironment,
  LPCSTR                lpCurrentDirectory,
  LPSTARTUPINFOA        lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);

更多示例

DECLSPEC_IMPORT WINBASEAPI void * __cdecl MSVCRT$memset(void *_Dst,int _Val,size_t _Size);

DECLSPEC_IMPORT WINBASEAPI WINBOOL WINAPI KERNEL32$CreateProcessA (LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, WINBOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation);

DECLSPEC_IMPORT WINBASEAPI LPVOID WINAPI KERNEL32$VirtualAllocEx (HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);

DECLSPEC_IMPORT WINBASEAPI WINBOOL WINAPI KERNEL32$WriteProcessMemory (HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten);

DECLSPEC_IMPORT WINBASEAPI DWORD WINAPI KERNEL32$QueueUserAPC (PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
DECLSPEC_IMPORT WINBASEAPI DWORD WINAPI KERNEL32$ResumeThread (HANDLE hThread);

demo2.c (无参数,windows API调用)

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


DECLSPEC_IMPORT WINBASEAPI BOOL WINAPI KERNEL32$CreateProcessA(
  LPCSTR                lpApplicationName,
  LPSTR                 lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL                  bInheritHandles,
  DWORD                 dwCreationFlags,
  LPVOID                lpEnvironment,
  LPCSTR                lpCurrentDirectory,
  LPSTARTUPINFOA        lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);


void demo(char * args, int length) {
    STARTUPINFOA si = { 0 };
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi = { 0 };
    BOOL Test = KERNEL32$CreateProcessA(NULL, "C:\\Windows\\System32\\notepad.exe", NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);

}

demo.cna

alias hello {
    btask($1, script_resource("demo2.o"));

    $handle = openf(script_resource("demo2.o"));
    $data   = readb($handle, -1);
    closef($handle);


    $args = bof_pack($1, "zi", "", 0);

    btask($1, "Running Hello BOF");

    beacon_inline_execute($1, $data, "demo", $args);
}

参考链接

https://www.cobaltstrike.com/help-beacon-object-files
https://www.cobaltstrike.com/aggressor-script/functions.html
http://evilash.me/2020/08/18/BOF.html
https://github.com/boku7/HOLLOW/blob/main/hollow.x64.c - 这个例子不错


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。

文章标题:CS 4.1 BOF开发

本文作者:九世

发布时间:2021-07-28, 21:54:39

最后更新:2021-07-28, 22:08:51

原始链接:http://jiushill.github.io/posts/e42bb01c.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录