AI生成|CobaltStrike4.13LostinTranslation—BeaconInterpreter仓库源码解读

admin 2026-06-22 04:38:42 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: CobaltStrike4.13引入BeaconInterpreter和BOF-PE两大核心功能,前者通过内置VM实现C脚本直接解释执行,无需分配内存降低检测风险;后者支持原生PE格式BOF,允许使用C++、外部库等复杂功能。更新还包括LLVMBeacon、Payload版本控制等,显著提升后渗透操作效率与隐蔽性。官方开源beacon-interpreter开发包提供头文件与AI兼容指南。 综合评分: 85 文章分类: 红队,渗透测试,内网渗透,恶意软件,安全工具


cover_image

AI 生成 | Cobalt Strike 4.13 Lost in Translation — Beacon Interpreter 仓库源码解读

原创

GLM-5.2 GLM-5.2

赛博生存指南

2026年6月19日 16:43 浙江

在小说阅读器读本章

去阅读

Cobalt Strike 4.13 的 Beacon Interpreter要终结,编译、上传、执行、翻 Beacon Console 看报错、再编译的BOF反馈循环。

2026 年 6 月 10 日,Fortra 发布 Cobalt Strike 4.13,代号 “Lost in Translation”

这是个一语双关的标题:既是经典电影《迷失东京》的英文原名,也精准概括了本次更新的核心主线——「翻译/转换」。Teamserver 把 C 翻译成字节码、BOF-PE 让原生 PE 格式在 Beacon 里翻译运行、Beacon 自身从 MSVC 向 LLVM 工具链迁移……整整一个大版本,都在解决「如何把更高层的代码,翻译进那个本该轻量的 Beacon」。

本文先拆解官方博客里 4.13 的全部更新,再结合 Fortra 同步开源的 beacon-interpreter 仓库做一次源码级解读——它正是 Beacon Interpreter 的官方开发支持包。


一、4.13 都更新了什么

| 模块 | 更新 | 一句话价值 | | — | — | — | | Beacon Interpreter | Beacon 内置 C 脚本 VM | 不再需要分配内存,直接在 Beacon 里跑 C | | BOF-PE | 支持原生 DLL/EXE 格式 BOF | 可用错误处理、C++、外部库,甚至 Rust | | LLVM Beacon | 基于 LLVM 的新 Beacon | 更小 payload,下版本弃用 MSVC Beacon | | Payload Store | payload 集中存储 + 版本控制 | 每个 Beacon 可追溯到具体导出版本 | | Malleable Profile Overrides | .mpo 覆盖文件 | 改 C2 设置不再需要重启 Teamserver | | REST API | WebSockets + gRPC 流式 | 取代状态轮询,生态集成更顺 | | UX | docking / 自定义表格 / 新字体 | LDAP 查询结果可渲染成可交互表格 | | 凭证管理 | 控制台高亮入库 + 右键动作 | Kerberos 票据处理流程大幅简化 |

其中前两项 Beacon Interpreter 和 BOF-PE 共同构成了博客所说的 “Post-Ex Evolution”(后渗透演进),是这次的重头戏。


二、为什么是现在:BOF 被推到了极限

要理解 Beacon Interpreter 的分量,得先回顾 BOF(Beacon Object File)的设计初衷。

BOF 是 Cobalt Strike 创始人 Raphael Mudge 提出的抽象——本质上是在位置无关代码(PIC)之上,恢复了少量便利(动态函数解析等)。它从设计上就是轻量、低开销、即用即走:Beacon 拿到 BOF,分配一块内存、加载、执行、释放。

但十年下来,使用者把这套设计逼到了墙角:

  1. 1. 想要更高层的抽象却得不到——比如异常处理,BOF 基本不支持。想写复杂 tradecraft 的操作者非常痛苦。
  2. 2. 工作流本身很笨重。最讽刺的例子:你写一个 BOF 只是为了释放内存,Beacon 为了执行它,还得再申请并释放一块内存

4.13 的解法是双管齐下:Beacon Interpreter 解决”轻量脚本”场景,BOF-PE 解决”复杂 tradecraft”场景。


三、Beacon Interpreter:让 Beacon 直接解释执行 C

工作原理

当你运行一个 Beacon Interpreter 脚本(比如 helloworld.c),流程是这样的:

helloworld.c
      │
      ▼  Teamserver 端编译
中间字节码 (bytecode)
      │
      ▼  随 C2 任务下发
Beacon 内置 VM 解释执行
      │
      ▼  通过 FFI 调用
Windows API / BOF API

