Henry's Blog
  • CobaltStrike系列
    • CobaltStrike的基本操作
    • CobaltStrike会话管理
    • CobaltStrike重定向服务
    • CobaltStrike钓鱼攻击
    • 凭据导出与存储
    • Beacon的常用操作
    • DnsBeacon详解
    • 权限提升
    • 简单的内网信息收集
    • Cross2生成LinuxShell
    • CNA插件开发
    • Profile编写规则
    • BOF开发
    • execute-assembly原理
    • Vps搭建可能遇到的问题
  • OPSEC(免杀)
    • BypassPPL
    • Certutil绕过技巧
    • DLL劫持技术(白+黑)
    • PEB伪装
    • PpidSpoofing
    • Python反序列化免杀
    • WebShell绕过技巧
    • mimikatz免杀
    • 利用CobaltStrikeProfile实现免杀
    • 利用Windows异常机制实现Bypass
    • 削弱WindowsDefender
    • 模拟Powershell实现Bypass
    • 浅谈CobaltStrikeUDRL
    • 添加用户和计划任务(Bypass)
    • 移除NtDll的hook
    • 定位修改MsfShellcode特征码实现免杀
    • 利用COM接口实现进程断链执行.md
    • 免杀工具篇
      • Invoke-Obfuscation
      • Shellter
    • 流量检测逃避
      • CobaltStrike流量逃避.md
      • MSF流量加密.md
      • NC反弹Shell流量加密.md
  • Shellcode加密
    • 前置知识
    • XOR加密
    • AES加密
  • Shellcode加载器
    • 常见的加载方式
    • 分离加载
    • 创建纤程加载
    • 动态调用API加载
    • 基于APC注入加载
    • 基于反调试加载
    • 基于回调函数加载
    • 基于线程池加载
    • 模块踩踏
    • 进程镂空注入(傀儡进程)
    • 反射dll注入(内嵌式)
  • Web渗透
    • 信息收集
    • 各类Webshell
    • 基本漏洞利用
    • 远程命令执行漏洞
    • sql注入
    • sqlmap的使用方法
  • 内网渗透
    • 内网渗透前置知识
    • BadUsb制作
    • Linux反弹Shell总结
    • 内网渗透技术总结
    • 横向移动
      • GoToHttp
      • MS14-068
      • PassTheHash
      • PassTheTicket
      • Psexec
      • RustDesk
      • SMB横移
      • WMI横移
      • 用户枚举与爆破
    • 流量加密
      • CobaltStrike流量加密
      • MsfShell流量加密
      • OpenSSL加密反弹shell
  • 协议分析
    • TCP_IP协议
  • 权限提升
    • 土豆提权原理
    • UAC提权
  • 蓝队技术
    • 应急响应流程总结
  • 进程注入
    • Conhost注入
    • session0注入
    • 内核回调表注入
    • 剪切板注入
  • 逆向技术
    • HOOK技术
    • IDA遇到的坑
    • Shellcode的原理与编写
    • Windbg的使用
    • 使用Stardust框架编写Shellcode
    • PeToShellcode
    • 破解系列
      • PUSH窗体大法
      • VM绕过技巧(易语言)
      • Crackme_1
      • 反破解技术
      • 按钮事件特征码
      • 逆向调试符号
      • 破解实例
        • IDA逆向注册码算法
  • 钓鱼技术
    • Flash网页钓鱼
    • LNK钓鱼
    • 自解压程序加载木马
  • 隧道应用
    • 隧道应用前置知识
    • BurpSuite上游代理
    • DNS隧道传输
    • EarthWorm内网穿透
    • Frp内网穿透
    • ICMP隧道传输
    • MsfPortfwd端口转发
    • Neo-reGeorg内网穿透
    • NetCat工具使用
    • Netsh端口转发
    • SSH端口转发
    • 正向连接与反向连接
  • 基础学习
    • C和C++
      • C++编程
      • C程序设计
    • Linux学习
      • Linux Shell编程
      • linux基础
    • Python基础
      • python之Socket编程
      • python之多线程操作
      • python基础
      • python算法技巧
    • Qt基础
      • Qt笔记
    • 逆向基础
      • PE结构
      • Win32
      • 汇编语言
  • 漏洞复现
    • Web漏洞
      • ApacheShiro反序列化漏洞
    • 系统漏洞
      • Linux漏洞
        • ShellShock(CVE-2014-6271)
  • 靶场系列
    • Web靶场
      • pikachu靶场
      • sqli-labs
      • upload-labs
    • 内网靶场
      • Jarbas靶场
      • SickOS靶场
      • W1R3S靶场
      • prime靶场
      • vulnstack靶场系列一
      • vulnstack靶场系列二
      • vulnstack靶场系列四
  • 代码审计
    • PHP代码审计基础
  • 一些杂七杂八的
    • 开发工具与环境
      • Github的使用
      • JSP环境搭建
      • Pycharm设置代码片段
      • VS2017安装番茄助手(破解版)
      • VisualStudio项目模板的使用
      • WindowsServer搭建IIS环境
      • 安装Scoop
      • c++安装vcpkg
      • dotnet-cnblog的安装与使用
      • gitbook使用教程
      • kali安装burpsuite
      • 配置win2012域服务器
      • VSCode配置MinGW
    • 踩坑记录
      • BurpSuite导入证书
      • Powershell禁止执行脚本
      • centos7没有显示ip
      • kali安装pip2
      • oracle12没有scott用户
