用 Speakeasy 模拟恶意 Shellcode

安全侠2020-08-27 10:13:03

为了能够大规模仿真恶意软件样本,我们通过Speakeasy仿真框架。Speakeasy旨在使非恶意软件分析人员的用户能够尽可能轻松地自动获取分类报告,并使工程师能够编写自定义插件来分类恶意软件。

Speakeasy最初是为了模拟Windows内核模式的恶意软件而创建的,现在也支持用户模式示例。该项目的主要目标是针对x86和amd64平台进行动态恶意软件分析的Windows操作系统的高分辨率仿真。存在类似的仿真框架来仿真用户模式二进制文件。Speakeasy尝试通过以下方式与其他仿真框架区分开来:

  • 专为模拟Windows恶意软件而设计
  • 支持内核模式二进制文件的仿真,以分析难以分类的rootkit
  • 由当前恶意软件趋势推动的仿真和API支持,为社区提供了无需额外工具即可提取危害指标的方法
  • 完全可配置的仿真环境,无需其他代码

该项目当前支持内核模式驱动程序,用户模式Windows DLL和可执行文件以及shellcode。可以自动模拟恶意软件样本,并生成报告供以后进行后期处理。正在进行的项目目标将是继续增加对新的或流行的恶意软件家族的支持。

在此博客文章中,我们将展示一个Speakeasy在从在线恶意软件集合中获取的Cobalt Strike Beacon示例中自动提取网络指标的有效性示例。

背景

Windows恶意软件的动态分析一直是恶意软件分析过程中的关键步骤。了解恶意软件如何与Windows API交互以及提取有价值的基于主机和基于网络的危害指标(IOC)对于评估恶意软件对受影响的网络的影响至关重要。通常,以自动化或有针对性的方式执行动态分析。恶意软件可以排队等待在沙盒中执行以监视其功能,也可以手动进行调试以显示沙盒运行期间未执行的代码路径。

过去,代码仿真一直用于测试,验证甚至是恶意软件分析。能够模拟恶意代码可从手动和自动分析中获得许多好处。CPU指令的仿真允许对二进制代码进行全面检测,在此过程中,可以影响控制流以最大程度地覆盖代码。在仿真时,可以监视和记录所有功能,以便快速提取危害或其他有用情报的指标。

与在管理程序沙箱中执行相比,仿真具有一些优势。关键优势是降低噪音。在仿真时,唯一可以记录的活动是由恶意软件作者编写的,或者是在二进制文件中静态编译的。虚拟机管理程序中的API挂钩(尤其是从内核模式的角度来看)可能很难归因于恶意软件本身。例如,沙箱解决方案通常会在不知道恶意软件作者是否打算分配内存,还是由较低级别的API负责内存分配的情况下挂接堆分配器API调用。

但是,仿真也有缺点。由于我们要从分析阶段中删除操作系统,因此,作为仿真器,我们现在负责提供API调用和仿真期间发生的内存访问的预期输入和输出。为了成功地模拟预期在合法Windows系统上运行的恶意软件样本,这需要大量的精力。

Shellcode作为攻击平台

通常,shellcode是使攻击者在受感染的系统上保持隐身的绝佳选择。Shellcode在可执行内存中运行,不需要磁盘上的任何文件进行备份。这使攻击者代码可以轻松隐藏在大多数形式的传统法医分析无法识别的内存中。必须首先确定装入shellcode的原始二进制文件,或者必须从内存中转储shellcode本身。为了避免检测,可将shellcode隐藏在出现的良性加载程序中,然后注入到另一个用户模式进程中。

在本博客系列的第一部分中,我们将展示在事件响应调查期间遇到的一种较为常见的Shellcode恶意软件样本中进行仿真的有效性。Cobalt Strike是一个商业渗透测试框架,通常使用阶段程序来执行其他代码。分段器的一个示例是通过HTTP请求下载其他代码并执行HTTP响应数据的分段器。在这种情况下,数据是shellcode,通常以解码循环开始,然后是有效的PE,该PE包含反射性地加载自身的代码。对于Cobalt Strike,这意味着它可以从可执行标头的开头执行,并将自身加载到内存中。在“钴打击”框架内,这种情况下的有效载荷通常是称为信标的植入物。信标被设计为驻留在内存中的后门,用于在受感染的Windows系统上维护命令和控制(C2)。它是使用Cobalt Strike框架构建的,无需进行任何代码修改,并且可以轻松构建以使其核心功能以及命令和控制信息得到修改。

