朝鲜半岛

朝鲜APT组织APT37利用网络钓鱼邮件部署RokRat远程访问木马

APT37 组织

APT37 又名 ScarCruft、Reaper 和 Red Eyes,是一个由朝鲜政府支持的黑客组织,自 2012 年以来一直活跃。最初,其行动主要针对韩国的公共和私营部门,但在 2017 年,其目标扩大到日本、越南、中东以及医疗保健和制造业等行业。到 2023 年,APT37 已转向针对 Windows 和 Android 平台用户的网络钓鱼活动。

该组织以利用各种攻击媒介而闻名,包括通过群聊平台传播恶意 LNK 文件来感染受害者。

技术要点

  • 感染媒介:攻击始于包含隐藏恶意 LNK 文件的 ZIP 附件的网络钓鱼电子邮件,这些文件伪装成与朝鲜事务或贸易协议相关的文件。执行后,LNK 文件使用批处理脚本和 PowerShell 启动多阶段攻击,最终以 RokRat 作为最终有效载荷。
  • 主机分析:RokRat 收集详细的系统信息,包括操作系统版本、计算机名称、登录用户和可执行文件路径。它还会检索硬件详细信息、跟踪系统正常运行时间、枚举正在运行的进程并捕获屏幕截图。然后这些数据会被泄露到命令和控制 (C2) 服务器。
  • C2 通信:RokRat 滥用 pCloud、Yandex 和 Dropbox 等云服务作为其命令和控制 (C2) 通道,使用其 API 发送、下载和删除文件。它还在其代码中嵌入 OAuth 令牌,以促进与这些服务的无缝通信。
  • 命令执行:RokRAT 可以在受感染的系统上执行命令,允许攻击者执行各种活动,例如数据泄露、系统侦察和进程终止。它可以通过 cmd.exe 执行远程命令、收集和上传文件、扫描系统驱动器、删除特定文件以及从命令和控制 (C2) 检索其他有效负载。

感染流程

感染始于看似关键的网络钓鱼电子邮件,因为攻击者使用网站上的真实信息使其看起来更可信。这些电子邮件包含伪装成文档的恶意 LNK 文件的 ZIP 文件。执行后,它会启动下一阶段的攻击。

[API 响应流程]

图(1):感染流程图

第 1 阶段 - LNK 文件

文件中嵌入的代码.lnk执行调用 PowerShell 的命令。

[API 响应流程]

图(2):LECmd 输出

首先,它会检查自己是否从System32Program Files运行。如果是,它会转到该%temp%目录。然后,它会使用一个简单的技巧,通过搜索.lnk大小为0x0DD4B11F字节的文件来读取自身。

一旦找到,它会从.lnk文件中提取多个有效载荷并将其保存在%temp%目录中。

[]

提取的文件为:

  • 在偏移量0x111E处,提取0xAD36字节并将其保存为.hwpx,立即执行。
  • 在偏移量 0xBE54 处,提取 0xD9190 字节并将其保存为caption.dat
  • 在偏移量 0xE4FE4 处,提取 0x0636 字节并将其保存为elephant.dat
  • 在偏移量0xE561A处,提取0x0147字节并将其保存为sharkeba.bat,然后执行。

为了使提取过程自动化,我编写了一个快速脚本。

import os
import sys
def extract_embedded_files(lnk_path, output_dir):
    try:
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        with open(lnk_path, 'rb') as lnk_file:
            
            lnk_file.seek(0x0000111E)
            hwpx_data = lnk_file.read(0x0000AD36)
            hwpx_path = os.path.join(output_dir, "extracted.hwpx")
            with open(hwpx_path, 'wb') as f:
                f.write(hwpx_data)
            print(f"HWPX file extracted")
            
            lnk_file.seek(0x0000BE54)
            exe_data = lnk_file.read(0x000D9190)
            exe_path = os.path.join(output_dir, "caption.dat")
            with open(exe_path, 'wb') as f:
                f.write(exe_data)
            print(f"Caption.dat extracted")
            
            lnk_file.seek(0x000E4FE4)
            string_data = lnk_file.read(0x00000636)
            string_path = os.path.join(output_dir, "elephant.dat")
            with open(string_path, 'wb') as f:
                f.write(string_data)
            print(f"Elephant.dat extracted")
            
            lnk_file.seek(0x000E561A)
            bat_data = lnk_file.read(0x00000147)
            bat_path = os.path.join(output_dir, "sharke.bat")
            with open(bat_path, 'wb') as f:
                f.write(bat_data)
            print(f"Batch file extracted")
                    
    except :
        print(f"Error occured ")

