对 APT28/SOFACY 使用的名为 SKINNYBOY 的新型恶意软件的逐步分析
2021-08-12 12:40:00 Author: www.4hou.com(查看原文) 阅读量:47 收藏

恶意软件使用 systeminfo 命令提取有关它感染的设备的配置信息,然后通过生成 tasklist 进程来检索进程列表。以下目录的内容以及进程的输出都是 base64 编码的,并被泄露到 C2 服务器 updaterweb[.]com:

Desktop folder

C:\Program Files

C:\Program Files (x86)

C:\Users\< User >\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Administrative Tools

C:\Users\< User >\AppData\Roaming

C:\Users\< User >\AppData\Roaming\Microsoft\Windows\Templates

C:\WINDOWS

C:\Users\< User >\AppData\Local\Temp

网络通信时使用的用户代理设置为“Opera”,POST请求的结构如下:“id=< hostname >#Username#< Serial number in decimal >&current=1&total=1&data=< data to be exfiltrated >”。 “cmd=y”命令用于从C2服务器下载DLL文件,使用LoadLibraryW API加载,执行第一个序号函数。

技术分析

SHA256:ae0bc3358fef0ca2a103e694aa556f55a3fed4e98ba57d16f5ae7ad4ad583698

DLL 有 2 个导出(DllEntryPoint 和 RunMod)。研究人员已经使用 rundll32.exe 通过调用 RunMod 函数来运行 DLL:

1.jpg

恶意软件通过调用 CreateEventW API 创建一个未命名的事件对象:

2.jpg

进程使用 CreateThread 函数创建了两个新线程:

3.jpg

4.jpg

GetMessage 例程用于从线程的消息队列中检索消息:

5.jpg

恶意进程枚举所有消息,如果消息等于 0x16(WM_ENDSESSION - 通知应用程序会话是否结束),它会中断循环:

6.jpg

线程活动——StartAddress 函数

恶意软件使用 CreatePipe API 创建一个匿名管道:

7.jpg

GetStartupInfoA 用于从创建调用进程时检索 STARTUPINFO 结构的内容:

8.jpg

二进制文件创建了一个运行 systeminfo 命令的新进程,该命令显示有关计算机及其操作系统的配置信息:

9.jpg

之前创建的管道用作进程间通信机制,systeminfo 命令的输出通过 ReadFile 函数调用读取:

10.jpg

11.jpg

通过创建运行 tasklist 命令的新进程来检索进程列表:

12.jpg

tasklist 命令的输出使用 ReadFile API 传输到主进程:

13.jpg

14.jpg

二进制文件使用 SHGetFolderPathW 例程获取 Desktop 文件夹的路径:

15.jpg

该进程使用 FindFirstFileW 和 FindNextFileW 函数枚举桌面目录中的文件/目录:

16.jpg

17.jpg

二进制文件在文件夹名称前后添加了18个“#”字符,如下所示:

18.jpg

之前提取的文件和目录列表与上面的字符串连接起来,如下图所示:

19.jpg

以下目录也是后门的目标“C:\Program Files”, “C:\Program Files (x86)”, “C:\Users\< User >\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Administrative Tools”, “C:\Users\< User >\AppData\Roaming”, “C:\Users\< User >\AppData\Roaming\Microsoft\Windows\Templates”, “C:\WINDOWS” and “C:\Users\< User >\AppData\Local\Temp”. The SHGetFolderPathW function is utilized to obtain some of these folder names (0x2a = CSIDL_PROGRAM_FILESX86, 0x30 = CSIDL_ADMINTOOLS, 0x1a = CSIDL_APPDATA, 0x15 = CSIDL_TEMPLATES and 0x24 = CSIDL_WINDOWS):

20.jpg

21.jpg

22.jpg

23.jpg

24.jpg

GetTempPathW API 用于检索 %TEMP% 目录的路径:

25.jpg

该文件使用 InternetOpenW API 初始化 WinINet 函数的使用(用户代理被硬编码为“Opera”):

26.jpg

使用 InternetSetOptionW 例程(0x6 = INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT and 0x5 = INTERNET_OPTION_CONTROL_SEND_TIMEOUT)将发送和接收超时设置为 600 秒:

27.jpg

28.jpg

恶意进程在端口 443 上建立到 C2 服务器 updaterweb[.]com 的连接:

29.jpg

使用 GetComputerNameA API 检索本地计算机的 NetBIOS 名称:

30.jpg

GetUserNameA 用于提取与当前线程关联的用户名:

31.jpg

恶意软件通过调用 GetVolumeInformationW 的函数提取当前目录根目录的卷序列号:

32.jpg

该过程使用 XOR 算法解密一些重要的字符串,密钥为“CEJ&V%$839y92m”和“qpzoamxiendufbtbf3-#$*40fvnpwOPDwdkvn”。已经计算出字符串“id=%s#%s#%u&cmd=y”和“id=%s#%s#%u&current=%s&total=%s&data=”:

33.jpg

34.jpg

systeminfo 命令的输出加 tasklist 命令的输出加目标目录列表及其内容使用 CryptBinaryToStringA API (0x1 = CRYPT_STRING_BASE64) 进行 base-64 编码:

35.jpg

36.jpg

HttpOpenRequestW 例程用于创建 HTTP POST 请求句柄:

37.jpg

恶意软件在 HTTP 请求句柄中添加了一个 HTTP 请求标头(“application/x-www-form-urlencoded”):

38.jpg

使用 HttpSendRequestExW API 将请求发送到 HTTP 服务器,如下图所示:

39.jpg

在443端口连接C2服务器失败的情况下,进程尝试连接80端口:

40.jpg

之前提取的信息被泄露到 C2 服务器(id=< hostname >#Username#< Serial number in decimal >&current=1&total=1&data=< base-64 encoded data computed above >):

41.jpg

线程将之前创建的事件设置为信号状态:

42.jpg

线程活动:sub_6BD71960 函数

该线程使用 ResetEvent 例程将之前创建的事件设置为无信号状态:

43.jpg

有一个类似的工作流程,从调用 InternetOpenW 函数开始,直到连接到端口 443(或端口 80,如果第一个不成功)上的 C2 服务器。这次的 POST 请求不同,因为它包含用于下载 DLL 文件的“cmd=y”命令:

44.jpg

恶意软件使用 InternetQueryDataAvailable 例程查询服务器以确定可用数据量:

45.jpg

潜在的 DLL 文件是使用 InternetReadFile API 从句柄中读取的,前 4 个字节表示数据大小,还有 32 个字节表示内容的 SHA256 哈希值,我们将在接下来的段落中描述:

46.jpg

预期的 DLL 是 base64 编码的,因为该进程尝试使用 CryptStringToBinaryA 函数(0x1 = CRYPT_STRING_BASE64)对其进行解码:

47.jpg

48.jpg

CryptAcquireContextA 用于获取 Microsoft RSA 和 AES 加密提供程序 (0x18 = PROV_RSA_AES) 的句柄:

49.jpg

CryptCreateHash 例程用于创建 CSP(加密服务提供程序)哈希对象 (0x800c = CALG_SHA_256) 的句柄:

50.jpg

在 base64 编码的 DLL 文件被解码后,恶意软件会使用 SHA256 算法哈希应该包含 DLL 文件的缓冲区:

51.jpg

通过调用CryptGetHashParam API提取哈希值,如图52(0x2 = HP_HASHVAL):

52.jpg

53.jpg

恶意进程验证上面计算出的哈希值是否与 DLL 文件附带的 32 字节缓冲区重合,当然,在我们的例子中响应是模拟的,但我们可以调整它以通过比较:

54.jpg

55.jpg

GetTempPathW 用于检索 %TEMP% 目录的路径:

56.jpg

恶意进程会在%TEMP%目录下创建一个名为fvjoik.dll的文件,如下图:

57.jpg

新创建的文件填充有从 C2 服务器下载的潜在 DLL:

58.jpg

使用 LoadLibraryW 例程将 DLL 文件加载到当前进程的地址空间中:

59.jpg

恶意软件将使用序号 1 执行导出的函数,如下图所示:

60.jpg

函数完成后,会调用 WinExec 来删除之前创建的 DLL 文件:

61.jpg

该进程再次与 C2 服务器通信,我们相信它传输了 DLL 执行的结果(我们不会在此处详细介绍,因为它与目前描述的活动几乎相同)。请求的参数同样还是id=< hostname >#Username#< Serial number in decimal >&current=1&total=1&data=< data to be transmitted >。

主线程活动

主线程将之前创建的事件设置为信号状态:

64.jpg

恶意软件使用GetExitCodeThread API获取两个线程的终止状态:

63.jpg

64.jpg

本文翻译自:https://cybergeeks.tech/skinnyboy-apt28/如若转载,请注明原文地址


文章来源: https://www.4hou.com/posts/L0Kp
如有侵权请联系:admin#unsafe.sh