重新审视用户定义的反射加载器第 2 部分:混淆和屏蔽(翻译)
字数 1394 2025-08-18 11:36:48

用户定义的反射加载器(UDRL)高级混淆与屏蔽技术

概述

本文是"重新审视用户定义的反射加载器"系列的第二部分,重点介绍如何通过混淆和屏蔽技术增强Cobalt Strike Beacon的规避能力。我们将深入探讨如何自定义反射加载器来超越标准可延展C2配置文件的限制,实现更高级的静态规避技术。

UDRL与可延展C2的对比

标准可延展C2的局限性

  • stage.obfuscate仅屏蔽RAW Beacon有效负载的部分内容
  • 不屏蔽默认反射加载器、DOS存根或Sleep Mask
  • 修改选项与默认反射加载器紧密耦合

UDRL的优势

  • 完全控制Beacon的转换过程
  • 可以修改任何位置的任何值,不受特定位置限制
  • 通过BEACON_RDLL_GENERATE*挂钩接收原始Beacon进行自定义处理

高级PE头修改技术

自定义PE头结构

typedef struct _SECTION_INFORMATION {
    DWORD VirtualAddress;
    DWORD PointerToRawData;
    DWORD SizeOfRawData;
} SECTION_INFORMATION, *PSECTION_INFORMATION;

typedef struct _PE_HEADER_DATA {
    DWORD SizeOfImage;
    DWORD SizeOfHeaders;
    DWORD entryPoint;
    QWORD ImageBase;
    SECTION_INFORMATION Text;
    SECTION_INFORMATION Rdata;
    SECTION_INFORMATION Data;
    SECTION_INFORMATION Pdata;
    SECTION_INFORMATION Reloc;
    DWORD ExportDirectoryRVA;
    DWORD DataDirectoryRVA;
    DWORD RelocDirectoryRVA;
    DWORD RelocDirectorySize;
} PE_HEADER_DATA, *PPE_HEADER_DATA;

实现步骤

  1. 使用Aggressor Script的pedump()生成Beacon的PE头映射
  2. 使用Sleep的pack()函数创建自定义头结构
  3. 移除原始PE头并附加PE节区到新结构
  4. 在加载器中调整指针以正确处理修改后的结构

内存布局调整

  • 偏移RAW Beacon基地址以正确识别节区
  • 偏移加载映像基地址以确保内存布局正确

字符串转换技术

安全字符串替换

  • 使用strrep_pad()函数而非标准替换
  • 用NULL字节填充输入字符串以保持节区大小不变
  • 替换关键字符串如"beacon.x64.dll"和"ReflectiveLoader"

节区屏蔽技术

高级节区屏蔽

  1. 创建包含XOR密钥信息的扩展PE头结构
typedef struct _KEY_INFO {
    size_t KeyLength;
    char* Key;
} KEY_INFO, *PKEY_INFO;

typedef struct _XOR_KEYS {
    KEY_INFO TextSection;
    KEY_INFO RdataSection;
    KEY_INFO DataSection;
} XOR_KEYS, *PXOR_KEYS;
  1. 为每个节区生成随机长度XOR密钥
  2. 在加载器中动态检索和使用密钥

多层混淆技术

压缩层实现

  • 使用Microsoft LZNT1压缩算法
  • 通过RtlDecompressBuffer进行解压
  • 添加UDRL_HEADER_DATA结构存储压缩信息
typedef struct _UDRL_HEADER_DATA {
    DWORD CompressedSize;
    DWORD RawFileSize;
    DWORD LoadedImageSize;
} UDRL_HEADER_DATA, *PUDRL_HEADER_DATA;

加密层实现

  • 使用RC4等流密码加密压缩后的数据
  • 在加载器中动态解密

Base64编码

  • 使用Aggressor Script的base64_encode()降低熵值
  • 在加载器中添加Base64Decode()函数

熵值管理策略

熵值影响

  • 混淆显著增加文件熵值(从6.188到7.999)
  • 高熵值可能触发PE恶意软件模型警报

熵值优化

  • 使用Base64编码降低熵值(从7.999降至6.001)
  • 考虑自定义shellcode运行器以避免默认可执行文件的高熵