def main():
    lnk_path = ''
    output_dir = ''
    extract_embedded_files(lnk_path, output_dir)

if __name__ == "__main__":
    main()

最后,它会删除原始.lnk文件以掩盖其踪迹。

[]

第 2 阶段 - 被释放的

HWPX 文档

[API 响应流程]

图(3):VT 上的 HWPX 文档

这是一份诱饵文件,旨在让受害者误以为他们打开的是正常文件,而真正的攻击则在后台运行。它看起来像是一份公共服务记录表,在韩国通常用于官方推荐和表彰。

[API 响应流程]

图(4):HWPX文档内容

shark.bat

首先分析shark.bat,然后提取并执行 。此批处理脚本在最小化的隐藏窗口中启动 PowerShell。然后,它elephant.dat%temp%目录中读取,将其加载到内存中,并使用 执行它Invoke-Command

[API 响应流程]

图(5):使用的脚本

elephant.dat

尽管它的名字如此,但这是另一个用于在内存中加载和执行有效负载的 PowerShell 脚本。它从目录中读取加密文件caption.dat(第四个提取的文件)%temp%,并使用**单字节 XOR 密钥“d”**对其进行解密以获取可执行内容。

[API 响应流程] 解密后,脚本会加载必要的函数以kernel32.dll在内存中执行有效载荷。它会分配内存并创建线程来运行解密的有效载荷。

[API 响应流程]

第 3 阶段 - [shellcode]

解密的 shellcode 从硬编码的加密数据中解密 PE 文件。

[API 响应流程]

图(6):解密后的shellcode。

shellcode 从偏移量0x58B处的内存中读取数据,其中第一个字节是 XOR 密钥,接下来的四个字节是加密数据的长度,其余的是加密的 PE 文件。它通过将每个字节与密钥进行 XOR 来解密 PE,将其加载到内存中,解析导入并执行。

[API 响应流程]

图(7):加密数据结构

我们可以使用这个IDApython脚本转储解密的PE文件。

def save_to_file(file_path, data):
    with open(file_path, 'wb') as file:
        file.write(data)

addr = 0x58B

xor_key = idc.get_bytes(addr, 1)  

data_size = idc.get_wide_dword(addr + 1)  # read 4-byte data size

enc_data = idc.get_bytes(addr + 5, data_size)  # get encrypted data

dec_data = bytes(b ^ xor_key for b in enc_data)

save_to_file('dump_file.bin', dec_data)

最终有效载荷——RokRat

最后一个有效载荷是RokRat,这是 APT37 威胁组织主要使用的远程访问木马 (RAT)。该样本于 2024 年 10 月编译,此前曾在 2024 年 12 月的另一次攻击中出现过。

[API 响应流程]

图(8):VT 上的 Rokrat。

反分析

加密字符串

Rokrat 使用两种自定义字符串解密技术来隐藏其字符串。

一种技术是将字符串存储为堆栈字符串,使用简单的基于减法的转换进行加密,使用第一个字符作为密钥,然后从每个后续字符中减去一个固定值(2048)。

另一种方法是使用第一个字节作为密钥来加密字符串。每次处理两个字节,然后从每个字节中减去密钥即可得到原始文本。

[API 响应流程]

图(9):使用的加密算法。

以下是完整的解密字符串列表:

IsWow64Process
C:\Program Files\VMware\VMware Tools\vmtoolsd.exe
HARDWARE\DESCRIPTION\System

反虚拟机

Rokrat 通过 vmtoolsd.exe 检测 VMware Tools 的存在。它首先检查可执行文件是否存在于其默认安装路径中,然后检索其版本详细信息。如果找到该文件并成功提取其元数据,则假定它在 VMware 虚拟机内运行。

[API 响应流程]

图(10):使用了 Anti vm。

检测沙箱

该函数在C:\Windows中创建然后删除一个随机文件,这是恶意软件和沙盒检测中常用的技术,用于测试文件系统的写入权限或引入执行延迟。

[API 响应流程] 图(11):检测沙箱。

此外,Rokrat 使用 IsDebuggerPresent 检查调试器。

收集主机信息

RokRat 收集有关受感染系统的详细信息。它首先检索系统版本并确定进程是否在 下运行WOW64

此外,它还收集与系统相关的详细信息,例如计算机名称登录的用户名可执行文件的完整路径

它从注册表中检索额外的系统详细信息,并以毫秒为单位确定系统的正常运行时间(不包括睡眠时间)。

[API 响应流程]

图(12):收集的信息。

它还从注册表中提取系统详细信息,包括SystemBiosVersion

[API 响应流程]

图(13):从注册表获取硬件信息。