所有这些使攻击者能够在受感染的网络上快速构建和部署新的信标植入变体。因此,有必要使用一种工具来快速提取Beacon的可变组件,并且理想情况下,它不需要恶意软件分析师的宝贵时间。

Speakeasy设计

Speakeasy当前使用基于QEMU的仿真器引擎Unicorn来仿真x86和amd64体系结构的CPU指令。Speakeasy旨在将来通过抽象层支持任意仿真引擎,但目前依赖Unicorn。

分析所有样本可能总是需要使用完整的操作系统沙箱来进行分析,因为通常情况下模拟所有Windows都是不可行的。沙箱可能难以按需扩展,并且可能很费时间来运行样本。但是,通过确保我们模拟特定的恶意软件家族(例如本例中的Beacon),我们可以快速减少反向工程变体的需求。能够以自动化方式生成高级分类报告通常是对恶意软件变体所需要的所有分析。这使恶意软件分析人员有更多时间专注于可能需要更深入分析的样本。

Shellcode或Windows PE被加载到模拟地址空间中。在尝试模拟恶意软件之前,创建了有助于Windows内核模式和用户模式的基本模拟所需的Windows数据结构。进程,驱动程序,设备和用户模式库是“伪造的”,以便为恶意软件提供逼真的执行环境。恶意软件将能够与模拟文件系统,网络和注册表进行交互。所有这些仿真子系统都可以使用提供给每个仿真运行的配置文件进行配置。

Windows API由Python API处理程序处理。这些处理程序将尝试模拟这些API的预期输出,以便恶意软件样本将继续其预期的执行路径。在定义API处理程序时,所需要做的就是API的名称,API期望的参数数量以及可选的调用约定规范。如果未提供调用约定,则假定为stdcall。当前,如果尝试了不支持的API调用,则Speakeasy将记录不受支持的API并继续到下一个入口点。图1显示了由kernel32.dll导出的Windows HeapAlloc函数的示例处理程序。


图1:Windows HeapAlloc函数的示例处理程序

默认情况下模拟所有入口点。例如,对于DLL,将模拟所有导出,对于驱动器,将分别模拟IRP主要功能。此外,还会跟踪在运行时发现的动态入口点。动态入口点的一些示例包括创建的线程或注册的回调。在尝试确定恶意软件感染的影响时,将活动归因于特定的入口点对于查看整个图片至关重要。

报告中

当前,模拟器捕获的所有事件均被记录并由JSON报告表示,以便于后期处理。该报告包含在仿真过程中记录的关注事件。像大多数模拟器一样,所有Windows API调用都与参数一起记录。仿真所有入口点并为其标记相应的API列表。除了API跟踪外,还会调用其他特定事件,包括文件,注册表和网络访问。所有已解码或“内存驻留”的字符串都将转储并显示在报告中,以揭示在静态字符串分析中找不到的有用信息。图2显示了Speakeasy JSON报告中记录的文件读取事件的示例。


图2:Speakeasy报告中的文件读取事件

速度

因为该框架是用Python编写的,所以速度是一个明显的问题。Unicorn和QEMU用C编写,提供了非常快的仿真速度。但是,我们编写的API和事件处理程序使用Python。本机代码和Python之间的转换非常昂贵,应尽量减少。因此,目标是仅在绝对必要时才执行Python代码。默认情况下,我们在Python中处理的唯一事件是内存访问异常或Windows API调用。为了捕获Windows API调用并在Python中模拟它们,导入表中掺杂了无效的内存地址,因此我们仅在访问导入表时才切换到Python。当shellcode访问恶意软件的模拟地址空间中加载的DLL的导出表时,将使用类似的技术。

