CobaltStrike逆向学习系列(6):Beacon sleep_mask 分析
字数 1793 2025-08-07 08:22:18
CobaltStrike Beacon sleep_mask 逆向分析教学文档
1. 概述
CobaltStrike 提供了一个内存混淆功能,在 Beacon 休眠(Sleep)时会将自身代码混淆以避免检测。本文详细分析 sleep_mask 功能的实现机制。
2. C2Profile 配置解析
sleep_mask 功能通过 C2Profile 配置启用,关键配置项包括:
- rwx 权限设置:决定是否对 text 段进行混淆
- obfuscate 设置:本文不重点关注此项
- 内存区域配置:
- 存储 text 段结尾地址到 index=41 的位置
- 检查 text 段与 rdata 段之间的空白区域是否足够256字节(推测用于存放加解密函数)
2.1 内存区域处理流程
- 默认添加 0 和 4096 到配置中
- 循环添加内容:
- 循环条件:text 段且不允许使用 rwx
- 当禁止 rwx 时,text 段不会被添加到 index=42 的项中(不会被混淆)
- 最后添加零作为结束标记
3. userwx "true" 时的行为分析
3.1 加解密函数定位
- 通过设置断点快速定位加解密函数
- 调用链分析:
- 主循环最后有一个处理 Sleep 的函数
- 通过判断 0x29 位置的值决定是否直接调用 Sleep
- 使用 sleep_mask 时,0x29 存储 text 段的结尾地址
3.2 加解密过程
-
函数参数传递:
- 传入当前函数和加解密函数
- 计算两个函数地址的差值(即加解密函数长度)
-
内存操作:
- 从 0x29 取出 text 段结尾地址
- 从全局变量获取 PE 头位置
- 相加得到内存中 text 段的结尾地址(用于存放加解密函数)
-
关键数据结构:
- 申请 32 字节空间:
- 前8字节:PE 头地址
- 后8字节:0x2A 的地址(之前构造的结构)
- 将加16的位置传入
- 申请 32 字节空间:
-
密钥生成:
- 首选使用 CryptoAPI 生成密钥
- 失败时使用自定义算法生成密钥
-
加解密函数调用:
- 参数1:构造的结构
- 参数2:Sleep 函数
- 参数3:时间参数
3.3 加解密函数分析
-
参数解析:
- 参数是指针类型,取数组下标1的值(0x2A 对应的值)
- v6:第一个值 sectionAddress
- v7:第二个值 sectionEnd
- v3 后移用于判断跳出规则(最后添加的两个零)
-
混淆条件:
- do-while 循环条件:sectionAddress < sectionEnd
- 效果:对所有代码进行混淆
-
解密逻辑:
- 与加密逻辑对称
3.4 内存状态验证
-
Sleep 状态:
- 代码段被混淆
-
接收命令状态:
- 代码段被混淆
结论:允许 RWX 权限时,代码段会被混淆
4. userwx "false" 时的行为分析
4.1 理论验证
根据之前的分析,当禁止 RWX 权限时:
- text 段不会被添加到 index=42 的混淆项中
- 代码段不会被混淆
4.2 内存状态验证
-
Sleep 状态:
- 代码段保持原样
-
接收命令状态:
- 代码段保持原样
结论:禁止 RWX 权限时,代码段不会被混淆
5. 关键点总结
-
rwx 权限决定混淆范围:
- 允许时:混淆 text 段
- 禁止时:不混淆 text 段
-
加解密函数位置:
- 位于 text 段与 rdata 段之间的空白区域
- 需要至少256字节空间
-
混淆触发时机:
- Beacon 进入 Sleep 状态时触发加密
- 接收命令时触发解密
-
密钥生成:
- 优先使用 CryptoAPI
- 备选自定义算法
-
数据结构:
- 使用32字节结构存储关键地址信息
- 以双零作为结束标记
6. 检测与对抗思路
-
检测点:
- 查找 text 段与 rdata 段之间的可疑代码(加解密函数)
- 监控 Sleep 前后的内存变化
- 检测 CryptoAPI 的异常使用模式
-
对抗思路:
- 修改默认的加解密算法
- 动态调整混淆区域
- 实现多阶段混淆机制
7. 参考实现伪代码
// 主循环中的Sleep处理
void HandleSleep() {
if (global_29) { // 使用sleep_mask
// 准备加解密
PrepareEncryptDecrypt(current_func, encrypt_func);
// 加密内存
EncryptMemory();
// 执行Sleep
Sleep(duration);
// 解密内存
DecryptMemory();
} else {
// 直接Sleep
Sleep(duration);
}
}
// 加解密函数
void EncryptDecryptFunc(void* structure) {
uint64_t* params = (uint64_t*)structure;
uint64_t sectionStart = params[0];
uint64_t sectionEnd = params[1];
// 生成密钥
if (!GenerateKeyWithCryptoAPI()) {
GenerateKeyWithCustomAlgo();
}
// 混淆代码
while (sectionStart < sectionEnd) {
// 混淆操作
XorMemory(sectionStart, key);
sectionStart++;
}
}
8. 扩展研究建议
- 分析不同CobaltStrike版本的sleep_mask实现差异
- 研究绕过内存扫描的进阶混淆技术
- 探索对抗EDR的sleep_mask增强方案
- 开发基于此原理的自定义混淆模块
通过本文分析,可以深入理解CobaltStrike Beacon的sleep_mask工作机制,为红队工具开发和蓝队检测提供技术参考。