FishMonger 的武器库升级了:适用于 Windows 的 SprySOCKS

来源: https://www.welivesecurity.com/en/eset-research/fishmongers-arsenal-upgraded-sprysocks-windows/

ESET 研究人员发现了适用于 Windows 的 SprySOCKS,这是 FishMonger 开发的后门程序,它利用内核驱动程序实现高级隐蔽性。

ESET 研究人员发现了SprySOCKS的两个此前未被记录的 Windows 变种。SprySOCKS 是一种此前仅存在于 Linux 系统中的后门程序,据报道曾被 FishMonger 组织使用。该组织据信由一名名为 I-SOON 的中国承包商运营。虽然我们最初是在 VirusTotal 上发现这些恶意软件样本的,但 ESET 的遥测数据显示,该恶意软件在 2023 年至 2024 年间确实存在活动,受害者遍布洪都拉斯、台湾、泰国和巴基斯坦,攻击目标主要为政府机构。

已发现的Windows变种系统内部标记为WIN_DRV和WIN_PLUS。两者均预装了硬编码的C&C配置,并支持TCP、UDP和WebSocket协议通信。其核心后门功能支持超过30条C&C命令,涵盖系统信息收集、进程枚举、服务管理以及文件管理等多种功能,例如文件列表、创建、删除和传输。

除了核心后门功能外,WIN_DRV版本还利用内核驱动程序来隐藏恶意软件的网络连接、进程、文件和注册表项,并启用 TCP 流量转移,使恶意软件操作者能够通过受害者设备上的随机 TCP 端口向后门发送命令,而不会在网络流量中暴露后门的真实监听端口。

根据 ESET 遥测数据,有有限的迹象表明,某些 SprySOCKS 攻击场景可能涉及 UEFI 启动工具包组件,可能利用 CVE-2023-24932 漏洞。

本报告提供的分析使我们有很高的信心将这些新的 Windows 变体归因于 FishMonger。

FishMonger 简介

FishMonger——据信由名为I-SOON的中国承包商运营(参见我们的2023年第四季度至2024年第一季度APT活动报告)——是一个隶属于Winnti集团的网络间谍组织,极有可能在中国成都活动。它也被称为Earth Lusca、TAG-22、Aquatic Panda或Red Dev 10。我们在2020年初发布了对FishMonger的分析报告,当时该组织在2019年6月开始的香港公民抗议活动期间,对香港的大学进行了大规模攻击。据趋势科技报道,该组织还以发动水坑攻击而闻名。FishMonger的工具集包括ShadowPad、Spyder、Cobalt Strike、FunnySwitch、SprySOCKS和BIOPASS RAT。

技术分析

在本节中,我们将对 FishMonger 的 SprySOCKS 后门的这些新的 Windows 变种进行技术分析。

导致我们发现这一问题的存档于 2024 年 4 月以klelam00007.zip的名称上传到 VirusTotal ;其内容如图 1 所示。


该压缩包包含各种文件,包括用于托管 DLL 侧加载的合法文件,以及三个可疑的、带有.dat扩展名的加密文件。我们后续的分析显示,这些加密文件包含 FishMonger SprySOCKS 后门程序的一个全新、此前未公开的 Windows 版本,其开发者将其命名为WIN_DRV。进一步调查在 ESET 遥测数据中发现了另一个后门版本,名为WIN_PLUS。

初始访问

FishMonger 一直以来都以攻击受害者的公共服务器为目标,他们通常会利用服务器端的 N 天漏洞来获取初始访问权限。虽然我们无法确认 FishMonger 在此次攻击活动中入侵受害者系统的确切方式,但部分受害者设备上存在服务器操作系统,以及 FishMonger 的典型作案手法表明,攻击者很可能是通过配置错误或未打补丁的公共应用程序入侵的。

适用于 Windows 的 SprySOCKS

2023年9月,趋势科技发布了一份关于新型FishMonger Linux后门的报告,分析师将其命名为SprySOCKS。该后门的代码基于名为Trochilus的开源Windows远程访问木马(RAT),并与RedLeaves后门有若干共同特征;然而,它经过了扩展和修改,足以被视为一种新型后门。在本报告中,我们将分析SprySOCKS v1.8的两个尚未公开的Windows变种:

  • 其中一款被开发者命名为WIN_DRV,它使用内核驱动程序来实现高级隐蔽功能。
  • 另一个没有驱动程序的版本名为WIN_PLUS。

如图 2 所示,后门版本类型和编号在二进制文件中是硬编码的。


Trend Micro报告中提到的 Linux 版 SprySOCKS 后门的大部分特征和功能,也同样存在于本报告中新发现的 Windows 版 SprySOCKS 变种中。这些特征和功能包括:

  • 采用相同的C&C消息格式
  • 非常相似的C&C命令(以及一些额外的命令),
  • 使用相同的加密密钥和算法,并且
  • 使用相同的静态链接网络库(HP-Socket)。

这两个新的 SprySOCKS 变种,其核心后门功能(包括 C&C 通信和可用命令)非常相似。最显著的区别在于最终后门的加载方式、隐蔽性的提升以及组件名称和路径。

在以下小节中,我们首先分析各个 SprySOCKS 变体的执行链中涉及的组件,然后描述后门组件,该组件对于两个变体来说基本相同。

WIN_DRV 组件

我们在上传到 VirusTotal 的一个压缩包中发现了SprySOCKS 的WIN_DRV版本,该版本自带一个空的 C&C 服务器配置。因此,该版本不会主动连接任何远程地址;然而,它仍然能够在受害者设备的随机端口上启动一个 TCP 服务器,从而充当被动后门。有趣的是,攻击者无需知道该服务器的 TCP 端口号,因为正如后文所述,WIN_DRV版本使用的 RawWNPF 驱动程序允许将任何开放端口上接收到的 TCP 流量静默重定向到后门本身(更多信息请参见*RawWNPF 驱动程序* 部分)。

如图 1 所示,包含SprySOCKS WIN_DRV版本的归档文件包含以下几个文件:

  • klelam00007.bat – 一个负责持久化后门的批处理脚本。如图 3 所示,它:

○将当前工作目录中的所有文件复制到%SystemRoot%\Fonts目录(为了正常工作,批处理文件需要部署在与归档文件中其他文件相同的目录中)。

○创建一个名为ApphostRegistrationVerifier的计划任务,该任务配置为在每次系统启动时以NT AUTHORITY\SYSTEM权限执行ApphostRagistreationVerifier.exe(这是一个合法且经过有效签名的可执行文件,攻击者将其重命名以模仿合法的 Microsoft 签名AppHostRegistrationVerifier.exe )。攻击者利用Windows 加载 DLL 的方式,使用众所周知的DLL 侧加载技术,通过合法的签名应用程序加载他们自己的恶意 DLL(在本例中为tpsvcloc.dll)。具体来说,在本例中,攻击者使用了通过 MFC 卫星 DLL 进行恶意软件侧加载的技术(请注意tpsvcloc.dll文件名中的loc字符串)。

  • ApphostRagistreationVerifier.exe – 一个合法的 ThinPrint’ AutoConnect 打印机创建服务签名可执行文件(SHA-1:FFC3AA7909D4E72C360D65A1F45260DFFE5C99B7),用于加载tpsvc.dll库。
  • tpsvc.dll – 一个合法的、已签名的库,用于加载tpsvcloc.dll库。
  • tpsvcloc.dll – SprySOCKS 后门加载器,
  • X1B5206BDC1743DD.dat – 一个加密容器,包含 SprySOCKS 后门和以下两个文件的副本,
  • KX1B5206BDC1743DD.dat – DriverLoader,一个加密的内核驱动程序,负责从KW1B5206BDC1743FP.dat加载另一个内核驱动程序,以及
  • KW1B5206BDC1743FP.dat – RawWNPF,一个加密内核驱动程序,负责隐藏后门的文件和网络活动。


图 4 描绘了 SprySOCKS WIN_DRV变体的执行链。