内存管理

Speakeasy在模拟器引擎的内存管理之上实现了轻量级的内存管理器。跟踪并标记由恶意软件分配的每个内存块,以便可以获取有意义的内存转储。能够将活动归因于特定的内存块对于分析人员而言非常有用。记录对敏感数据结构的内存读写可以揭示API调用记录未揭示的恶意软件的真实意图,这对于rootkit等样本尤其有用。

Speakeasy提供了可选的“内存跟踪”功能,该功能将记录样本展示的所有内存访问。这将记录所有读取,写入和执行到内存。由于仿真器标记了所有分配的内存块,因此有可能从该数据中收集更多上下文。如果恶意软件钩住关键数据结构或将执行转移到动态映射的内存,这将被揭示出来,对于调试或归因很有用。但是,此功能的成本很高,并且默认情况下未启用。

呈现给恶意软件的模拟环境包括Shellcode用于定位和执行导出的Windows系统功能的通用数据结构。为了调用Win32 API,必须解析导出的函数,从而对目标系统产生有意义的影响。在大多数情况下(包括信标),这些功能是通过遍历过程环境块(通常称为PEB)来定位的。Shellcode可以从PEB访问进程的虚拟地址空间内所有已加载模块的列表。

图3显示了通过模拟Beacon shellcode示例生成的内存报告。在这里,我们可以跟踪在PEB上行走的恶意软件,以查找kernel32.dll的地址。然后,该恶意软件手动解析并调用“ VirtualAlloc” API的函数指针,然后继续进行解码并将其自身复制到新缓冲区中,以进行执行。


图3:内存跟踪报告

配置

Speakeasy高度可配置,并允许用户创建自己的“执行配置文件”。可以指定不同的分析级别,以优化各个用例。最终目标是允许用户在不更改代码的情况下轻松切换配置选项。当前,配置文件的结构为JSON文件。如果用户未提供配置文件,则框架将提供默认配置。各个字段记录在Speakeasy项目中。

图4显示了网络仿真器配置子部分的代码片段。在这里,用户可以指定在进行DNS查找时返回哪些IP地址,或者在某些信标示例的情况下,指定在TXT记录查询期间返回哪些二进制数据。HTTP响应也配置了自定义响应。


图4:网络配置

许多HTTP登台者都会使用HTTP GET请求来检索Web资源。通常,例如使用Cobalt Strike或Metasploit分级机时,此缓冲区将立即执行,以便可以开始执行下一个阶段。可以使用Speakeasy配置轻松配置此响应。在图4的配置中,除非被覆盖,否则框架将提供引用的default.bin文件中包含的数据。该文件当前包含调试中断指令(int3),因此,如果恶意软件尝试执行数据,它将退出并记录在报告中。使用此工具,我们可以轻松地将恶意软件标记为可下载其他代码的下载器。还存在用于文件系统和注册表仿真的配置字段。

局限性

如前所述,仿真带来了一些挑战。与正在仿真的系统保持功能均等是一场持续的战斗。但是,它提供了控制恶意软件和更多自省选项的独特机会。

在仿真未完全完成的情况下,仍然可以生成仿真报告和内存转储,以收集尽可能多的数据。例如,后门可能会成功安装其持久性机制,但无法连接到其C2服务器。在这种情况下,仍会记录有价值的基于主机的指标,并且可以为分析师提供价值。

可以快速轻松地将缺少的API处理程序添加到仿真器中,以处理这些情况。对于许多API处理程序而言,仅返回成功代码就足以使恶意软件继续执行。虽然不可能对每个恶意软件进行完全仿真,但是针对特定恶意软件家族的功能可以极大地减少反向工程相同家族变种的需求。

用法

现在可以在我们的GitHub上使Speakeasy 。它可以使用随附的Python安装程序脚本安装,也可以使用提供的Dockerfile安装在Docker容器中。它与平台无关,可用于在Windows,Linux或MacOS上模拟Windows恶意软件。可以在项目的README上找到更多信息。

