0%

Dissecting APT21 samples using a step-by-step approach

在这篇博文中,详细分析了与名为 APT21 的 APT(高级持续威胁)攻击者相关联的恶意文件(称为“Travelnet”的后门)。

Travelnet

第一个文件是用于将恶意 DLL(NetTraveler 木马)注册为服务的投放程序。 该木马的主要目的是收集有关环境的信息,例如用户名、主机名、主机的 IP 地址、Windows 操作系统版本、CPU 的不同配置、有关内存消耗的信息、进程列表。

恶意进程对磁盘以及 USB 驱动器和网络共享上的.doc/.docx/.xls/.xlsx/.txt/.rtf/.pdf 文件感兴趣,以便渗漏它们。在整个感染过程中,会创建多个.ini 配置文件,并且恶意软件还能够在受感染的机器上下载和执行其他文件。数据使用基于Lempel-Ziv的自定义算法进行压缩,并使用修改后的 Base64 算法进行编码,然后再将其泄露到命令和控制服务器。

1.Dropper

恶意软件执行的第一步包括创建名为“立即安装服务”的互斥锁(注意空格)。互斥锁用于避免已感染的计算机再次感染

API:CreateMutexA

创建一个配置文件config_t.dat,配置文件由WritePrivateProfileStringA填充

API:CreateFileA

    WritePrivateProfileStringA

在恶意代码的精确位置发现加密字节,加密包含了XOR操作,解密结束后发现是URL(C2服务器)

注意在文件0x334偏移处有一字节表示恶意软件是否用代理,如果是0,配置文件中UP=0,如果是1,UP=1,并且还有PS (proxy address), PP (proxy port), PU (proxy user), PW (proxy password), PF (unknown)

RegQueryValueExA该函数用来搜索与“HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Svchost”相关联的netsvcs(svchost.exe)的类型和数据

API:RegQueryValueExA

恶意文件枚举主机上所有可用的服务,将其与硬编码列表中的进行比较,第一个系统上没有的服务便被用来当作恶意目的。策略:枚举所有服务相对应的键值,查看服务是否被安装。第一个没被安装的服务是FastUserSwitchingCompatibility, RegOpenKeyExA 用于检查服务是否存在。