两个关键设计决定了它的全部特性:

  • • VM 是 Beacon 原生的。执行时不需要额外分配内存,也不改变既有内存的权限——这直接抹掉了 BOF 最大的内存检测面。
  • • 编译在 Teamserver 端完成。用户不再需要本地编译 C 脚本(不像 BOF 那样要 x86_64-w64-mingw32-gcc 一通操作)。

这个 VM 最初基于开源的 picoc 项目,但 Fortra 对其做了大幅重构和扩展以适配 Beacon 的需求。

四种交互方式

| 入口 | 用途 | | — | — | | beacon-interpreter 命令 | Beacon 控制台直接执行 | | bbeacon_interpreter | Aggressor 脚本函数 | | REST API | 程序化集成 | | Script Editor(IDE) | GUI 内置编辑器,近实时反馈 |

Script Editor 的诞生动机很真实:Fortra 团队自己 dogfooding 时,被 BOF 那条 “写→编译→重跑→看 Console→循环” 的慢反馈折磨够了,于是把 IDE 直接塞进了客户端。现在可以在客户端里开发能力,近乎即时看到结果

与 Windows API 的桥梁:BOF 风格 DFR

Interpreter 的 C 子集贴近 C89/C99,但调用 Windows API 时有个门槛——VM 必须知道怎么调。解法是沿用 BOF 的 DFR(Dynamic Function Resolution)函数定义语法:

KERNEL32$LoadLibraryA: ptr (ptr);

声明之后,LoadLibrary 就能像写普通 Windows 程序一样使用了。Teamserver 还自带了一批常用头文件,通过标准 C include 引入,例如 #include&nbsp;<msvcrt.h> 拿到微软 C 运行时,#include&nbsp;<beacon.h> 拿到完整 BOF API,#include&nbsp;<internal.h> 里的 DbgPrintf 还能用 DebugView 调试。

注意:这些头文件不是与 Windows SDK 的 1:1 映射,会有缺口。需要补充时,把自定义头放进 server/interpreter/includes/user 目录即可被立即识别。

最后,Fortra 把这套开发支持包开源到了公开 GitHub——也就是本文后半部分的源码分析对象。


四、源码分析:官方开源的 beacon-interpreter 仓库

仓库地址:https://github.com/Cobalt-Strike/beacon-interpreter

注意:这里开源的是开发支持包(头文件 + AI 指南 + 示例),不是解释器/VM/编译器的实现。VM 本体闭源在 Teamserver 中。

项目概览

| 项目 | 详情 | | — | — | | 角色 | Beacon Interpreter 脚本开发支持包 | | 组成 | skills.md (AI 生成指南)+ interpreter_demo.c(示例)+ interpreter-includes/(头文件集) | | 头文件规模 | 34 个文件,约 10,500 行 | | 许可证 | Apache 2.0 | | 最大的头 | winnt.h (2,659 行)、winbaseapi.h(1,075 行) |

三大组成

1. skills.md(357 行) —— 写给 AI agent 的兼容性规则。这是最有意思的一份文档:Fortra 显然预期到大量 Interpreter 脚本会由 AI 生成,于是直接把 VM 的所有”坑”明文写了下来。

2. interpreter_demo.c(223 行) —— 一份”特性考试题”,系统性演练了链式赋值、逗号表达式、三目运算、位运算、while/do/switch/goto、数组与指针算术、__builtin_offsetof、链表、union 字节拆分、u64/i64、宽字符,以及原生 API 的直调与函数指针调用。

3. interpreter-includes/ —— 头文件分三层:

  • • 聚合层:windows.h 仅 include winnt/winbaseapi/winerror/msvcrt(用 BUILTINS_WINDOWS_H 这类 guard,提示是 CS builtins 头的精简镜像)
  • • 基础类型层:wintypes.h 定义 DWORD/HANDLE/SIZE_T 等,并用 _WIN32 宏切换指针大小
  • • 各 DLL 的 FFI 声明层:advapintapimsvcrtpsapiwinsock2 等逐库组织

VM 执行模型:三个反直觉点

skills.md 反复强调,这不是标准 C 运行时:

  1. 1. 没有隐式 main()。顶层语句就是入口;定义了 main() 还要自己显式 main(); 调用(demo 里 run_demo() 在文件末尾被手动调用)。

  2. 2. __argc / __argv 不是 POSIX 参数。这是新手最大的坑:

    读取方式完全同 BOF,要用 BeaconDataParse / BeaconDataExtract:

   if&nbsp;(__argc >&nbsp;0) {
   &nbsp; &nbsp; datap args = {0};
   &nbsp; &nbsp; BeaconDataParse(&args, __argv, __argc);
   &nbsp; &nbsp; char&nbsp;*message = BeaconDataExtract(&args,&nbsp;NULL);
   &nbsp; &nbsp; // ...
   }
  • • __argc = Beacon 打包参数缓冲区的字节数
  • • __argv = 指向该缓冲区的指针
  1. 3. 小端字节码假设,运行时容量有限(栈、调用深度、局部/全局变量数都有上限)——禁止无界递归和超大局部状态。