以下三个小节对上述组件进行了技术分析:SprySOCKS 加载器、DriverLoader 驱动程序和 RawWNPF 驱动程序。

SprySOCKS 加载器

加载程序首先检查是否存在虚拟环境和一些安全产品。它会在加载程序的进程中查找特定的库(即:snxhk.dll、SxWrapper.dll、SxIn.dll、SXIn64.dll和SbieDll.dll),如果找到其中任何一个,则会退出。

下一步,它会验证图 3 中的klelam00007.bat脚本是否已成功设置持久化。为此,它会检查当前加载器的映像是否从 %SystemRoot%\Fonts\ 目录加载,并尝试访问%SystemRoot%\Fonts\X1B5206BDC1743DD.dat、%SystemRoot%\Fonts\‌tpsvc.dll和%SystemRoot%\Fonts\tpsvcloc.dll文件。如果发现其中任何文件不在预期位置,它会自行设置持久化,具体操作如下:

  • 将X1B5206BDC1743DD.dat、tpsvc.dll、tpsvcloc.dll和ApphostRagistreationVerifier.exe从当前工作目录复制到%SystemRoot%\Fonts\目录,
  • 将%SystemRoot%\Fonts\ApphostRagistreationVerifier.exe应用程序注册为vds.exe(一种可在系统启动时自动执行的虚拟磁盘服务)的调试器,方法是将该应用程序的路径写入注册表值HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\vds.exe\debugger。
  • 将affair-build.bat文件放入%SystemRoot%\Fonts\目录,然后通过cmd.exe执行它。如图 5 所示,该脚本通过从部署目录中删除文件来清除此过程的痕迹,并通过重新启动vds服务再次执行恶意软件(现在从%SystemRoot%\Fonts\)。


启用持久化后,加载器将继续从位于%SystemRoot%\Fonts\X1B5206BDC1743DD.dat的加密容器加载有效载荷。解密算法和密钥:ECB 模式下的 128 位 AES,密钥为硬编码的uXQLESMXGaRMs6BL。

这会生成由开源工具DllToShellCode生成的 shellcode。在执行 shellcode 之前,它会将容器中剩余的加密有效载荷提取到单独的文件中:

  • %SystemRoot%\Fonts\KX1B5206BDC1743DD.dat
  • %SystemRoot%\字体\KW1B5206BDC1743FP.dat

完成后,加载器会使用从spoolsv.exe获取的令牌,通过CreateProcessAsUserW 函数创建一个新的 svchost.exe 进程,并利用进程分身技术将后门程序的 shellcode 注入到该进程中。在注入过程中,shellcode 会被放入%TEMP%目录下的一个临时文件中,该文件的文件名以TH为前缀。

最后一步,加载器会解密并执行 DriverLoader,这是一个隐藏在之前释放的KX1B5206BDC1743DD.dat文件中的内核驱动程序。DriverLoader 首先被解密,然后解密后的内容保存到C:\Windows\System32\drivers\fsdiskbit.sys。为了执行该驱动程序,加载器会手动创建一个名为 msidiskserver 的新服务注册表项,并将其ImagePath值指向释放的驱动程序(如图 6 所示),从而将该驱动程序安装为微型筛选器驱动程序。加载器还会调用NtLoadDriver Windows API 函数,并将该注册表项作为参数来加载驱动程序。如果未检测到任何错误,加载器会删除msidiskserver注册表项和fsdiskbit.sys文件。之后,加载器完成操作并退出。

DriverLoader 驱动程序

在深入了解 DriverLoader 的功能之前,需要注意一点:随着 Windows Vista 的发布,微软引入了驱动程序签名强制 (DSE) 机制,该机制确保只有经过有效签名的内核模式组件才能在 Windows 内核中执行。这意味着,攻击者若要执行fsdiskbit.sys驱动程序(即 DriverLoader),则需要使用受信任的证书对其进行签名。

为了使驱动程序至少能在一些过时或配置错误的系统上运行,攻击者使用了GitHub上PastDSE项目仓库中泄露的证书,并用该证书对fsdiskbit.sys驱动程序进行了签名。有关所用证书的信息,请参见图7。


现在来看它的功能。这个组件的用途非常明确:加载另一个驱动程序,这次只在内存中加载。首先,它读取并解密之前由加载器创建的C:\Windows\Fonts\KW1B5206BDC1743FP.dat文件的内容。它使用与加载器相同的算法和密钥:ECB 模式下的 128 位 AES 加密,密钥为uXQLESMXGaRMs6BL。解密后的数据包含一个本地 PE 二进制文件(在*RawWNPF 驱动程序* 部分中描述),然后手动映射该文件并执行其入口点。

DriverLoader 二进制文件中嵌入了 PDB 路径:

C:\Users\xdd\Desktop\今天\2023-4-11\2023-04-10__园艺驱动加载功能__集成到内测3中-未完成\DriverMemoryLoadDriver\x64\Release\DriverMemoryLoadDriver.pdb

简体中文机器翻译如下:

  • 今天:今天
  • 操作系统驱动加载功能__集成到内测3中-未完成:注册表驱动加载功能__集成到内测3中-未完成

从符号路径可以看出,该组件似乎至少从 2023 年 4 月就开始开发,这与 DriverLoader 的编译时间戳相吻合。同样,路径中的字符串表明,该驱动程序所属的项目在编译时可能仍在开发中。

RawWNPF 驱动程序

与WIN_PLUS版本相比, RawWNPF 驱动程序使WIN_DRV版本的 SprySOCKS 后门更加隐蔽。它允许隐藏后门在受感染系统上的恶意活动,并且可以通过调用驱动程序的自定义 I/O 控制代码 (IOCTL) 进行配置。该驱动程序会创建一个名为\Device\RawWNPF 的设备驱动程序;表 1 显示了可用 IOCTL 的列表及其简要说明。

IOCTL 描述
0x220200 配置驱动程序以隐藏与指定本地 TCP 端口之间的活动网络连接。
0x220300 取消隐藏配置为0x220200 的网络连接。
0x220340 在隐藏连接列表中插入一个条目。
0x220344 从隐藏连接列表中删除一个条目。
0x220348 清除所有隐藏连接列表。
0x22034C 查看隐藏连接列表。
0x220350 将具有指定 PID 的进程插入到隐藏进程列表中。
0x220354 从隐藏进程列表中删除具有指定 PID 的进程。
0x220358 清除所有隐藏进程。
0x22035C 读取隐藏进程列表。
0x222000 初始化驱动程序的主要功能(隐藏网络连接、隐藏进程、隐藏恶意软件组件、网络过滤器、持久性保护)。初始化完成后,可以使用其他 IOCTL 来配置具体要隐藏哪些内容。
0x222004 返回两个硬编码的 DWORD 值:1和2。这可能是驱动程序的版本号。
0x222008 删除驱动程序的二进制文件(如果存在)。
隐藏指定进程

RawWNPF 驱动程序可以配置为根据进程 ID 隐藏进程,并且可以通过调用驱动程序的 IOCTL 0x220358、0x22035C、0x220354和0x220350来管理隐藏进程列表。为了隐藏进程,驱动程序会拦截 NtQuerySystemInformation 系统调用的执行,并在检索有关正在运行的进程的信息时(即,如果SystemProcessInformation传递给SystemInformationClass参数)修改其输出。如果此 API 函数检索到的任何进程与驱动程序隐藏进程列表中的进程匹配,则驱动程序会将该进程从函数的输出中移除。内核驱动程序拦截NtQuerySystemInformation系统调用的方式似乎很大程度上基于InfinityHookPro项目的源代码。

隐藏网络活动

