背景
大约三个月前,一种新的攻击技术出现在安全社区,名为「进程重镜像」。 这项技术是由 McAfee 安全团队在一篇标题为“进程重镜像和终端安全解决方案绕过”的博文中发布的,在这种攻击技术发布的几天后,我的一个同事也是朋友—— Dwight ——拿出了概念验证代码(PoC),演示了这种技术,可以在他的 GitHub 上找到。 虽然这项技术还没有映射到 MITRE ATT&CK 中,但我相信它属于防御躲避战术。
尽管我写这篇博客文章的目的是展示用于检测这种攻击的方法,奇热但是它假设你已经读过 McAfee 安全团队发布的博客文章并且看过 Dwight 的概念验证代码。 这次攻击的简要概要如下:
进程重镜像是一种攻击技术,它利用了 Windows 操作系统在确定进程镜像 FILE 对象位置过程中的不一致性。 这意味着攻击者可以删除磁盘上的二进制文件,并通过将其初始执行完整文件路径替换为受信任的二进制文件来隐藏该文件的物理位置。 这反过来允许攻击者绕过 Windows 操作系统进程属性验证,将自己隐藏在他们选择的进程镜像的上下文中。
这种攻击包括三个阶段:
· 将二进制文件写入到磁盘ーー这里假设攻击者可以将二进制文件写入到磁盘。
· 未检测到的二进制加载。这将是进程创建后加载的原始镜像。
· 恶意二进制文件被“重镜像”到一个攻击者希望以某种方式出现的已知的好的二进制文件。 这是可以实现的,因为重命名镜像时,虚拟地址描述符(VAD)不更新。 因此,当应用程序查询时,这会返回错误的进程镜像文件信息。
这使对手有机会防御性地规避分析人员和事件响应者的检测工作。 组织往往没有收集到“正确”的数据。 通常,数据是非结构化的、无必要的,并且缺乏得出结论所需的实质性细节。 如果没有高质量的数据,组织可能会对在其环境中运行的技术视而不见。 此外,由于过于依赖 EDR 产品的基本配置(例如,Windows Defender 等) ,你将检测的细节提供给第三方,而第三方可能使用或不使用正确的函数调用来检测这种恶意行为(例如 GetMappedFileName 可以正确检测这种重镜像攻击)。 基于这些因素,这种攻击允许对手成功逃避侦测。 要了解更多关于这种攻击的内容和信息,请查看关于这个主题的原始博客文章中的 “技术探秘” 部分。
注意: GetMappedFileName 是应用程序用于查询进程信息的 API。 它检查所请求的地址是否在指定进程地址空间中的内存映射文件内。 如果地址在内存映射文件内,它将返回内存映射文件的名称。 这个 API 需要 PROCESS_QUERY_INFORMATION 和 PROCESS_VM_READ 访问权限。 任何时候当某个句柄具有了访问权限 PROCESS_QUERY_INFORMATION,它也就被授予了 PROCESS_QUERY_LIMITED_INFORMATION 权限。 这些访问权限的位掩码是 0x1010。 这可能看起来很熟悉,因为这是 Mimikatz 所期望的访问权限之一。 Matt Graeber 提醒过我,在尝试检测基于授权访问的可疑访问 LSASS 时,这是许多误报的来源。
透明化
这次攻击发布后,我花了一个星期六的时间创建了一个威胁追踪假设,我仔细的研究了数据行为,并找到了它们之间的关系。 在查看 Dwight 的 POC 时,我注意到代码中的 Win32 APIktv调用,从这些调用中,我确信我可以将这些 API 调用与特定的事件关联起来。 因为像许多防御者一样,我对 EDR 产品及其日志记录能力做了假设。
在没有已知 API 到事件 ID 映射的情况下,我开始自己映射这些调用。 我一开始映射的是 Sysmon。 这需要逆向 Sysmon 驱动程序将 API 调用映射到事件注册机制的事件 ID。 这里要感谢 Matt Graeber,感谢他在这个任务中帮助了我,并且花时间教我逆向的过程。 创建这个映射是我实现检测策略的一个关键部分,没有它就不可能实现最终的检测策略。
进程重镜像检测
检测方法
用于这一检测的方法如下:
· 阅读进程重镜像攻击的技术报告。
· 查看Dwight 的 POC 代码。
· 获得关于攻击如何执行的知识后,在数据和攻击行为之间建立关系。
· 执行攻击。
· 应用前面获得的研究知识并结合数据关系进行鲁棒性检测。
检测步骤
当我浏览这个博客的 “Technical Deep Dive”部分时,我突然想到:
https://securingtomorrow.mcafee.com/other-blogs/mcafee-labs/in-ntdll-i-trust-process-reimaging-and-endpoint-security-solution-bypass/
上面的图片中显示了几个 API 调用,它们的使用极大的激发了我的兴趣。
· LoadLibrary
· CreateProcess
根据我在 Sysmon 驱动程序内部的逆向研究,这两个 API 调用都是通过事件注册机制漏斗式进行的。 然后,Sysmon 驱动程序使用必要的输入 / 输出接口控制(IOCTLxise)代码调用这种机制来查询数据。 然后将查询的数据拉回到 Sysmon 二进制文件中,后者将生成相关的事件 ID。
对于上述两个 API 调用的相关过程如下图所示:
Sysmon 事件 ID 1的映射: 进程创建
Sysmon 事件 ID 7的映射: 镜像加载
根据这项研究和 McAffee 文章中的“技术揭秘”部分,我确切地知道执行此攻击时将生成什么数据。 Sysmon 对 LoadLibrary 的每个调用应该有一个 ID是 7的事件,对 CreateProcess 的调用同样应该有一个 ID 是1的事件; 但是,如何将数据转换为可操作的数据呢? 特别是威胁追踪人员可以很容易地使用和操纵以满足他们需要的数据? 为此,我们将重点放在数据标准化和数据质量上。
数据质量源于数据标准化。 数据标准化是将数据转换为通用可读格式的过程,然后可以方便地进行分析。 数据质量是确保环境正在收集正确的数据的过程,然后可以对特定的攻击技术进行合理化处理。 这可以通过理解非恶意数据的行为并创建此次攻击期间提供的数据的行为相关性来实现。
例如,在创建进程时,OriginalFileName (Sysmon 的一个相对较新的添加项)应该与 Sysmon 事件 ID 1中的 Image 部分相匹配。 假设你想要启动 PowerShell,当你启动 PowerShell 时 OriginalFileName 将是 PowerShell.exe,Image(镜像) 将是 C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe。 当这两者不匹配时,它可能是恶意活动的一个指示器。 在进程重镜像之后,应用程序调用 GetMappedFileName API 来检索进程镜像文件,Windows 将返回错误的文件路径。
可以在ID是 1的事件中的 Image 字段和 ID是 7的事件中的 ImageLoaded 字段之间建立关联。 由于事件 ID 1和7都具有 OriginalFileName 字段,分析人员可以对这两个事件的数据执行 JOIN 操作。 在这个 JOIN 上,结果将显示创建进程的相同进程路径和加载进程的镜像应该相等。 通过这种关联,我们可以确定这两个事件来自同一个活动子集。
上述相互关系如下图所示:
我们基于这篇文章中的“功能”章节进行检测:https://securingtomorrow.mcafee.com/other-blogs/mcafee-labs/in-ntdll-i-trust-process-reimaging-and-endpoint-security-solution-bypass/
虽然可以使用 Sysmon 的 ID为 1的事件和 Sysmon ID 为7的事件建立关系,但是可以基于用户模式 API NtCreateFile 建立另一个关系。 这将通过事件注册机制 FltRegisterFilter实现,它在 Sysmon 中会创建一个 ID为 11的事件(事件含义:文件创建)。
此关系可以在 Sysmon 中 ID 为1的事件的 Image 字段上关联,该字段应与 Sysmon 中 ID 为11的事件 TargetFilename 匹配。 Sysmon 中的 ID为 1的事件 ParentProcessGuid 也应该匹配 Sysmon 中ID 为11的事件的 ProcessGuid字段,以确保事件都是由同一个进程引起的。
既然研究已经完成,那么这些假设必须得到验证。
数据分析
下面显示了正在执行的攻击命令。 该进程(phase1.exe)是通过加载二进制文件(svchost.exe)创建的,然后重镜像为 lsass.exe。
.\CSProcessReimagingPOC.exe C:\Windows\System32\svchost.exe C:\Windows\System32\lsass.exe
下面是我们在上面讨论的问题的 SparkSQL 分析代码:
使用 Jupyter notebook 和 SparkSQL 运行查询Gist
我试图让用户尽可能地阅读 JOIN 函数。 需要注意的一点是,这个查询是从 Sysmon 中的原始数据日志中提取的。 没有在 SIEM 管道中执行转换。
下面是使用 SparkSQL 在 Jupyter notebook 中进行的关联分析和数据相关性的直观表示。
如果创建的文件随后移动到不同的目录,以及如果文件的 OriginalFileName 不等于 Sysmon 事件 ID 1的 Image,则也会检查此查询。 (例如: 用 Image ——“ ApplyTrustOffline.exe”和 OriginalFileName ——“ ApplyTrustOffline.PROGRAM”创建进程)在这些检查之后,查询将只返回重镜像攻击的结果。
查询中关联的图表视图
上面的 SQL 查询的输出可以在下面看到。 在攻击后的数据查询输出中发现的事件似乎有“重复项”。 事实并非如此。 每次运行攻击时,都会有一个 Sysmon 事件 ID 11(FileCreate) 在每次 Sysmon 事件 ID 1(Process Creation) 之后触发。 这与上面讨论过的攻击行为有相关性。
查询输出
与以下分析相关的数据集和 Jupyter Notebook 可以在我的 GitHub 上找到。 我鼓励任何人把它拉到自己的电脑上,自己动手分析数据。 如果你没有一个实验室来做测试,你可以在这里找到: https://github.com/jsecurity101/mordor/tree/master/environment/shire/aws。
下面分析了运行的数据集的阶段和信息。 这与上面的查询相关:
需要记住的一件事是,当恶意二进制被重新映射到攻击者选择的二进制时(第三阶段) ,你将不会看到“ phase1.exe”被重新映射到“ lsass.exe”。 这是这种攻击特有的行为; Windows 将返回不正确的文件对象。 这并不能破坏这种检测方法。 我们的目标是发现攻击的行为,一旦发现,你就可以顺着“ phase1.exe”的 ProcessGuid,或者转到它的完整路径,找到 Image 属性的二进制文件的镜像。 “ Phase1.exe”将出现在重新镜像的二进制文件的上下文中。
上图显示的是在重镜像执行成功后,phase1.exe 的属性
结语
进程重镜像攻击技术真的激起了我的兴趣,因为这种技术的焦点似乎就是做到“在雷达下飞行”,以避免检测。 攻击者利用的每种技术都会有跟踪攻击行为的数据。 这可以加以利用,但只有在我们理解了数据和数据源之后才可以做到充分的利用。 从基于特征的搜索转向更多的数据驱动的威胁追踪方法将有助于检测的鲁棒性。
致谢
非常感谢 Matt Graeber 帮助我完成 Sysmon 驱动程序的逆向处理过程。 致 Dwight Hohnstein,感谢他的 POC 代码。 最后,感谢 Brian Reitz 在 SQL 运行不正常时给我提供的帮助。
参考资料和资源
· 进程重镜像和终端安全解决方案绕过
· 进程重镜像 POC 代码
· 微软官方说明文档