Vice Society 是一种勒索软件,采用强大的加密算法来锁定存储在受感染系统上的数据Vice Society 是一个相对较新的恶意软件,于 2021 年年中首次出现。
在最近一次事件响应(IR)活动中,unit42团队发现,Vice Society勒索软件组织使用自定义的Microsoft PowerShell(PS)脚本从受害者网络中窃取数据。我们将对所使用的脚本进行分解,解释每个函数是如何工作的,以便了解这种数据窃取方法。
该组织使用多种方法从受害者的网络中窃取数据。一些使用者会使用外部工具,包括FileZilla、WinSCP和rclone等工具。还有使用者使用 LOLBAS(Living off the Land Binaries And Scripts)技术,如PS脚本,通过远程桌面协议(RDP)复制/粘贴和微软的Win32 API(例如Wininet.dll调用)。让我们来看看当使用PS脚本自动执行勒索软件攻击的数据泄露阶段时会发生什么。
使用LOLBAS等内置数据泄露方法的攻击者不需要引入可能被安全软件或基于人工的安全检测机制标记的外部工具。这些方法还可以隐藏在一般操作环境中,很容易躲过安全检测。
例如,PS脚本经常在典型的Windows环境中使用。当攻击者想要悄无声息地发起攻击时,PS代码通常是首选。
2023年初,unit42团队发现Vice Society勒索软件组织使用了一个名为为w1.ps1的脚本从受害网络中窃取数据。在本例中,脚本是从Windows事件日志(WEL)中恢复的。具体而言,该脚本是从Microsoft Windows PowerShell/Operational WEL提供程序中发现的事件ID 4104:脚本块日志记录事件中恢复的。
虽然必须在Windows中启用脚本块日志记录才能记录所有脚本块,但Microsoft默认情况下使用一些未记录的后端魔法来记录其认为是恶意的事件。因此,即使在脚本块日志记录尚未完全启用的环境中,事件ID 4104事件也可能对你的分析有用。
unit42研究人员看到了使用以下PS命令执行的脚本:
此脚本调用使用统一资源名称(URN)路径中的本地域控制器(DC)IP地址(如上面的[redected_IP]所示),指定DC上的s$admin共享。请注意,由于脚本是通过客户端的DC部署的,因此目标计算机可能是攻击者尚未获得直接访问权限的计算机。因此,网络中的任何端点都可能成为脚本的目标。为PS可执行文件提供-ExecutionPolicy Bypass参数以绕过任何执行策略限制。
该脚本不需要任何参数,因为从网络复制哪些文件是脚本本身负责的。是的,你没有看错:脚本是自动化的,因此可以选择应该窃取的数据。
脚本首先声明两个用于受害者识别的常量$id和$token。在我们识别的脚本中,这些值分别被硬编码为“TEST”和“TEST_1”:
从逻辑上讲,这些变量可以设置为更具体的值,以识别实际的受害者。我们不确定这是否真的是一个测试阶段,或者这些值是否会简单地保持在这个测试状态。
接下来,脚本声明代码库中的重要函数。表1提供了脚本函数的概述。这是按照函数被调用的顺序列出的,而不是它们被声明的顺序。
脚本函数概述
下图概述了函数之间的流程,有助于突出显示脚本的函数。
w1.ps1脚本的函数图
在调用任何声明的函数之前,脚本会通过Windows Management Instrumentation(WMI)识别系统上安装的任何驱动器。通过一些简单的筛选来获取wmiobject win32_volume的调用提供了一个名为$drives的数组,该数组将包含安装在计算机上的驱动器列表。然后将找到的每个驱动器路径分别传递给Work()函数。下图显示了相关的代码片段。
脚本的前导码,用于识别并处理每个挂载卷
在前导码中采取了以下操作:
1.它创建一个名为$drives的数组,并用主机上挂载的卷列表填充该数组。win32_volume中的DriveType枚举引用本地磁盘。有关详细信息,请参阅Microsoft的Win32_Volume Class文档。
2.它作为$drive遍历主机上标识的驱动器,将每个标识的驱动器路径传递给Work()函数。
下图显示了这段代码在只挂载了一个驱动器的普通Windows主机上可能执行的操作示例。
带有单个挂载驱动器的主机上的$drives和$drive变量的示例值
对于标识的每个驱动器名称,前导码都会调用Work()函数来处理驱动器上的目录。
每次调用Work()时,函数都会作为$disk接收一个驱动器路径,用于目录搜索和处理。下图显示了Work()函数的开头。
Work()函数的开头
在上述代码中采取以下操作:
1.它创建$folders和$jobs数组;
2.它创建$store元组,用于存储上面创建的数组;
3.它声明了Show()函数。
下图显示了Work()函数的其余代码,它位于Show()函数下方。
Work()函数的剩余部分
在上述代码中采取了以下操作:
4.它将当前卷字符串传递给Get-ChildItem,并筛选出一系列31个潜在的目录路径,以避免处理基于系统或应用程序的文件。然后,它将每个根目录名称传递给Show()函数以进行进一步处理。
有关被忽略的根目录的列表,请参见附录。
5.将根目录文件夹传递给Show()函数后,Work()函数递归地搜索根目录中的子目录。与前面的筛选类似,与排除列表不匹配的子目录会被发送到Show()函数进行处理。
有关被忽略的根子目录的列表,请参见附录。
6.Show()函数创建PowerShell作业以方便窃取数据。该函数一次处理5个目录组。这部分代码可以起到保护作用,以确保处理所有剩余的文件夹分组。
例如,如果总共识别了212个目录,这段代码将确保处理最后两个目录。
Show()函数的作用是接收要处理的目录名。Show()函数的概述如下所示
Show()函数的概述
在上述代码中采取了以下操作:
1.该函数收集提供的目录名,直到它可以创建一个由5个目录名组成的分组。一旦向函数提供了5个目录名,它将它们传递给CreateJobLocal()函数以创建PowerShell作业,以便从目录组中导出数据。
2.该脚本实现了速率限制,因为它一次只希望处理5个目录组的最多10个作业。如果正在运行的作业超过10个,脚本将休眠5秒钟,并重新检查正在运行的作业的数量。
注意:这显示了在整体脚本设计方面的专业编码水平。脚本的编写是为了避免主机的资源被淹没。造成这种情况的确切原因在于开发者,但该方法与一般的编码最佳实践相一致。
CreateJobLocal()函数为窃取数据设置了一个多处理队列。下图显示了CreateJobLocal()函数的开头部分。
CreateJobLocal()函数的概述
在上述代码中采取了以下操作:
1.它为正在创建的作业创建一个伪随机名称。作业名称将由5个字母字符组成(包括小写和大写字符)。
例如,以下是脚本在随机调试会话中生成的五个作业名称:iZUIb、dlHxF、VCHYu、FyrCb和GVILA。
2.它设置一个PowerShell作业,该作业具有一个代码结构,该代码结构将是脚本中此时创建的脚本块。
此时,在CreateJobLocal()中声明了fill()函数。我们将很快回到这个问题。首先,我们将继续处理CreateJobLocal()函数的剩余部分。下图显示了这段代码的下一部分。
属于CreateJobLocal()函数的附加代码
下面是上述CreateJobLocal()代码库的描述:
3.它为要窃取的文件创建一个$fileList数组,然后循环遍历当前组中的目录(如上所述,它通常以五个为一组处理目录)。
4.它设置名为$include和$ excluded的包含和排除数组。
5.有关这些数组的值列表,请参见附录。
它循环遍历给定目录组中的目录,并使用正则表达式根据$include数组中硬编码的值筛选要包含的文件夹。
此时,函数使用excludes来进一步筛选应该被盗取的文件。
CreateJobLocal()函数的剩余部分
以下是剩余CreateJobLocal()代码库的描述:
1.如果某个目录与包含列表匹配,则它会查找该目录中没有在排除列表中找到的扩展名、大于10 KB且具有扩展名的所有文件。
注意:测试证实,该脚本会忽略大小小于10 KB的文件和没有文件扩展名的文件。
2.即使一个目录没有通过正则表达式匹配包含列表,也会检查目录的文件,以确定是否应将其包含在窃取内容中。
这看起来是文件匹配包含列表的第二次尝试,因为比较是使用Get-ChildItem cmdlet的-Include参数完成的,而不是在上面第5步中执行正则表达式比较的-Like比较。
它循环遍历标识为窃取的文件,并调用fill()函数来窃取每个文件。
下图显示了在我们的恶意软件分析虚拟机(VM)中运行时选择的第一组五个文件夹的脚本。这些值将因运行脚本的计算机而异。我们只是想展示脚本始在测试环境中搜索数据的位置。
该脚本的示例运行显示了标识为窃取的前5个目录
fill()函数执行实际的数据窃取。此函数用于构建将用于窃取文件的URL,并使用System.Net.Webclient对象通过HTTP POST事件使用对象的.UploadFile方法执行实际的窃取。下图显示了fill()函数。
fill()函数的概述
在上述代码中采取了以下操作:
1.虽然从技术上讲不是实际的fill()函数的一部分,但在每个文件上传URL中都使用了整个脚本前两行的变量$id和$token。
2.它构建了一个$prefix值,其中包括脚本中两个最重要的攻击指标(IoC)。
2.1 IP地址
这是攻击者的基础设施/服务器IP地址,文件将被上传到该IP地址。
2.2网络端口号
这个端口号可以是80443,也可以是一个自定义端口号,例如通常与临时端口范围相关联的端口号。
3.它实例化一个WebClient对象,该对象将用于执行基于HTTP的数据窃取。
4.它构建了一个$fullPath变量,这是正在上传文件的完整文件路径。
注意:这一点很重要,因为这意味着每个HTTP POST事件都将包括文件的完整路径。如果你能够通过此路径获得源主机的IP地址,那么你将能够在事后构建一个被窃取文件的列表。
5.它通过组合$prefix、$token、$id和$fullPath变量来构建文件上传的完整URL $uri。
6.它调用WebClient.UploadFile()方法来上传文件。
注意:这将创建一个HTTP POST事件。
为了查看脚本的POST请求在攻击者的web服务器上是什么样子,研究人员在本地虚拟机上设置了一个服务器,引导他们的恶意软件分析机器使用该虚拟机作为其网关并运行脚本。下面是脚本在测试环境中执行时创建的三个POST请求示例。
请注意,上面的192.168.42[.]100地址是研究人员使用的测试客户端虚拟机的IP。在现实场景中,Vice Society的网络服务器会在这个位置指示受害者的出口IP地址。
基于以上结果,我们可以获得关于脚本启动的HTTP活动的一些重要信息:
1.fullpath POST参数不包括发送文件的驱动器号。
2.该脚本没有向web服务器提供用户代理字符串。
如果你的环境中运行了网络安全监控(NSM)或入侵检测系统(IDS)(如Zeek),或者数据包捕获系统,那么就可能能够看到传出的POST请求。这些传出的日志可能以字节为单位显示请求的长度(重点关注传出的字节数与总字节数),这有助于确定哪些版本的文件被窃取掉了。
Vice Society的PowerShell数据窃取脚本是一个简单的数据窃取工具。使用多处理和排队来确保脚本不会消耗太多系统资源。然而,该脚本将重点放在文件扩展名超过10 KB的文件以及符合其包含列表的目录中,这意味着该脚本不会窃取不符合此描述的数据。
不幸的是,Windows环境中PS脚本的性质使得我们难以预防这种类型的威胁。不过研究人员在检测中总结了一些提前发现它们的线索和技巧。
参考及来源:https://unit42.paloaltonetworks.com/vice-society-ransomware-powershell/