驱动程序可以配置为隐藏特定的活动连接(指定 IP 地址、端口或二者组合),使其不会出现在诸如netstat.exe等常用网络管理工具的输出中。这是通过一种众所周知的技术实现的(例如,[1][2][3]等),攻击者在nsiproxy.sys Windows 内核驱动程序的DeviceIoControl函数中,对 IOCTL 0x12001B的IoCompletionRoutine进行钩取。nsiproxy 的0x12001B IOCTL 处理程序中的代码负责检索活动连接列表,钩取其IoCompletionRoutine允许攻击者遍历检索到的列表,检查是否存在特定的端口、地址或两者兼有,如果找到匹配项,则隐藏列表中的特定连接。图 8 显示了负责隐藏网络连接的钩取函数。


除了隐藏活动网络连接外,该驱动程序还包含一项有趣的功能,允许它将从任何开放的 TCP 端口接收到的 TCP 数据包重定向到 IOCTL 0x220200配置的指定 TCP 端口(实际上是 SprySOCKS 后门 TCP 服务器的端口),但前提是接收到的 TCP 数据包含特制数据。为了实现这一点,该驱动程序使用 Windows 筛选平台 (WFP) API 函数注册自己的数据包过滤器对象,手动解析传输的 IPv4 数据包的内容(入站和出站流量都会被检查),如果在接收到的 TCP 数据包中检测到特制数据,则会重定向流量。此功能的主要目的似乎是为了能够在无需在二进制文件中嵌入 C&C 地址的情况下与恶意后门建立联系。此外,即使可以使用 Wireshark 等工具检查此类重定向的流量,也不会暴露真实的端口(流量被重定向到的端口);因此,很难调查这些恶意流量的真实目标。

表 2 列出了已安装的数据包过滤器及其标识信息。

滤光层名称 筛选对象名称和 GUID 筛选对象标注名称和 GUID
入站 IP 数据包 v4 层 交付优化(TCP-In)
{E980088D-BE44-4057-8E5C-C7FDF8968795} COInbound
{DE0D7F67-94ED-4DDB-8215-9C028B54661B}
出站 IP Packer v4 层 交付优化(TCP 输出)
{33F76397-DBCB-445E-8EC3-AA51ED302D15} CO出站
{8280DDF3-7489-4402-B9D8-96B50912346B}
ALE Con​​nect v4 层 交付优化(TCP-In)
{5746AF70-2917‑4861-97E6-D5E4DD569F2D} COAuthConnect
{A33E1AA8-9B0F-44A3-B24A-AEB04CA54C3B}
ALE Listen v4 层 交付优化(TCP-In)
{7CB4DFB4-0D20-402D-A49D-BA9660D026E6} COAuthListen
{40045FAF-6BAE-4B48-9119‑31B48FFEA629}
ALE 接收/接受 v4 层 交付优化(TCP-In)
{2C1AB6EF-0B65-4634‑8666-BCB2CF9C72E9} COAuthAccept
{DDFE5189‑389F-437F-9B92-59495ED2181A}
ALE 资源分配 v4 层 交付优化(TCP-In)
{B4AE248F-98D5-446F-88EB-14CF605AE722} COAuthResAssignment
{FE570356-A1A9-413C-94CC-BD6C448E9969}
隐藏后门文件

该驱动程序通过将自身注册为微型过滤器驱动程序并安装以下回调来隐藏/保护 SprySOCKS 后门的文件:

  • 每次IRP_MJ_CREATE I/O 请求都会触发预操作回调,负责在每次尝试从驱动程序的隐藏/受保护文件列表中创建或打开文件或目录时返回STATUS_NO_SUCH_FILE 。
  • 预操作回调函数在每个IRP_MJ_DIRECTORY_CONTROL I/O请求时触发,负责过滤掉与目录枚举无关的请求,以便只有与目录枚举相关的请求才会传递给后操作回调函数。
  • 当IRP_MJ_DIRECTORY_CONTROL I/O请求通过预操作回调检查后,会触发此操作后回调。此回调负责从任何目录列表尝试中移除隐藏/受保护文件的条目。

以下硬编码的文件名列表受驱动程序保护:

  • \SystemRoot\Fonts\tpsvc.dll
  • \SystemRoot\Fonts\tpsvcloc.dll
  • \SystemRoot\Fonts\ApphostRagistreationVerifier.exe
  • \SystemRoot\Fonts\X1B5206BDC1743DD.dat
  • \SystemRoot\Fonts\KX1B5206BDC1743DD.dat
  • \SystemRoot\Fonts\KW1B5206BDC1743FP.dat
保护持久性

驱动程序调用CmRegisterCallbackEx来安装一个RegistryCallback例程,该例程负责隐藏用于 SprySOCKS 加载程序持久化的注册表项:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\vds.exe。因此,所有打开或枚举该注册表项的尝试都会被驱动程序过滤掉。

WIN_PLUS 组件

在 SprySOCKS WIN_PLUS版本中,我们首先在遥测数据中发现了恶意加密容器,首次命中记录可追溯到 2024 年 7 月,位于巴基斯坦一名受害者的设备上。该容器包含 SprySOCKS 后门和 SprySOCKS 加载器。C&C 配置也存在,如图 9 所示。


加密容器位于受感染系统的以下路径:

C:\Windows\System32\spool\drivers\color\config.dat

解密后,容器中包含 SprySOCKS 加载器和 SprySOCKS 后门本身。对容器中的 SprySOCKS 后门进行进一步分析表明,在这种情况下,似乎还有一个额外的组件负责从加密容器中加载 SprySOCKS 加载器。该组件(在本分析中称为第一阶段加载器)应作为打印处理器安装在以下注册表项下:

HKLM\SYSTEM\ControlSet001\Control\Print\Environments\Windows x64\Print Processors\VSPMsg

有趣的是,当我们搜索遥测数据中与VSPMsg字符串相关的任何内容时,我们发现了一个部署在洪都拉斯两台不同受害者设备上的文件,路径为C:\Windows\System32\spool\prtprocs\x64\VSPMsg.dll。该文件是负责执行上述config.dat文件中 SprySOCKS 加载器的第一阶段加载器。

图 10 展示了SprySOCKS WIN_PLUS变体的执行图。

第一级装载机

该加载器首先检查它是否由spoolsv.exe执行,如果不是则退出;这样做是为了使其行为对自动化恶意软件分析沙箱不可见,因为该加载器旨在作为打印处理器运行。它继续解密加密容器C:\Windows\System32\spool\drivers\color\config.dat中的 SprySOCKS 加载器。首先,它使用硬编码密钥 uXQLESMXGaRMs6BL 对加载器进行 128 位 AES-ECB 解密,然后通过进程复制将其注入到新创建的svchost.exe进程中。同时,SprySOCKS 加载器被放入%TEMP%目录下的一个临时文件中,文件名前缀为TH。

该示例导出两个函数:

  • 获取错误消息模块
  • 设置错误消息模块

SetErrorMessageModule函数本身不执行任何操作,而GetErrorMessageModule函数则用于设置加载器自身的持久性。执行此函数时,它会将加载器注册为打印处理器,具体操作为:创建HKLM\SYSTEM\ControlSet001\Control\Print\Environments\Windows x64\Print Processors\VSPMsg注册表项,将Driver注册表值设置为VSPMsg.dll,并将硬编码的C:\ProgramData\Microsoft Event\PFs\VSPMsg.dll文件复制到C:\Windows\System32\spool\prtprocs\x64\目录。接下来,它会将加密容器从C:\ProgramData\Microsoft Event\PFs\config.dat复制到C:\Windows\System32\spool\drivers\color\config.dat,最后生成affair-build.bat批处理脚本并将其放置到C:\Windows\System32\spool\drivers\color\目录并执行该脚本。如图 11 所示,该脚本的目的是通过删除原始部署目录中的文件来掩盖加载器的痕迹,并通过重新启动打印后台处理程序服务来触发新安装的打印处理器的执行。

prySOCKS 加载器

该加载器首先创建一个硬编码名称为fqwhi2d1qaz2 的互斥体,然后从位于C:\Windows\System32\spool\drivers\color\config.dat 的加密容器中加载 SprySOCKS 后门。它使用硬编码密钥uXQLESMXGaRMs6BL对后门进行 128 位 AES-ECB 解密,然后通过进程分身将其注入到新创建的 svchost.exe 进程中。同时,SprySOCKS 加载器被放置在%TEMP%目录下的一个临时文件中,该文件的文件名前缀为TH。

