影响平台:Windows
受影响的用户:任何组织
威胁程度:高
几年来,勒索软件一直是各组织面临的主要威胁,造成的损失估计高达数十亿美元。为了令勒索攻击实施有效,勒索软件进行的一个常见行动是擦除卷影备份(即影子副本),从而使受害者无法恢复任何已加密的文件。
在这篇文章中,我们回顾了勒索软件用于删除影子副本的现有方法,以便让防御者重新总结他们需要保护自己和数据资源免受攻击的技术。此外,我们还揭露了可能被勒索软件使用的新方法。分享这些方法将使防御者能够针对这些潜在的未来技术部署适当的检测,因为我们以后遇到它们只是时间问题,这也将给现有的防护报警系统带来新的冲击。
在我们开始之前,关于卷影复制架构,有几个重要元素读者应该熟悉。
卷影复制服务(VSS):该服务负责协调执行影子复制相关操作的实体之间的所有行动,如相关的写入者和提供者。VSS使用COM(Component Object Model)技术实现,读者应该对本文后面的部分有基本的熟悉。
VSS写入器(VSS Writers):这些组件负责提供稳定的数据管道,由服务进行备份。Windows有一长串的 “In-Box VSS Writers”,用于各种软件组件。
VSS提供者(VSS Providers):这些组件创建和维护实际的影子副本对象。其有两种主要类型的提供者:“硬件提供者”和“软件提供者“。
图1中可以看到VSS架构图,说明了各组件及其关系。
图1:MSDN的总体架构图
系统提供者是Windows上的默认提供者,目前以软件提供者的形式实现。它是处理影子副本删除尝试时最常见的目标。系统提供者采用了写后复制(C-o-W)机制,因此快照只保存卷上正在进行的更改。这些更改被保存在指定的 “diff area “存储位置,通常是在同一个卷上。但它们也可以保存在任何足够大的NTFS卷上。
有两种方法可以删除影子副本。第一种是使用命令行工具明确地删除影子副本,或者以各种介入API方式编程(我们将在本文后面介绍)。
第二种方法是间接的,因为它依赖于可以控制 “diff area “的大小。如果现有的快照超过了新调整的diff区域的大小,提供者就会放弃快照以释放空间,如图2中的文档所解释的那样。(注意,设置的最小可能大小是320MB) 。
注意,使用VSS需要管理员权限。
图2:来自MSDN的调整警告
有几个著名的命令行实用程序可以管理VSS:vssadmin.exe,从Windows XP开始,每一个新的Windows安装都会有,还有WMIC.exe(WMI命令行),它提供了对Windows管理工具的访问。行为者随着时间的推移,演化出对这些实用程序的使用,以对抗防御者的检测。
第一个也是最常用的方法是用vssadmin运行删除命令。
vssadmin delete shadows /all /quiet
据观察,利用这种方法的一些臭名昭著的勒索软件家族有Ryuk、WannaCry、Dharma、RobinHood、Hermes、Phobos和Locky等等
在这种方法广为人知并被防御后,攻击者开始利用WMIC.exe删除影子副本,使用以下参数。
wmic shadowcopy delete /nointeractive
这种方法在勒索软件作者中也非常流行,GandCrab、Robinhood、Phobos、LockBit、Rapid和JCry都采用了这种方法。
另一方面,与前两种方法相比,重新调整大小在勒索软件家族中是一种比较新的方法,虽然也是用vssdamin来执行,但目前此类攻击方法还不常见。
vssadmin resize shadowstorage /for=<backed volume>/on=<backup location volume> /maxsize=<new size>
图3:Ryuk使用的调整命令字符串大小的示例
这种方法被一些勒索软件家族使用,如Nemty、Ryuk、Hermes、Rapid和MegaCortex(唯一一个真正使用最小尺寸的勒索软件),我们预计未来会看到这种方法被更广泛地使用。
这种方法的问题是,我们不一定知道diff区域的空间被使用了多少,这有可能导致这样一种情况:尽管调整了大小,但有些快照可能不会被删除。由于系统提供者使用的是C-o-W,所以在创建快照之前,变化会被保存到diff区域。为了克服这个问题,在调整大小的操作后,diff区域应该以等于或大于其缩小后的大小来填充数据,然后再创建一个新的快照,以触发删除所有现有的快照。
勒索软件作者的最新方法是直接从他们的代码(或脚本)中调用删除影子副本。而PowerShell命令则受到勒索软件的青睐,在一行简单的代码中列举并删除所有影子副本的实例。
通过WMI的Win32_ShadowCopy类和有用的PowerShellcmdlet来访问WMI对象,可以方便地实现这一点,从下面的例子中可以看出。
1. Get-WmiObject Win32_ShadowCopy| % { $_.Delete() }
2. Get-WmiObject Win32_ShadowCopy| Remove-WmiObject
Get-WmiObject cmdlet 被 Nemty 和 Sodinokibi 使用。 Sodinokibi 作为一个子进程运行 PowerShell ,命令行参数为 base64 编码,解码为:
Get-WmiObject Win32_Shadowcopy| ForEach-Object { $_Delete(); }
在接下来的章节中,我们将介绍尚未被发现的 ITW的删除方法。
在本节中,我们讨论了删除影子副本的新方法,这些影子副本有可能在未来被勒索软件使用。第一种方法提出了额外的PowerShell技巧来触发删除,而第二和第三种方法则利用了VSS架构的行为和内部工作机制。
虽然我们还没有遇到任何使用这个的勒索软件,但可以使用CIM cmdlets来代替WMI的。
Get-CimInstanceWin32_ShadowCopy|Remove-CimInstance
当在远程机器上进行基于CIM的调用时,它们会通过WinRM而不是DCOM发送。
PowerShell cmdlets 也支持别名。有些是内置的,比如Get-WmiObject的gwmi,或者Get-CimInstance的gcim。新的别名可以通过New-Alias cmdlet来创建,现有的别名可以通过Set-Alias cmdlet来修改。
也可以在没有PowerShell.exe二进制的情况下运行PowerShell脚本。某些LOLBins可以执行Powershell脚本,例如SyncAppvPublishingServer.exe。这些二进制文件的优点是它们可以绕过应用程序的黑名单防御。
与其使用已知的主机进程作为PowerShell核心,不如使用.NET框架从自己的进程中执行PowerShell脚本。比如UnmanagedPowerShell和SharpPick。参见: https://github.com/leechristensen/UnmanagedPowerShell , https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerPick/SharpPick
什么是LoLBins?
LoLBin是操作系统提供的任何二进制文件,通常用于合法目的,但也可能被恶意行为者滥用。一些默认的系统二进制文件具有意想不到的副作用,这可能会让攻击者在利用后隐藏其活动。
WMI可以通过COM来编程使用,而不是命令行工具或PowerShell,正如我们前面提到的,VSS架构本身就是基于COM的,所以可以直接使用更直接的方法来操作这些对象。
如果我们看一下vssadmin的底层,我们可以很快注意到,它使用VSSCoordinatorCOM类与IVssCoordinator接口来向VSS服务发出删除请求。这个对象是在一个名为vss_ps.dll的代理DLL中实现的。
图4:IVssCoordinator接口的代理DLL的注册表查询情况
按照这个发现,显而易见的方向是直接使用相同的COM对象,因此,留下vssadmin二进制是多余的。相关的接口定义出现在vscoordint.idl中,旧版Windows SDK可以找到。删除函数的定义是
HRESULT DeleteSnapshots( VSS_ID SourceObjectId, VSS_OBJECT_TYPEeSourceObjectType。 BOOL bForceDelete, LONG* plDeletedSnapshots, VSS_ID* pNondeletedSnapshotID)
SourceObjectId是影子副本本身的GUID标识,eSourceObjectType设置为VSS_OBJECT_SNAPSHOT。
还有一些文档化的VSS对象提供了管理快照的所有必要功能。其中之一是IVssSoftwareSnapshotProvider接口,它也可以用来调用所需的删除操作。改变diff区域的大小可以使用IVssDifferentialSoftwareSnapshotMgmt接口来完成。
当删除快照时,执行流得到的是向volsnap.sys发送IOCTLs的提供者(swprv.dll)。内核驱动不执行任何访问检查,无论是对设备打开请求,还是对发送到它的IOCTLs,都不执行任何访问检查,以验证源头是提供者服务进程,所以可以从任何进程发送这些IOCTLs,甚至可以处置COM层。
使用ProcMon,我们可以很容易地跟踪提供者执行的操作。
1.打开影子拷贝卷的句柄(例如:/Device/HarddiskVolumeShadowCopy1)。 2.发送未记录的IOCTL_VOLSNAP_SET_APPLICATION_INFO。 3.用IOCTL_VOLUME_SET_GPT_ATTRIBUTES将卷设置为隐藏。(如果还没有的话) 4.接下来,通过发送FSCTL_DISMOUNT_VOLUME和IOCTL_VOLUME_OFFLINE禁用卷。 5.打开备份卷的句柄(即C:,影子副本属性中的 “原始卷”)。 6.发送未记录的IOCTL_VOLSNAP_DELETE_SNAPSHOT (0x53C038),同时在输入缓冲区中传递要删除的快照名称。
查询影子副本属性可以使用我们之前介绍的工具(vssadmin、WMI和COM对象)。步骤1-4是可选的,但要记住,它们保证了程序的有效性,跳过它们可能会导致失败或意外的结果。
图5:IOCTL删除调用的ProcMon日志
为了调整diff区域的大小,提供者向原卷发送未记录的IOCTL_VOLSNAP_SET_MAX_DIFF_AREA_SIZE(0x53C028),如图6所示。
图6:swprv.dll中ChangeDiffAreaMaxmiumSize下的无文档IOCTL。
即使驱动程序会验证请求的源头是提供商的服务,将代码注入其中以执行上述操作也会绕过该检查。
我们所介绍的方法在不同的层次上进行操作,每一种方法都提出了一些检测机制的选择。
首先要从命令行参数扫描开始,这是一个非常初级的解决方案。虽然它涵盖了当今勒索软件使用的大多数技术,但防御者必须考虑到语法的多样化风格,并能够处理新的混淆形式和发现新的LOLBins。此外,还有一些已知的技术可以隐藏命令行参数。
如果是作为一个通用的方法,则需要某种形式的COM监控。
一个直观的解决方案可以是搜索任何在意外进程中加载库的异常情况。例如,如果vss_ps.dll被vssadmin.exe或wmiprvse.exe以外的进程加载(当使用WMI时),它们可以被认为是可疑的。然而,这可能会产生误报(FalsePositive),因为它不能保证vss_ps.dll确实被使用,而且影子副本被删除。监视实际的COM对象会得到更准确的结果。监视对注册表中相关键的访问是可能的,但在误报方面存在同样的问题。相反,使用 COM 对象代理和过滤器可能被证明是适当的解决方案。
最终的解决方案是监控执行流程中的最后一步,因为它是所有方法的共同交叉点–对驱动程序的设备IO控制调用。这些应该是源于提供者服务的。在每个进程中的DeviceIoControl和ZwDeviceIoControlFile等函数上安装钩子来监视这些调用是可能的,但攻击者可以不费吹灰之力就能躲过。使用ETW事件来检测这些IOCTL代码是一种比较可行的可能性。最后一种选择是使用内核驱动程序并执行IRP过滤,它也支持阻止任何潜在的恶意请求的能力。
在这篇文章中,我们回顾了删除影子副本的不同方法,从已知的命令行实用程序到各种程序形式。
几乎所有这些方法都以这样或那样的方式操作COM对象,甚至那些没有正式公开的对象。我们演示了一种替代方法,它不依赖于这些对象,而是模仿它们的操作,同时直接访问影子拷贝设备。
我们提出了不同的想法来检测和防止任何对所述方法的恶意使用,因为仅仅依靠命令行参数进行检测被证明是徒劳的。首选的方法是监控对影子拷贝设备本身的访问。但是,即使如此,在未有能力检测COM对象的操作前提下,依靠命令行参数进行检测也是非常有效的一种手段。
总而言之,这项研究强调了一个前提,道高一尺,魔高一丈。即防御者必须随时与时俱进,不断更新采用新的检测方法和能力。
原文参考: https://www.fortinet.com/blog/threat-research/stomping-shadow-copies-a-second-look-into-deletion-methods