安装后,Speakeasy可以用作独立库,也可以使用提供的run_speakeasy.py脚本直接调用。
包含的脚本旨在模拟单个样本,并使用记录的事件生成JSON报告。图5显示了run_speakeasy.py的命令行参数。


图5:run_speakeasy.py的命令行参数

Speakeasy还提供了丰富的开发和挂钩界面,用于编写自定义插件。这将在以后的博客文章中更详细地介绍。

模拟信标植入

对于此示例,我们将仿真Shellcode,该Shellcode解码并执行Beacon植入程序变体,该变体的SHA-256哈希值为7f6ce8a8c2093eaf6fea1b6f1ef68a957c1a06166d20023ee5b637b5f7838918。我们首先验证样本的文件格式。预期该示例将由加载程序启动,或用作漏洞有效负载的一部分。


图6:恶意软件的十六进制转储示例

在图6中,我们可以清楚地看到该文件不是PE文件格式。看到许多shellcode示例的分析人员可能会注意到前两个字节:“ 0xfc 0xe8”。这些字节反汇编为intel汇编指令“ cld”和“ call”。“ cld”指令是放置独立的shellcode的常见前奏,因为它将清除方向标志,从而使恶意软件可以轻松地分析系统DLL导出表中的字符串数据。shellcode通常使用以下调用指令,通过在其后跟随“ pop”指令来获取其当前程序计数器。这使恶意软件可以从内存中发现其执行位置。

由于我们可以肯定地确定此样本是shellcode,因此我们将使用图7所示的命令行调用Speakeasy。


图7:用于模拟恶意软件示例的命令行

这将指示Speakeasy将偏移量为零的样本模拟为x86 shellcode。注意:即使我们正在仿真代码而不实际执行代码,它们仍然是攻击者生成的二进制文件。在使用任何本机CPU仿真引擎发现漏洞的情况下,在虚拟机中仿真恶意代码仍然是明智的选择。

仿真后,将生成一个名为“ report.json”的报告。此外,还将压缩仿真环境的完整内存转储并将其写入“ memory_dump.zip”。该恶意软件将被加载到假容器过程内部的模拟内存中,以模拟shellcode预期在其中运行的真实执行环境。一旦开始模拟,模拟的API调用将连同其参数和返回值一起记录到屏幕上。图8显示了Beacon示例,该示例分配了一个新的内存缓冲区,它将在其中复制自身。然后,该恶意软件开始手动解决它需要执行的导出。


图8:网络配置

经过额外的解码和设置后,恶意软件尝试连接到其C2服务器。在图9中,我们可以看到使用Wininet库的恶意软件使用HTTP连接和读取了C2服务器中的数据。


图9:Wininet API调用以连接到C2

恶意软件将无限循环,直到从C2服务器接收到期望的数据为止。Speakeasy将在预定时间后超时并生成JSON报告。


图10:网络C2事件

在生成的报告的“ network_events”和“ traffic”部分中汇总了网络指标。在图10中,我们可以看到IP地址,端口号,在这种情况下,还可以看到与恶意软件建立的连接相关的HTTP标头。

在此示例中,当我们模拟示例时,我们指示Speakeasy创建模拟地址空间的内存转储。将为每个内存分配及其周围的上下文创建一个ZIP存档。该上下文包括基址,大小和由仿真器分配的标签,以标识内存分配对应的内容。图11显示了在仿真过程中创建的内存转储文件的片段。文件名包含与每个内存分配关联的标签和基址。


图11:通过仿真获得的单个存储块

如果仅在这些内存转储上运行字符串,我们可以快速找到有趣的字符串以及Beacon配置数据,如图12所示。


图12:恶意软件的配置字符串数据

在分类分析中,我们可能仅关心已知家族的恶意软件变体的危害指标。但是,如果需要对样本进行完全反向工程,我们还可以DLL形式恢复Beacon恶意软件的解码版本。通过简单地对“ MZ”魔术字节执行原始grep,我们发现唯一的问题是与原始样本分配有关的内存转储以及恶意软件将自身复制到的虚拟分配缓冲区(图13)。