SprySOCKS 后门

最后,我们来分析 SprySOCKS 后门本身。WIN_DRV 和 WIN_PLUS 这两个变体的功能几乎相同,区别仅在于使用的具体文件路径和注册表项,而且如前所述,WIN_PLUS版本没有使用 RawWNPF 驱动程序来实现更高的隐蔽性。

本报告分析的两种变种均为名为PrcsServer.dll的 DLL 文件,导出名为Stop的函数。它们首先创建一个名为prcs-server-run 的互斥锁,随后立即初始化后门的主要功能,包括初始化和启动 C&C 通信通道(基于硬编码配置)以及设置键盘记录器。除了这些操作之外,WIN_DRV后门版本还会通过调用 RawWNPF 驱动程序的0x222000 IOCTL 处理程序来初始化该驱动程序,然后通过调用驱动程序的0x220350 IOCTL来隐藏自身进程。

仅当%appdata%\Microsoft\Vault\lgf.dat目录下存在一个 INI 文件,该文件包含一个名为key 的属性且其值为1 的配置节时,键盘记录功能才会激活。如果满足这些条件,两个后门程序都会创建一个名为Global{DCAA7ED8-521B-4EAB-BE21-65254CF59239} 的互斥体,并定期将剪贴板数据以及活动窗口标题和按键记录到%appdata%\Microsoft\Vault\lg.dat文件中。文件中的数据使用密钥为0x44 的单字节 XOR 密码进行加密。

C&C通信

该后门支持三种与C&C服务器通信的协议——TCP、UDP和WebSocket——并且可以同时充当客户端和服务器。其网络相关功能主要基于HP-Socket网络框架,部分加密功能则使用Crypto++库实现。

C&C 配置嵌入在后门中,可能包含:

  • 最多可以指定三个 IP 地址和相关端口,每个地址指定一个 C&C 服务器 IP 地址及其用于通信通道(TCP、UDP 或 WebSocket)的端口;
  • 最多可以设置三个端口号,每个端口号指定后门监听新连接的端口。其中一个用于 TCP 服务器,一个用于 UDP 服务器,一个用于 WebSocket 服务器。

图 9 显示了WIN_PLUS版本的一个配置示例,其中包含:

  • TCP 通信通道的 C&C 地址和端口:207.148.78[.]36:443。
  • UDP 通信通道的 C&C 地址和端口:207.148.78[.]36:53。
  • WebSocket 通信通道的 C&C 地址和端口:207.148.78[.]36:80。
  • 后门 TCP 服务器监听端口:53781。

在建立任何连接或启动服务器之前,SprySOCKS WIN_DRV版本会通过调用 RawWNPF 驱动程序的 IOCTL 0x220340和0x220200 ,隐藏配置中地址或端口的所有连接。因此,即使这些连接处于活动状态,也不会出现在netstat.exe等工具的输出中。此外,这两个后门版本都会执行两次netsh.exe实用程序:

netsh.exe netsh advfirewall firewall delete rule name=“Core Networking - Packet Too Big(ICMPv6 - In)”

netsh advfirewall firewall add rule name=“Core Networking - Packet Too Big(ICMPv6 - In)” dir=in action=allow protocol=tcp localport=53781

第一条命令删除指定的防火墙规则,第二条命令添加一条与刚刚删除的规则同名的新防火墙规则,允许所有入站 TCP 流量发送到配置中指定的后门 TCP 服务器端口。

如果 C&C 配置为空(例如我们在 VirusTotal 上发现的WIN_DRV版本),后门程序会启动一个 TCP 服务器,监听受感染机器上的一个随机端口,并通过调用 RawWNPF 驱动程序的 IOCTL 0x220200来隐藏该端口。此调用不仅使 TCP 服务器不出现在标准网络工具的输出中,还激活了 RawWNPF 驱动程序提供的 TCP 重定向功能。攻击者可以利用此功能,通过向受害者机器上的任何开放 TCP 端口发送特制的 TCP 数据,在不知道后门程序实际监听端口的情况下,向其发送命令。

对于 TCP 通信通道,C&C 协议似乎与趋势科技报告中分析的 Linux 版本相同。每次发送实际后门数据之前,它都会发送一个 12 字节的头部,其中包含头部其余部分的 32 位 CRC 校验码、一个 DWORD 魔数0xACACBCBC以及一个 DWORD 值,用于指定头部之后数据的大小。

UDP 和 WebSocket 通道的魔数不同,消息头格式和大小也不同。UDP 通道的魔数为0xACACBFBC ,位于 36 字节消息头的偏移量0x1C处,其后是一个 DWORD 值,用于指定后续数据的大小。WebSocket 通道的魔数为0x1BDCCBAA,用作WebSocket 消息头中的掩码键。图 12 显示了包含各通信通道魔数的网络流量捕获结果。


头部之后,紧接着是 32 位 CRC,然后是 WORD 值0x0003(可能表示加密方法),接着是 128 位 AES-ECB 模式加密数据(使用硬编码密钥QFTHEYjzX3RBOMgZ),该数据已进行 base64 编码。

图 13 显示了 C&C 消息解码和解密前后的示例。


ESET 研究人员发现了SprySOCKS的两个此前未被记录的 Windows 变种。SprySOCKS 是一种此前仅存在于 Linux 系统中的后门程序,据报道曾被 FishMonger 组织使用。该组织据信由一名名为 I-SOON 的中国承包商运营。虽然我们最初是在 VirusTotal 上发现这些恶意软件样本的,但 ESET 的遥测数据显示,该恶意软件在 2023 年至 2024 年间确实存在活动,受害者遍布洪都拉斯、台湾、泰国和巴基斯坦,攻击目标主要为政府机构。

已发现的Windows变种系统内部标记为WIN_DRV和WIN_PLUS。两者均预装了硬编码的C&C配置,并支持TCP、UDP和WebSocket协议通信。其核心后门功能支持超过30条C&C命令,涵盖系统信息收集、进程枚举、服务管理以及文件管理等多种功能,例如文件列表、创建、删除和传输。

除了核心后门功能外,WIN_DRV版本还利用内核驱动程序来隐藏恶意软件的网络连接、进程、文件和注册表项,并启用 TCP 流量转移,使恶意软件操作者能够通过受害者设备上的随机 TCP 端口向后门发送命令,而不会在网络流量中暴露后门的真实监听端口。

根据 ESET 遥测数据,有有限的迹象表明,某些 SprySOCKS 攻击场景可能涉及 UEFI 启动工具包组件,可能利用 CVE-2023-24932 漏洞。

本报告提供的分析使我们有很高的信心将这些新的 Windows 变体归因于 FishMonger。

本文要点:

  • 我们发现了 FishMonger SprySOCKS后门的两个此前未被记录的 Windows 变种。
  • ESET 遥测数据显示,2023 年至 2024 年间,其活动主要针对洪都拉斯、台湾、泰国和巴基斯坦的政府机构。
  • 这两个 Windows 版本都支持通过 TCP、UDP 和 WebSocket 协议进行通信,并实现了 30 多个命令。
  • WIN_DRV变体创建了一个隐蔽的被动 TCP 后门,依靠内核驱动程序在检测到接收到的 TCP 数据包中包含特殊构造的数据时,将流量重定向到后门的隐藏 TCP 端口。

鱼贩简介

FishMonger——据信由名为I-SOON的中国承包商运营(参见我们的2023年第四季度至2024年第一季度APT活动报告)——是一个隶属于Winnti集团的网络间谍组织,极有可能在中国成都活动。它也被称为Earth Lusca、TAG-22、Aquatic Panda或Red Dev 10。我们在2020年初发布了对FishMonger的分析报告,当时该组织在2019年6月开始的香港公民抗议活动期间,对香港的大学进行了大规模攻击。据趋势科技报道,该组织还以发动水坑攻击而闻名。FishMonger的工具集包括ShadowPad、Spyder、Cobalt Strike、FunnySwitch、SprySOCKS和BIOPASS RAT。