由 GitBook 提供支持
在本页
  • 前言
  • 环境准备
  • 使用步骤
  • 踩坑记录
  • 1.bof应尽量使用C语言
  • 2.inline-execute无法接收参数?
  • 3.报错:Unknown symbol '__chkstk'
  • 参考链接
  1. CobaltStrike系列

BOF开发

上一页Profile编写规则下一页execute-assembly原理

最后更新于1年前

前言

Beacon Object File(BOF) 从Cobalt Strike4.1开始所添加的新功能,它允许你使用C语言编写扩展来扩展Beacon的功能。这些扩展可以在运行时直接加载到Beacon的内存中并执行,无需在目标机器的磁盘上创建任何文件

BOF的一个关键特性是它的运行时环境非常有限。它不能直接调用Windows API,而只能通过Cobalt Strike提供的一组函数来与操作系统进行交互。这样做的原因是为了防止BOF在运行时出错导致Beacon崩溃。然而,尽管这种限制使得编写BOF相对复杂一些,但BOF仍然是一个非常强大的工具,可以用来添加各种自定义功能到Beacon中

一旦BOF编译完成,你可以通过Beacon的"inline-execute"命令来加载并执行BOF。这个命令会将BOF上传到Beacon的内存中并立即执行它,无需将BOF写入到磁盘

环境准备

Github上有很多开发BOF的项目,这里我推荐以下两个项目,前者是开发bof的VisualStuido项目模板,此模板对BOF函数进行了宏定义,这样我们可以像使用C语言一样来开发BOF项目;后者是开发BOF项目所需的头文件,如果此项目更新了,我们可以将此项目的头文件替换掉模板项目的头文件

  • bof的visual studio模板:https://github.com/securifybv/Visual-Studio-BOF-template

  • bof所需的头文件:https://github.com/trustedsec/CS-Situational-Awareness-BOF

不过我更加推荐使用evilashz师傅整理好的模板:https://github.com/evilashz/Visual-Studio-BOF-template

此模板通过DLL名称将WindowsApi函数进行了归类,例如kernel32.dll的导出函数定义就写在kernel32.h里

在函数定义里可以发现有加上KERNEL32$这种前缀,为何CobaltStrike的Bof要使用这种前缀呢,个人推测原因有以下两点:

  • 直接调用: 通过这种方式,BOF可以直接调用DLL中的原生函数,而不需要在BOF的导入表中声明它们。这有助于BOF保持小型和轻量级。

  • 隐蔽性: 使用这种前缀来直接调用API函数可以增加对某些安全解决方案的隐蔽性,因为它们可能不会检测到这些不常见的调用模式

beacon.h定义了与Cobalt Strike Beacon交互所需要的各种数据类型和函数

具体来说,这个文件包含了以下部分:

  • 数据API:这部分定义了一个数据结构(datap),以及一些函数,这些函数用于解析和操作这种数据结构。datap 结构包含原始缓冲区的指针,当前缓冲区的指针,剩余的数据长度,以及缓冲区的总大小。

  • 格式API:这部分定义了一个格式化数据的结构(formatp),以及一些函数,这些函数用于分配、重置、释放和操作这种数据结构。formatp 结构与 datap 结构非常相似,但它是用于格式化数据,而不是解析数据。

  • 输出函数:这部分定义了一些宏和函数,用于向 Beacon 的输出流中输出数据。函数 BeaconPrintf 和 BeaconOutput 可以分别用于格式化输出和二进制输出。

  • 令牌函数:这部分定义了一些函数,用于在 Beacon 中使用和操作 Windows 访问令牌。这些函数包括 BeaconUseToken(使用指定的令牌)、BeaconRevertToken(恢复到之前的令牌)、BeaconIsAdmin(检查当前令牌是否具有管理员权限)。

  • 注入函数:这部分定义了一些函数,用于在新的或已经存在的进程中注入 payload。这些函数包括 BeaconGetSpawnTo(获取 Beacon 的 SpawnTo 设置)、BeaconInjectProcess(在指定进程中注入 payload)、BeaconInjectTemporaryProcess(在临时进程中注入 payload)、BeaconCleanupProcess(清理进程信息)。

  • 实用函数:这部分定义了一些实用函数,例如 toWideChar(将一个字符串转换为宽字符字符串)。

bofdefs.h文件定义了许多函数,这些函数实际上是 Windows API 的宏定义,它们使得开发者能够在 Beacon Object File(BOF)中方便地调用 Windows API,就像使用C语言一样

使用步骤

将下载的模板文件解压至visualstudio的模板目录(%UserProfile%\Documents\Visual Studio 2022\Templates\ProjectTemplates),随后重启VisualStuido

