Cobalt Strike Beacon重构之Bof功能开发
字数 2513 2025-09-01 11:26:02

Cobalt Strike Beacon BOF功能开发详解

0x01. 前言

本文详细解析Cobalt Strike Beacon的BOF(Bypass Object File)功能开发,涵盖BOF介绍、开发流程、COFF文件格式解析、重定位处理机制以及Cobalt Strike客户端的处理逻辑。通过本文,您将全面掌握BOF开发的核心技术。

0x02. BOF介绍

BOF(Bypass Object File)本质上是一个COFF(Common Object File Format)文件,即编译后但未链接的目标文件(.obj)。在Cobalt Strike中,通过inline-execute命令可以将BOF文件加载到Beacon内存中,经过修复后执行。

BOF的优势:

  • 提高OPSEC(操作安全性),避免执行高危指令如shell
  • 为红队测试人员提供高度可扩展性
  • 内存中执行,减少磁盘痕迹

0x03. BOF开发基础

开发环境准备

可以使用Visual Studio或MinGW进行BOF开发,生成.obj文件。推荐使用以下模板项目:

基本开发流程

  1. 编写C/C++代码
  2. 编译生成.obj文件
  3. 使用PEView等工具查看COFF格式
  4. 通过inline-execute命令执行BOF

0x04. Beacon内部API

BOF可以调用一系列Beacon内部API,这些API分为以下几类:

1. Win32 API

主要用于函数动态解析:

DECLSPEC_IMPORT WINAPI NETAPI32$DsGetDcNameA(...);
DECLSPEC_IMPORT WINAPI NETAPI32$NetApiBufferFree(...);

2. 数据解析API

  • BeaconDataParse
  • BeaconDataPtr

3. 内容格式化API

  • BeaconFormatAlloc
  • BeaconFormatReset

4. 打印输出API

  • BeaconOutput
  • BeaconPrintf

5. Beacon内部功能API

  • BeaconUseToken
  • BeaconRevertToken
  • BeaconSpawnTemporaryProcess

6. 辅助性API

  • toWideChar

0x05. COFF文件格式详解

文件头结构

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;              // 目标机器类型(0x14C=x86, 0x8664=x64)
    WORD    NumberOfSections;     // 节区数量
    DWORD   TimeDateStamp;        // 时间戳
    DWORD   PointerToSymbolTable; // 符号表指针
    DWORD   NumberOfSymbols;      // 符号数量
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} IMAGE_FILE_HEADER;

节表结构

typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[8];              // 节区名称(UTF-8编码,占满8字节)
    union {
        DWORD   PhysicalAddress;
        DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;       // COFF中通常为0
    DWORD   SizeOfRawData;        // 节在文件中的大小
    DWORD   PointerToRawData;     // 节数据在文件中的位置
    DWORD   PointerToRelocations; // 重定位条目指针
    DWORD   PointerToLinenumbers; // 行号条目指针
    WORD    NumberOfRelocations;  // 重定位条目数
    WORD    NumberOfLinenumbers;  // 行号条目数
    DWORD   Characteristics;      // 节属性
} IMAGE_SECTION_HEADER;

重定位表结构

typedef struct _IMAGE_RELOCATION {
    union {
        DWORD   VirtualAddress;   // 重定位地址偏移(相对于当前节基址)
        DWORD   RelocCount;       // 重定位计数
    };
    DWORD   SymbolTableIndex;     // 符号表索引
    WORD    Type;                 // 重定位类型
} IMAGE_RELOCATION;

重定位类型(x64架构)

类型值 名称 描述
1 IMAGE_REL_AMD64_ABSOLUTE 绝对地址
2 IMAGE_REL_AMD64_ADDR64 64位绝对地址
3 IMAGE_REL_AMD64_ADDR32 32位绝对地址
4 IMAGE_REL_AMD64_REL32 32位相对地址
5 IMAGE_REL_AMD64_REL32_1 32位相对地址(偏移1字节)
6 IMAGE_REL_AMD64_REL32_2 32位相对地址(偏移2字节)
7 IMAGE_REL_AMD64_REL32_3 32位相对地址(偏移3字节)
8 IMAGE_REL_AMD64_REL32_4 32位相对地址(偏移4字节)
9 IMAGE_REL_AMD64_REL32_5 32位相对地址(偏移5字节)