图13:包含已解码恶意软件的内存转储

如果我们查看原始shellcode缓冲区中的字节,我们可以看到它在被复制之前已被解码,并且位于内存中,准备以偏移量0x48进行转储。现在,我们可以成功地将解码后的Beacon DLL加载到IDA Pro中进行全面分析(图14)。


图14:已解码的恶意软件已成功加载到IDA Pro中

结论

在此博客文章中,我们演示了如何使用Speakeasy仿真框架自动对Beacon恶意软件样本进行分类。我们使用它来发现有价值的网络指示器,从内存中提取其配置信息,并获取已解码的Beacon DLL进行进一步分析。

beacon仿真软件
本作品采用《CC 协议》,转载必须注明作者和本文链接
本次工作中,我们利用各种不同的攻击场景评估EDR和其他端点安全方案在APT检测及阻止方面的效率。但无论如何这项工作不应作为任何特定EDR方案的安全投资指南。事实上,定制EDR规则可能会显著改变他们的作用。由于并不只依靠特征值,所以EDR也能够检测未知威胁,并在产生破坏之前阻止他们。
是一套用于对域名进行侦察的工具。该程序会检查 SPF 和 DMARC 记录中是否存在允许欺骗的弱配置。用于发现计算机网络上的主机和服务,从而构建网络的“地图”。自动渗透测试侦察扫描仪。不受 API 限制,因为它使用 Selenium 检测浏览器。输出报告以帮助关联跨站点的目标。是一个 python 脚本,它检查电子邮件帐户是否在数据泄露中受到损害,如果电子邮件帐户受到损害,它会继续查找受损害帐户的密码。LinkedIn 枚举工具,通过搜索引擎抓取从组织中提取有效员工姓名。
为了能够大规模仿真恶意软件样本,我们通过Speakeasy仿真框架。Speakeasy旨在使非恶意软件分析人员的用户能够尽可能轻松地自动获取分类报告,并使工程师能够编写自定义插件来分类恶意软件。 Speakeasy最初是为了模拟...
如果成功连接到管道, 使用WriteFile函数将shellcode数据写入已连接的命名管道。使用IDA分析检查导出函数:第一个是反射式DLL注入,限于篇幅,在本篇中不展开分析第二个是DLL的入口函数。在后续的文章中,会根据检测特征和csprofile的绕过按照专题进行分析。同时,大部分的CS检测特征都是在此。而在后续的文章分析中,将会着重的分析CS beacon中使用到的几种DLL注入方式;beacon config的检测;同时结合CS profile 的配置,研究一下CS的对抗检测方式。
从零开始开发CS beacon
2021-12-21 16:01:20
因为我也才学golang,基本面向github编程,在网上只找到python版加解密的方式,所以需要翻译成go语言。
Beacon 通常是反射加载到内存中,还可以配置各种内存中混淆选项以隐藏其有效负载。 Beacon 可以配置各种内存中混淆选项以隐藏其有效负载。例如,obfuscate-and-sleep 选项会试图在回调之间屏蔽部分 Beacon 有效负载,以专门避开基于特征的内存扫描。
Beacon 通常是反射加载到内存中,还可以配置各种内存中混淆选项以隐藏其有效负载。Beacon 可以配置各
SMB Beacon 与命名管道在 Windows 中,无管理员权限的情况下,即无法添加白名单。定义特定版本的协议的消息数据包集称为方言。进行身份验证后,用户可以访问服务器上不受共享级别安全性保护的所有共享。
CobaltStrike ShellCode详解
2022-08-04 16:51:50
接下来就是重点了,加载起来的这段shellcode开头先将DF标志位置0,这里为什么这样做后面会提到。
微软社区网友 LiCaoZ 发文表示,自 8 月 19 日 11 时起,包括必应搜索在内的部分 Microsoft 服务受到了部分地区中国移动省份网关屏蔽,流向 Microsoft 数据中心节点的数据包会在经过省份网关时被丢弃。
安全侠
暂无描述