C 子集与限制

支持常规 C 的大部分,但有一组硬限制,且这些限制彼此呼应:

| 限制 | 说明 / demo 如何规避 | | — | — | | 无 float/double | 只能用整数/定点 | | void * 不可直接解引用/下标 | demo 里 ((int *)vp)[0] 先转型 | | 脚本函数不支持变参,也不能经函数指针调用 | demo 的 GETPID_FN 调用的是原生 FFI 指针,合法 | | struct 按值传参/返回受限 | 优先用指针传递聚合类型 | | 宏非完整预processor | 复杂逻辑改用普通函数 | | 声明符须保守 | 避免异形函数指针声明 |

FFI 契约:整套自己的函数签名语法

这是整个体系最特别的地方,沿用 BOF DFR 风格:

KERNEL32$GetLastError: u32 ();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // LIB$Function: 返回类型 约定 (参数...)
MSVCRT$printf: &nbsp; &nbsp; &nbsp; &nbsp;cdecl&nbsp;i32&nbsp;(cstr, ...);&nbsp; // cdecl + 变参
USER32$GetDesktopWindow: ptr ();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // demo 中自定义签名

规则:

  • • 约定:cdecl / stdcall / 省略(省略=stdcall)。变参仅 cdecl 合法
  • • 64 位脚本约定可省;32 位 VM 必须指定,否则崩溃。
  • • 原子类型表(注意:没有浮点,呼应上面的限制):

| 类型 | 含义 | | — | — | | void | 无返回值 | | i16u16 | 16 位有/无符号 | | i32u32 | 32 位有/无符号 | | i64u64 | 64 位有/无符号 | | ptr | 指针 | | cstr | C 字符串(等价 ptr,推荐用于字符串形参) | | size_t | 对齐 Windows SIZE_T,指针大小 |

beacon.h 的隐藏威力:暴露 Beacon 内部运行时

beacon.h(267 行)是这套头里信息量最大的,内容分两组:

公开 API(常规):BeaconDataParse/Extract(参数解析)、BeaconPrintf/Output(回调输出)、BeaconFormat*(格式化缓冲)、Beacon*Process(注入/派生)、BeaconUseToken/RevertToken(令牌)、BeaconVirtualAlloc/Protect/...(Beacon-gate 包装的内存 API)。

内部数据结构(高级,这才是亮点):

typedef&nbsp;struct&nbsp;_SYSCALL_API_ENTRY&nbsp;{
&nbsp; &nbsp; PVOID fnAddr;
&nbsp; &nbsp; PVOID jmpAddr;
&nbsp; &nbsp; DWORD sysnum;&nbsp; &nbsp; &nbsp;// ← 直接拿到 syscall number
} SYSCALL_API_ENTRY;

typedef&nbsp;struct&nbsp;_BEACON_INFO&nbsp;{
&nbsp; &nbsp; unsigned&nbsp;int&nbsp;version;
&nbsp; &nbsp; char&nbsp; * sleep_mask_ptr;
&nbsp; &nbsp; // ... sleepmask / beacon 内存布局
&nbsp; &nbsp; ALLOCATED_MEMORY allocatedMemory;
} BEACON_INFO;

SYSCALL_API 直接暴露了 NT 系统调用号与跳板地址,ALLOCATED_MEMORY 暴露了 sleepmask 的内存区域布局,BEACON_INFO 暴露了 Beacon 自身指针。这意味着 Interpreter 脚本的能力远超普通 BOF——能直接做 direct syscall、读写 Beacon 内存、自定义 sleepmask、操作数据存储(Data Store)。换句话说,脚本可以深入操作 Beacon 自身运行时

输出与大缓冲

skills.md 专门叮嘱:BeaconPrintf 用于状态/摘要,不要在紧凑循环里高频调用;大量数据应走 BeaconFormat 流程(Alloc → Printf → ToString → Free)分块输出,避免压垮 Cobalt Strike 客户端。


五、同台对比:BOF / BOF-PE / Beacon Interpreter

