初始访问操作第二部分:进攻性DevOps
挑战
在成熟组织的Windows端点防御技术栈中,红队初始访问操作面临严峻挑战。为了在高度检测环境中成功实现初始访问,生成的软件工件需满足以下最低要求:
- 生成的软件工件需具有独特性,以规避静态分析检测。
- 在用户模式工件执行时抑制Windows事件跟踪。
- 内核回调通知要么“不引人注意”,要么最好被禁用。
- 工件API使用不足以触发动态NTDLL API挂钩行为。
- 从进程树分析角度看,父子进程关系不引人注意。
- 任何进程线程创建最好由某些签名/合法的磁盘(DLL模块)工件支持。
- 沙箱执行将迫使我们的工件立即中止/终止。
- 任何内核级利用不能使用阻止列表中的驱动程序。
虽然上述目标易于表述,但实现这些目标的实际软件/恶意软件开发技术却非易事。为了完全有效,我们需要能够动态重新编译恶意软件工件,以更改工件大小和熵、使用独特加密密钥、重新处理传入的shellcode、提供引入操作员可配置选项的能力、工件签名等。所有这些都直接指向采用持续集成/持续开发(CI/CD)方法,为生成的工件实现一定程度的持续防御规避。我们利用GitLab社区版的CI/CD功能集来实现这一方法。以下描述了一种我称之为“恶意软件即服务(MAAS)”的通用方法,并引入一个公共仓库作为模板,供您实现类似目标。
GitLab CI/CD流水线
GitLab CI/CD流水线由易于人类理解的YML文件语法驱动,只需在GitLab仓库的主目录中放置名为“.gitlab-ci.yml”的文件即可启用。
- YML语法允许我们在流水线中定义构建阶段,每个阶段关联不同的作业。
- 任何单个流水线运行都可以通过仓库的“git commit”和推送或合并操作触发。
- YML语法允许我们定义触发操作,从而允许动态创建子流水线。
- 任何子流水线只是由父/全局YML配置触发的另一个YML文件。
GitLab运行器
GitLab运行器是安装在独立服务器或虚拟容器上的软件,使用GitLab API轮询仓库以执行流水线作业。当首次启动时,GitLab运行器会通过API注册自身,从而允许其随后处理发送给它的任何流水线作业。
运行器将处理GitLab YML文件中的指令,在大多数情况下,这将包括处理YML内容中脚本标签指示的脚本。该脚本通常由本地操作系统“shell”执行,在Windows情况下可能是CMD.EXE,在Linux情况下可能是/bin/bash或类似。使用的“shell”是可配置的,例如,如果您希望跨平台使用通用shell语法,可以设置为“pwsh.exe”或“pwsh”。
基于我们的软件编译需求,我们选择部署基于Windows的运行器和基于Linux的运行器,Windows系统上配置了PowerShell,Linux运行器上配置了默认的/bin/bash shell,我们选择在Docker容器内部署这些运行器。
使用Docker的具体架构选择主要由生成动态流水线配置信息的Python脚本集驱动。Docker本质上减轻了整体环境中的版本控制和变更控制负担。
在我们的案例中,我们确实需要完整的Microsoft编译工具链,以及基于Linux的mingw-gcc、Golang、Rust和完整的mono/.NET安装。这需要部署基于Windows和Linux的运行器架构与共享存储。下图是我们的1.0版本架构。
精明的观察者会注意到Docker部署在Linux主机上,但未部署在Windows架构中。虽然可以在Windows平台上运行Docker,但在该架构的第一个版本时,需要在HyperV Windows容器模式或Linux容器模式之间选择,因此以原生操作系统形式部署这些服务器变得更容易。您还会注意到整个架构包含在ESXi管理程序中,未来将扩展和复制以实现冗余。
工件生成Docker容器
在后端使用Docker swarm和共享存储允许我们部署专用的Docker容器用于动态恶意软件生成。我们目前有两种不同类型的容器,一种是基于Python的框架,用于编译C#、Golang和C/C++源代码,另一种专用于Rust语言和编译器。
作为C#/.NET框架容器系统的一部分,我们部署了模块来执行源代码混淆、各种规避技术(如ETW和AMSI绕过补丁),以及根据需要执行PE/COFF修复的代码,例如重新计算PE头校验和。
CI/CD流水线执行
下图直接从GitLab捕获,显示了流水线执行的各个阶段。列出了早期准备阶段、工件生成阶段、动态子流水线触发阶段和后处理活动。CI/CD流水线的部分执行专用任务,例如从现有恶意软件工件生成MSIX/AppX和ClickOnce包。
流水线作业并行化通过GitLab运行器配置选项和整体架构中的多个Docker容器注册实现。其中一个专用容器使用资源脚本消耗的概念,允许我们按架构和编译语言拆分编译作业。当然,还有其他方法可以并行化运行器执行作业,具体取决于动态子流水线YML配置的生成方式。
GitLab运行器YML文件和Python生成脚本
主/父流水线脚本包含在仓库根目录的“.gitlab-ci.yml”文件中。在此文件中,定义了动态子流水线触发器,这些触发器调用用于为下游阶段流水线作业执行生成更多YML配置的Python脚本。这些生成的YML文件工件从流水线执行的早期阶段传递到后期阶段。
下图是主“.gitlab-ci.yml”文件的快照,显示了众多方面,包括流水线阶段、全局流水线触发操作的工作流规则,以及动态为下游阶段生成一些YML的初始准备阶段。
为了完整起见,我还包含了一个配置部分的截图,显示了作为流水线“BakingMalware”阶段一部分执行的动态触发器依赖关系。
如何操作恶意软件工件生成流水线
红队操作员可能需要提供许多潜在输入。这些可能是任何东西,从提供shellcode本身、配置各种规避开关、IP地址信息、URL等。
我们亲切地称我们的内部流水线为Payload或Malware Buffet,因此,我提供了一个名为“BuffetConfig.yml”的配置文件,操作员必须编辑该文件,然后推送更改并触发流水线执行。这个特定的YML文件由流水线执行中的各种脚本处理,与驱动流水线本身的YML内容明显不同。
为了进一步增强和标准化我们的配置,该“BuffetConfig.yml”文件的默认参数现在使用Python“pydantic”模型在Python类中表示。这一步允许我们进一步朝着由我们组织中的其他操作部署软件自动触发此流水线的方向迈进。在我们的路线图中,还计划直接提供一个用于配置目的的Web界面。
此图是此“BuffetConfig.yml”文件部分内容的示例。请注意,“Zulu Foxtrot”是对恶意软件工件生成容器的引用。
流水线执行的预期结果
当流水线触发且所有阶段都已执行时,我们在后处理阶段生成包含生成工件的ZIP文件,供红队操作员使用。将有多个ZIP文件,包含原始工件本身(EXE、DLL、反射DLL、XLL和其他所需文件)、清单信息、MSIX/AppX、ClickOnce和其他打包方法。
使用仅配置一个工件生成容器的适度配置,示例结果如下:
- 57个二进制工件和基于HTML的MANIFEST
- 19个EXE,包括Windows托管(.NET)和原生非托管变体
- 26个DLL,包括托管和非托管
- 4个RDLL(反射原生/非托管)
- 6个XLL(Excel DLL)
- 9个MSIX/AppX包
- 9个Click Once包
- 在适度的20Mb工件膨胀(熵减少器)配置下,产生超过1GB的总数据内容
指标和跟踪
流水线的最后后处理阶段之一使用Python脚本计算生成工件的各种哈希(MD5、SHA1和SHA256),并将结果写入SQLITE数据库,附带日期/时间戳信息用于跟踪目的。
这些数据允许我们做许多事情,包括以图形形式生成随时间推移的工件生成摘要。下图显示了2023年9月期间流水线的一些工件生成统计数据。
CI/CD方法的优势
结合Docker容器框架,我们可以在每次流水线运行时实现自动化的独特二进制工件生成交付。这包括大量多样化的工件类型,具有用于任何嵌入工件的独特加密密钥生成和独特的源代码混淆技术。
整体流水线方法使我们能够灵活地以系统方式添加或修改新的恶意软件开发技术,并快速提供给红队操作员。流水线还为不同形式的预处理和后处理打开了机会,无论是进一步嵌入shellcode编码,还是以工件后重新打包的形式。毫无疑问,这种方法使我们能够提供轻松规避静态工件分析阶段的防御绕过技术,而是将负担上移/提高工件执行中行为分析的门槛。
CI/CD方法的缺点
流水线配置和执行具有显著的复杂性。存在许多软件依赖,形式为多种语言编译器、多种不同工具以及GitLab运行器上的版本控制问题。
此外,CI/CD流水线故障排除的速度是一个挑战,平均流水线运行需要3到10分钟。当前架构对配置输入中的简单语法错误过于敏感,Python脚本膨胀水平不断增加以驱动动态元素。
使用“git”本身并不是理想的操作员用户界面,向前端Web界面方法的移动仍在路线图上以改进这方面。
最后,红队操作员确实因生成工件的巨大多样性而遭受某种压倒性因素。这可以表述为一种“有太多玩具可玩”的问题。提醒操作员“阅读清单”是这方面的一个方面,然而,未来有可能引入配置预设,以帮助解决流水线执行结果的不确定性和压倒性方面。
渗透测试员杂谈
在成功采用这项技术一定程度后,我决定非正式地调查我们的渗透测试员关于这一创造。我问了这个问题:“手动生成您现在从恶意软件buffet流水线自动获得的必要规避工件需要多少小时?”
回应和随后的讨论由这些想法总结:
- 我们认为这为每个客户参与节省了8-16小时的时间。
- 我的开发技能有限,这个流水线对我来说是无价/关键资源。
- 在这存在之前,我会花2天时间在互联网上摸索并编译各种概念验证(POC)代码,只是希望它能为我工作。
- 您的工作改变了我的操作方式。我现在更专注于参与操作本身。
- 您的工作为我们的客户参与带来了更多一致性。
结论
应注意,流水线中采用的底层技术多种多样,包括在线发布的项目,以及Black Hills Information Security编写的软件。在开发规避恶意软件工件的过程中,有许多技术,我们站在社区中许多愿意分享研究和资源的伟人的肩膀上。
从CI/CD开发的角度来看,我整理了一个资源,应被视为建立您自己流水线项目的模板方法。这是一种“按数字绘画”的指南努力,您可以在这里找到:https://github.com/yoda66/MAAS
投入开发的许多方面的著名工具和项目包括以下:
- WinDBG – 是的,Windows调试器。寻找MS应用商店版本!
- System Informer - https://systeminformer.sourceforge.io
- SysInternals Process Explorer - https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer
- API Monitor - http://www.rohitab.com/apimonitor
- MS Visual Studio、Mono和Mingw-w64交叉编译器
- 用于许多YML生成脚本的Python3
- PE-SIEVE - https://github.com/hasherezade/pe-sieve
- DnSpy - https://github.com/dnSpy/dnSpy
- Resource Hacker - https://www.angusj.com/resourcehacker/
- 许多不同的.NET混淆技术和项目
- SysWhispers3 - https://github.com/klezVirus/SysWhispers3
此外,有许多优秀的个人和公司慷慨地分享关于各种开发和规避技术的博客和文章。以下是我在不同时间参考的各种资源列表。当然,鉴于我们工作的性质,发布的信息一直在变化。希望您喜欢阅读本文,并获得一些您可能选择在您的工作中采用的技术和方法的见解。
- https://docs.gitlab.com/ee/ci/
- https://defuse.ca/online-x86-assembler.htm
- https://www.blackhillsinfosec.com/avoiding-memory-scanners/
- https://www.elastic.co/fr/security-labs/upping-the-ante-detecting-in-memory-threats-with-kernel-call-stacks
- https://www.cobaltstrike.com/blog/behind-the-mask-spoofing-call-stacks-dynamically-with-timers
- https://jsecurity101.medium.com/uncovering-windows-events-b4b9db7eac54
- https://codemachine.com/articles/x64_deep_dive.html
- https://www.crowdstrike.com/blog/crowdstrikes-advanced-memory-scanning-stops-threat-actor/
- https://securityintelligence.com/x-force/direct-kernel-object-manipulation-attacks-etw-providers/
- https://www.mdsec.co.uk/2023/09/nighthawk-0-2-6-three-wise-monkeys/
阅读:第一部分 务必在今天美国东部时间下午1点(预热闲聊从12:30开始)观看Joff的网络直播“探索Windows下的Python‘psutil’模块”。提供录制版本。 在这里找到:https://www.youtube.com/live/_cTiTHZfewY
您可以直接从Joff本人那里了解更多信息,通过他的课程:
- 正则表达式,您的新生活方式
- 企业攻击者模拟和C2植入开发
- Python简介 提供实时/虚拟和点播!
谈论信息安全新闻 – 2024年2月28日 事件响应的OSINT(第二部分)