CCob/BOF.NET

GitHub: CCob/BOF.NET

为 Cobalt Strike Beacon Object Files 提供 .NET 运行时环境,让安全研究人员可以用托管代码快速开发 BOF,免去了原生编译的复杂性。

Stars: 772 | Forks: 111

# BOF.NET - Cobalt Strike Beacon Object Files 的 .NET 运行时 ## 简介 BOF.NET 是一个小型的原生 BOF 对象,结合了 BOF.NET 托管运行时,支持直接在 .NET 中开发 Cobalt Strike BOF。BOF.NET 免去了原生编译的复杂性以及手动导入原生 API 的麻烦。测试 BOF.NET 程序集通常也要容易得多,因为 .NET 程序集可以使用传统的托管调试器进行调试。 ## Cobalt Strike 兼容性 BOF.NET 1.1.3 及以下版本兼容 Cobalt Strike 4.8 及以下版本。BOF.NET 1.2.0+ 版本兼容 4.9+ 版本,因为现在使用了 Beacon API 的 `BeaconGetValue` 和 `BeaconAddValue`。 ## 快速开始 实现你的第一个 BOF.NET 类非常简单。从 [BOFNET NuGet](https://www.nuget.org/packages/BOFNET) 包中添加对 BOF.NET 运行时 DLL 的引用,并创建一个继承自 `BeaconObject` 的类。需要一个带有 `BeaconApi` 对象作为唯一参数的强制性构造函数。该参数应传递给 `BeaconObject` 基类构造函数。 最后,重写 `Go` 函数。参数将为你预先处理,就像 `Main` 函数在普通 .NET 程序集中的行为一样。 ``` namespace BOFNET.Bofs { public class HelloWorld : BeaconObject { public HelloWorld(BeaconApi api) : base(api) { } public override void Go(string[] args) { BeaconConsole.WriteLine($"[+] Welcome to BOF.NET { (args.Length > 0 ? args[0] : "anonymous" )}"); } } } ``` 编译好 BOF.NET 程序集后,从发布页面或 nuget.org 下载 .nupkg。使用你喜欢的解压软件打开该包,并提取 lib 文件夹的内容。将你首选目标框架文件夹中的 BOFNET.DLL 移动到与 .cna 和 BOF obj 文件相同的文件夹中。最终的结构应该如下所示。 ``` . +-- | +-- BOFNET.dll | +-- bofnet.cna | +-- bofnet_execute.cpp.x86.obj | +-- bofnet_execute.cpp.x64.obj ``` 将 bofnet.cna aggressor 脚本加载到 Cobalt Strike 中,即可开始使用你的 BOF.NET 类。 在任何 BOF.NET 类被使用之前,需要在 beacon 实例中初始化 BOF.NET 运行时。 ``` bofnet_init ``` 一旦运行时加载完成,你可以继续加载更多的 .NET 程序集,包括其他 BOF.NET 类。BOF.NET 现在支持分块加载程序集,因此也可以加载大型程序集(1M+)。 ``` bofnet_load /path/to/bofnet/HelloWorld.dll ``` 你可以使用 `bofnet_listassemblies` 别名确认库是否已加载。可以通过执行 `bofnet_list` 别名来显示实现了 `BeaconObject` 的完整类列表。 最后,一旦确认程序集已加载且 BOF.NET 类可用,你就可以执行它了。 ``` bofnet_execute BOFNET.Bofs.HelloWorld @_EthicalChaos_ ``` 你也可以只使用类名的简写方式,但这仅在只有一个同名 BOF.NET 类存在时才有效。 ``` bofnet_execute HelloWorld @_EthicalChaos_ ``` ## Cobalt Strike 客户端集成 BeaconObject 类实现了一些功能,允许自定义实现屏幕截图、文件下载(来自内存 😊)、键盘记录器和哈希转储。例如,如果内置的键盘记录器或屏幕截图实现导致 Windows Defender 或其他 AV 引擎查杀你的 beacon,你可以实现自己的版本。相关函数记录如下。 ``` void SendScreenShot(byte[] jpgData, int session, string userName, string title) ``` * `jpgData` 原始 JPEG 图像数据。 * `session` 截取屏幕截图的用户会话 ID。 * `userName` 在该会话下运行的用户名。 * `title` 用于屏幕截图的窗口标题。 ``` SendKeystrokes(string keys, int session, string userName, string title) ``` * `keys` 捕获的按键序列。 * `session` 截取屏幕截图的用户会话 ID。 * `userName` 在该会话下运行的用户名。 * `title` 捕获按键所在的应用程序窗口标题。 ``` DownloadFile(string fileName, Stream fileData) ``` * `fileName` 用于 beacon 中元数据的文件名。 * `fileData` 用于文件内容的可读流。 `DownloadFile` 将锁定 beacon 并使其在下载完成前无响应! ``` SendHashes(UserHash[] userHashes) ``` * `userHashes` 已捕获的用户名集合。 ## Beacon 命令参考 | 命令 | 描述 | |----------------------------------------|--------------------------------------------------------------------------| | bofnet_init | 在 beacon 进程内初始化 BOF.NET 运行时 | | bofnet_list | 列出所有可执行的 BOF.NET 类 | | bofnet_listassembiles | 列出当前加载到 BOF.NET 运行时中的程序集 | | bofnet_execute *bof_name* [*args*] | 执行 BOF.NET 类,可提供可选参数 | | bofnet_load *assembly_path* | 从内存中将额外的 .NET 程序集加载到 BOF.NET 运行时中。 | | bofnet_shutdown | 关闭 BOF.NET 运行时 | | bofnet_job *bof_name* [*args*] | 将 BOF.NET 类作为后台作业(线程)执行 | | bofnet_jobs | 列出所有当前活动的 BOF.NET 作业 | | bofnet_jobstatus *job_id* | 转储后台作业中任何挂起的控制台缓冲区 | | bofnet_jobkill *job_id* | 转储后台作业中任何挂起的控制台缓冲区,然后终止该作业。警告:当终止已转换为本机代码的线程时,可能会导致死锁 | | bofnet_boo *booscript.boo* | 在单独的临时 AppDomain 中编译并执行 Boo 脚本 | | bofnet_vfs_add *local_path* *vfs_filename* *content_type* | 从操作员机器添加文件并存储在 BOFNET VFS 中 | ## 内置 BOFS ### VFS 引入了基本的内存文件/blob 存储概念。其他 BOF(如 WebServer BOF)可以使用此功能来托管内存中的文件。 #### 示例 将文件添加到 BOF.NET VFS 并存储为 `application/octet-stream` MIME 类型 ``` bofnet_vfs_add c:\tools\BOFNET.dll BOFNET.dll application/octet-stream ``` 列出 VFS 中的所有文件 ``` bofnet_execute VFS list ``` 下载存储在 VFS 中的 `BOFNET.dll` 文件 ``` bofnet_execute VFS download BOFNET.dll ``` ### 截图 (Screenshot) 功能如其名,简单的截图功能。 ### WebServer 利用 Microsoft 的 HTTP Server API 托管内存中的 Web 服务器。存储在 BOF.NET VFS 中的文件由该 Web 服务器托管。 #### 示例 ``` bofnet_job HttpServer http://localhost:1337/ ``` ![WebServer](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/af7f8bd873123049.png) ## 注意事项 根据目标操作系统的不同,应使用相应的发行版(net35/net40)。运行时将尝试使用作为 .NET v4 一部分提供的 `CLRCreateInstance` 函数来创建 .NET v4 CLR。如果找不到该函数,则使用较旧的机制来初始化 .NET v2。目前,原生组件无法动态确定要加载哪个托管运行时,因此请确保使用正确的发行版文件夹。完全更新的 Windows 7 通常会安装 .NET 4,因此在大多数情况下,你需要 dist 文件夹中的 net461 文件夹。像 XP 这样的旧操作系统则取决于已安装的内容。 BOF.NET 将遵循与其原生 BOF 对应项相同的限制。BOF.NET 类的执行在内部使用 `inline_execute` 功能。因此,任何 BOF.NET 调用都会阻塞 beacon,直到其完成。 BOF.NET 确实有一个额外的好处,即加载的程序集保持持久化。这有助于在 BOF.NET 类中使用线程,而无需担心程序集在 `Go` 函数完成后被卸载。但是你**不能**写入 beacon 控制台或使用任何其他 beacon BOF API,因为这些在 BOF 返回后早已被 Cobalt Strike 释放。 如果你想使用线程将 BOF.NET 类作为后台作业执行,请使用 `bofnet_job` 命令。这会将调用封装在一个单独的线程中,并为你透明地处理 `BeaconConsole` 写入。请注意长时间运行的作业和大量的控制台输出,因为控制台缓冲区会被缓存,直到调用 `bofnet_jobstatus`。 ## BOF.NET 是如何工作的? BOF.NET 包含一个小型的原生 BOF,充当通往托管世界的桥梁。当调用 `bofnet_init` 时,这将在 beacon 运行的进程内启动托管 CLR 运行时。一旦 CLR 启动,就会创建一个单独的 .NET AppDomain 来托管由 BOF.NET 加载的所有程序集。随后,BOF.NET 运行时程序集从内存加载到 AppDomain 中,以支持 BOF.NET 的其余功能。没有任何 .NET 程序集是从磁盘加载的。 此后所有未来的 BOF.NET 调用通常由 `BOFNET.Runtime` 类中的 `InvokeBof` 方法处理。这使得原生 BOF 代码保持小巧简洁,并将所有运行时逻辑推送到托管 BOF.NET 运行时中。 ## 构建 BOF.NET 使用 CMake 构建系统以及 MinGW GCC 编译器来生成 BOF 文件,并使用 .NET core msbuild 项目类型来构建托管运行时。因此,在构建之前,需要满足所有这些先决条件并在 PATH 中可用。 从检出目录的根目录发出以下命令: ### Windows ``` mkdir build cd build cmake -DCMAKE_BUILD_TYPE=MinSizeRel -G "MinGW Makefiles" .. cmake --build . cmake --install . ``` ### Linux 在 Linux 上,我们利用 CMake 工具链文件通过 mingw 编译器交叉编译原生 BOF 对象。对于托管组件,请确保已从 .NET core 安装了 dotnet 命令行工具。 ``` mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX=$PWD/install -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_TOOLCHAIN_FILE=../toolchain/Linux-mingw64.cmake .. cmake --build . cmake --install . ``` ### Docker 如果你更愿意在 Linux 上使用预装了所有构建依赖项的 docker 镜像进行构建,可以使用 `ccob/windows_cross` 镜像。 ``` docker run --rm -it -v $(pwd):/root/bofnet ccob/windows_cross:latest /bin/bash -c "cd /root/bofnet; mkdir build; cd build; cmake -DCMAKE_INSTALL_PREFIX=$PWD/install -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_TOOLCHAIN_FILE=../toolchain/Linux-mingw64.cmake ..; cmake --build .; cmake --install ." ``` 完成这些步骤后,`build\dist` 文件夹应包含构建产物,并应准备好在 Cobalt Strike 中使用。 ## 参考 * https://modexp.wordpress.com/2019/05/10/dotnet-loader-shellcode/ - 使用原生原始 COM 接口创建 CLR * https://gist.github.com/sysenter-eip/1a985a224c67aa78f62be83f190b6e86 - 声明 BOF 导入的绝佳技巧
标签:Bash脚本, Beacon API, Beacon Object Files, BOF, Cobalt Strike, CTF学习, DNS 解析, Gophish, HTTP工具, Malware Development, Raspberry Pi, UML, XML 请求, 内存执行, 内网渗透, 加载器, 可信计算, 多人体追踪, 安全开发, 客户端加密, 客户端加密, 攻击模拟, 攻击诱捕, 数据展示, 欺骗防御, 红队, 运行时, 远程控制, 驱动签名利用