进程枚举固定

RokRat 收集有关正在运行的进程的详细信息,包括其进程 ID (PID)、可执行文件名称和文件路径。这些信息被格式化为"%spid:%d,name:%s,path:%s%s",并被存储和准备泄露。

[API 响应流程]

图(14):进程枚举函数。

截取屏幕截图。

RokRat 捕获屏幕截图、处理图像(将其转换为 JPEG)并准备进行数据泄露。

[API 响应流程]

C2 通信

RokRat 滥用 pCloud、Yandex 和 Dropbox 等合法云服务作为命令和控制 (C2) 通道。通过使用这些平台的 API,RokRat 可以无缝窃取被盗数据、下载其他有效负载并执行命令,同时混入正常网络流量中。此外,它还具有测试模式,可让其在本地机器上运行。

手术 云提供商 API
上传文件 Dropbox https://content.dropboxapi.com/2/files/upload
Yandex 磁盘 https://cloud-api.yandex.net/v1/disk/resources/upload?path=%s&overwrite=%s
云端 https://api.pcloud.com/uploadfile?path=%s&filename=%s&nopartial=1
下载文件 Dropbox https://content.dropboxapi.com/2/files/download
Yandex 磁盘 https://cloud-api.yandex.net/v1/disk/resources/download?path=%s
云端 https://api.pcloud.com/getfilelink?path=%s&forcedownload=1&skipfilename=1
列出文件夹 Dropbox https://api.dropboxapi.com/2/files/list_folder
Yandex 磁盘 https://cloud-api.yandex.net/v1/disk/resources?path=%s&limit=500
云端 https://api.pcloud.com/listfolder?path=%s
删除文件 Dropbox https://api.dropboxapi.com/2/files/delete
Yandex 磁盘 https://cloud-api.yandex.net/v1/disk/resources?path=%s&permanently=%s
云端 https://api.pcloud.com/deletefile?path=%s

它的代码中还包含 OAuth 令牌,以便与这些云服务进行通信。

主要使用 pCloud 进行命令和控制 (C2) 操作。它通过包含硬编码 OAuth 令牌的 HTTP 请求与 pCloud 进行身份验证: JINs7ZDb7OvfloXrYZt8wH7kZ7LjAjGKBckj4kTgWSBiDSVWF1fKX

它还通过欺骗其 User-Agent 字符串来隐藏其 HTTP 流量,使其看起来像是合法的 Googlebot 请求: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)

[API 响应流程]

图(15):Http请求示例。

RokRat 在窃取数据之前会结合使用 XOR 混淆和 RSA 加密。它首先使用随机生成的密钥进行 XOR 加密来混淆数据,使其难以识别。然后,它使用 RSA 加密混淆的数据,确保只有拥有私钥的攻击者才能解密。

命令

RokRat 从其命令与控制 (C2) 服务器检索加密命令,使用 AES-CBC 模式进行加密。然后它在本地解密命令并在系统上执行它们。

命令‘0’

此命令将发送数据标志设置为 0(假),意味着应停止数据收集。

命令 - ‘i’

该命令将发送数据标志设置为 1(true),表示收集到的信息已准备好发送到命令和控制(C2)服务器。

命令 - ‘j’ 或 ‘b’

这会创建一个终止过程,强制恶意软件停止运行并退出。

Command - ‘d’

此命令执行删除操作,从 Windows 启动文件夹和 AppData 目录中删除不同的脚本和快捷方式文件。它针对.VBS(VBScript)、、.CMD(.BAT批处理脚本)、.LNK(快捷方式) 以及执行期间创建的任何其他文件。

    del "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\*.VBS" 
    "%appdata%\*.CMD" 
    "%appdata%\*.BAT" 
    "%appdata%\*01" 
    "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\*.lnk" 
    "%allusersprofile%\Microsoft\Windows\Start Menu\Programs\Startup\*.lnk" /F /Q

删除完成后,命令将启动终止过程以关闭 RAT。

命令 - ‘f’

此命令与上一个命令类似,但它不针对 .lnk(快捷方式)文件。

del \"%appdata%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*.VBS\"\
   "%appdata%\\*.CMD\" \
   "%appdata%\\*.BAT\" \
   "%appdata%\\*01\" /F /Q"

一旦删除完成,该命令还会启动终止过程以关闭 RAT。

命令 - ‘g’

此命令只是重置内存并将其擦除,使其为另一项操作做好准备。

命令 - ‘h’

此命令会扫描所有逻辑驱动器,包括固定驱动器、可移动驱动器和网络驱动器,以递归方式列出其内容并将结果保存在临时文件中。然后,该文件会被上传到命令和控制 (C2) 服务器,之后会被删除以消除任何痕迹。