符号表结构

typedef struct _IMAGE_SYMBOL {
    union {
        BYTE    ShortName[8];     // 符号名(≤8字节)
        struct {
            DWORD   Short;        // 前4字节为0
            DWORD   Long;         // 后4字节为字符表偏移
        } Name;
    };
    DWORD   Value;                // 符号在节中的偏移或绝对偏移
    SHORT   SectionNumber;        // 符号所属节区号
    WORD    Type;                 // 符号类型(0x0=非函数,0x20=函数)
    BYTE    StorageClass;         // 存储类
    BYTE    NumberOfAuxSymbols;  // 辅助符号数
} IMAGE_SYMBOL;

存储类(StorageClass)

名称 描述
2 EXTERNAL 外部符号
3 STATIC 静态符号
6 LABEL 标签符号

0x06. Cobalt Strike客户端处理流程

1. 客户端处理步骤

  1. Coff文件内容传入PostExInlineObject#go函数
  2. 调用OBJExecutable#parse解析COFF文件
  3. 构造数据包,包含:
    • 命令号
    • obj入口函数(go)
    • .text段数据长度+内容
    • .rdata段数据长度+内容
    • .data段数据长度+内容
    • 重定位信息
    • 入口函数参数

2. 重定位信息结构

客户端通过OBJExecutable#getRelocation返回的重定位信息结构:

类型值 描述
1024 重定位位置在.rdata区段
1027 重定位对应外部函数
1028 重定位信息结束标识符

3. Beacon端处理流程

  1. 解析数据包内容
  2. 分配内存(初始RW,后改为RWX)
  3. 处理重定位信息
  4. 执行BOF

关键处理函数:

  • processRelocation: 处理重定位
  • FindOrAddDynamicFunction: 查找或添加动态函数

0x07. BOF开发常见问题

1. 未初始化的全局变量

问题:Cobalt Strike 4.4客户端未处理.bss段
解决方案:避免使用未初始化的全局变量

2. Windows API调用崩溃

问题:堆不匹配导致崩溃
解决方案:使用正确的堆分配方式

// 正确分配方式
char* buffer = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);

// 正确释放方式
HeapFree(GetProcessHeap(), 0, buffer);

3. 堆栈扩展问题

问题:缺少_chkstk_ms辅助函数
解决方案:避免使用大量栈空间(>4KB)

4. 大型switch语句崩溃

问题:BOF只适合小型switch语句
解决方案:改用if/else结构

5. x64下全局变量错误

问题:编译器优化导致全局变量位置错误
解决方案:添加额外的非零全局变量打乱对齐

0x08. 总结

本文详细介绍了BOF开发的全流程,从基础概念到COFF文件格式解析,再到Cobalt Strike客户端的处理机制。关键点包括:

  1. BOF本质是未链接的COFF文件
  2. COFF文件格式的详细结构解析
  3. 重定位处理的核心机制
  4. Beacon内部API的分类和使用
  5. 常见问题及解决方案

通过掌握这些知识,您可以开发出高效、稳定的BOF功能模块,提升红队测试的灵活性和隐蔽性。