技术分析

在本节中,我们将对 FishMonger 的 SprySOCKS 后门的这些新的 Windows 变种进行技术分析。

导致我们发现这一问题的存档于 2024 年 4 月以klelam00007.zip的名称上传到 VirusTotal ;其内容如图 1 所示。

图 1. VirusTotal 上显示的klelam00007.zip的内容

该压缩包包含各种文件,包括用于托管 DLL 侧加载的合法文件,以及三个可疑的、带有.dat扩展名的加密文件。我们后续的分析显示,这些加密文件包含 FishMonger SprySOCKS 后门程序的一个全新、此前未公开的 Windows 版本,其开发者将其命名为WIN_DRV。进一步调查在 ESET 遥测数据中发现了另一个后门版本,名为WIN_PLUS。

初始访问

FishMonger 一直以来都以攻击受害者的公共服务器为目标,他们通常会利用服务器端的 N 天漏洞来获取初始访问权限。虽然我们无法确认 FishMonger 在此次攻击活动中入侵受害者系统的确切方式,但部分受害者设备上存在服务器操作系统,以及 FishMonger 的典型作案手法表明,攻击者很可能是通过配置错误或未打补丁的公共应用程序入侵的。

适用于 Windows 的 SprySOCKS

2023年9月,趋势科技发布了一份关于新型FishMonger Linux后门的报告,分析师将其命名为SprySOCKS。该后门的代码基于名为Trochilus的开源Windows远程访问木马(RAT),并与RedLeaves后门有若干共同特征;然而,它经过了扩展和修改,足以被视为一种新型后门。在本报告中,我们将分析SprySOCKS v1.8的两个尚未公开的Windows变种:

  • 其中一款被开发者命名为WIN_DRV,它使用内核驱动程序来实现高级隐蔽功能。
  • 另一个没有驱动程序的版本名为WIN_PLUS。

如图 2 所示,后门版本类型和编号在二进制文件中是硬编码的。

图 2. WIN_DRV (左)和 WIN_PLUS (右)Windows SprySOCKS 后门变体 中硬编码的版本类型和编号

Trend Micro报告中提到的 Linux 版 SprySOCKS 后门的大部分特征和功能,也同样存在于本报告中新发现的 Windows 版 SprySOCKS 变种中。这些特征和功能包括:

  • 采用相同的C&C消息格式
  • 非常相似的C&C命令(以及一些额外的命令),
  • 使用相同的加密密钥和算法,并且
  • 使用相同的静态链接网络库(HP-Socket)。

这两个新的 SprySOCKS 变种,其核心后门功能(包括 C&C 通信和可用命令)非常相似。最显著的区别在于最终后门的加载方式、隐蔽性的提升以及组件名称和路径。

在以下小节中,我们首先分析各个 SprySOCKS 变体的执行链中涉及的组件,然后描述后门组件,该组件对于两个变体来说基本相同。

WIN_DRV 组件

我们在上传到 VirusTotal 的一个压缩包中发现了SprySOCKS 的WIN_DRV版本,该版本自带一个空的 C&C 服务器配置。因此,该版本不会主动连接任何远程地址;然而,它仍然能够在受害者设备的随机端口上启动一个 TCP 服务器,从而充当被动后门。有趣的是,攻击者无需知道该服务器的 TCP 端口号,因为正如后文所述,WIN_DRV版本使用的 RawWNPF 驱动程序允许将任何开放端口上接收到的 TCP 流量静默重定向到后门本身(更多信息请参见*RawWNPF 驱动程序* 部分)。

如图 1 所示,包含SprySOCKS WIN_DRV版本的归档文件包含以下几个文件:

  • klelam00007.bat – 一个负责持久化后门的批处理脚本。如图 3 所示,它:

○将当前工作目录中的所有文件复制到%SystemRoot%\Fonts目录(为了正常工作,批处理文件需要部署在与归档文件中其他文件相同的目录中)。

○创建一个名为ApphostRegistrationVerifier的计划任务,该任务配置为在每次系统启动时以NT AUTHORITY\SYSTEM权限执行ApphostRagistreationVerifier.exe(这是一个合法且经过有效签名的可执行文件,攻击者将其重命名以模仿合法的 Microsoft 签名AppHostRegistrationVerifier.exe )。攻击者利用Windows 加载 DLL 的方式,使用众所周知的DLL 侧加载技术,通过合法的签名应用程序加载他们自己的恶意 DLL(在本例中为tpsvcloc.dll)。具体来说,在本例中,攻击者使用了通过 MFC 卫星 DLL 进行恶意软件侧加载的技术(请注意tpsvcloc.dll文件名中的loc字符串)。

  • ApphostRagistreationVerifier.exe – 一个合法的 ThinPrint’ AutoConnect 打印机创建服务签名可执行文件(SHA-1:FFC3AA7909D4E72C360D65A1F45260DFFE5C99B7),用于加载tpsvc.dll库。
  • tpsvc.dll – 一个合法的、已签名的库,用于加载tpsvcloc.dll库。
  • tpsvcloc.dll – SprySOCKS 后门加载器,
  • X1B5206BDC1743DD.dat – 一个加密容器,包含 SprySOCKS 后门和以下两个文件的副本,
  • KX1B5206BDC1743DD.dat – DriverLoader,一个加密的内核驱动程序,负责从KW1B5206BDC1743FP.dat加载另一个内核驱动程序,以及
  • KW1B5206BDC1743FP.dat – RawWNPF,一个加密内核驱动程序,负责隐藏后门的文件和网络活动。

图 3. klelam00007.bat设置 SprySOCKS 后门的持久性(为了便于阅读,添加了换行符)

图 4 描绘了 SprySOCKS WIN_DRV变体的执行链。

图 4. SprySOCKS WIN_DRV变体的执行链

以下三个小节对上述组件进行了技术分析:SprySOCKS 加载器、DriverLoader 驱动程序和 RawWNPF 驱动程序。

SprySOCKS 加载器

加载程序首先检查是否存在虚拟环境和一些安全产品。它会在加载程序的进程中查找特定的库(即:snxhk.dll、SxWrapper.dll、SxIn.dll、SXIn64.dll和SbieDll.dll),如果找到其中任何一个,则会退出。

下一步,它会验证图 3 中的klelam00007.bat脚本是否已成功设置持久化。为此,它会检查当前加载器的映像是否从 %SystemRoot%\Fonts\ 目录加载,并尝试访问%SystemRoot%\Fonts\X1B5206BDC1743DD.dat、%SystemRoot%\Fonts\‌tpsvc.dll和%SystemRoot%\Fonts\tpsvcloc.dll文件。如果发现其中任何文件不在预期位置,它会自行设置持久化,具体操作如下:

  • 将X1B5206BDC1743DD.dat、tpsvc.dll、tpsvcloc.dll和ApphostRagistreationVerifier.exe从当前工作目录复制到%SystemRoot%\Fonts\目录,
  • 将%SystemRoot%\Fonts\ApphostRagistreationVerifier.exe应用程序注册为vds.exe(一种可在系统启动时自动执行的虚拟磁盘服务)的调试器,方法是将该应用程序的路径写入注册表值HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\vds.exe\debugger。
  • 将affair-build.bat文件放入%SystemRoot%\Fonts\目录,然后通过cmd.exe执行它。如图 5 所示,该脚本通过从部署目录中删除文件来清除此过程的痕迹,并通过重新启动vds服务再次执行恶意软件(现在从%SystemRoot%\Fonts\)。

图 5. 由 SprySOCKS 加载器执行的affair-build.bat 文件

启用持久化后,加载器将继续从位于%SystemRoot%\Fonts\X1B5206BDC1743DD.dat的加密容器加载有效载荷。解密算法和密钥:ECB 模式下的 128 位 AES,密钥为硬编码的uXQLESMXGaRMs6BL。

