前言

在这篇文章中,我们将分析UPAS Kit漏洞利用工具包和Kronos银行木马,这两款恶意软件最近因背后的故事而成为焦点。

背景

2017年5月,WannaCry给全球150多个国家造成了巨大的破坏,并拖垮了来自各行各业的公司。幸运的是,英国安全研究人员马库斯·哈钦斯(Marcus Hutchins)通过发现第一个“自毁开关(kill switch)”,阻止了这次袭击。

然而,当哈钦斯被美国联邦调查局(FBI)逮捕和调查时,感谢的浪潮迅速转变,因为他涉嫌参与了制造和传播Kronos银行木马。但是哈钦斯的痛苦并没有就此结束,他最近又因为被认为是另一种恶意软件UPAS Kit漏洞利用工具包的作者而被重新调查。

到目前为止,虽然已经对Kronos进行了大量分析,但是在UPAS Kit上还没有同样的在线可用性。所以Check Point研究团队决定仔细研究一下。

Check Point 研究团队同时发布了一条免责声明“我们的研究并不试图暗示或断言马库斯·哈钦斯所担任的角色,或者其他方面。对于这两种恶意软件而言,仅仅是对它们进行比较。我们的研究也没有显示任何确凿的证据表明Kronos和UPAS Kit是否由同一个人编写的。”

初始化阶段

解析ntdll.dll函数

UPAS Kit使用多个底层ntdll函数并在运行时解析其地址。虽然它可能成为阻止分析的手段,但这本身并不是一个非常复杂的技巧。负责此加载操作的过程遍历包含以下结构条目的函数表:

typdef struct _ntdll_function_entry {

CHAR * function_name;

PVOID function_address;

} ntdll_function_entry;

它只需使用每个条目的字符串字段并使用Win32 API函数GetProcAddress解析相应的地址。这可以在下图中看到:

图1:UPAS套件解析ntdll功能

事实上,Kronos木马使用了类似的方法来实现相同的目标。但是,在这种情况下,函数名不会以明文形式保存在二进制文件中,而是作为字符串散列。此外,某些已解析的功能可用作系统调用,因此无论是通过沙箱模拟器还是手动检测恶意软件的活动都会更加困难。为此,Kronos利用一个稍微不同的函数入口结构,如下所示:

typedef struct _ntdll_function_entry {

CHAR * function_name_hash;

PVOID function_address;

DWORD encoded_syscall_number;

DWORD is_used_as_syscall_flag;

} ntdll_function_entry;

这当然并不意味着后者是第一种方法的扩展机制,但是如果我们比较加载函数的顺序(表项位于二进制文件中的顺序),可以看到这两种情况之间有一些重叠。

图2:加载的ntdll函数顺序的比较

反虚拟机

为了避免在分析环境中执行,恶意软件采用了两种技术。第一种技术避免了ThreatExpert沙盒的检测,即使用函数GetVolumeInformationW检索系统卷序列号,并检查值0xCD1A40(对应于上述沙箱)。第二种技术是众所周知的,它是对VMWare的工件进行检查,检查来自用于来宾操作系统和主机之间通信的虚拟I/O端口的响应。值得注意的是,一旦恶意软件检测到一个不需要的环境,它就会通过生成一个错误框来响应,如下所示:

图3:UPAS Kit使用的反虚拟机技术

此外,需要注意的是,Kronos所做的等效检查差异很大。这些检查的目的是为了在恶意软件的地址空间中寻找各种进程或已加载模块的存在,这些模块可能表明其执行的环境的性质。

与前一种情况相比,这种类型的检查包含了更多的场景,这可能意味着规避过程是由不同的作者编写的,或者同一作者对同一个问题采取了不同的解决方法。

全局互斥

bot生成的互斥体名称是动作的结果——MD5(system_volume_serial ||“LPLl3h3lDh1d3djP7P3”)。如果在互斥体名称的生成中出现错误,则会为其设置硬编码值(“A5DEU79”)。

图4:互斥体名称的生成

在这种情况下,在执行MD5函数时,Kronos和UPAS Kit可以在Kronos和UPAS Kit之间发现相似之处,这是由以色列网络安全公司Intezer的Ignacio Sanmillan(@ulexec)所指出的。

但更明显的是,它通过计算MD5(system_volume_serial),以类似的方式创建一个互斥体名称,如果失败,则将其分配给MD5(“Kronos”)。

自安装

为了保持持久性,UPAS Kit会执行几项常见操作。

首先,它将自身复制到%APPDATA%下的新建目录中,命名为“Microsoft”,同样的操作会%TEMP%目录下进行。复制的文件的名称将是上述中全局互斥体名称的前七个字符,这一点在%APPDATA%和%TEMP%相同,只是在%TEMP%目录下会附加“_l.exe”和“_a.exe”。