与该服务相关联的dll将被删除,然后一个同名服务将被创建冒充为合法服务,服务的二进制路径为%SystemRoot%\System32\svchost.exe-k netsvcs,可以在网址(https://lolbas-project.github.io/查看到更多的合法进程和dll。

API:RegOpenKeyExA

    DeleteFileA

    CreateServiceA

在该服务下方一个新的键值parameters被创建,这个键值被用来将恶意dll注册为一个服务.

img

进程创建一个temp.bat的空文件作为初始可执行文件,该文件的目的是通过添加ServiceDll条目,将前面恶意程序删除后重新创建的dll注册为服务。因为文件时重新创建的,所以为了不引起怀疑,修改时间戳是一种规避技术。

现在这个dll中都是恶意代码,甚至路径看起来都是合法的。将DLL文件注册为服务是一种持久性机制。使用StartServiceA启动新创建的服务,并将执行流传递给DLL导出函数ServiceMain:

API:RegCreateKeyA

    WriteFileA

    StartServiceA

2.DLL File

恶意软件执行的第一个步骤之一是调用GetProcessWindowsStation,该API返回当前窗口的句柄,然后使用OpenWindowsStationA打开交互式窗口Winsta0。进程使用setProcessWindowsStation函数将指定的窗口Winsta0分配给调用进程,该窗口是唯一的交互式窗口(服务应该是交互式的)。与之前一样,这个进程也会创建一个互斥锁,如果存在,将会退出而不重新感染主机。

API:GetProcessWindowsStation

    OpenWindowsStationA

    setProcessWindowsStation

    CreateMutexA

它从由第一个进程创建的配置文件config_t.dat中检索几个元素:WebPage、DownCmdTime、UploadRate、AutoCheck、UP和CheckedSuccess(此时不存在,因此函数返回0)。使用GetPrivateProfileString和GetPrivateProfileInt提取所有值。

API:GetPrivateProfileString

    GetPrivateProfileInt

进程会创建一个与执行文件同名的log文件,该文件会枚举C:\ProgramFile(x86) 下的路径,并将输出复制到新创建的文件中

API:CreateFileA

恶意软件正在查找名为“C:\Users<Username>\AppData\Local\Microsoft\Windows\History\History.IE5\index.dat”的文件,该文件包含Internet浏览历史活动,包括基于Internet的搜索和打开的文件.故恶意软件打开注册键Shell Folders并提取History值,以及从Internet Explorer键中提取Version值,获得的信息附加到log文件中(包括操作系统版本)

API:RegOpenKeyExA

    RegQueryValueExA

    GetVersionExA

网络通信中使用的用户代理始终设置为“Mozilla/4.0(compatible; MSIE 6.0)”。还有一个Accept 请求(httP标头。该进程尝试连接到(http://www.microsoft.com/info/privacy_security.htm (此URL过去可用)以验证是否存在网络连接,如果成功,也会把相应的信息输出到log文件。

img

API:InternetOpenA

    (httpOpenRequestA

如果连接不成功,进程会找到explorer.exe并试图打开。基本上,攻击者的目的是通过调用OpenProcessToken来窃取explorer.exe进程令牌,以打开与explorer.exe关联的访问令牌,然后使用ImpersonateLoggedOnUser函数模拟用户的安全上下文

API:Process32First 

    Process32Next

    OpenProcess

    OpenProcessToken

    ImpersonateLoggedOnUser

该进程使用RegOpenKeyExA打开“HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Internet Settings”注册表项,然后提取ProxyEnable值以查看计算机是否使用代理服务器,并且提取ProxyServer(网络上代理服务器的主机名/IP)和ProxyOverride(绕过代理服务器的主机名/IP)。收集到这些信息后,再次连接同样地URL,成功后会将信息输出到log文件。

API:RegOpenKeyExA

如果该方法奏效,恶意程序会修改config_t.dat文件中地值,如果失败就会将失败信息记录在log文件,一共会尝试四次方法。如果所有方法都失败了,感染就会停止,并且会执行一些自我删除操作。

如果有一个方法奏效,那么恶意软件会休眠一分钟,然后创建一个线程1,再休眠十秒创建一个线程2

2.1 Thread1

首先,线程检索与“C:\”目录关联的卷序列号(“A2C9-AD2F”)。该序列号将用作与C2服务器通信时的主机id。此外,它还查找计算机的NETBIOS名称,与当前线程关联的用户名,检索计算机的主机名,使用gethostbyname/inet\n函数打印计算机的IP地址。枚举可用的磁盘驱动器,它感兴趣的是类型3。获取系统物理和虚拟内存,除此以外还获取了其他的键值信息,并将目前为止提取地信息存储在system_t.dll中,以便对其进行过滤。

下一步是创建管道,用作进程间通信机制,创建一个新的进程“ipconfig/all”,输出将通过管道传输回原始流程。

API:getVolumeInformation

    GetComputerNameA

    GetUserNameA

    gethostname

    GetLogicalDrivers

    GetDriverTypeA

    GlobalMemoryStatus

    CreatePipe

    CreateProcessA

    ......

恶意软件使用GetPrivateProfileInt函数检查config_t.dat中的UP值。根据卡巴斯基报告,system_t.dll文件的内容将使用基于Lempel-Ziv的自定义算法进行压缩,并使用修改后的Base64算法进行编码。

编码后地数据通过一个向vipmailru[.]com(C2服务器)的GET请求进行过滤。如果服务器返回成功,那么就过滤成功,恶意程序会删除system_t.dll文件,进程会执行另一个GET请求(参数包含action = getcmd),请求的结果有相应的开头和结束的格式,在开头结束中间的数据会被保存在stat_t.ini。进程会再执行一个GET请求(参数包含action = gotcmd)

如前所述,如果一切正常,则文件需要包含“Success”字符串的(httP响应。进程正在删除一个名为“C:\Windows\SysWOW64\dnlist.ini”的文件,该文件目前不存在。该文件将创建,并使用以下数据填充该文件:

img

删除文件stat_t.ini,然后调用GetACP,该API返回操作系统的当前Windows ANSI代码页标识符。因为在dnlist.ini中ScanAll的值为True,所以恶意软件扫描所有可用的磁盘驱动器,然后将它们的类型与3(固定驱动器)或4(远程驱动器)进行比较。枚举所有文件以及路径,路径记录命名为dn,文件命名为fn,如下图,保存在enumfs.ini。这样针对c:\的操作是递归的,并应用于每个目录。枚举完成后发送给服务器。

img

API:GetLogicalDrivers

    GetDriverTypeA

恶意进程试图打开目前不存在的uenumfs.ini,然后枚举在“C:\User\AppData\Local\Temp\ntvba00.tmp\”中找到的文件。此特定目录将由Thread2创建,并包含已选择要导出到C2服务器的所有文件。现在该进程再次使用参数“action=getdata”联系 C2 服务器。 它需要以下响应之一:“A2C9AD2F:UNINSTALL”、“A2C9AD2F:UPDATE”、“A2C9AD2F:RESET”或“A2C9AD2F:UPLOAD”(注意“A2C9AD2F”是之前提取的卷序列号)

Case1:UNINSTALL

删除相应键值,并且删掉enumfs.ini、dnlist.ini、udidx.ini、uenumfs.ini、stat_t.ini文件,C2服务器通过执行带有“action=updated”参数的GET请求得知操作已完成。

Case2:UPDATE

删除上述的同样的键值以及文件,使用“action=datasize”参数向C2服务器发出GET请求,如果一切正常,(httP响应应包括“Success:”.恶意软件会下载一个update.exe的文件。

下载文件的字节与“MZ”(Windows中可执行文件、DLL文件的格式)进行比较,并且它还查找特定偏移量处的“PE”字符串。下载的文件保存为“C:\Windows\install.exe”,并由恶意进程运行。然后执行同样的GET请求表示操作已完成。

Case3:RESET

同样删除ini文件,然后执行同样的GET请求表示操作已完成。

Case4:UPLOAD

此情况与UPDATE相同,不同之处在于未删除任何文件/注册表项。

在执行流通过所有案例后,流程休眠60秒,然后返回到循环中。

2.2 Thread2

主要是一些窗口的操作,恶意软件对参数为DBT_DEVICEARRIVAL(0x8000)的WM_DEVICECHANGE(0x219)消息感兴趣,这意味着有插入了新的USB驱动器或系统上安装了网络共享文件夹这样的事件

从dnlist.ini解析的USearch和UTypeLimit值应设置为True,dnlist.ini中的UAuto值也应设置为False(这可能表明是否应自动过滤目标文件)。攻击者还对Types参数(目标扩展)感兴趣,稍后我们将了解原因。其想法是扫描插入的每个设备以及主机上安装的网络共享,并在uenumfs.ini文件中创建一个“文件系统”结构(就像在Thread1中所做的那样)

与第一种情况一样,此搜索将递归地应用于驱动器上找到的每个目录。该进程创建一个“C:\Users<Username>\AppData\Local\Temp\ntvba00.tmp\”目录,其属性设置为hidden。还将创建以下文件:“C:\Windows\SysWOW64\uenumfs.ini”(其内容将类似于enumfs.ini)。进程还会比较文件的后缀,并且为符合文件格式的文件计算一个HASH值(文件名和最后修改时间)。文件会被复制到tmp的文件夹下,并以新的文件名命名(hidden file–year-month-day-hour-minute-5f7a78e7927532ba2a930ec8d47e252a)

该进程将创建“C:\Windows\SysWOW64\udidx.ini”文件,并将添加所有按照前面说明计算的哈希,新文件的最后修改时间戳设置为从初始文件提取的值。

最后,该文件使用DefWindowProcA API来确保应用程序不处理的窗口消息具有默认处理功能。

Reference

(https://cybergeeks.tech/dissecting-apt21-samples-using-a-step-by-step-approach/