这会生成由开源工具DllToShellCode生成的 shellcode。在执行 shellcode 之前,它会将容器中剩余的加密有效载荷提取到单独的文件中:

  • %SystemRoot%\Fonts\KX1B5206BDC1743DD.dat
  • %SystemRoot%\字体\KW1B5206BDC1743FP.dat

完成后,加载器会使用从spoolsv.exe获取的令牌,通过CreateProcessAsUserW 函数创建一个新的 svchost.exe 进程,并利用进程分身技术将后门程序的 shellcode 注入到该进程中。在注入过程中,shellcode 会被放入%TEMP%目录下的一个临时文件中,该文件的文件名以TH为前缀。

最后一步,加载器会解密并执行 DriverLoader,这是一个隐藏在之前释放的KX1B5206BDC1743DD.dat文件中的内核驱动程序。DriverLoader 首先被解密,然后解密后的内容保存到C:\Windows\System32\drivers\fsdiskbit.sys。为了执行该驱动程序,加载器会手动创建一个名为 msidiskserver 的新服务注册表项,并将其ImagePath值指向释放的驱动程序(如图 6 所示),从而将该驱动程序安装为微型筛选器驱动程序。加载器还会调用NtLoadDriver Windows API 函数,并将该注册表项作为参数来加载驱动程序。如果未检测到任何错误,加载器会删除msidiskserver注册表项和fsdiskbit.sys文件。之后,加载器完成操作并退出。

图 6. SprySOCKS WIN_DRV加载器创建的服务注册表项

DriverLoader 驱动程序

在深入了解 DriverLoader 的功能之前,需要注意一点:随着 Windows Vista 的发布,微软引入了驱动程序签名强制 (DSE) 机制,该机制确保只有经过有效签名的内核模式组件才能在 Windows 内核中执行。这意味着,攻击者若要执行fsdiskbit.sys驱动程序(即 DriverLoader),则需要使用受信任的证书对其进行签名。

为了使驱动程序至少能在一些过时或配置错误的系统上运行,攻击者使用了GitHub上PastDSE项目仓库中泄露的证书,并用该证书对fsdiskbit.sys驱动程序进行了签名。有关所用证书的信息,请参见图7。

图 7. DriverLoader 的代码签名证书

现在来看它的功能。这个组件的用途非常明确:加载另一个驱动程序,这次只在内存中加载。首先,它读取并解密之前由加载器创建的C:\Windows\Fonts\KW1B5206BDC1743FP.dat文件的内容。它使用与加载器相同的算法和密钥:ECB 模式下的 128 位 AES 加密,密钥为uXQLESMXGaRMs6BL。解密后的数据包含一个本地 PE 二进制文件(在*RawWNPF 驱动程序* 部分中描述),然后手动映射该文件并执行其入口点。

DriverLoader 二进制文件中嵌入了 PDB 路径:

C:\Users\xdd\Desktop\今天\2023-4-11\2023-04-10__园艺驱动加载功能__集成到内测3中-未完成\DriverMemoryLoadDriver\x64\Release\DriverMemoryLoadDriver.pdb

简体中文机器翻译如下:

  • 今天:今天
  • 操作系统驱动加载功能__集成到内测3中-未完成:注册表驱动加载功能__集成到内测3中-未完成

从符号路径可以看出,该组件似乎至少从 2023 年 4 月就开始开发,这与 DriverLoader 的编译时间戳相吻合。同样,路径中的字符串表明,该驱动程序所属的项目在编译时可能仍在开发中。

RawWNPF 驱动程序

与WIN_PLUS版本相比, RawWNPF 驱动程序使WIN_DRV版本的 SprySOCKS 后门更加隐蔽。它允许隐藏后门在受感染系统上的恶意活动,并且可以通过调用驱动程序的自定义 I/O 控制代码 (IOCTL) 进行配置。该驱动程序会创建一个名为\Device\RawWNPF 的设备驱动程序;表 1 显示了可用 IOCTL 的列表及其简要说明。

表 1. RawWNPF 驱动程序处理的 IOCTL 列表

IOCTL 描述
0x220200 配置驱动程序以隐藏与指定本地 TCP 端口之间的活动网络连接。
0x220300 取消隐藏配置为0x220200 的网络连接。
0x220340 在隐藏连接列表中插入一个条目。
0x220344 从隐藏连接列表中删除一个条目。
0x220348 清除所有隐藏连接列表。
0x22034C 查看隐藏连接列表。
0x220350 将具有指定 PID 的进程插入到隐藏进程列表中。
0x220354 从隐藏进程列表中删除具有指定 PID 的进程。
0x220358 清除所有隐藏进程。
0x22035C 读取隐藏进程列表。
0x222000 初始化驱动程序的主要功能(隐藏网络连接、隐藏进程、隐藏恶意软件组件、网络过滤器、持久性保护)。初始化完成后,可以使用其他 IOCTL 来配置具体要隐藏哪些内容。
0x222004 返回两个硬编码的 DWORD 值:1和2。这可能是驱动程序的版本号。
0x222008 删除驱动程序的二进制文件(如果存在)。
隐藏指定进程

RawWNPF 驱动程序可以配置为根据进程 ID 隐藏进程,并且可以通过调用驱动程序的 IOCTL 0x220358、0x22035C、0x220354和0x220350来管理隐藏进程列表。为了隐藏进程,驱动程序会拦截 NtQuerySystemInformation 系统调用的执行,并在检索有关正在运行的进程的信息时(即,如果SystemProcessInformation传递给SystemInformationClass参数)修改其输出。如果此 API 函数检索到的任何进程与驱动程序隐藏进程列表中的进程匹配,则驱动程序会将该进程从函数的输出中移除。内核驱动程序拦截NtQuerySystemInformation系统调用的方式似乎很大程度上基于InfinityHookPro项目的源代码。

隐藏网络活动

驱动程序可以配置为隐藏特定的活动连接(指定 IP 地址、端口或二者组合),使其不会出现在诸如netstat.exe等常用网络管理工具的输出中。这是通过一种众所周知的技术实现的(例如,[1][2][3]等),攻击者在nsiproxy.sys Windows 内核驱动程序的DeviceIoControl函数中,对 IOCTL 0x12001B的IoCompletionRoutine进行钩取。nsiproxy 的0x12001B IOCTL 处理程序中的代码负责检索活动连接列表,钩取其IoCompletionRoutine允许攻击者遍历检索到的列表,检查是否存在特定的端口、地址或两者兼有,如果找到匹配项,则隐藏列表中的特定连接。图 8 显示了负责隐藏网络连接的钩取函数。

图 8. Hex-Rays 对 nsiproxy 的 IoCompletionRoutine钩子进行反编译,该钩子负责隐藏网络连接

除了隐藏活动网络连接外,该驱动程序还包含一项有趣的功能,允许它将从任何开放的 TCP 端口接收到的 TCP 数据包重定向到 IOCTL 0x220200配置的指定 TCP 端口(实际上是 SprySOCKS 后门 TCP 服务器的端口),但前提是接收到的 TCP 数据包含特制数据。为了实现这一点,该驱动程序使用 Windows 筛选平台 (WFP) API 函数注册自己的数据包过滤器对象,手动解析传输的 IPv4 数据包的内容(入站和出站流量都会被检查),如果在接收到的 TCP 数据包中检测到特制数据,则会重定向流量。此功能的主要目的似乎是为了能够在无需在二进制文件中嵌入 C&C 地址的情况下与恶意后门建立联系。此外,即使可以使用 Wireshark 等工具检查此类重定向的流量,也不会暴露真实的端口(流量被重定向到的端口);因此,很难调查这些恶意流量的真实目标。

表 2 列出了已安装的数据包过滤器及其标识信息。

表 2. RawWNPF 驱动程序注册的 WFP 过滤器对象