实现流程总结

  1. 初始转换:

    • 替换PE头为自定义结构
    • 安全修改字符串
    • 屏蔽关键节区
  2. 多层混淆:

    • 压缩处理后的Beacon
    • 加密压缩后的数据
    • Base64编码最终产物
  3. 加载流程:

    • Base64解码
    • RC4解密
    • LZNT1解压
    • 使用自定义加载器加载Beacon

防御规避考量

  • 本文技术主要针对静态检测(YARA等)
  • 运行时仍需Sleep Mask等技术进行内存屏蔽
  • 这只是"深度规避"方法的一个方面,还需结合其他技术

开发建议

  1. 使用UDRL-VS套件作为开发基础
  2. 将加载器功能模块化为库
  3. 测试时对照开源YARA规则集验证效果
  4. 考虑熵值影响,必要时进行优化

通过本文介绍的技术,开发者可以创建高度定制化的反射加载器,显著提升Beacon对抗静态分析的能力。这些方法展示了UDRL提供的巨大灵活性,为红队操作提供了更多规避可能性。

用户定义的反射加载器(UDRL)高级混淆与屏蔽技术 概述 本文是"重新审视用户定义的反射加载器"系列的第二部分,重点介绍如何通过混淆和屏蔽技术增强Cobalt Strike Beacon的规避能力。我们将深入探讨如何自定义反射加载器来超越标准可延展C2配置文件的限制,实现更高级的静态规避技术。 UDRL与可延展C2的对比 标准可延展C2的局限性 stage.obfuscate 仅屏蔽RAW Beacon有效负载的部分内容 不屏蔽默认反射加载器、DOS存根或Sleep Mask 修改选项与默认反射加载器紧密耦合 UDRL的优势 完全控制Beacon的转换过程 可以修改任何位置的任何值,不受特定位置限制 通过 BEACON_RDLL_GENERATE* 挂钩接收原始Beacon进行自定义处理 高级PE头修改技术 自定义PE头结构 实现步骤 使用Aggressor Script的 pedump() 生成Beacon的PE头映射 使用Sleep的 pack() 函数创建自定义头结构 移除原始PE头并附加PE节区到新结构 在加载器中调整指针以正确处理修改后的结构 内存布局调整 偏移RAW Beacon基地址以正确识别节区 偏移加载映像基地址以确保内存布局正确 字符串转换技术 安全字符串替换 使用 strrep_pad() 函数而非标准替换 用NULL字节填充输入字符串以保持节区大小不变 替换关键字符串如"beacon.x64.dll"和"ReflectiveLoader" 节区屏蔽技术 高级节区屏蔽 创建包含XOR密钥信息的扩展PE头结构 为每个节区生成随机长度XOR密钥 在加载器中动态检索和使用密钥 多层混淆技术 压缩层实现 使用Microsoft LZNT1压缩算法 通过 RtlDecompressBuffer 进行解压 添加 UDRL_HEADER_DATA 结构存储压缩信息 加密层实现 使用RC4等流密码加密压缩后的数据 在加载器中动态解密 Base64编码 使用Aggressor Script的 base64_encode() 降低熵值 在加载器中添加 Base64Decode() 函数 熵值管理策略 熵值影响 混淆显著增加文件熵值(从6.188到7.999) 高熵值可能触发PE恶意软件模型警报 熵值优化 使用Base64编码降低熵值(从7.999降至6.001) 考虑自定义shellcode运行器以避免默认可执行文件的高熵 实现流程总结 初始转换 : 替换PE头为自定义结构 安全修改字符串 屏蔽关键节区 多层混淆 : 压缩处理后的Beacon 加密压缩后的数据 Base64编码最终产物 加载流程 : Base64解码 RC4解密 LZNT1解压 使用自定义加载器加载Beacon 防御规避考量 本文技术主要针对静态检测(YARA等) 运行时仍需Sleep Mask等技术进行内存屏蔽 这只是"深度规避"方法的一个方面,还需结合其他技术 开发建议 使用UDRL-VS套件作为开发基础 将加载器功能模块化为库 测试时对照开源YARA规则集验证效果 考虑熵值影响,必要时进行优化 通过本文介绍的技术,开发者可以创建高度定制化的反射加载器,显著提升Beacon对抗静态分析的能力。这些方法展示了UDRL提供的巨大灵活性,为红队操作提供了更多规避可能性。