然后,将检查当前文件名并与新生成的文件名进行比较,如果两者不匹配,那么恶意软件则将会从%APPDATA%中的新路径执行。如果检查成功(即在第二次恶意软件从%APPDATA%路径运行时),则当前文件路径将写入众所周知的注册表运行密钥Software \ Microsoft \ Windows \ CurrentVersion \ Run(在HKLM和HKCU下),其中密钥的名称与复制文件的名称相同。

最后,恶意软件将使用IsWow64Process或GetNativeSystemInfo函数建立当前的系统架构(如果前者不可用),并将其返回给主函数。

图5:架构检查

用于文件、注册表键和互斥体的命名约定与Kronos类似,它使用MD5(system_volume_serial)的前八个字符来实现此目的。

进程注入

由恶意软件进行的注入取决于系统架构。在32位系统中,它会创建“explorer.exe”进程并并将其自身的映像注入其中;而在64位系统中,它将在“iexplore.exe”的32位版本中这样做,这个进程驻留在“%ProgramFiles x86)%\ Internet Explorer ”。注入函数本身获得PID和目标进程的主线程句柄,以及注入发生后要执行的函数的地址。

为了进行成功的注入,UPAS Kit使用一个简单的技巧。首先将其当前虚拟映像复制到缓冲区,然后尝试在远程进程中的任意地址分配带有映像大小的内存。分配的检索基址将被用于重新定位注入的映像,该映像驻留在复制的缓冲区中,并将其写入目标进程。然后,它将准备一个硬编码调用存根并覆盖其三个DWORD,以便它将调用注入时应执行的函数。这些DWord概述如下:

图6:调用存根和替换的字节

在堆栈中推送的结构用于传递一些参数,这些参数稍后将被钩子(hook)函数使用。这些参数包括:

typedef struct _config_struct {

DWORD whitelisted_process_pid;

CHAR whitelisted_run_key_name [16];

wchar_t whitelisted_malware_binary_path [260];

wchar_t mutex_name [260];

DWORD ntdll_load_status;

DWORD some_flag;

} config_struct;

最后,为了触发远程进程中请求的函数的执行,恶意软件将通过调整Context结构中的EAX的值来调用远程进程的入口点,然后继续执行通过调用NtSetContextThread函数。如果失败,它将尝试直接用CreateRemoteThread函数产生目标函数(而不是调用存根)。

图7:在注入过程中开始执行

在与上述相比,Kronos进行了一种不同类型的注入,如这里所述。。话虽如此,我们还是可以注意到两个注入实现之间的相似之处,因为两者都试图将恶意软件的进程标记提升到SeDebugPrivilege,这对于注入的成功并不是强制性的。标记提升函数的调用以及函数本身(在两个二进制文件中都是相同的)如下所示:

图8:Kronos和UPAS Kit之间的注入比较

注入有效载荷

同样,在注入后执行的有效载荷将根据底层系统体系结构而有所不同。对于32位进程,注入的有效载荷将执行以下操作:

  根据传递给它的config_struct分配全局变量(如前一节所述)

  加载dll的原始映像

  使用由注入过程设置的互斥体名称创建互斥体

  检查是否有卸载标志,如果没有

  创建一个线程,将自身注入所有其他进程中,并将钩子函数设置为在注入时应执行的函数。

  创建一个线程,负责通过USB媒体传播恶意软件。

  与C2服务器进行无限循环的通信。

64位有效载荷非常相似,只是它不检查卸载标志(因此如果需要,不能进行恶意软件的卸载),并且不会将自身注入所有其他进程中,从而使rootkit无用。两个有效载荷的比较可以在下图中看到:

图9:将UPAS Kit初始注入到explorer.exe \ iexplore.exe后调用的函数

在随后的章节中,我们将重点讨论挂钩机制和C2通信,因此我们只会在这里介绍通过USB媒体的横向移动。它的做法是通过注册一个新的窗口类(使用前面描述的互斥体的名称)并输入一个无尽的消息循环。

图10:注册USB扩展线程的窗口类

每个截获的消息将由一个函数处理,该函数将检查它是否表示新媒体的插入,如果是,则会启动传播操作并将其报告给C2服务器。

图11:USB传播线程的窗口类处理程序

传播自身通过将恶意软件文件复制到USB驱动器并使用字符串“[autorun] \ r \ nopen = <恶意软件文件名> _a.exe \ r \ n”生成新的autorun.inf文件而发生。然后,扩展器将查找任何.lnk文件,并将用以下路径替换它们的原路径:

/C start \”\” \”\\” && start \”\” \”_l.exe\”

这会导致原始文件和恶意软件文件都会因按下相应的快捷方式而被执行。替换操作使用IShellLinkW COM类完成,如下所示:

图12:替换.lnk文件中的路径

用户模式Rootkit功能

UPAS Kit使用了一个非常直接的内联钩子机制,它使用以下流程工作:

a).检查目标函数是否已被挂钩(通过比较它的第一个字节到0xE9,即jmp指令)

b).如果不是,则它开始分解函数的第一个字节,直到它处理至少5个字节。为此,它使用一个简单的反汇编引擎,该引擎仅计算每条指令的反汇编字节数。这些字节被称为被盗字节。

c).准备一个包含21个NOP字节(0x90)的缓冲区,然后将盗来的字节读入其中。此外,它还修改了最后5个字节,并跳转到被盗字节后面的地址。然后将缓冲区的保护设置为与原始字节相同(即应该是可执行的)。

d).将原始函数的被窃字节部分设置为0,并将前5个字节替换为对钩子函数的跳转。

以下ntdll.dll函数被挂钩,旨在隐藏恶意软件的组件,从而使其变得隐蔽:

  NtResumeThread:拦截,将恶意软件二进制文件注入到新创建的进程中。

  NtQuerySystemInformation:检查请求的信息类是否是SystemProcessInformation,如果是,则将请求的PID与列入白名单的explorer.exe PID进行比较。如果这些匹配,它将设置以下SYSTEM_PROCESS_INFORMATION条目(对应于流氓explorer.exe之前的进程)指向explorer.exe的后续进程。

  NtQueryDirectoryFile:隐藏恶意软件副本所在的目录

  NtEnumerateValueKey:隐藏与恶意软件相对应的注册表运行密钥

  NtDeleteValueKey:同上

  NtSetValueKey:如果请求的密钥是恶意软件的运行密钥,则避免该操作

  NtSetInformationFile:检查文件信息类是否符合下列之一:FileDispositionInformation,FileRenameInformation、FileEndOfFileInformation或FileAllocationInformation。如果是,将文件名与白名单中的恶意软件的副本二进制文件进行比较,如果匹配则避免该操作。

  NtOpenProcess:如果请求的PID是流氓explorer.exe进程的PID,则避免该操作。

  NtWriteFile:如果目标文件是恶意软件的二进制文件,则避免该操作。

值得注意的是,Kronos使用的挂钩方法有很大不同。虽然两者都进行内联挂钩,但Kronos使用更稳定、更安全的实现。内联钩子引入了一个并发问题,即在所有被盗字节被覆盖之前发生的上下文切换可能会导致系统崩溃,因为它的代码不是一致的状态。因此,Kronos挂钩方法使用“lock cmpxch8b”指令对前言字节进行原子写入。从这个意义上说,UPAS Kit的挂钩引擎要简单得多,而是使用WriteProcessMemory函数执行不安全的写操作。

但是,同样可以发现一些相似之处,那就是钩子函数本身。上述八个挂钩在Kronos中以相似的形式出现,并且用途完全相同。这表明,这些二进制文件中的部分rootkit组件可能被重用。

CnC通信

与C&C服务器的交互使用HTTP协议完成。大部分通信是在恶意软件执行所有其他操作(即注入、挂接和USB扩展)之后完成的。在这个通信序列中,恶意软件会恶意软件无限期地指向服务器,并使用以下信息更新服务器:

  系统架构

  标志,指示%TEMP%目录中的恶意软件副本是否仍然存在

  操作系统版本

  Bot版本(本例为1.0.0.0)

反过来,服务器可以用两个命令之一来响应:“卸载(uninstal)”和“下载(download)”。后者还可以包含两个子命令之一:“更新(update)”和“执行(execute)”,这些都是不言而喻的。多个命令可以在一个响应中发送,由“|”字符分隔,命令序列将在第一次出现“!”字符后开始。每个命令的参数由空格分隔。

发送到C2服务器的另一个可能的消息是对受感染USB的更新,一旦AutoRun文件和恶意软件二进制文件复制到其中,它将被发送。

从本质上说,这是UPAS Kit的核心作用,即充当其他模块的隐蔽和有感染力的下行器。在2012年发售的此恶意软件的部分模块可以在exploit.in论坛的以下主题中找到:

虽然我们没有调查其他模块,但从他们的描述中可以看出,它们与ZeuS及其一些变体使用的模块相似

参考

  Kronos分析:

  https://www.lexsi.com/securityhub/overview-kronos-banking-malware-rootkit/?lang=en

  https://blog.malwarebytes.com/cybercrime/2017/08/inside-kronos-malware/

  UPAS Kit CnC面板分析:

  https://malware.dontneedcoffee.com/2012/08/inside-upas-kit1.0.1.1.html

妥协指标(IOCs)

         分析中的UPAS Kit样本:

1e87d2cbc136d9695b59e67f37035a45a9ad30f5fccc216387a03c0a62afa9d4

         分析中的Kronos样本(在Lexsi的文章中分析):

4181d8a4c2eda01094ca28d333a14b144641a5d529821b0083f61624422b25ed

声明:本文来自黑客视界,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。