滤光层名称 筛选对象名称和 GUID 筛选对象标注名称和 GUID
入站 IP 数据包 v4 层 交付优化(TCP-In)
{E980088D-BE44-4057-8E5C-C7FDF8968795} COInbound
{DE0D7F67-94ED-4DDB-8215-9C028B54661B}
出站 IP Packer v4 层 交付优化(TCP 输出)
{33F76397-DBCB-445E-8EC3-AA51ED302D15} CO出站
{8280DDF3-7489-4402-B9D8-96B50912346B}
ALE Con​​nect v4 层 交付优化(TCP-In)
{5746AF70-2917‑4861-97E6-D5E4DD569F2D} COAuthConnect
{A33E1AA8-9B0F-44A3-B24A-AEB04CA54C3B}
ALE Listen v4 层 交付优化(TCP-In)
{7CB4DFB4-0D20-402D-A49D-BA9660D026E6} COAuthListen
{40045FAF-6BAE-4B48-9119‑31B48FFEA629}
ALE 接收/接受 v4 层 交付优化(TCP-In)
{2C1AB6EF-0B65-4634‑8666-BCB2CF9C72E9} COAuthAccept
{DDFE5189‑389F-437F-9B92-59495ED2181A}
ALE 资源分配 v4 层 交付优化(TCP-In)
{B4AE248F-98D5-446F-88EB-14CF605AE722} COAuthResAssignment
{FE570356-A1A9-413C-94CC-BD6C448E9969}
隐藏后门文件

该驱动程序通过将自身注册为微型过滤器驱动程序并安装以下回调来隐藏/保护 SprySOCKS 后门的文件:

  • 每次IRP_MJ_CREATE I/O 请求都会触发预操作回调,负责在每次尝试从驱动程序的隐藏/受保护文件列表中创建或打开文件或目录时返回STATUS_NO_SUCH_FILE 。
  • 预操作回调函数在每个IRP_MJ_DIRECTORY_CONTROL I/O请求时触发,负责过滤掉与目录枚举无关的请求,以便只有与目录枚举相关的请求才会传递给后操作回调函数。
  • 当IRP_MJ_DIRECTORY_CONTROL I/O请求通过预操作回调检查后,会触发此操作后回调。此回调负责从任何目录列表尝试中移除隐藏/受保护文件的条目。

以下硬编码的文件名列表受驱动程序保护:

  • \SystemRoot\Fonts\tpsvc.dll
  • \SystemRoot\Fonts\tpsvcloc.dll
  • \SystemRoot\Fonts\ApphostRagistreationVerifier.exe
  • \SystemRoot\Fonts\X1B5206BDC1743DD.dat
  • \SystemRoot\Fonts\KX1B5206BDC1743DD.dat
  • \SystemRoot\Fonts\KW1B5206BDC1743FP.dat
保护持久性

驱动程序调用CmRegisterCallbackEx来安装一个RegistryCallback例程,该例程负责隐藏用于 SprySOCKS 加载程序持久化的注册表项:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\vds.exe。因此,所有打开或枚举该注册表项的尝试都会被驱动程序过滤掉。

WIN_PLUS 组件

在 SprySOCKS WIN_PLUS版本中,我们首先在遥测数据中发现了恶意加密容器,首次命中记录可追溯到 2024 年 7 月,位于巴基斯坦一名受害者的设备上。该容器包含 SprySOCKS 后门和 SprySOCKS 加载器。C&C 配置也存在,如图 9 所示。

图 9. SprySOCKS WIN_PLUS版本的C&C 配置

加密容器位于受感染系统的以下路径:

C:\Windows\System32\spool\drivers\color\config.dat

解密后,容器中包含 SprySOCKS 加载器和 SprySOCKS 后门本身。对容器中的 SprySOCKS 后门进行进一步分析表明,在这种情况下,似乎还有一个额外的组件负责从加密容器中加载 SprySOCKS 加载器。该组件(在本分析中称为第一阶段加载器)应作为打印处理器安装在以下注册表项下:

HKLM\SYSTEM\ControlSet001\Control\Print\Environments\Windows x64\Print Processors\VSPMsg

有趣的是,当我们搜索遥测数据中与VSPMsg字符串相关的任何内容时,我们发现了一个部署在洪都拉斯两台不同受害者设备上的文件,路径为C:\Windows\System32\spool\prtprocs\x64\VSPMsg.dll。该文件是负责执行上述config.dat文件中 SprySOCKS 加载器的第一阶段加载器。

图 10 展示了SprySOCKS WIN_PLUS变体的执行图。

图 10. SprySOCKS WIN_PLUS变体执行方案

第一级装载机

该加载器首先检查它是否由spoolsv.exe执行,如果不是则退出;这样做是为了使其行为对自动化恶意软件分析沙箱不可见,因为该加载器旨在作为打印处理器运行。它继续解密加密容器C:\Windows\System32\spool\drivers\color\config.dat中的 SprySOCKS 加载器。首先,它使用硬编码密钥 uXQLESMXGaRMs6BL 对加载器进行 128 位 AES-ECB 解密,然后通过进程复制将其注入到新创建的svchost.exe进程中。同时,SprySOCKS 加载器被放入%TEMP%目录下的一个临时文件中,文件名前缀为TH。

该示例导出两个函数:

  • 获取错误消息模块
  • 设置错误消息模块

SetErrorMessageModule函数本身不执行任何操作,而GetErrorMessageModule函数则用于设置加载器自身的持久性。执行此函数时,它会将加载器注册为打印处理器,具体操作为:创建HKLM\SYSTEM\ControlSet001\Control\Print\Environments\Windows x64\Print Processors\VSPMsg注册表项,将Driver注册表值设置为VSPMsg.dll,并将硬编码的C:\ProgramData\Microsoft Event\PFs\VSPMsg.dll文件复制到C:\Windows\System32\spool\prtprocs\x64\目录。接下来,它会将加密容器从C:\ProgramData\Microsoft Event\PFs\config.dat复制到C:\Windows\System32\spool\drivers\color\config.dat,最后生成affair-build.bat批处理脚本并将其放置到C:\Windows\System32\spool\drivers\color\目录并执行该脚本。如图 11 所示,该脚本的目的是通过删除原始部署目录中的文件来掩盖加载器的痕迹,并通过重新启动打印后台处理程序服务来触发新安装的打印处理器的执行。

图 11. 第一阶段 SprySOCKS WIN_PLUS加载器使用的affair-build.bat批处理脚本

SprySOCKS 加载器

该加载器首先创建一个硬编码名称为fqwhi2d1qaz2 的互斥体,然后从位于C:\Windows\System32\spool\drivers\color\config.dat 的加密容器中加载 SprySOCKS 后门。它使用硬编码密钥uXQLESMXGaRMs6BL对后门进行 128 位 AES-ECB 解密,然后通过进程分身将其注入到新创建的 svchost.exe 进程中。同时,SprySOCKS 加载器被放置在%TEMP%目录下的一个临时文件中,该文件的文件名前缀为TH。

SprySOCKS 后门

最后,我们来分析 SprySOCKS 后门本身。WIN_DRV 和 WIN_PLUS 这两个变体的功能几乎相同,区别仅在于使用的具体文件路径和注册表项,而且如前所述,WIN_PLUS版本没有使用 RawWNPF 驱动程序来实现更高的隐蔽性。

本报告分析的两种变种均为名为PrcsServer.dll的 DLL 文件,导出名为Stop的函数。它们首先创建一个名为prcs-server-run 的互斥锁,随后立即初始化后门的主要功能,包括初始化和启动 C&C 通信通道(基于硬编码配置)以及设置键盘记录器。除了这些操作之外,WIN_DRV后门版本还会通过调用 RawWNPF 驱动程序的0x222000 IOCTL 处理程序来初始化该驱动程序,然后通过调用驱动程序的0x220350 IOCTL来隐藏自身进程。

