CobaltStrike逆向学习系列(5):Bypass BeaconEye
字数 1266 2025-08-07 08:22:15

CobaltStrike逆向学习系列(5): Bypass BeaconEye 技术详解

0x00 概述

本文详细分析CobaltStrike BeaconEye检测原理及两种有效的Bypass方法,适合红队研究人员和逆向工程师学习如何绕过BeaconEye检测。

0x01 BeaconEye检测原理

检测机制

BeaconEye通过yara规则检测Beacon,主要针对C2Profile的结构特征:

  1. 内存结构特征

    • Beacon解析后,每个配置项占16字节
    • 前8字节为type类型
    • 后8字节为data数据
  2. 关键yara规则

    • 第一条规则匹配全零区域(Beacon解析时直接偏移index位置)
    • 后续规则匹配特定类型序列:short(1)、short(1)、int(2)、int(2)、short(1)

检测依据

只要打破上述内存结构规则,即可实现Bypass。

0x02 Bypass方法1:内存结构破坏

实现思路

利用C2Profile解析时的内存布局特性进行绕过:

  1. 内存填充

    • 16字节中实际只使用第一位和后面数据
    • 中间零值区域无实际意义
    • 申请内存时填充非零值破坏特征
  2. 实现方式

    • 直接修改字节码(较困难)
    • 使用寄存器操作(如将其他寄存器值替换到edx)
    • 使用inline Hook(实现相对简单)

0x03 Bypass方法2:全面HOOK方案

整体架构

此方案较为复杂但效果更好,适合长期使用和二次开发:

  1. C2Profile处理流程

    • Controller按格式组成数组
    • Patch到beacon.dll
    • beacon.dll Patch到Loader
    • Beacon执行时解析为使用格式
  2. 最佳修改点

    • 重写Loader最方便
    • 便于后续特征修改和二次开发

关键函数

需要修改四个核心函数:

  1. 解析函数

    • 当fdwReason传入1时执行C2Profile解析
    • 可直接HOOK此函数
  2. 取值函数

    • ulParseProfile - 解析配置
    • ulGetShortValue - 获取short值
    • ulGetIntValue - 获取int值
    • ulGetPtrValue - 获取指针值

X64偏移地址

ULONG_PTR ulParseProfile = ImageBase + 0x18694;
ULONG_PTR ulGetShortValue = ImageBase + 0x18664;
ULONG_PTR ulGetIntValue = ImageBase + 0x185DC;
ULONG_PTR ulGetPtrValue = ImageBase + 0x18630;

代码重写策略

  1. 基础功能

    • 内存申请赋值
    • 取Short值
    • 取Int值
    • 取Ptr值
  2. 数据结构设计

    • 简单罗列:易于实现但取值麻烦
    • 定长结构:便于定位
    • 复杂结构:插入垃圾字符,使用自定义格式

X86特殊处理

在X86架构上需要注意:

  • beacon.dll使用寄存器传参而非堆栈
  • 通过edx寄存器传递参数
  • 可使用内嵌汇编获取参数:
__asm mov index, edx

0x04 实施建议

  1. 方法选择

    • 快速测试:使用方法1
    • 长期使用:推荐方法2
  2. 开发注意事项

    • 保持与原结构的功能兼容性
    • 测试各取值函数的稳定性
    • 考虑跨平台兼容性(X86/X64)
  3. 增强隐蔽性

    • 在自定义格式中加入随机数据
    • 实现动态内存布局
    • 定期变更数据结构

通过以上方法,可有效绕过BeaconEye基于内存结构的检测机制,同时为后续的Beacon定制开发奠定基础。

CobaltStrike逆向学习系列(5): Bypass BeaconEye 技术详解 0x00 概述 本文详细分析CobaltStrike BeaconEye检测原理及两种有效的Bypass方法,适合红队研究人员和逆向工程师学习如何绕过BeaconEye检测。 0x01 BeaconEye检测原理 检测机制 BeaconEye通过yara规则检测Beacon,主要针对C2Profile的结构特征: 内存结构特征 : Beacon解析后,每个配置项占16字节 前8字节为type类型 后8字节为data数据 关键yara规则 : 第一条规则匹配全零区域(Beacon解析时直接偏移index位置) 后续规则匹配特定类型序列:short(1)、short(1)、int(2)、int(2)、short(1) 检测依据 只要打破上述内存结构规则,即可实现Bypass。 0x02 Bypass方法1:内存结构破坏 实现思路 利用C2Profile解析时的内存布局特性进行绕过: 内存填充 : 16字节中实际只使用第一位和后面数据 中间零值区域无实际意义 申请内存时填充非零值破坏特征 实现方式 : 直接修改字节码(较困难) 使用寄存器操作(如将其他寄存器值替换到edx) 使用inline Hook(实现相对简单) 0x03 Bypass方法2:全面HOOK方案 整体架构 此方案较为复杂但效果更好,适合长期使用和二次开发: C2Profile处理流程 : Controller按格式组成数组 Patch到beacon.dll beacon.dll Patch到Loader Beacon执行时解析为使用格式 最佳修改点 : 重写Loader最方便 便于后续特征修改和二次开发 关键函数 需要修改四个核心函数: 解析函数 : 当fdwReason传入1时执行C2Profile解析 可直接HOOK此函数 取值函数 : ulParseProfile - 解析配置 ulGetShortValue - 获取short值 ulGetIntValue - 获取int值 ulGetPtrValue - 获取指针值 X64偏移地址 代码重写策略 基础功能 : 内存申请赋值 取Short值 取Int值 取Ptr值 数据结构设计 : 简单罗列:易于实现但取值麻烦 定长结构:便于定位 复杂结构:插入垃圾字符,使用自定义格式 X86特殊处理 在X86架构上需要注意: beacon.dll使用寄存器传参而非堆栈 通过edx寄存器传递参数 可使用内嵌汇编获取参数: 0x04 实施建议 方法选择 : 快速测试:使用方法1 长期使用:推荐方法2 开发注意事项 : 保持与原结构的功能兼容性 测试各取值函数的稳定性 考虑跨平台兼容性(X86/X64) 增强隐蔽性 : 在自定义格式中加入随机数据 实现动态内存布局 定期变更数据结构 通过以上方法,可有效绕过BeaconEye基于内存结构的检测机制,同时为后续的Beacon定制开发奠定基础。