本文将介绍一些基于内存的攻击中最常见的技术,并寻求一种低干扰方法来检测隐藏在内存中的攻击。
内存攻击技术
内存攻击常见的技术包括shellcode注入,反射式DLL注入,内存模块,Process Hollowing,重写模块以及Gargoyle(ROP / APC)。
ShellCode注入技术
Shellcode注入是最基本的内存攻击技术,也是使用时间最长的。 shellcode注入的基本方法是包含四个步骤:
1.打开目标进程(OpenProcess);
2.在进程中分配一大块内存(VirtualAllocEx);
3.将shellcode有效内容写入新分配的部分(WriteProcessMemory);
4.在远程进程中创建一个新的线程来执行shellcode(CreateRemoteThread);
臭名昭著的远程控制木马Poison Ivy使用就是这种技术,这是多年来其吸引很多APT攻击组织的一个重要原因。
如果你使用x64dbg提取Poison Ivy样本并在VirtualAllocEx上设置断点,你将能很快找到负责注射的代码块。
如上图所示,调用VirtualAllocEx之前的push 40指令对应于PAGE_EXECUTE_READWRITE的页面访问保护值。在ProcessHacker下面的一个Poison Ivy植入的内存布局的截图中,你可以看到它分配了以下这些RWX部分。
典型的代码部分类型为“Image”,并映射到磁盘上的文件。不过,由于有些类型不会映射到磁盘上的文件。因此,它们被称为未回调的可执行部分或浮动代码。从这些类型的内存区域开始的线程是异常的,是恶意活动进行攻击的预兆。 ProcessHacker还可以显示恶意软件线程的调用堆栈,调用堆栈中会有多个函数不映射到与加载的模块相关联的内存。
反射DLL注入
由Steven Fewer开发的反射式DLL注入是另一种内存攻击技术。 Metasploit的Meterperter有效载荷是第一次完全把这种技术工具化的尝试,截至目前,仍有许多恶意软件家族在使用Meterperter有效载荷。反射式DLL注入通过创建一个DLL,在执行攻击时会将自身映射到内存中,而不依赖于Window的加载器。除了shellcode被替换为自映射DLL,注入过程与shellcode注入是一样的。添加到DLL的自映射组件负责解析导入地址,修复重定位以及调用DllMain函数。攻击者可以从C / C ++而不是汇编语言编写更高级别的语言。
经典反射式DLL注入,如Meterpreter所使用的,很容易被检测到。因为这个过程中留下了大量的RWX内存部分,即使是关闭会话进程。这些未回执的可执行存储器部分的开头包含完整的MZ / PE标题,如下图所示。但是,其他反射式DLL实现可以删除标题并修复内存泄漏。
加载在内存中的DLL也方便地导出一个名为ReflectiveLoader()的自描述函数。
内存模块
内存模块是另一种内存驻留攻击技术,它类似于反射式DLL注入,注射器或加载器负责将目标DLL映射到内存而不是DLL映射本身。本质上,内存模块加载器重新实现了LoadLibrary函数,但它在内存中的缓冲区而不是磁盘上的文件中起作用。最初的设计是为了在当前流程中进行映射,但升级后的技术可以将模块映射到远程进程。大多数攻击的实现都会使用目标DLL的部分权限,并避免使用痕迹太重的RWX方法。
NetTraveler是一个使用内存模式攻击技术的恶意软件家族。NetTraveler在启动时,它解包核心功能并将其映射到内存中。页面权限更接近于合法的DLL,但是内存区域仍然是私有的,而不是映像过来的。
活动线程在这些私有区域有起始地址,调用堆栈还显示了这些恶意部分。
Winnti是使用内存模块技术的另一个恶意软件家族,如下所示,它们会在第一页的部分权限上有一小部分内存模块。
然而,Winnti的示例显然更加先进一些,因为DLL中的MZ / PE头被擦除,使其更难以检测。
Process Hollowing
Process Hollowing是现代恶意软件常用的一种进程创建技术,虽然在使用任务管理器之类的工具查看时,这些进程看起来是合法的,但是该进程的代码实际上已被恶意内容所替代。
它涉及创建一个暂停的进程,从进程中取消映射的原始可执行文件,为进程分配和写入一个新的有效载荷,使用SetThreadContext将原始线程的执行重定向到新的有效载荷,最后调用ResumeThread来完成。而更加隐蔽的变体会使用创建/映射部分API来避免WriteProcessMemory。写入代码后,必须知道进程新的入口点在哪里,新的Process Hollowing攻击都会采用跳转来修改入口点,而不是使用SetThreadContext。
DarkComet是使用Process Hollowing的许多恶意软件家族之一,它可以同时使用几种工具来检测Process Hollowing,它的恶意活动会用CREATE_SUSPENDED标志攻击过程的发生,如以下所示的DarkComet样本。
重写模块
到目前为止,所有讨论的技术都能导致执行非映像支持的代码,因此可以直接对这些代码进行检测。而重写模块技术则避开了这些,使其更难以被检测。该技术包括将未使用的模块映射到目标进程,然后用自己的有效载荷重写模块,Flame病毒是第一个大规模利用此技术的恶意软件家族。最近,Careto和Odinaff恶意软件家族也使用了重写模块技术。可以使用各种技术来检测重写模块的使用,主要利用的是将存储器与磁盘上的相关数据进行比较。
GARGOYLE
gargoyle是一个将一个程序的所有可执行代码都隐藏在不可执行的内存块中的技术。在一些程序员定义区间内,gargoyle会活跃起来,结合一些ROP欺骗,把自己标记为可执行并实施攻击。
在扫描内存来寻找异常时,通常会扫描可执行的内存块,gargoyle可以在Windows上实现将数据隐藏在不可执行的内存块中。
检测这种攻击者技术的一种方法是检查线程和用户APC,以获取ROP链的证据。
如何检测内存中的攻击
鉴于这些技术的广泛应用,安全人员必须对基于内存的攻击技术保持高度警惕。然而,目前大多数安全产品还无法大规模地对这种技术进行检测,从而使其肆意横行。
为此,有安全公司实现了可以广泛进行检测的方法,即在其PowerShell工具Get-InjectedThreads上实现了一种相对较低干扰的内存威胁检测方法。该方法可以扫描系统上的活动线程可疑的起始地址。用户可以利用它扫描其网络中的主机,并快速识别许多内存常驻恶意软件技术。该脚本通过使用NtQueryInformationThread函数查询每个活动线程来检索其起始地址。然后,使用VirtualQueryEx函数查询起始地址,以确定相关的节点属性。如果线程启动的存储器区域是未回调的并且是可执行的,即不是映像类型并且具有执行位设置,那么该线程就被认为是注入的。下图就显示了在感染9002 RAT样本的系统上运行时的样本检测。
该脚本将捕获各种恶意软件家族利用shellcode注入,反射DLL,内存模块和一些Process Hollowing技术。但是,它不能替代全面防止内存攻击的安全产品,如EndGame。