仅当%appdata%\Microsoft\Vault\lgf.dat目录下存在一个 INI 文件,该文件包含一个名为key 的属性且其值为1 的配置节时,键盘记录功能才会激活。如果满足这些条件,两个后门程序都会创建一个名为Global{DCAA7ED8-521B-4EAB-BE21-65254CF59239} 的互斥体,并定期将剪贴板数据以及活动窗口标题和按键记录到%appdata%\Microsoft\Vault\lg.dat文件中。文件中的数据使用密钥为0x44 的单字节 XOR 密码进行加密。

C&C通信

该后门支持三种与C&C服务器通信的协议——TCP、UDP和WebSocket——并且可以同时充当客户端和服务器。其网络相关功能主要基于HP-Socket网络框架,部分加密功能则使用Crypto++库实现。

C&C 配置嵌入在后门中,可能包含:

  • 最多可以指定三个 IP 地址和相关端口,每个地址指定一个 C&C 服务器 IP 地址及其用于通信通道(TCP、UDP 或 WebSocket)的端口;
  • 最多可以设置三个端口号,每个端口号指定后门监听新连接的端口。其中一个用于 TCP 服务器,一个用于 UDP 服务器,一个用于 WebSocket 服务器。

图 9 显示了WIN_PLUS版本的一个配置示例,其中包含:

  • TCP 通信通道的 C&C 地址和端口:207.148.78[.]36:443。
  • UDP 通信通道的 C&C 地址和端口:207.148.78[.]36:53。
  • WebSocket 通信通道的 C&C 地址和端口:207.148.78[.]36:80。
  • 后门 TCP 服务器监听端口:53781。

在建立任何连接或启动服务器之前,SprySOCKS WIN_DRV版本会通过调用 RawWNPF 驱动程序的 IOCTL 0x220340和0x220200 ,隐藏配置中地址或端口的所有连接。因此,即使这些连接处于活动状态,也不会出现在netstat.exe等工具的输出中。此外,这两个后门版本都会执行两次netsh.exe实用程序:

netsh.exe netsh advfirewall firewall delete rule name=“Core Networking - Packet Too Big(ICMPv6 - In)”

netsh advfirewall firewall add rule name=“Core Networking - Packet Too Big(ICMPv6 - In)” dir=in action=allow protocol=tcp localport=53781

第一条命令删除指定的防火墙规则,第二条命令添加一条与刚刚删除的规则同名的新防火墙规则,允许所有入站 TCP 流量发送到配置中指定的后门 TCP 服务器端口。

如果 C&C 配置为空(例如我们在 VirusTotal 上发现的WIN_DRV版本),后门程序会启动一个 TCP 服务器,监听受感染机器上的一个随机端口,并通过调用 RawWNPF 驱动程序的 IOCTL 0x220200来隐藏该端口。此调用不仅使 TCP 服务器不出现在标准网络工具的输出中,还激活了 RawWNPF 驱动程序提供的 TCP 重定向功能。攻击者可以利用此功能,通过向受害者机器上的任何开放 TCP 端口发送特制的 TCP 数据,在不知道后门程序实际监听端口的情况下,向其发送命令。

对于 TCP 通信通道,C&C 协议似乎与趋势科技报告中分析的 Linux 版本相同。每次发送实际后门数据之前,它都会发送一个 12 字节的头部,其中包含头部其余部分的 32 位 CRC 校验码、一个 DWORD 魔数0xACACBCBC以及一个 DWORD 值,用于指定头部之后数据的大小。

UDP 和 WebSocket 通道的魔数不同,消息头格式和大小也不同。UDP 通道的魔数为0xACACBFBC ,位于 36 字节消息头的偏移量0x1C处,其后是一个 DWORD 值,用于指定后续数据的大小。WebSocket 通道的魔数为0x1BDCCBAA,用作WebSocket 消息头中的掩码键。图 12 显示了包含各通信通道魔数的网络流量捕获结果。

图 12. SprySOCKS 网络流量捕获,显示了 TCP、UDP 和 WebSocket(从上到下依次为)C&C 通信通道中使用的 magic 值

头部之后,紧接着是 32 位 CRC,然后是 WORD 值0x0003(可能表示加密方法),接着是 128 位 AES-ECB 模式加密数据(使用硬编码密钥QFTHEYjzX3RBOMgZ),该数据已进行 base64 编码。

图 13 显示了 C&C 消息解码和解密前后的示例。

图 13. Wireshark 中显示的 SprySOCKS C&C 消息示例(左)及其解码解密后的内容(右)

解密后的 C&C 消息中的__msgid值用于指定后门应执行的命令(由消息 ID 标识)。后门支持的消息 ID 列表及其描述见表 3。请注意,我们并未对所有这些命令进行深入分析;因此,部分描述仅是对消息 ID 所关联的代码/功能的粗略概述。

表3. SprySOCKS C&C 命令;标有 * 的描述为初步评估

消息 ID 描述
0x09 收集客户端(受害者)系统信息,包括:计算机名称、操作系统版本、网络适配器信息、内存信息、CPU 信息、当前权限、系统语言和版本、当前时间以及后门版本(1.8)和版本类型(WIN_DRV或WIN_PLUS)。
0x0A 启动交互式控制台。
0x0B 在交互式控制台中写入内容。
0x0D 关闭交互式控制台。
0x0E 指定一个额外的通信通道(不要启动该通道)。可能需要指定一个额外的备用 C&C 服务器。
0x0F 向其他目标发送 C&C 消息。*
0x11 列举所有进程。
0x12 枚举由进程 ID 指定的进程的模块。
0x13 终止由PID指定的进程。
0x14 关闭所有连接。
0x16 获取当前通信渠道信息。
0x17 指定其他通信通道(TCP、UDP 或 WebSocket)并启动它们。
0x19 卸载后门程序并退出。
0x1E 列出所有服务。
0x1F 为指定服务配置启动类型。
0x20 以指定名称启动服务。
0x21 使用指定的dwControl参数调用ControlService函数。
0x22 从服务管理器中删除指定的服务。如果服务正在运行,此操作不会停止该服务。
0x23 初始化 SOCKS 代理。
0x24 终止 SOCKS 代理。*
0x25 通过 SOCKS 代理发送数据。
0x26 SOCKS代理相关命令。*
0x2A 上传指定文件。*
0x2B 文件传输相关辅助命令。*
0x2C 下载指定文件。*
0x2D 文件传输相关辅助命令。*
0x3C 枚举可用磁盘空间。
0x3D 列出指定目录中的文件。
0x3E 删除指定文件。
0x3F 创建指定目录。
0x40 重命名指定文件。
0x41 执行一个已存在的文件。
0x42 复制指定文件。
0x43 列出已登录用户最近使用的 Windows 目录中的文件:
%APPDATA%\Microsoft\Windows\Recent\
%APPDATA%\Microsoft\Office\Recent|

网络基础设施

本次攻击活动中仅发现了一个 C&C 地址:207.148.78[.]36 ,该地址硬编码在SprySOCKS 后门的WIN_PLUS变体的配置中(如图 9 所示) 。

配置中后门用于与 C&C 服务器通信的端口:

  • TCP:443
  • UDP:53
  • WebSocket:80

正如趋势科技的报告中所提到的,IP 地址207.148.75[.]122(与上述 C&C 服务器属于同一 IP 地址范围207.148.64.0/20)在 2023 年 6 月被 FishMonger 运营商用作 SprySOCKS 分发服务器。该 IP 地址范围属于 Vultr 云托管提供商。

结论

SprySOCKS Windows 版本的发现(此前该后门程序仅存在于 Linux 系统上)标志着 FishMonger 跨平台能力的显著扩展。我们的分析表明,Windows 版本保留了其 Linux 版本的大部分核心架构,包括 C&C 协议、加密方式和整体命令处理逻辑,同时在必要时替换了 Windows 原生机制,并通过引入内核驱动程序提高了后门程序的隐蔽性。鉴于目前仅有少量迹象表明可能与 UEFI 启动套件有关,我们建议密切关注该组织的活动。

文章前 3/4 部分发了两遍,截断在 图 13 显示了 C&C 消息解码和解密前后的示例