用来检测异常活动的最有用的技术之一是对父子进程关系的分析,然而,技术更高明更强大的攻击者可以使用父PID(PPID)欺骗来绕过此操作,从而允许从任意父进程执行恶意进程。尽管这项技术本身并不新鲜,虽然Cobalt Strike和DidierStevens 对其进行了详细介绍,但在检测此类攻击方面进行的专门研究却很少。
在本文中,我们将探讨该技术的工作原理以及防御者如何利用Windows事件跟踪(ETW)来检测该技术。我们还将发布概念验证PowerShell脚本以执行PPID欺骗和DLL注入,以及一个Python脚本,该脚本利用pywintrace库来检测此活动。
为什么首先要进行欺骗?
过去,攻击者通常能在发动攻击时不留下任何痕迹,但是随着EDR的兴起和威胁搜寻的兴起,情况就开始发生变化了。特别是使用父子进程分析已经成为一种有用的技术,用于检测在网络攻击杀伤链的几乎每个阶段产生的异常活动。
我们在Countercept上使用的一些示例:
- 宏有效载荷传递: WinWord生成过程;
- JS / VBS C#有效载荷传递: cscript生成csc;
- 横向移动:services/wmiprvse产生新流程;
这迫使攻击者重新评估他们的方法,并着眼于像PPID欺骗这样的技术,以绕过现代的防御策略。
通过CreateProcessA进行欺骗
有许多不同的方法可以欺骗父进程,在这篇文章中,我们将关注一个最简单和最常用的技术,涉及到API调用CreateProcessA。
毫不奇怪,CreateProcessA允许用户创建新流程,并且默认情况下,将使用继承的父级创建流程。但是,此函数还支持一个名为“lpStartupInfo”的参数,你可以在其中定义要使用的父进程。这个功能是在Windows Vista中加入UAC后首次引入的,目的是为了正确设置父级。
在更深层次的技术水平上,lpStartupInfo参数指向STARTUPINFOEX结构。此结构包含一个lpAttributeList,你可以使用UpdateProcThreadAttribute通过“PROC_THREAD_ATTRIBUTE_PARENT_PROCESS”属性设置进程的父进程。
顺便提一下,这种方法也可以用于特权升级。文档中提到“从指定进程继承的属性包括句柄、设备映射、处理器关联、优先级、配额、进程令牌和作业对象”。“Adam Chester有一个博客,展示了如何滥用它来获得Windows系统。
如何欺骗父进程?
在网络上立足的最常见方法之一是使用恶意宏文档,许多有效载荷通常会启动新进程,例如cmd,PowerShell,regsvr32或certutil。图3显示了从winword生成rundll32的一个示例。但是,这种行为是相对异常的,并且大多数防御策略都很容易检测到。
为了克服这个问题,攻击者可以改用CreateProcessA技术的VBS宏实现从预期的父进程启动有效载荷(例如Explorer启动cmd)以与环境融合,下图概述了如何实现的过程。
我们不会发布此VBS代码,然而,更多信息可以在这里找到。
但是,我们可以采取进一步措施来完全避免使用常见的Windows实用程序吗?一种选择是使用某种形式的DLL或内存注入在已经运行的进程中加载有效载荷。
为了说明这一点,我们基于Didier Stevens]的代码创建了一个PowerShell脚本,该脚本可用于创建具有欺骗性父级的进程,然后在其中注入DLL。
为了演示如何使用该脚本隐藏活动,我们查看了Windows 10上常用的进程。我们看到的一种非常常见的合法关系是“ svchost.exe”启动“ RuntimeBroker.exe”。
使用PowerShell脚本,我们能够模拟这个活动,并通过“ svchost.exe”强制生成合法的“ RuntimeBroker.exe”,然后注入并执行DLL有效载荷。
此向量显示了此类技术如何潜在地绕过专注于父子关系的检测规则。
如何查找到攻击者?
如上所述,我们介绍了CreateProcessA技术如如何欺骗父级ID的,并且从安全团队的角度来看,如果你使用任务管理器或进程资源管理器查询正在运行的进程,则会看到欺骗性的ID。但是,有什么方法可以找出真实的ID?
Windows中最好的取证数据源之一是Windows事件跟踪(ETW),ETW提供有关系统上发生的事件的实时数据流,这是我们在Countercept的端点代理中使用的东西。
特别是Microsoft-Windows-Kernel-Process提供程序可以为流程创建提供一些有用的见解,并可以帮助我们检测流程ID欺骗。在下面的示例中,你将看到如何从“winword.exe”(PID 9224)生成“rundll32.exe”(PID 5180)(图9)。
查看收集到的ETW数据(图10),你将看到多个ProcessId字段,包括EventHeader ProcessId以及实际事件ProcessID和ParentProcessID。尽管这有些令人困惑,但通读MSDN文档,我们发现EventHeader ProcessId实际上标识了生成事件的进程,即父进程。
在这个合法的示例中,你会注意到EventHeader ProcessId和ParentProcessId正确匹配。
在第二个示例中,我们执行了恶意的PowerShell脚本,并通过“svchost.exe”(PID 4652)生成了“RuntimeBroker.exe”(PID 4976)。
和以前一样,我们可以看到ETW生成了一个流程事件(图12);但是,这次的EventHeader ProcessId和ParentProcessID是不同的。实际上,EventHeader ProcessId显示了真正的父级关系,即“ winword.exe”(PID 9224),因为我们刚刚发现有人在执行ParentPID欺骗!
但是,就像在威胁检测中一样,事情并非如此简单,如果你尝试大规模进行此操作,你将发现合法欺骗会带来误报。一个常见的示例是用户帐户控制(UAC),用于提升进程特权。在Windows 10中,当UAC执行时,应用程序信息服务(通过svchost)用于启动提升的进程,但随后将欺骗父级以显示原始调用方。下面的示例显示了提升后的cmd.exe如何将explorer.exe作为父级显示,而实际上它是svchost.exe。
我们看到的另一个误报与WerFault的崩溃处理有关,在下面的示例中,当MicrosoftEdge崩溃时,使用svchost启动WerFault.exe,并且将父级欺骗为MicrosoftEdge.exe。
出于测试的目的,我们创建了一个简单的概念验证Python脚本,该脚本使用pywintrace记录来自ETW的事件,比较PID,然后过滤结果以消除误报(图15)。
可以在我们的Github 上找到PowerShell欺骗脚本的代码以及检测脚本。
总结
在这篇文章中,我们展示了攻击者如何利用合法的Windows功能来欺骗防御者,并可能绕过基于父子关系的检测技术。
但是,从防御的角度来看,我们已经展示了对ETW进程事件的分析如何轻松地突出显示异常的父级欺骗并帮助发现进程的真正来源。
本文翻
发表评论