在创建项目时选择类型为Beacon Object File的项目

在头文件列表可以看到beacon.h和bofdefs.h

打开项目的Batch生成,勾选上BOF配置。配置管理器的编译环境也需设置为BOF

以下是一个简单的bof项目,用于实现向控制台输出字符串

  • BOF入口:代码定义了BOF的入口函数go,当你在Cobalt Strike中使用inline-execute命令加载并执行你的BOF时,这个函数将被调用。你可以在这个函数中添加你的BOF代码

  • 非BOF入口:这部分代码定义了非BOF的入口函数main。当你在非Cobalt Strike环境中运行你的代码时,这个函数将被调用。你可以在这个函数中添加你的非BOF代码

#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


#ifdef BOF
void go(char* buff, int len) {
	BeaconPrintf(CALLBACK_OUTPUT, "Hello, World!");
}


#else

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

#endif

项目生成后会生成一个.obj文件,也就是编译未链接的目标文件,在CobaltStrike中你可以使用inline-execute命令来加载并执行你的.obj文件,此命令将你的 .obj 文件加载到 Beacon 的内存中,然后调用你的 go 函数,命令格式如下所示

beacon> inline-execute your_bof.obj

踩坑记录

1.bof应尽量使用C语言

编写bof时应该尽量使用C语言来编写,如果你使用C++来编写很可能会出现如下图所示的错误:Could not resolve API

这是因为C++为了支持函数重载,会对函数名进行修饰,从而导致函数的实际名称与你在代码中看到的名称不同,因此当你尝试在BOF解析某个函数时,可能会找不到它

2.inline-execute无法接收参数?

如下是一个简单的bof项目源码,用于在beacon命令行输出bof接收的参数

void go(char* buff, int len) {

	// datap是BOF框架中定义的结构体,用于解析从Beacon接收到的数据
	// 当你在Beacon执行BOF时,可以向BOF传递一些参数,这些参数会被打包成一个字节流
	// BOF会使用datap结构体来解析这个字节流,从而获取到传递的参数
	datap parser;

	wchar_t* username;
	wchar_t* password;

	// 初始化datap结构体变量(parser),用于解析从Beacon接收到的字节流(buff)
	BeaconDataParse(&parser, buff, len);
	username = (wchar_t*)BeaconDataExtract(&parser, NULL);
	password = (wchar_t*)BeaconDataExtract(&parser, NULL);

	BeaconPrintf(CALLBACK_OUTPUT, "Extracted username: %S", username);
	BeaconPrintf(CALLBACK_OUTPUT, "Extracted password: %S", password);
}

但是从输出结果来看,bof并没有接收到参数,而是显示(null)。所以说,如果要给BOF传递参数,还是得使用CNA脚本的bof_pack函数来打包参数,然后使用beacon_inline_execute函数来执行BOF

3.报错:Unknown symbol '__chkstk'

当你执行bof项目时可能会遇到如下图所示的错误,其根本原因出在你bof的源码上,当你的源代码使用大量的局部变量或数组时,编译器会插入一个__chkstk调用来确保有足够的堆栈空间。而在BOF中,由于我们没有完整的C运行时环境,所以这个函数是不存在的

当时我的bof源码定义了个特别大的局部数组,如下代码所示

WCHAR output[4096] = {0};

为了解决这个问题,应该减少局部变量的大小,使用动态内存分配来创建所需的数组,比如HeapAlloc和HeapFree,更正后的代码如下:

WCHAR *output = (WCHAR *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 4096 * sizeof(WCHAR));

参考链接

  • http://mp.weixin.qq.com/s?__biz=MzI5NzU0MTc5Mg==&mid=2247484673&idx=1&sn=d1628ed1f77c638ba414185bfeabf8ee&chksm=ecb2cccedbc545d89bd098632be7fb23c273e585a4f2167089b39d483c42deac13b6078ba3b5&scene=126&sessionid=1658057738&key=ffca75888bc216b14d1a0902587e61caf0fefe2cfd31cfccaef08baab2efb4a9952f320749796d966ba2829cd33e4a301cc25916b74879ea9c6bd6de9d2f06ca9beb159028a59e4ce006bc8276b59ee20d18fba2db40dbeccec3351295fad8192f098aee34bfed114a7c0c700ba46bc16f0a9a660f7801c96a668a64fd5a1a7c&ascene=15&uin=MTA3Mzc3OTIzNQ%3D%3D&devicetype=Windows+Server+2016+x64&version=6307001e&lang=zh_CN&session_us=gh_5b8184332bc1&exportkey=AaYcTeWdxPQAKdPy7RMIrxs%3D&acctmode=0&pass_ticket=H5DatfK1H7UD%2FQIL%2B8Md2%2BlWZOBY12u%2F%2FD4TQgyDk5zYF8C5%2BgX4U3zhXOnsq%2BtU&wx_header=0&fontgear=2

image-20230818102012570
image-20230818102755777
image-20230818103047212
image-20230726233950177
image-20230726234108233
image-20230726235028577
image-20230727091013243
image-20230818094623207
image-20230818100321336
image-20230819221112051