概述
通常情况下,在对攻击活动进行检测的过程中,我们会遇到一些难以有效检测的攻击技术。我们是否找到或创建了攻击的概念证明(PoC)?我们是否已经掌握了攻击的底层技术?我们是否可以将威胁事件与恶意活动相关联以创建一些分析逻辑?有哪些特点会在所有的攻击中保持不变?有哪些是会发生变化的?所有上述这些,都是在研究一种攻击技术时通常会提出的问题。
在这篇文章中,我将逐步使用称为“能力抽象”的技术,逐步剥离出使攻击成为可能的基础技术。对于“能力抽象”这个名词,Jared Atkinson在他的文章《Capability Abstraction》中已经做了详细描述。由于我们会持续用到这一概念,建议各位读者可以首先了解这篇文章。
在对进程进行检测的过程中,我们往往希望拥有理想化的步骤,但有时可能很难实际做到这一点,因此我们只能尽最大程度的努力。
在这一系列的文章中,我们将详细介绍用于创建检测的方法,我们将集中讨论一种被称为Process Hollowing的技术。系列文章将分为三部分:
第一部分:研究
第二部分:数据关联
第三部分:分析逻辑
我将与Josh Praeger(Bouj33 Boy)、David Polojac共同开展这一系列研究,我们期望这一系列研究的成果可以应用于其他技术上,但在我们的文章中,将以“检测进程注入技术”为例。
研究
要创建任何检测,第一步就是选择相应的攻击技术。这些攻击技术可能来源于文章、攻击源、MITRE ATT&CK知识库、实际威胁事件、红队测试或其他资源。通过这样的方式,我们就可以选择一种技术。有些时候,所选择的技术往往过于广泛,我们就必须要再将其细分为“子技术”。进程注入就是一个很好的例子。这种技术有很多不同的变体,我们可以将其细分为DLL注入、反射型DLL注入等等。关注子技术,可以让我们更加明确地确定检测范围。但如果同时定义了太多子技术的检测方法,就很容易在最终的检测中失去侧重性和准确性。
一旦选择了一种技术或子技术,我往往倾向于查看MITRE ATT&CK框架中是否有相应信息。在深入研究基础技术之前,我们通过查询框架的方式进行初步分析。
Process Hollowing的MITRE ATT&CK描述:
通过上面的描述,我们初步了解了如何定义Process Hollowing,以及这种攻击的工作方式。但是,我们还需要更多上下文来创建可操作的检测方式。在MITRE的页面上,有一个“检测与参考”部分。其中的“检测”部分指出:
“监视API调用可能会产生大量数据,并且可能无法直接用于防御,除非收集在特定情况下已知恶意调用序列的信息,否则无法有效将合法使用的API函数与恶意行为区分开来。取消映射进程内存的API调用(例如:ZwUnmapViewOfSection或NtUnmapViewOfSection)和可用于修改另一个进程中内存的API调用(例如:WriteProcessMemory)均可以用于该技术”。
在这一章中,提到了执行Process Hollowing的不同API调用。尽管这本质上非常有趣,但实际在“检测”部分还没有提供足够的上下文来深入探讨API调用。
接下来,我们可以来看一下MITER中提到的一些参考。在这里,我注意到了Endgame的《十种进程注入技术:常见进程注入技术和发展趋势》这篇文章。
与MITRE最初的报告相比,这篇文章中包含更多的细节。我从中提取到一些关键信息包括:
1、恶意软件会从目标进程的内存中取消映射(镂空)合法代码;
2、恶意软件会使用恶意可执行文件覆盖目标进程的内存空间。
这使我从更高的角度上获得了更多的见解,即如何执行Process Hollowing这一过程。但是,我还需要进一步探讨更加具体的实现方式,以便创造更为可靠的检测方法。
针对每种进程注入技术,Endgame都提供了有关攻击如何进行的技术摘要。由于我可以利用其它上下文进行检测,因此这些描述很有帮助。从这些信息中,我得到了如下结论:
1、使用CreateProcess Win32 API以挂起状态(CREATE_SUSPENDED)创建一个进程。
2、攻击者需要取消目标进程中的内存映射,这是通过使用ZwUnmapViewOfSection或NtUnmapViewOfSection来完成的。
3、加载程序将利用VirtualAllocEx为目标进程内的恶意软件分配内存。
4、WriteProcessMemory用于将恶意软件部分写入目标进程空间。
5、调用ResumeThread可以使主线程退出挂起状态,以允许进程运行。
在深入探讨这些函数之前,我们还想追踪一些其他问题:
1、当利用其中一些API调用时,我们期望看到哪些数据?
2、这种攻击的隐藏行为和显式行为分别是什么?在保证有效执行攻击的前提下,攻击者有哪些地方是可以调整的,而又有哪些地方是无法调整的?
为了回答这些问题,我开始浏览Microsoft文档,以深入分析这里所使用的API调用。我们以CreateProcessA为例。
CreateProcessA:
现在,我们需要了解一下CreateProcessA的用途,以及攻击者是否可以使用其他Win32 API调用来执行创建进程的相同任务。通过对这篇文档进行进一步研究,我可以看到这个API的作用,以及可以用于创建进程的其他API调用。此外,需要关注的是,这个进程是在挂起的线程中创建的,但这又意味着什么?
进程创建标志:
Create_Suspended标志:
尽管这里的描述相对较少,但也提供了必要的上下文信息:
1、可以将Create_Suspended标志传递给以下任何API调用:
CreateProcessA
CreateProcessAsUser
CreateProcessWithLogonW
CreateProcessWithTokenW
2、在传递此标志时,将会影响进程的主线程。
3、在调用ResumeThread之前,主线程不会运行。
注意:大家可能希望对上面列出的其他API和函数调用进行深入的分析,在进行这一项研究的过程中,一个比较好的方法是查看一些概念证明(PoC)代码示例。在GitHub上,可以找到很多。
通过这样的方式,我们可以理解攻击背后的技术,了解到攻击者可以通过哪些不同的变体来更改函数或API调用,同时保证相同的攻击行为。作为防御者,这一点非常重要。如果能够剥离攻击者为执行特定行为所使用技术的不同分层,我们就能够更加有效地进行检测。作为抽象的另一种方法,我们可以进一步剥离各层,以查看有文档记录的API调用、无记录的API调用以及系统调用,并找到它们之间的共性和联系。
现在,我们已经通过研究这些API和函数调用获得了更多的上下文,我们想知道执行此攻击行为时将会触发哪种类型的日志。创建此检测时,我希望尽可能地减少假设。为此,我将对创建进程时所触发的事件进行一些研究。针对这里的场景,我将使用Sysmon数据传感器。
Sysmon Event ID: 1:
每当在主机上创建进程时,Sysmon都会创建一个事件。对于检测而言,这还不够,我们还需要知道如何触发这些事件,以及攻击者可能以什么方式绕过这一项日志记录。这样一来,我们就能够在创建检测时抓住我们的盲点和需要进行假设的内容。换而言之,我们需要测量对日志传感器的信任程度,而为了测量这一点,唯一的方式就是首先掌握其工作原理。
去年,我创建了一个将Windows API映射到Sysmon Events的项目,该项目映射了Sysmon执行日志记录的方式。在项目中,研究了如何通过特定的事件注册机制(ERM)传递API,以及Sysmon如何利用该进程来创建特定的事件ID。
下图展示了Sysmon是如何新建进程创建事件的。
进程创建事件映射:
在映射中,我们清楚地了解到Sysmon是如何记录进程创建事件的。此外,我们也可以获知攻击者如何能规避这些事件的生成。攻击者可能会采取一些可行的方案,包括但不限于:
1、使用其他API调用来创建进程;
2、篡改ERM的记录。
在我们针对所有API和函数调用都完成上述分析工作后,就可以开始尝试执行此类攻击,使用概念证明作为我们的检测逻辑。随后,我们可以使用PoC作为构建和连续测试我们检测逻辑的方式。我们还可以使用这个PoC来确定哪些是需要检测的相关日志事件。欢迎大家继续关注本系列的第二篇文章,我们将会进行详细讨论。
总结
对于构建检测方式的整体过程而言,前期研究的这一步常常会被大家忽视,但这正是我们构建检测的基础。为了开发出强大的检测功能,我们必须要首先了解可以执行此攻击的基础技术。Jared Atkinson在最近的一篇文章中谈到了能力抽象的问题,这是一个可以将工具、功能或攻击原理剥离和分解的过程。为了构建检测方式,我们可以查看这些抽象的内容,并将其用于我们的检测工作中。
能力抽象的过程始于研究。它可以引导我们发现各种不同的API调用、函数和日志记录功能,从而最大程度地提高检测效率,这样就可以在寻找恶意活动的过程中不再盲目浏览日志。这一过程,有助于我们识别可能发生的误报,帮助我们明确所做的假设,并有助于发现在构建检测的过程中可能会发现的盲点。
SpecterOps的检测工程团队会采用这种方法,并与我们的企业和个人客户共同进行实践。欢迎大家继续关注这一系列文章的第2部分和第3部分,我们将会详细讨论如何隔离恶意活动、在数据中寻找关联性、如何选择我们要创建的检测类型(检测光谱),以及如何实际编写这些检测方式。
发表评论
您还未登录,请先登录。
登录