在红队行动中,进程隐藏、系统调用隐藏、代码混淆以及绕过AV/EDR(防病毒软件/终端检测与响应)等技术是常见的讨论话题。但如果你不仅仅想依赖教程,避免被束缚,还希望独立探索这些技术,就必须深入理解防病毒软件和EDR的基本工作原理。我们将深入探讨这些原理。本篇文章将使用SentinelOne解决方案作为示例来解剖EDR内部架构。
历史
早期计算机恶意软件刚刚出现的时候,它们通常是由一些疯狂且热衷于编程每天只穿着拖鞋坐在电脑前的人出于娱乐目的而编写的,是真正意义上的业余爱好者,而不是以此追求利润。随着网络的发展,某天开始,这些人开始从“只是为了好玩”变成了“为什么不从中赚点钱呢,嘿嘿”。于是,大规模的黑客生意开始上演。
与此同时,国家队也意识到了这些“新型武器”的潜力,有时它们甚至能够颠覆整个国家(例如,Stuxnet在以色列和伊朗的核武器冲突中就起到了这样的作用)。
从历史上看,杀毒软件(AV)是最早开发的安全解决方案之一,旨在应对这些新兴威胁。
起初,杀毒软件主要进行静态分析,检测方式主要基于恶意文件的签名。随着时间的推移,签名检测方法发生了一些变化:例如,可以使用字节序列,不仅可以使用静态序列,还可以使用模糊匹配序列,?号可以被用任何字节代替
$scan_1 = { d1 ?? 33 ?? fc 81 ?? ff 00 00 00 c1 ?? 17 }
随着时间的推移,杀毒软件开始进行动态分析,例如,通过在沙盒(sandbox)中模拟恶意程序的运行来检测威胁。
与之相对,恶意软件开发者(maldev)反击,开发了规避沙盒检测的技术,并实现了反向工程和反调试的技术。
随着时间的推移,软件开发商不得不适应恶意软件的演变,开发出更加健壮和智能的解决方案。这也催生了新的术语,用于产品的营销和销售(如EDR/XDR/MDR)。
2013 年,Anton Chuvakin(毕业于莫斯科国立大学物理系并在国外工作的俄罗斯计算机安全专家)提议确定一类新的防止黑客攻击的工具,并将其称为 ETDR(端点威胁检测和响应) ,后来被普遍缩写成EDR。其中端点包括服务器、桌面工作站、笔记本电脑和智能手机。
我可以说EDR 是一种 AV,但具有更多的功能和检测手段。我们将会进一步探讨其中的原因。
运作方式
EDR 和 传统安全软件之间的主要区别在于处理特定计算机上发生的本地数据和日志记录事件,EDR会实时收集其监控系统的数据。数据可以包括文件、IP 地址、URL、注册表项、进程。简而言之,系统上可能发生的所有事情都会被收集。然后这些数据会被发送到云端
在上图中,我们可以看到两个 URL。第一个对应于管理界面,第二个对应于解决方案发布者的“云”。
该解决方案的分析师和用户可以连接到互联网上公开的界面,这使他们能够管理受监控的机器、警报、配置和安全策略。
当检测到威胁时,EDR还可以使用预先配置的操作 进行响应(停止进程、关闭主机、在网络上隔离它等)。
软件组件
安装代理时,通常会在此处创建一个目录:
此目录包含代理使用的所有可执行文件、库、配置文件和资源。
S1 在系统上安装代理时注册了 3 个驱动程序:
SentinelDeviceControl
SentinelELAM
SentinelMonitor
在这些驱动程序中,SentinelDeviceControl用于监视系统。更准确地说,它监听发生的事件并向系统提供一个函数,称为回调例程,当它感兴趣的事件发生时(例如创建进程、线程等),该函数将被执行。
微软在这里记录了这个机制:https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/callback-objects
这样做有什么意义呢?通过监视每个新进程或线程,驱动程序可以注入一个 DLL,该 DLL 将负责监视进程对 Windows API 函数的调用。这称为 API挂钩。
例如,如果我们在计算机上启动记事本,我们可以看到两个DLL(kern3l32.dll和ntd1l.dll)注入到进程的虚拟内存空间中。
注入的 DLL 用于监视记事本进程对 Windows API 函数(位于kernel32.dll和ntdll.dll中)的调用。
既然可以用HOOK技术来监控进程的行为,那为什么驱动程序为不直接在内核层使用HOOK而是系统回调呢?
为了能够理解这一点,需要具有操作系统理论的基本知识。为此,这里将介绍 Windows 系统的体系结构
Windows 系统架构
“数字世界的等级社会:内核贵族与用户庶民”
天地玄黄,宇宙洪荒,混沌初开,天地初辟。最初,程序和人类一样,都是一群自由自在的野猴子。
一切程序都是平等的。甚至操作系统盘踞的地方,我们普通人写的程序照样可以过去窥探,甚至修改。
比如在早先的DOS江湖中,有一种叫做TSR的程序,翻译过来就是“终止并驻留内存”的程序。这类程序的招数,就是悄悄地篡改操作系统的中断服务程序。
原本,操作系统就像是大剧院的舞台总监,所有的节目安排、灯光调度、音响控制,统统得通过它来指挥。可TSR程序偏偏不按套路出牌,突然在舞台总监面前架起一副导演椅,喊道:“不必再找总监,我现在来当导演!”
结果,操作系统懵了:“我是谁?我在干嘛?怎么就有人抢了我的导演椅?”它试图叫回手下的工作人员:“喂!我是总监啊!听我的!”但这群人不懂什么是戏剧指挥,谁指挥得响亮,他们就听谁的。
于是乎,任何人都可以随便拉个小凳子过来:“今天这场戏,我来安排!总监?哈,这场戏是我编的,关总监啥事?来,叫声‘导演大人’,我就给你安排个好角色!”
听上去很荒谬吧?但当年的很多程序,都是靠这种“夺权”的方式实现功能的
天子宁有种邪?兵强马壮者为之
再比如,调试程序时,需要在程序里“下断点”。技术上怎么做到的呢?其实CPU已经准备好了,它专门划出了一个3号中断,供调试器使用。如果你是调试器,就大胆地接管这个3号中断吧(所谓“接管”int 3,实质上就是把自己的服务函数的入口指针写进中断向量表中第三个格子)。
当其他程序需要调试时,你只要把目标指令换成`int 3`,程序一旦执行到这里,CPU一看,`int 3`软中断指令来了,立刻触发中断,把程序的控制权交给调试器。
那么,如果我不想自己的软件被别人逆向破解呢?很简单,我也去接管`int 3`,把原先接管的调试器挤走。
就这么乱,这样下去显然不行,必须得好好整顿一下。CPU开发商出手了......
因为要保护中断向量表等关键区域,就必须依赖CPU的支持。如果CPU不支持,那么只要是CPU可访问的区域,任何应用程序都能自由访问。因为在CPU的视角中,操作系统是一组指令,病毒也是一组指令——我如何区分你们?
因此近现代CPU分为几个不同的特权级,一般来说ring 0是最高特权级,CPU启动后最早执行的那个程序天然具有ring 0权限;然后,这个程序负责启动其它程序、并为它们指定权限。
Windows 操作系统仅使用 2 个环:环 0 和环 3,分别对应于内核模式和用户模式。
没错。这就是君(操作系统)权神(CPU)授:它是CPU执行的第一个程序,所以它就是神的代言人,就有最高权限。
当代Windows 操作系统的体系结构,下图如下图所示:
在图中,可以清楚地看到用户模式和内核模式之间的边界。
内核层
那么内核具体干些什么?
主要负责管理硬件资源(如声卡、显卡、网络接口等)并提供关键功能,如内存管理、程序启动和数据管理。
从程序员的角度,内核提供了可以被驱动程序或用户模式应用程序调用的函数(系统服务、例程)。
这些函数的地址存放在系统服务调度表 (SSDT) 中。
每个函数都有一个与之关联的 syscall 标识符,该标识符实际上是 SSDT 表的一个索引。
系统服务调度程序使用此 syscall 将 Windows API 函数调用从用户模式转换为相应的内核函数。
内核挂钩技术
杀软要逮住病毒,就需要监视系统,所以有个最简单粗暴的办法,就是加载一个内核驱动,让这个驱动做一件猥琐的事情:把正常的操作系统代码覆盖掉,改成先跳转到自己的函数里,执行检查、过滤、记录之类的,再跳回去继续执行——这就是所谓的Hook。所以,也有人吐槽“杀软才是最大的病毒”嘛。
NtOpenProcess 函数的 SSDT 挂钩示例:
在这里,恶意软件或 EDR 更改了 SSDT 表中 NtOpenProcess 函数的地址 (或 64 位系统上的偏移量) 。
当用户模式下的应用程序或驱动程序调用此函数时,它将被发送到恶意软件或 EDR 函数的地址。
然后,恶意软件或 EDR 函数执行其操作,然后将流重定向到原始 NtOpenProcess 函数。
内核补丁保护 (Patchguard)?
但由于所有其他程序都依赖于内核,因此内核上最微小的“错误”都可能导致它们崩溃或导致它们的行为不可预测。内核代码中最微小的错误都可能使系统不稳定。
Microsoft为了系统的稳定性,在64位系统中加入了PatchGuard(一个内核保护系统)
有了PatchGuard之后,一旦对被保护的这些系统区域进行了修改并且没有即时还原,就会在定期的扫描中被检测出来,导致计算机蓝屏重启,蓝屏代码 CRITICAL_STRUCTURE_CORRUPTION
所以杀毒在具有PatchGuard的系统中,就如同被拔掉牙的老虎,防护能力大大减弱
PS:腾讯大名鼎鼎的TenProtect,也是在这之后,大不如从前,不过导致蓝屏之类的概率也会同时降低
道高一尺魔高一丈,360搞出了这个核晶引擎,利用VT虚拟化技术的拓展页表,来绕过PatchGuard
日常使用虚拟机时,你可以对虚拟机为所欲为,同样,360将我们使用的系统变成了一个虚拟机
所以它也可以对系统进行各种深度的diy,来完成被PatchGuard阻止的行为,达到原先的保护效果。
但是由于VT技术先天的复杂性和兼容性,当你在一台机器上运行多个虚拟化管理程序(如VMware、Hyper-V、VirtualBox等)时,它们可能会争夺对VT技术的控制权。这是因为VT技术通常只能由一个虚拟化管理程序独占使用。
虽然可以用虚拟化嵌套来解决:虚拟化嵌套允许底层虚拟化软件(如Hyper-V或VMware)将VT-x或AMD-V的特性“传递”给其虚拟机。这样,即使你在物理主机上运行了多个虚拟化软件,嵌套虚拟机也能够继续使用硬件虚拟化功能。
不过
第一,虚拟化嵌套会增加系统的复杂性和资源消耗,导致性能下降。嵌套的虚拟机通常运行得不如直接运行在物理主机上的虚拟机那么高效。
第二,并不是所有虚拟化软件都支持虚拟化嵌套。例如,某些旧版本的VMware或VirtualBox可能不完全支持虚拟化嵌套。宿主和嵌套虚拟机的配置也可能受到限制
所以才有了一系列利用虚拟化文件致盲核晶的Tips
Kernel Callbacks 内核回调
与此同时,微软也提供了微过滤器、过滤驱动、内核回调这些机制,规范Hook行为——你要拦截啥?直接调用这个函数注册一个回调就好;不用了?调用另一个函数把回调取消掉吧。
例如,每当系统上有新进程运行时,注册了PsSetCreateProcessNotifyRoutine的驱动程序会收到通知,并且可以选择执行操作:
阻止进程的启动。
将 DLL 注入其内存空间以执行挂钩。
用户层组件
内核了解完之后,我们再来探寻与内核交互的用户层组件部分
通常,在安装代理后,S1创建了多个服务
Sentinel Agent
SentinelHelperService
SentinelOne Agent Log Processing Service
SentinelOne Static Service
为什么要使用服务?
因为EDR 是由多个程序组成的,它们运行并互相协调以形成一个和谐的整体来监视整个系统。
如果用户每次打开电脑时都必须手动启动所有程序,那十分麻烦,所以都过服务来自启动这些“程序集”
SentinelAgent 和 SentinelHelperService 是“自己的进程”,另外两个(SentinelStaticEngine 和 LogProcessorService)是“共享进程”。
SentinelAgent 服务允许您启动 SentinelAgent.exe 程序,该程序在某种程度上是 EDR 的核心。然后,该程序将调用其他组件(DLL、可执行文件、驱动程序)来检测可能的威胁并在机器上做出反应。
如图所示,SentinelAgent.exe使用另外两个程序:SentinelAgentWorker.exe和SentinelStaticEngineScanner.exe。
“Worker”是向其分配特定任务的程序。完成此任务后,结果将通过回调方法返回到源程序。
SentinelStaticEngine服务管理SentinelStaticEngine.exe的启动,该服务支持下载最新的病毒定义和签名,并调用SentinelStaticEngineScanner.exe。顾名思义,后者负责静态分析。SentinelAgent也可以在需要时调用他。
最后,LogProcessorService 处理 Windows 事件日志的处理。
保护措施
这些服务和进程经常受到攻击,Microsoft引入了“受保护的进程”和“受保护的服务”的概念,以防止用户(甚至是特权用户)与它们交互。
Protected Process
在 Windows 安全模型中,使用包含 SeDebugPrivilege 权限的令牌(例如管理员帐户的令牌)运行的任何进程都可以对计算机上的任何其他进程的任何访问权限。
这使它能够读取或写入其他进程的内存,向其中注入代码,挂起线程,简而言之,可以完全控制它们。
从 Windows Vista 和 Windows Server 2008 开始,Microsoft 引入了受保护的进程。
受保护的进程及其拓展PPL(受保护的轻型进程)在其 EPROCESS 结构中有一个特殊的位,该位修改进程管理器的安全例程的行为,以拒绝最初授予管理员帐户的某些访问权限。
任何应用程序都可以创建受保护的进程。但是,仅当进程的映像已由 Windows Media 证书签名时,操作系统才允许保护进程。
Protected Process Light (PPL)
从 Windows 8.1 和 Windows Server 2012 开始,Microsoft 引入了 PPL 功能,该功能是受保护进程模型的扩展。此新扩展的目标是为受保护进程的访问控制级别带来更精细的度。
PPL 进程的保护方式与“受保护进程”相同,但使用的签名者列表的信任级别从最高 (WinSystem) 到最低 (None) 不等。
以下是与“签名者”关联的保护类型列表。
这种层次结构导致了进程保护的差异。
例如,受 PsProtectedSignerWinSystem 保护的进程将有权访问所有其他进程。
在 S1 的情况下,SentinelAgent.exe 和 SentinelHelperService.exe进程受到保护:
当尝试结束SentinelAgent.exe进程或其中一个子进程时发生的情况,理论上用户(即使是最特权的用户)也不可能终止受保护的进程:
Protected services
因为服务的存在(自启动进程),所以就算你杀死了进程,但这只是暂时的,无论如何它都会重新出现
所以服务也是一个针对的点,正是出于这个原因,Microsoft引入了受保护的服务概念,它是受保护进程模型的一种变体,主要是为了保护反恶意软件服务不被修改(代码注入,启动,停止,激活和禁用)。
换言之,只有由 Microsoft 或防病毒解决方案发布者的证书签名的代码才允许加载到受保护的服务中
为了使反恶意软件服务作为受保护的服务运行,发布者必须在计算机上安装 ELAM 驱动程序。
另外,Microsoft表示,“新的安全模型还允许受恶意软件保护的服务启动受保护的子进程。这些子进程在与父服务相同的保护级别下运行,并且必须使用通过 ELAM 资源部分注册的同一证书对其二进制文件进行签名。
最后,在SERVICE_LAUNCH_PROTECTED_INFO框架中定义了服务的保护级别。
以下是尝试停止 SentinelAgent 服务时发生的情况:
OK,我们对EDR架构的大致解剖到此结束,下一篇文章将介绍如何用EDR先天设计架构的缺陷来绕过它的监视
SentinelOne及其它EDR安装包星球自取
信 安 考 证
CISP、PTE、PTS、DSG、IRE、IRS、NISP、PMP、CCSK、CISSP、ISO27001... |