[API 响应流程]

图(16):该函数扫描所有逻辑驱动器。

命令——'e'

该命令通过cmd.exe执行从C2服务器接收的指令,允许远程执行系统命令。

[API 响应流程]

图(17):命令e。

命令 - ‘c’

此命令从 C2 服务器接收路径,并检查它是文件还是目录。如果路径是目录,则该函数读取其文件、处理它们、加密其内容,然后将其上传到 C2 云服务器。

[API 响应流程]

如果路径是文件,则根据文件扩展名应用过滤。当过滤器设置为“普通”时,它专门针对与文档相关的文件类型,例如.XLS.DOC.PPT.TXT.M4A.AMR.PDF.HWP。但是,如果过滤器设置为“全部”,它会收集和上传任何类型的文件。

[API 响应流程]

命令 [1-9]

这些命令下载有效负载并执行它:

下载(命令 1、2、5、6):

这些命令会从攻击者指定的 URL 动态获取辅助负载。此过程包括打开与 URL 的 HTTP 连接并下载数据,而无需任何额外的解密。

[API 响应流程]

图(18):从互联网下载文件。

下载(命令 3、4、7、8、9):

这些命令从 C2 云服务下载有效载荷。下载后,将解密有效载荷,并通过检查验证其完整性。

执行(命令 1、2、3、4):

在这种情况下,代码会检查下载是否成功。如果成功,代码会创建一个新线程来执行有效载荷。如果执行成功,它会将“ OK ”写入临时文本文件(%temp%\r.txt)。如果执行失败,它会将“ BD ”写入同一文件。

[API 响应流程]

此外,还执行批处理脚本来收集系统信息,包括:

  • 正在运行的进程列表
  • 启动项
  • 系统配置
  • 路线详情

这些信息被保存到同一个临时文本文件**(r.txt)**中,加密后泄露到C2服务器。泄露后,文件被删除。

[API 响应流程]

执行(命令 5、6、7、8、9):

在这种情况下,它还会检查下载是否成功。如果成功,它会构造一个文件路径。然后,它会创建一个名为的临时文件KB400928_doc.exe,将提取的数据写入其中,并使用执行该文件ShellExecuteA

YARA 规则

rule detct_RokRat
{
    meta:
        description = "Detects Rokrat payload using some of the hardcoded strings "
        author = "Mohamed Ezzat (@ZW01f)"
        hash1  = "09a4adef9a7374616851e5e2a7d9539e1b9808e153538af94ad1d6d73a3a1232"
        hash2  = "94159655fa0bfb1eff092835d8922d3e18ca5c73884fd0d8b78f42c8511047b6"
    strings:
      // apis used 
      $s0 = "https://api.pcloud.com/deletefile?path=%s"  wide
        $s1 = "https://api.dropboxapi.com/2/files/list_folder"  wide
        $s3 = "https://cloud-api.yandex.net/v1/disk/resources/upload?path=%s&overwrite=%s" wide 
        $s4 = "https://cloud-api.yandex.net/v1/disk/resources?path=%s&limit=500" wide
      $s5 = "https://cloud-api.yandex.net/v1/disk/resources?path=%s&permanently=%s" wide
      // file it use for download payloads . 
      $s6 = "KB400928_doc.exe"
      $s7 = "%04d%02d%02d %02d%02d%02d" wide
    condition:
        uint16(0) == 0x5A4D and all of ($s*) 
} 

IoC

阶段 哈希
Zip 文件 cfc814a16547dd4e92607bd42d2722cc567492e88d2830d7d28a0cc20bf3950c
Lnk 文件 7df7ad7b88887a06b559cd453e7b65230d0cccff1a403328a521d8753000c6c9
hwpx 文档 9d96e4816a59475768d461a71cecf20fd99215ce289ecae8c865cf45feeb8802
鲨鱼蝙蝠 5306582c8a24508b594fed478d5abaa5544389c86ba507d8ebf98c5c7edde451
大象档案 2b6928101efa6ededc7da18e7894866710c10794b8cbaf43b48c721e9731c41a
标题.dat 6d790df4a2c81e104db10f5e47eb663ca520a456b1305e74f18b2f20758ea4e1
shellcode-第 3 阶段 1c4cd06ebece62c796ea517bf26cc869fa71213d17e30feb0f91c8a4cfa7ef1b
RokRat – 最终载荷 09a4adef9a7374616851e5e2a7d9539e1b9808e153538af94ad1d6d73a3a1232

相关文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

返回顶部按钮