| 维度 | 传统 BOF | BOF-PE(4.13) | Beacon Interpreter(4.13) | | — | — | — | — | | 代码形态 | 位置无关 COFF | 原生 DLL/EXE | C 源码,Teamserver 编译字节码 | | 内存开销 | 需分配/释放内存 | 需加载 PE | 无需额外分配内存 | | 高级特性 | 弱(无异常处理) | 强(C++/异常/外部库) | 中(C 子集,无浮点) | | 本地编译 | 需要 | 需要 | 不需要 | | 反馈循环 | 慢 | 慢 | 快(Script Editor 近实时) | | 适用语言 | C | C/C++/Rust | C | | 复杂 tradecraft | 受限 | 最强 | 中等 |

三者并非替代关系,而是分工:Interpreter 管”快速、轻量、无内存抖动”的脚本场景,BOF-PE 管”复杂、需要完整语言特性”的重量级场景,BOF 继续兜底。


六、从防御视角看 Beacon Interpreter

对蓝队而言,这次更新值得认真对待。博客里一句不经意的话,其实是给防御方的核心提醒:

As the VM is native to Beacon, it does not need to allocate any additional memory (or fluctuate the memory permissions of previously allocated memory).

这句话翻译成检测语言就是:围绕”内存申请 + RWX 权限变更 + 执行”这套经典 BOF 检测链,对 Interpreter 脚本可能整体失效。脚本不再在堆上落一块可执行内存,而是跑在 Beacon 既有的 VM 解释器里。

但盲区不等于隐身。新的检测面在别处:

  1. 1. 字节码特征。脚本要先被 Teamserver 编译成中间字节码、随 C2 任务下发。这套自定义字节码指令集本身,以及它在 C2 流量里的形态,是新的识别维度。
  2. 2. 解释器驻留。VM 本体是 Beacon 的常驻代码,无论脚本是否运行都存在,可作为静态特征。
  3. 3. FFI 调用边界。脚本能力再强,最终调用 Windows API 时仍要经过 LIB$Func 解析,API 调用行为(尤其 beacon.h 暴露的 SYSCALL_API、内存操作类 API)仍是行为监控的着力点。
  4. 4. checkin_delay。4.13 新增的 Malleable C2 选项,用于打乱反射加载与首次元数据交换的时间关联——这也提示蓝队:加载时机与首次回连的时间相关性,本身就是一条检测线索。

一句话:Interpreter 把内存层面的噪声降到了最低,代价是把战场从”内存权限”转移到了”字节码与 C2 流量”。


结语

“Lost in Translation” 是个恰如其分的代号。4.13 这一整版都在做同一件事:把更多、更高层的代码,翻译进那个曾经只愿接纳 PIC 的 Beacon。

对红队,Beacon Interpreter 消灭了 BOF 的内存抖动和缓慢反馈,Script Editor 让能力开发像写脚本一样轻;对防御方,熟悉了十年的”BOF 申请内存→改权限→执行”检测模型正在被悄悄架空,新的战场在字节码和 C2 流量里悄然展开。

官方同时开源开发支持包、还专门写了 skills.md 给 AI 看——这个信号也很明确:未来的 Interpreter 脚本,大概率大半是 AI 生成的。攻防双方,都得开始熟悉这套新的「翻译」规则。


本文基于 Cobalt Strike 官方 4.13 发布博客与公开开源的 beacon-interpreter 仓库撰写,仅作技术研究与防御教育用途。


参考资源

  • • Cobalt Strike 4.13: Lost In Translation — 官方博客[1]
  • • beacon-interpreter — 官方开源仓库(GitHub)[2]
  • • BOF-PE 参考实现(@CCob 提出,现由 NetSPI 维护)[3]

引用链接

[1] Cobalt Strike 4.13: Lost In Translation — 官方博客: https://www.cobaltstrike.com/blog/cobalt-strike-413-lost-in-translation [2] beacon-interpreter — 官方开源仓库(GitHub): https://github.com/Cobalt-Strike/beacon-interpreter [3] BOF-PE 参考实现(@CCob 提出,现由 NetSPI 维护): https://github.com/NetSPI/BOF-PE


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:赛博生存指南 GLM-5.2 GLM-5.2《AI 生成 | Cobalt Strike 4.13 Lost in Translation — Beacon Interpreter 仓库源码解读》

粽叶揽清风,岁岁皆安康 网络安全文章

粽叶揽清风,岁岁皆安康

文章总结: 该文档是好靶场团队发布的端午节推文,主要介绍其网络安全靶场平台的服务承诺和赛事活动。核心内容包含每日更新1000+靶场的运营模式、首届网安综合赛的七
评论:0   参与:  0