文章总结: CobaltStrike4.13引入BeaconInterpreter和BOF-PE两大核心功能,前者通过内置VM实现C脚本直接解释执行,无需分配内存降低检测风险;后者支持原生PE格式BOF,允许使用C++、外部库等复杂功能。更新还包括LLVMBeacon、Payload版本控制等,显著提升后渗透操作效率与隐蔽性。官方开源beacon-interpreter开发包提供头文件与AI兼容指南。 综合评分: 85 文章分类: 红队,渗透测试,内网渗透,恶意软件,安全工具
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. 想要更高层的抽象却得不到——比如异常处理,BOF 基本不支持。想写复杂 tradecraft 的操作者非常痛苦。
- 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 <msvcrt.h> 拿到微软 C 运行时,#include <beacon.h> 拿到完整 BOF API,#include <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仅 includewinnt/winbaseapi/winerror/msvcrt(用BUILTINS_WINDOWS_H这类 guard,提示是 CS builtins 头的精简镜像) - • 基础类型层:
wintypes.h定义DWORD/HANDLE/SIZE_T等,并用_WIN32宏切换指针大小 - • 各 DLL 的 FFI 声明层:
advapi、ntapi、msvcrt、psapi、winsock2等逐库组织
VM 执行模型:三个反直觉点
skills.md 反复强调,这不是标准 C 运行时:
-
1. 没有隐式
main()。顶层语句就是入口;定义了main()还要自己显式main();调用(demo 里run_demo()在文件末尾被手动调用)。 -
2.
__argc/__argv不是 POSIX 参数。这是新手最大的坑:读取方式完全同 BOF,要用
BeaconDataParse/BeaconDataExtract:
if (__argc > 0) {
datap args = {0};
BeaconDataParse(&args, __argv, __argc);
char *message = BeaconDataExtract(&args, NULL);
// ...
}
- •
__argc= Beacon 打包参数缓冲区的字节数 - •
__argv= 指向该缓冲区的指针
- 3. 小端字节码假设,运行时容量有限(栈、调用深度、局部/全局变量数都有上限)——禁止无界递归和超大局部状态。
C 子集与限制
支持常规 C 的大部分,但有一组硬限制,且这些限制彼此呼应:
| 限制 | 说明 / demo 如何规避 |
| — | — |
| 无 float/double | 只能用整数/定点 |
| void * 不可直接解引用/下标 | demo 里 ((int *)vp)[0] 先转型 |
| 脚本函数不支持变参,也不能经函数指针调用 | demo 的 GETPID_FN 调用的是原生 FFI 指针,合法 |
| struct 按值传参/返回受限 | 优先用指针传递聚合类型 |
| 宏非完整预processor | 复杂逻辑改用普通函数 |
| 声明符须保守 | 避免异形函数指针声明 |
FFI 契约:整套自己的函数签名语法
这是整个体系最特别的地方,沿用 BOF DFR 风格:
KERNEL32$GetLastError: u32 (); // LIB$Function: 返回类型 约定 (参数...)
MSVCRT$printf: cdecl i32 (cstr, ...); // cdecl + 变参
USER32$GetDesktopWindow: ptr (); // demo 中自定义签名
规则:
- • 约定:
cdecl/stdcall/ 省略(省略=stdcall)。变参仅cdecl合法。 - • 64 位脚本约定可省;32 位 VM 必须指定,否则崩溃。
- • 原子类型表(注意:没有浮点,呼应上面的限制):
| 类型 | 含义 |
| — | — |
| void | 无返回值 |
| i16 / u16 | 16 位有/无符号 |
| i32 / u32 | 32 位有/无符号 |
| i64 / u64 | 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 struct _SYSCALL_API_ENTRY {
PVOID fnAddr;
PVOID jmpAddr;
DWORD sysnum; // ← 直接拿到 syscall number
} SYSCALL_API_ENTRY;
typedef struct _BEACON_INFO {
unsigned int version;
char * sleep_mask_ptr;
// ... sleepmask / beacon 内存布局
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. 字节码特征。脚本要先被 Teamserver 编译成中间字节码、随 C2 任务下发。这套自定义字节码指令集本身,以及它在 C2 流量里的形态,是新的识别维度。
- 2. 解释器驻留。VM 本体是 Beacon 的常驻代码,无论脚本是否运行都存在,可作为静态特征。
- 3. FFI 调用边界。脚本能力再强,最终调用 Windows API 时仍要经过
LIB$Func解析,API 调用行为(尤其beacon.h暴露的SYSCALL_API、内存操作类 API)仍是行为监控的着力点。 - 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 仓库源码解读》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论