Cobalt Strike Beacon BOF功能开发详解 0x01. 前言 本文详细解析Cobalt Strike Beacon的BOF(Bypass Object File)功能开发,涵盖BOF介绍、开发流程、COFF文件格式解析、重定位处理机制以及Cobalt Strike客户端的处理逻辑。通过本文,您将全面掌握BOF开发的核心技术。 0x02. BOF介绍 BOF(Bypass Object File)本质上是一个COFF(Common Object File Format)文件,即编译后但未链接的目标文件(.obj)。在Cobalt Strike中,通过 inline-execute 命令可以将BOF文件加载到Beacon内存中,经过修复后执行。 BOF的优势: 提高OPSEC(操作安全性),避免执行高危指令如 shell 为红队测试人员提供高度可扩展性 内存中执行,减少磁盘痕迹 0x03. BOF开发基础 开发环境准备 可以使用Visual Studio或MinGW进行BOF开发,生成.obj文件。推荐使用以下模板项目: Visual-Studio-BOF-template Visual-Studio-BOF-template 基本开发流程 编写C/C++代码 编译生成.obj文件 使用PEView等工具查看COFF格式 通过 inline-execute 命令执行BOF 0x04. Beacon内部API BOF可以调用一系列Beacon内部API,这些API分为以下几类: 1. Win32 API 主要用于函数动态解析: 2. 数据解析API BeaconDataParse BeaconDataPtr 3. 内容格式化API BeaconFormatAlloc BeaconFormatReset 4. 打印输出API BeaconOutput BeaconPrintf 5. Beacon内部功能API BeaconUseToken BeaconRevertToken BeaconSpawnTemporaryProcess 6. 辅助性API toWideChar 0x05. COFF文件格式详解 文件头结构 节表结构 重定位表结构 重定位类型(x64架构) | 类型值 | 名称 | 描述 | |--------|------|------| | 1 | IMAGE_ REL_ AMD64_ ABSOLUTE | 绝对地址 | | 2 | IMAGE_ REL_ AMD64_ ADDR64 | 64位绝对地址 | | 3 | IMAGE_ REL_ AMD64_ ADDR32 | 32位绝对地址 | | 4 | IMAGE_ REL_ AMD64_ REL32 | 32位相对地址 | | 5 | IMAGE_ REL_ AMD64_ REL32_ 1 | 32位相对地址(偏移1字节) | | 6 | IMAGE_ REL_ AMD64_ REL32_ 2 | 32位相对地址(偏移2字节) | | 7 | IMAGE_ REL_ AMD64_ REL32_ 3 | 32位相对地址(偏移3字节) | | 8 | IMAGE_ REL_ AMD64_ REL32_ 4 | 32位相对地址(偏移4字节) | | 9 | IMAGE_ REL_ AMD64_ REL32_ 5 | 32位相对地址(偏移5字节) | 符号表结构 存储类(StorageClass) | 值 | 名称 | 描述 | |----|------|------| | 2 | EXTERNAL | 外部符号 | | 3 | STATIC | 静态符号 | | 6 | LABEL | 标签符号 | 0x06. Cobalt Strike客户端处理流程 1. 客户端处理步骤 Coff文件内容传入 PostExInlineObject#go 函数 调用 OBJExecutable#parse 解析COFF文件 构造数据包,包含: 命令号 obj入口函数(go) .text段数据长度+内容 .rdata段数据长度+内容 .data段数据长度+内容 重定位信息 入口函数参数 2. 重定位信息结构 客户端通过 OBJExecutable#getRelocation 返回的重定位信息结构: | 类型值 | 描述 | |--------|------| | 1024 | 重定位位置在.rdata区段 | | 1027 | 重定位对应外部函数 | | 1028 | 重定位信息结束标识符 | 3. Beacon端处理流程 解析数据包内容 分配内存(初始RW,后改为RWX) 处理重定位信息 执行BOF 关键处理函数: processRelocation : 处理重定位 FindOrAddDynamicFunction : 查找或添加动态函数 0x07. BOF开发常见问题 1. 未初始化的全局变量 问题:Cobalt Strike 4.4客户端未处理.bss段 解决方案:避免使用未初始化的全局变量 2. Windows API调用崩溃 问题:堆不匹配导致崩溃 解决方案:使用正确的堆分配方式 3. 堆栈扩展问题 问题:缺少_ chkstk_ ms辅助函数 解决方案:避免使用大量栈空间(>4KB) 4. 大型switch语句崩溃 问题:BOF只适合小型switch语句 解决方案:改用if/else结构 5. x64下全局变量错误 问题:编译器优化导致全局变量位置错误 解决方案:添加额外的非零全局变量打乱对齐 0x08. 总结 本文详细介绍了BOF开发的全流程,从基础概念到COFF文件格式解析,再到Cobalt Strike客户端的处理机制。关键点包括: BOF本质是未链接的COFF文件 COFF文件格式的详细结构解析 重定位处理的核心机制 Beacon内部API的分类和使用 常见问题及解决方案 通过掌握这些知识,您可以开发出高效、稳定的BOF功能模块,提升红队测试的灵活性和隐蔽性。