恶意软件开发者通常会使用各种技巧使分析工作变得更加困难。这些技巧包括使逆向工程复杂化的混淆技巧、逃避沙箱的反沙箱技巧、绕过静态检测的打包技巧等。多年来,各种恶意软件在野外使用的无数欺骗手段都记录了这一点。然而,尽管有许多可用的技巧,但在典型的恶意软件中很少实现这些技巧。

本文就以 Roshtyak 后门为例介绍恶意软件的自保护、杀软逃逸技巧。Raspberry Robin于2021年9月首次被发现,通过受感染的USB设备传播。本文的主题是一个我们称为 Roshtyak 的后门,它不是典型的恶意软件。 Roshtyak 反分析设计很多。有些是众所周知的,有些是我们从未见过的。从技巧角度来看,Roshtyak 的自我保护非常有趣。 Roshtyak 属于我们见过的反分析最成功的的恶意软件之一。我们希望通过发布我们对恶意软件及其保护技巧的研究和分析,帮助其他研究人员识别和应对类似的技巧,并强化他们的分析环境,使他们对所描述的绕过技巧加强防护。

Roshtyak 是 Raspberry Robin 使用的 DLL 后门,一种通过受感染的可移动驱动器传播的蠕虫,Raspberry Robin今年非常流行。

Red Canary 的研究人员于 2022 年 5 月发布了对 Raspberry Robin 的首次分析。6 月,赛门铁克发布了一份报告,描述了一次挖矿/剪贴板劫持操作,据报道,这让攻击者至少赚了170万美元。赛门铁克没有将恶意操作与 Raspberry Robin 联系起来。尽管如此,根据我们的分析,其幕后组织是Raspberry Robin。该评估基于我们分析中观察到的 C&C 重叠、以及很多与其他恶意软件相似性。Cybereason、微软和思科在 2022 年 7 月/8 月发布了进一步的报告。微软报告说,Raspberry Robin 感染导致了 DEV-0243(又名 Evil Corp)勒索行为。虽然我们无法确认此连接。尽管如此,我们仍然有理由相信挖矿软件有效载荷并不是 Raspberry Robin 感染被货币化的唯一方式。最近的其他报道也暗示了 Raspberry Robin 和 Evil Corp 之间可能存在的联系。

1.png

尽管发表了如此多的报道,但关于 Raspberry Robin 仍有许多未知数。恶意软件背后的最终目标是什么?谁负责运营 Raspberry Robin ?它是如何变得如此流行的?不幸的是,我们没有所有这些问题的答案。但是,我们可以回答我们多次看到的一个重要问题:在高度混淆的 DLL(或我们称之为 Roshtyak)中隐藏了哪些功能?为了回答这个问题,我们对 Roshtyak 示例进行了完全逆向工程。

Roshtyak介绍

Roshtyak 包含多达 14 层保护层,每层都经过高度混淆并服务于特定目的。一些工件表明这些层最初是 PE 文件,但被转换为只有以前的层知道如何解密和加载的自定义加密结构。许多反调试器、反沙盒、反虚拟机和反仿真器检查遍布各个层。如果其中一项检查成功检测到分析环境,那么将采取四个操作中的一个。

恶意软件调用自己的TerminateProcess,以避免显示任何进一步的恶意行为,并保持后续层的加密。

Roshtyak是故意撞车的。这与终止自身具有相同的效果,但由于Roshtyak的混淆特性,可能无法立即清楚崩溃是有意的还是因为一个漏洞。

恶意软件故意进入无限循环。由于循环本身位于混淆代码中并且跨越数千条指令,因此可能很难确定循环是否在为攻击做准备。

最有趣的情况是恶意软件通过解包和加载虚假有效负载来绕过成功检查,这发生在第八层,它加载了几十个反分析检查。每个检查的结果都用于修改全局变量的值。在第 8 层的数据段加密了两个有效载荷。真正的第 9 层和伪造的有效载荷,只有在执行所有检查后,全局变量与预期值匹配时,才会解密真正的第九层。如果检测到分析环境,则全局变量的值将与预期值不同,从而导致 Roshtyak 解包并执行虚假有效负载。

2.png

Roshtyak 的混淆导致即使是相对简单的函数也变得很大。如果想在合理的时间范围内对其进行逆向工程,就需要一些自定义的反混淆工具。

虚假有效载荷是一个 BroAssist(又名 BrowserAssistant)广告软件示例。我们认为,这个虚假的有效载荷旨在误导恶意软件分析师认为该示例没有实际情况那么有趣。当逆向工程师专注于快速解包示例时,整个示例可能看起来“只是”一个混淆的广告软件(而且是一个非常古老的广告软件),这可能会导致分析师对深入挖掘失去兴趣。事实证明,这些虚假的有效载荷恶作剧可能非常有效。从下面的屏幕截图中可以看出,它欺骗了至少一名研究人员,该研究人员漏洞地将 Raspberry Robin 蠕虫归因于虚假的 BrowserAssistant 有效载荷。

3.png

这表明,鉴于 Roshtyak 的设计和复杂性,犯这样的漏洞是多么容易。

复杂的混淆技巧

现在让我们直接详细介绍 Roshtyak 采用的一些有趣的规避技巧。

段寄存器

在执行的早期,Roshtyak 更喜欢使用不需要调用任何导入函数的检查。如果其中一项检查成功,则示例可以安静地退出,而不会生成任何可疑的 API 调用。下面是 Roshtyak 检查 gs 段寄存器行为的示例。该检查被设计为隐形的,周围的垃圾指令使其容易被忽视。

4.png

只有带下划线的指令是有用的

此检查背后的第一个想法是检测单个执行。在上面的代码片段之前,cx 的值被初始化为 2。在弹出ecx指令之后,Roshtyak检查cx是否仍然等于2。这将是预期的行为,因为该值应该在正常情况下通过堆栈和 gs 寄存器传播。但是,单个事件会重置 gs 选择器的值,这会导致最后弹出一个不同的值到 ecx 中。

但这项检查还有更多内容。作为上述两个 push/pop 对的副作用,gs 的值暂时更改为 2。在此检查之后,Roshtyak 进入一个循环,计算迭代次数,直到 gs 的值不再是 2。 gs 选择器在线程上下文切换后也会被重置,因此循环本质上是计算迭代次数,直到发生上下文切换。 Roshtyak 多次重复此过程,求出结果的平均值,并检查它是否属于裸机执行环境的合理范围。如果示例在虚拟机管理程序或模拟器中运行,则平均迭代次数可能会超出此范围,这使 Roshtyak 能够检测到不需要的执行环境。

Roshtyak 还检查 cs 段寄存器的值是 0x1b 还是 0x23。此时,0x1b 是在原生 x86 Windows 上运行时的预期值,而 0x23 是在 WoW64 中运行时的预期值。

通过随机 ntdll gadget注入 APC

Roshtyak从独立的进程中执行一些功能。例如,当它与它的C&C服务器通信时,它会生成一个新的看似无害的进程,如regsvr32.exe。通过使用共享段,它将通信模块注入到新进程的地址空间中。被注入的模块通过APC注入执行,使用的是NtQueueApcThreadEx。

有趣的是,ApcRoutine 参数(标记要安排执行的目标例程)并不指向注入模块的入口点。相反,它指向 ntdll 中看似随机的地址。仔细一看,我们发现这个地址不是随机选择的,而是 Roshtyak 扫描了 ntdll 的代码段来查找pop r32;retgadget(不包括pop,因为旋转堆栈是不可取的),并随机选择一个作为ApcRoutine。

5.png

随机弹出 r32; ret gadget 用作 APC 注入的入口点

查看 ApcRoutine 的调用约定可以理解发生了什么。 pop 指令使堆栈指针指向 NtQueueApcThreadEx 的 SystemArgument1 参数,因此 ret 指令有效地跳转到 SystemArgument1 指向的任何位置。这意味着通过滥用这个gadget,Roshtyak 可以将 SystemArgument1 作为 APC 注入的入口点。这混淆了控制流并使 NtQueueApcThreadEx 调用看起来更合法。如果有人挂钩此函数并检查 ApcRoutine 参数,它指向 ntdll 代码段的事实可能足以让他们相信该调用不是恶意的。

检查组合写入内存的读/写性能

在接下来的检查中,Roshtyak 分配一个带有 PAGE_WRITECOMBINE 标志的大内存缓冲区。该标志应该修改缓存行为以优化顺序写入性能,不过这是以读取性能和可能的内存排序为代价的。 Roshtyak 使用它来检测它是否在物理设备上运行。它进行了一项实验,首先写入分配的缓冲区,然后从分配的缓冲区中读取,同时使用一个单独的线程作为计数器来测量读写性能。该实验重复 32 次,只有在大多数情况下写性能至少是读性能的6倍时,才会通过检查。如果检查失败,Roshtyak就会故意选择漏洞的RC4密钥,从而导致无法正确地解密下一层。

隐藏shellcode

有趣的是,注入的 shellcode 也被隐藏了。当 Roshtyak 准备代码注入时,它首先创建一个大段并将其作为 PAGE_READWRITE 映射到当前进程中。然后,它用随机数据填充该段,并将 shellcode 放置在随机数据内的随机偏移处。由于 shellcode 只是一个相对较小的加载器,后面跟着看起来是随机的打包数据,所以整个段看起来像随机数据。

6.png

共享区段内字节的直方图。注意,它看起来几乎是随机的,最可疑的符号是空字节的轻微过度表示。

然后该段从当前进程中取消映射,并映射到目标进程中,在目标进程中使用上述 APC 注入技巧执行该段。添加随机数据是为了隐藏 shellcode 的存在。仅从目标进程的内存转储来看,该段可能看起来充满了随机数据并且不包含任何有效的可执行代码。即使有人怀疑该段中间某处的实际有效代码,也不容易找到它的确切位置。

7.png

共享段中 shellcode 的开始。可能很难确定确切的起始地址,因为它通常是从奇数bt指令开始的。

Ret2Kernel32

Roshtyak特别注意清理自己的攻击痕迹。每当不再需要某个字符串或某段内存时,Roshtyak 就会清除或释放它,以试图清除尽可能多的证据。 Roshtyak 的图层也是如此。每当一层完成其工作时,它就会在将执行传递到下一层之前进行自我释放。但是,该层不能简单直接地自我释放。如果它在当前正在执行的内存区域上调用 VirtualFree,整个进程将会崩溃。

因此,Roshtyak 通过在层转换期间执行的 ROP 链来释放层以避免此问题。当一个层即将退出时,它会在堆栈上构造一个 ROP 链并返回其中。下面可以看到这样一个 ROP 链的示例。该链首先返回 VirtualFree 和 UnmapViewOfFile 以释放上一层的内存。然后,它返回到下一层。下一层的返回地址设置为 RtlExitUserThread,以保障执行安全。

8.png

一个简单的 ROP 链,由 VirtualFree -> UnmapViewOfFile -> next layer -> RtlExitUserThread 组成。

MulDiv漏洞

MulDiv是一个由kernel32.dll导出的函数,它接受三个32位有符号整数作为参数。它将前两个参数相乘,将乘法结果除以第三个参数,并返回最后的结果四舍五入到最接近的整数。虽然这可能看起来是一个足够简单的函数,但在微软的实现中有一个古老的符号扩展漏洞。这个漏洞现在被认为是一个功能,可能永远不会被修复。

Roshtyak 知道该漏洞并通过调用 MulDiv(1, 0x80000000, 0x80000000) 来测试它的存在。在真实的 Windows 设备上,这会触发漏洞并且 MulDiv 漏洞地返回 2,即使正确的返回值应该是 1,因为 (1 * -2147483648) / -2147483648 = 1。这允许 Roshtyak 检测不复制漏洞的模拟器.例如,这成功检测到 Wine,有趣的是,它包含一个不同的漏洞,这使得上述调用返回 0。

篡改存储在堆栈中的返回地址

还有一些用来混淆函数调用的技巧。如上一节所示,Roshtyak喜欢使用ret指令调用函数。下一个技巧与此类似,因为它也操作堆栈,因此可以使用 ret 指令跳转到所需的地址。

为了实现这一点,Roshtyak 扫描当前线程的堆栈,寻找指向前一层代码段的指针,与其他层不同,这一层没有使用 ROP 链技巧释放。它用它想要调用的地址替换所有这些指针。然后它让代码多次返回,直到 ret 指令遇到一个被劫持的指针,将执行重定向到所需的地址。

恶意软件开发者通常会使用各种技巧使分析工作变得更加困难。这些技巧包括使逆向工程复杂化的混淆技巧、逃避沙箱的反沙箱技巧、绕过静态检测的打包技巧等。多年来,各种恶意软件在野外使用的无数欺骗手段都记录了这一点。然而,尽管有许多可用的技巧,但在典型的恶意软件中很少实现这些技巧。

本文就以 Roshtyak 后门为例介绍恶意软件的自保护、杀软逃逸技巧。Raspberry Robin于2021年9月首次被发现,通过受感染的USB设备传播。本文的主题是一个我们称为 Roshtyak 的后门,它不是典型的恶意软件。 Roshtyak 反分析设计很多。有些是众所周知的,有些是我们从未见过的。从技巧角度来看,Roshtyak 的自我保护非常有趣。 Roshtyak 属于我们见过的反分析最成功的的恶意软件之一。我们希望通过发布我们对恶意软件及其保护技巧的研究和分析,帮助其他研究人员识别和应对类似的技巧,并强化他们的分析环境,使他们对所描述的绕过技巧加强防护。

Roshtyak 是 Raspberry Robin 使用的 DLL 后门,一种通过受感染的可移动驱动器传播的蠕虫,Raspberry Robin今年非常流行。

Red Canary 的研究人员于 2022 年 5 月发布了对 Raspberry Robin 的首次分析。6 月,赛门铁克发布了一份报告,描述了一次挖矿/剪贴板劫持操作,据报道,这让攻击者至少赚了170万美元。赛门铁克没有将恶意操作与 Raspberry Robin 联系起来。尽管如此,根据我们的分析,其幕后组织是Raspberry Robin。该评估基于我们分析中观察到的 C&C 重叠、以及很多与其他恶意软件相似性。Cybereason、微软和思科在 2022 年 7 月/8 月发布了进一步的报告。微软报告说,Raspberry Robin 感染导致了 DEV-0243(又名 Evil Corp)勒索行为。虽然我们无法确认此连接。尽管如此,我们仍然有理由相信挖矿软件有效载荷并不是 Raspberry Robin 感染被货币化的唯一方式。最近的其他报道也暗示了 Raspberry Robin 和 Evil Corp 之间可能存在的联系。

1.png

尽管发表了如此多的报道,但关于 Raspberry Robin 仍有许多未知数。恶意软件背后的最终目标是什么?谁负责运营 Raspberry Robin ?它是如何变得如此流行的?不幸的是,我们没有所有这些问题的答案。但是,我们可以回答我们多次看到的一个重要问题:在高度混淆的 DLL(或我们称之为 Roshtyak)中隐藏了哪些功能?为了回答这个问题,我们对 Roshtyak 示例进行了完全逆向工程。

Roshtyak介绍

Roshtyak 包含多达 14 层保护层,每层都经过高度混淆并服务于特定目的。一些工件表明这些层最初是 PE 文件,但被转换为只有以前的层知道如何解密和加载的自定义加密结构。许多反调试器、反沙盒、反虚拟机和反仿真器检查遍布各个层。如果其中一项检查成功检测到分析环境,那么将采取四个操作中的一个。

恶意软件调用自己的TerminateProcess,以避免显示任何进一步的恶意行为,并保持后续层的加密。

Roshtyak是故意撞车的。这与终止自身具有相同的效果,但由于Roshtyak的混淆特性,可能无法立即清楚崩溃是有意的还是因为一个漏洞。

恶意软件故意进入无限循环。由于循环本身位于混淆代码中并且跨越数千条指令,因此可能很难确定循环是否在为攻击做准备。

最有趣的情况是恶意软件通过解包和加载虚假有效负载来绕过成功检查,这发生在第八层,它加载了几十个反分析检查。每个检查的结果都用于修改全局变量的值。在第 8 层的数据段加密了两个有效载荷。真正的第 9 层和伪造的有效载荷,只有在执行所有检查后,全局变量与预期值匹配时,才会解密真正的第九层。如果检测到分析环境,则全局变量的值将与预期值不同,从而导致 Roshtyak 解包并执行虚假有效负载。

2.png

Roshtyak 的混淆导致即使是相对简单的函数也变得很大。如果想在合理的时间范围内对其进行逆向工程,就需要一些自定义的反混淆工具。

虚假有效载荷是一个 BroAssist(又名 BrowserAssistant)广告软件示例。我们认为,这个虚假的有效载荷旨在误导恶意软件分析师认为该示例没有实际情况那么有趣。当逆向工程师专注于快速解包示例时,整个示例可能看起来“只是”一个混淆的广告软件(而且是一个非常古老的广告软件),这可能会导致分析师对深入挖掘失去兴趣。事实证明,这些虚假的有效载荷恶作剧可能非常有效。从下面的屏幕截图中可以看出,它欺骗了至少一名研究人员,该研究人员漏洞地将 Raspberry Robin 蠕虫归因于虚假的 BrowserAssistant 有效载荷。

3.png

这表明,鉴于 Roshtyak 的设计和复杂性,犯这样的漏洞是多么容易。

复杂的混淆技巧

现在让我们直接详细介绍 Roshtyak 采用的一些有趣的规避技巧。

段寄存器

在执行的早期,Roshtyak 更喜欢使用不需要调用任何导入函数的检查。如果其中一项检查成功,则示例可以安静地退出,而不会生成任何可疑的 API 调用。下面是 Roshtyak 检查 gs 段寄存器行为的示例。该检查被设计为隐形的,周围的垃圾指令使其容易被忽视。

4.png

只有带下划线的指令是有用的

此检查背后的第一个想法是检测单个执行。在上面的代码片段之前,cx 的值被初始化为 2。在弹出ecx指令之后,Roshtyak检查cx是否仍然等于2。这将是预期的行为,因为该值应该在正常情况下通过堆栈和 gs 寄存器传播。但是,单个事件会重置 gs 选择器的值,这会导致最后弹出一个不同的值到 ecx 中。

但这项检查还有更多内容。作为上述两个 push/pop 对的副作用,gs 的值暂时更改为 2。在此检查之后,Roshtyak 进入一个循环,计算迭代次数,直到 gs 的值不再是 2。 gs 选择器在线程上下文切换后也会被重置,因此循环本质上是计算迭代次数,直到发生上下文切换。 Roshtyak 多次重复此过程,求出结果的平均值,并检查它是否属于裸机执行环境的合理范围。如果示例在虚拟机管理程序或模拟器中运行,则平均迭代次数可能会超出此范围,这使 Roshtyak 能够检测到不需要的执行环境。

Roshtyak 还检查 cs 段寄存器的值是 0x1b 还是 0x23。此时,0x1b 是在原生 x86 Windows 上运行时的预期值,而 0x23 是在 WoW64 中运行时的预期值。

通过随机 ntdll gadget注入 APC

Roshtyak从独立的进程中执行一些功能。例如,当它与它的C&C服务器通信时,它会生成一个新的看似无害的进程,如regsvr32.exe。通过使用共享段,它将通信模块注入到新进程的地址空间中。被注入的模块通过APC注入执行,使用的是NtQueueApcThreadEx。

有趣的是,ApcRoutine 参数(标记要安排执行的目标例程)并不指向注入模块的入口点。相反,它指向 ntdll 中看似随机的地址。仔细一看,我们发现这个地址不是随机选择的,而是 Roshtyak 扫描了 ntdll 的代码段来查找pop r32;retgadget(不包括pop,因为旋转堆栈是不可取的),并随机选择一个作为ApcRoutine。

5.png

随机弹出 r32; ret gadget 用作 APC 注入的入口点

查看 ApcRoutine 的调用约定可以理解发生了什么。 pop 指令使堆栈指针指向 NtQueueApcThreadEx 的 SystemArgument1 参数,因此 ret 指令有效地跳转到 SystemArgument1 指向的任何位置。这意味着通过滥用这个gadget,Roshtyak 可以将 SystemArgument1 作为 APC 注入的入口点。这混淆了控制流并使 NtQueueApcThreadEx 调用看起来更合法。如果有人挂钩此函数并检查 ApcRoutine 参数,它指向 ntdll 代码段的事实可能足以让他们相信该调用不是恶意的。

检查组合写入内存的读/写性能

在接下来的检查中,Roshtyak 分配一个带有 PAGE_WRITECOMBINE 标志的大内存缓冲区。该标志应该修改缓存行为以优化顺序写入性能,不过这是以读取性能和可能的内存排序为代价的。 Roshtyak 使用它来检测它是否在物理设备上运行。它进行了一项实验,首先写入分配的缓冲区,然后从分配的缓冲区中读取,同时使用一个单独的线程作为计数器来测量读写性能。该实验重复 32 次,只有在大多数情况下写性能至少是读性能的6倍时,才会通过检查。如果检查失败,Roshtyak就会故意选择漏洞的RC4密钥,从而导致无法正确地解密下一层。

隐藏shellcode

有趣的是,注入的 shellcode 也被隐藏了。当 Roshtyak 准备代码注入时,它首先创建一个大段并将其作为 PAGE_READWRITE 映射到当前进程中。然后,它用随机数据填充该段,并将 shellcode 放置在随机数据内的随机偏移处。由于 shellcode 只是一个相对较小的加载器,后面跟着看起来是随机的打包数据,所以整个段看起来像随机数据。

6.png

共享区段内字节的直方图。注意,它看起来几乎是随机的,最可疑的符号是空字节的轻微过度表示。

然后该段从当前进程中取消映射,并映射到目标进程中,在目标进程中使用上述 APC 注入技巧执行该段。添加随机数据是为了隐藏 shellcode 的存在。仅从目标进程的内存转储来看,该段可能看起来充满了随机数据并且不包含任何有效的可执行代码。即使有人怀疑该段中间某处的实际有效代码,也不容易找到它的确切位置。

7.png

共享段中 shellcode 的开始。可能很难确定确切的起始地址,因为它通常是从奇数bt指令开始的。

Ret2Kernel32

Roshtyak特别注意清理自己的攻击痕迹。每当不再需要某个字符串或某段内存时,Roshtyak 就会清除或释放它,以试图清除尽可能多的证据。 Roshtyak 的图层也是如此。每当一层完成其工作时,它就会在将执行传递到下一层之前进行自我释放。但是,该层不能简单直接地自我释放。如果它在当前正在执行的内存区域上调用 VirtualFree,整个进程将会崩溃。

因此,Roshtyak 通过在层转换期间执行的 ROP 链来释放层以避免此问题。当一个层即将退出时,它会在堆栈上构造一个 ROP 链并返回其中。下面可以看到这样一个 ROP 链的示例。该链首先返回 VirtualFree 和 UnmapViewOfFile 以释放上一层的内存。然后,它返回到下一层。下一层的返回地址设置为 RtlExitUserThread,以保障执行安全。

8.png

一个简单的 ROP 链,由 VirtualFree -> UnmapViewOfFile -> next layer -> RtlExitUserThread 组成。

MulDiv漏洞

MulDiv是一个由kernel32.dll导出的函数,它接受三个32位有符号整数作为参数。它将前两个参数相乘,将乘法结果除以第三个参数,并返回最后的结果四舍五入到最接近的整数。虽然这可能看起来是一个足够简单的函数,但在微软的实现中有一个古老的符号扩展漏洞。这个漏洞现在被认为是一个功能,可能永远不会被修复。

Roshtyak 知道该漏洞并通过调用 MulDiv(1, 0x80000000, 0x80000000) 来测试它的存在。在真实的 Windows 设备上,这会触发漏洞并且 MulDiv 漏洞地返回 2,即使正确的返回值应该是 1,因为 (1 * -2147483648) / -2147483648 = 1。这允许 Roshtyak 检测不复制漏洞的模拟器.例如,这成功检测到 Wine,有趣的是,它包含一个不同的漏洞,这使得上述调用返回 0。

篡改存储在堆栈中的返回地址

还有一些用来混淆函数调用的技巧。如上一节所示,Roshtyak喜欢使用ret指令调用函数。下一个技巧与此类似,因为它也操作堆栈,因此可以使用 ret 指令跳转到所需的地址。

为了实现这一点,Roshtyak 扫描当前线程的堆栈,寻找指向前一层代码段的指针,与其他层不同,这一层没有使用 ROP 链技巧释放。它用它想要调用的地址替换所有这些指针。然后它让代码多次返回,直到 ret 指令遇到一个被劫持的指针,将执行重定向到所需的地址。

在这篇文章中,我将介绍我在逆转Office的身份验证机制时发现的两个问题,并提供一些不需要删除内存的POC工具来帮助恢复存储的令牌。

微软账户服务

我必须承认,当我第一次开始研究这个问题时,删除我正在运行的Word进程的内存并没有发现文档签名eyJ0eX。这是当前工具用来识别活动令牌的主要方法,我在Windows登录时使用Microsoft 365帐户。

事实证明,Microsoft Account (MSA)的身份验证令牌处理方式与通常的Azure AD SSO帐户不同。

让我们从查看经过MSA验证的Office会话开始,启动Microsoft Office并查看加载的DLL。其中最突出的是MicrosoftAccountWAMExtension.dll。将这个DLL加载到Ghidra中,我们可以开始寻找为MSA帐户生成身份验证令牌的原因。

如果我们在这个DLL中寻找RPC调用,就可以看到一堆被定向到名为wlidsvc的服务:

1.png

不幸的是,微软并没有为RPC调用此服务提供IDL(或者根本没有提供很多信息),所以我们将不得不做一些逆向工程来解决这个问题。

让我们将WinDBG附加到wlidsc并监视正在进行的RPC调用。在任何Office进程中进行身份验证之后,我们看到第一个调用是RPC方法WLIDCCreateContext以创建上下文,然后是WLIDCAcquireTokensWithNGC,最后是一系列其他调用,我们将暂时忽略这些调用。

如果我们在后一种方法中添加一个断点,那登录到Office中的MSA帐户会导致命中:

2.png

步进式(Stepping )直到我们点击ret并检查填充的参数,在参数12的内存区域中会显示一些有趣的东西。

3.png

对我来说,这确实是一个象征!如果我们打开像Fiddler这样的代理,我们会看到它与Office访问web服务时使用的身份验证令牌格式相匹配:

4.png

那么,我们如何从我们自己的工具中调用它呢?让我们使用James Forshaw的NtObjectManager生成一个可以使用的存根。

5.png

生成的RPC存根根据Windows版本的不同而不同,这是毫无价值的,例如,在Windows 10中,我们发现字段计数在输入结构上发生了变化,因此,如果你收到可怕的(0x800706F7) - The stub received bad data. 错误,请多家留意。

使用RPC客户端存根创建一个快速的C#应用程序,我们将重播我们之前观察到的入站RPC调用,并添加参数,这将给我们提供如下内容:

6.png

如果我们称之为:

7.png

由于这是MSA身份验证请求,我们将不得不使用Substrate等服务来访问Microsoft 365服务。旋转一个代理并在Office中导航是确定调用什么以及这些web服务采用什么参数的最佳方式。但你可以看到,passport令牌返回后,我们可以很好地进行身份验证和交互:

8.png

令牌缓存

现在我们已经了解了如何恢复MSA,那么Azure AD呢?通过Lee Christensen的帖子知道,我们可以很容易地按需请求新令牌,但是我们在Office进程中看到的缓存令牌被转储了,它们是如何在启动时加载的呢?

让我们提供一个新的主机并将我们的用户帐户与AzureAD相关联,然后登录到Office,再尝试找出令牌存储的位置。

9.png

为了确保我们在正确的轨道上,让我们从内存中转储一些字符串,并确保eyJ0eX签名存在。

10.png

我们再次深入搜索dll,但这次我们将重点关注Windows.Security.Authentication.Web.Core.dll。

这是一个WinRT库,因此我们需要深入Ghidra了解正在发生的事情。

AddWebTokenResponseToCache方法如下:

11.png

如果我们进一步研究,会发现此方法实际上负责将凭据缓存到序列化文件,这些文件可以在%LOCALAPPDATA%\Microsoft\TokenBroker\Cache中找到。

12.png

好的,让我们看看这些TBRES文件:

13.png

如果我们使用ProcMon,我们会看到这些文件确实在进程启动时被Office访问:

14.png

可以看到,这就是我们的身份验证信息存储的地方!查看JSON会发现一个IsProtected字段。在WinDBG中,我们将附加到Office,在CryptUnprotectData上添加断点并重新启动。果然,我们发现base64解密数据的内容被解密了。

15.png

JSON文件中我们特别感兴趣的字段是ResponseBytes,我添加了一个带有快速工具的repo,该工具可以解密这些文件,可以在这里找到。

在使用ProtectedData.Unprotect解密此数据后,我们看到了明文JWT。果然,解密它们会得到我们之前从内存中看到的相同信息:

16.png

来自不同提供者和应用程序的其他令牌也存储在这些文件中,包括MSA令牌,这也是毫无价值的。

现在我们知道了,Windows和Office用于Live和Azure的认证和缓存会话的几种不同方法。

POC可以在https://github.com/xpn/WAMBam上找到。

在这篇文章中,我将介绍我在逆转Office的身份验证机制时发现的两个问题,并提供一些不需要删除内存的POC工具来帮助恢复存储的令牌。

微软账户服务

我必须承认,当我第一次开始研究这个问题时,删除我正在运行的Word进程的内存并没有发现文档签名eyJ0eX。这是当前工具用来识别活动令牌的主要方法,我在Windows登录时使用Microsoft 365帐户。

事实证明,Microsoft Account (MSA)的身份验证令牌处理方式与通常的Azure AD SSO帐户不同。

让我们从查看经过MSA验证的Office会话开始,启动Microsoft Office并查看加载的DLL。其中最突出的是MicrosoftAccountWAMExtension.dll。将这个DLL加载到Ghidra中,我们可以开始寻找为MSA帐户生成身份验证令牌的原因。

如果我们在这个DLL中寻找RPC调用,就可以看到一堆被定向到名为wlidsvc的服务:

1.png

不幸的是,微软并没有为RPC调用此服务提供IDL(或者根本没有提供很多信息),所以我们将不得不做一些逆向工程来解决这个问题。

让我们将WinDBG附加到wlidsc并监视正在进行的RPC调用。在任何Office进程中进行身份验证之后,我们看到第一个调用是RPC方法WLIDCCreateContext以创建上下文,然后是WLIDCAcquireTokensWithNGC,最后是一系列其他调用,我们将暂时忽略这些调用。

如果我们在后一种方法中添加一个断点,那登录到Office中的MSA帐户会导致命中:

2.png

步进式(Stepping )直到我们点击ret并检查填充的参数,在参数12的内存区域中会显示一些有趣的东西。

3.png

对我来说,这确实是一个象征!如果我们打开像Fiddler这样的代理,我们会看到它与Office访问web服务时使用的身份验证令牌格式相匹配:

4.png

那么,我们如何从我们自己的工具中调用它呢?让我们使用James Forshaw的NtObjectManager生成一个可以使用的存根。

5.png

生成的RPC存根根据Windows版本的不同而不同,这是毫无价值的,例如,在Windows 10中,我们发现字段计数在输入结构上发生了变化,因此,如果你收到可怕的(0x800706F7) - The stub received bad data. 错误,请多家留意。

使用RPC客户端存根创建一个快速的C#应用程序,我们将重播我们之前观察到的入站RPC调用,并添加参数,这将给我们提供如下内容:

6.png

如果我们称之为:

7.png

由于这是MSA身份验证请求,我们将不得不使用Substrate等服务来访问Microsoft 365服务。旋转一个代理并在Office中导航是确定调用什么以及这些web服务采用什么参数的最佳方式。但你可以看到,passport令牌返回后,我们可以很好地进行身份验证和交互:

8.png

令牌缓存

现在我们已经了解了如何恢复MSA,那么Azure AD呢?通过Lee Christensen的帖子知道,我们可以很容易地按需请求新令牌,但是我们在Office进程中看到的缓存令牌被转储了,它们是如何在启动时加载的呢?

让我们提供一个新的主机并将我们的用户帐户与AzureAD相关联,然后登录到Office,再尝试找出令牌存储的位置。

9.png

为了确保我们在正确的轨道上,让我们从内存中转储一些字符串,并确保eyJ0eX签名存在。

10.png

我们再次深入搜索dll,但这次我们将重点关注Windows.Security.Authentication.Web.Core.dll。

这是一个WinRT库,因此我们需要深入Ghidra了解正在发生的事情。

AddWebTokenResponseToCache方法如下:

11.png

如果我们进一步研究,会发现此方法实际上负责将凭据缓存到序列化文件,这些文件可以在%LOCALAPPDATA%\Microsoft\TokenBroker\Cache中找到。

12.png

好的,让我们看看这些TBRES文件:

13.png

如果我们使用ProcMon,我们会看到这些文件确实在进程启动时被Office访问:

14.png

可以看到,这就是我们的身份验证信息存储的地方!查看JSON会发现一个IsProtected字段。在WinDBG中,我们将附加到Office,在CryptUnprotectData上添加断点并重新启动。果然,我们发现base64解密数据的内容被解密了。

15.png

JSON文件中我们特别感兴趣的字段是ResponseBytes,我添加了一个带有快速工具的repo,该工具可以解密这些文件,可以在这里找到。

在使用ProtectedData.Unprotect解密此数据后,我们看到了明文JWT。果然,解密它们会得到我们之前从内存中看到的相同信息:

16.png

来自不同提供者和应用程序的其他令牌也存储在这些文件中,包括MSA令牌,这也是毫无价值的。

现在我们知道了,Windows和Office用于Live和Azure的认证和缓存会话的几种不同方法。

POC可以在https://github.com/xpn/WAMBam上找到。

下面的伪代码或多或少地展示了SmartLocker非继承属性的最后一部分是如何工作的。

12.png

注意: 根据稍后如何使用此函数中的值来填充TraceLogging字符串,我们知道防御措施将评估过程的所有这一部分视为: Is防御措施Shell。

这或多或少就是我们通过在调用之后立即双击从资源管理器启动的进程所需要的:

13.png

CipCheckSmartlockerEAandProcessToken的情况就这样了,现在再说说CipExternalAuthorizationCallback。

现在,让我们说说Intelligent Security Graph所使用的代码段,它现在已被扩展以添加一些SAC功能。首先,将再次检查策略选项Intelligent Security Graph Authorization(智能安全图授权),如果未设置,函数将使用从CipCheckSmartlockerEAandProcessToken获取的值退出。如果该值在策略中处于活动状态(SAC策略就是这种情况),该函数将使用前面讨论的IsTrustedSigning来确定它是否应该继续。如果映像可信,将执行以下检查:

如果ValidatedSigningLevel等于“由使用AMPPL(7)的产品的AV签名”,并且策略的值为VerifiedAndReputableAllowAntiMalware,则分数将用值AllowAnti Malware(0x100000)进行异或运算,函数将返回。

如果映像不可信,则函数将继续查询防御措施。如上所述,向防御措施发出查询的函数是CiCatDbSmartlockerDefenderCheck。此函数将接收两个MPFILE_TRUST_EXTRA_INFO结构,一个填充请求数据,另一个接收回复数据。代码还将从FileObject传递FileName。MPFILE_TRUST_EXTRA_INFO结构如下所示。

14.png

双方之间的通信是使用RPC实现的,CI.dll将实现客户端,服务器将在cryptcatsvc.dll中实现。为了记录,RPC存根的IID是f50aac00-c7f3-428e-a022a6b71bfb9d43。

cryptcatsvc在服务CryptSvc中运行。在用于RPC服务器的发送函数中,我们重点关注以下函数:

s_SSCatDBSmartlockerDefenderCheck (Already present in 22H1);s_SSCatDBSmartlockerDefenderCheck2 (New to 22H2);s_SSCatDBSendSmartAppControlBlockToast;s_SSCatDBSendSmartAppControlSwitchEnforceToast;

SmartLockerDefenderCheck函数的v1和v2之间的最大区别在于,在v2中,该函数接受请求和回复MPFILE_TRUST_EXTRA_INFO作为其参数的一部分。这两个函数最终都调用了助手函数CatDBSmartlockerDefenderCheckHelper。

CI将从这些函数调用s_SSCatDBSmartlockerDefenderCheck2,它将首先加载MpClient.dll。

注意:在第一次执行时,将在防御措施配置中启用SmartLocker。该函数将调用MpClient导出的函数MpSmartLockerEnable。此函数只需注册Defender ELAM证书信息(打开Wdboot.sys的句柄并调用InstallELAMCertificateInfo),然后使用RPC从MpSvc.dll调用方法ServerMpEnableSmartLocker,它将检查防御措施配置中是否设置了SmartLockerMode,如果没有,它将写入。

打开库的句柄后,该函数将使用CI.dll提供的文件名来打开一个文件句柄,该句柄将被传递给MpClient导出的函数MpQueryFileTrustByHandle2,该函数只在来自于DefenderCheck2时被调用,如果是旧版本的DefenderCheck,则将调用MpQueryFileTrustByHandle。

在MpQueryFileTrustByHandle2内部,代码将使用该文件的句柄来创建文件映射,该文件映射将被防御程序用于对其进行内存扫描。下面的InSequence函数将通过从MpClient(客户端)到MpSvc(服务器)发出RPC调用来执行。显然,我们刚才看到的所有函数调用都接受CI.dll设置的MPFILE_TRUST_EXTRA_INFO作为参数的一部分。

ServerMpRpcMemoryScanStart:设置CMpMemScanContext和CMpMemScanEngineVfz(使用GetAttributeTrustCheck作为GetAttributions函数),并进行异步扫描;

ServerMpRpcMemoryScanQueryNotification:检索扫描信息;

ServerMpRpcMemoryScanClose:关闭并清除CMpMemScanContext。

这些函数的内部结构不在本文所讲的范围,我想强调的是,当启用SAC时,防御措施将主动扫描文件并进行云查询。

从扫描检索到的信息中有三个可能的信号:

0x31001:检索到的MPTRUST_INFO(IGS);

0x31002:检索到的MPFILE_TRUST_EXTRA_INFO(SAC);

0x4005:与RSIG_VIRINFO相关;

最后完成防御措施通信,下图显示了代码到达防御措施时客户端(CI)和服务器(cryptcatsvc)堆栈。

15.png

需要注意的是,如果我们的SAC处于强制状态,并且设备中没有互联网连接,则默认操作是阻止该进程,并且将显示一条通知,提示“智能应用程序控制无法验证此应用程序,请检查您的互联网连接,然后重试”。

返回外部授权回调,如果RPC调用失败,则未设置策略设置VerifiedAndReputableAllowUnknown,并且ValidateSigningLevel不是以下任何一项:

Microsoft Store signed app PPL (Protected Process Light)Microsoft Store-signedMicrosoft signedWindows signedOnly used for signing of the .NET NGEN compilerWindows Trusted Computing Base signed

然后将验证分数与值Unattainable(0x40000)进行异或运算,函数将返回。如果RPC调用成功,则将调用函数CiHandleDefenderSignals。顾名思义,此函数将处理防御措施发送回的消息。它将遍历返回的元素数,其中每个元素的类型为MPFILE_TRUST_EXTRA_INFO。根据ReplyType字段,它将执行不同的操作。更有趣的两种情况是:首先,当返回信任结果时。在该示例中,信息将指向MP_INFO_RESULT,其中的值将复制到验证上下文:

16.png

第二个有趣的示例是信息指向MP_NW_CONTROL枚举。在该示例中,根据控制命令,该功能将被禁用或切换到强制模式。这基本上将更新VerifiedAndReputablePolicyState RegKey,并更新WorkItem中的策略。

17.png

在我们从学习模式更改为强制模式的情况下,将发出对函数s_SSCatDBSendSmartAppControlSwitchEnforceToast的RPC调用。在此函数中,DLL wldap . DLL将被加载,然后调用函数WldpSendSmartAppControlSwitchEnforceToast。

从信号处理程序回来后,有一些细微差别。如果NW控制命令设置了标志IsUnfriendlyFile,则Score将更新为值UnfriendalyFile(0x80000),函数将返回。如果未设置标志,则TrustInfo和FileObject将被传递到带有标志0x82的函数CipSetFileCache中,这意味着EA $Kernel.Purge.CIpCache将用于存储此信息。

最后,需要根据防御程序返回的信任调整分数,有5个选项:

Trust == 1:分数将使用值0x202进行异或运算,不过我对这个值不太了解;

Trust == -1 (0xFFFFFFFF):如果策略设置VerifiedAndReputableAllowUnknown被设置,则分数将使用值AllowUnderknown(0x20000)进行异或运算;

Trust == -2 (0xFFFFFFFE):分数将使用值Malicious (0x80)进行异或运算;

Trust == -3 (0xFFFFFFFD):分数将用PUA(0x100)值进行异或运算;

任何其他情况下,分数将用值0x42进行异或运算。

这几乎就是外部授权回调的全部内容,现在我们回到调用外部授权回调时的SIPolicyValidateImageInternal!

SIPolicyValidateImageInternal

在进入外部授权回调之前,我们将讨论SIPolicyObjectValidationEngine函数如何遍历策略并调用内部SIPolicy ValidateImageInternal,后者稍后将调用外部auth回调。现在,调用回调后,我们返回到SIPolicyValidateImageInternal,并返回验证分数。如果启用了SAC,则该函数将继续评估分数,并将此分数传播到验证引擎分数,并根据该得分设置相应的NTSTATUS。

18.png

如上图所示,在大多数分支中,它会将相应的NTSTATUS设置为验证状态,然后跳转到我所称为ProcessDbgAndReprieve的状态。这只不过是一种检查内核调试器是否附加到调试器控制台中以记录策略冲突的方法。

19.png

如果未遵循前一个映像中的任何分支,或者分数为Unattainable但设置了AllowUnknown,则函数将继续根据策略规范评估对象。首先检查文件规范,这将在函数SIPolicyMatchFileRules内完成。此函数将接收以下参数:

具有要评估的文件规范的策略;

OriginalFileName;InternalName;FileDescription;ProductName;

我强烈建议阅读MSDN的“理解Windows防御应用程序控制(WDAC)策略规范和文件规范”一节,以了解更多关于策略规范和可用于它们的不同选项的内容。

与我们在第1部分中看到的Policy Secure Settings类似,该函数将使用作为key传递到函数bsearch的数据建立一个结构。关键结构具有以下原型:

20.png

bsearch函数的base和num将取自SI_POLICY结构。将策略解析为SI_policy结构时,将设置一个包含两个场景的数组。每个场景都包含其特定的文件规范、允许的签名者、拒绝的签名者和异常规范。如上所述,当调用SIPolicyMatchFileRules时,要评估的场景的特定数量被传递给函数。此数字将用作函数的索引,以了解要选取Scenarios数组的哪个元素。每个场景都由以下结构表示:

21.png

如果没有FileName级别的文件规范匹配,则函数将继续计算哈希级别的文件规范:

22.png

如果FileName或Hash匹配,则SIPolicyMatchFileRules返回TRUE,验证状态将设置为status_SYSTEM_INTEGRITY_POLICY_VIOLATION。

如果对SAC策略使用的哈希和文件名感兴趣,可以查看策略的FileRule标签下的整个列表。

如果没有匹配的文件规范,则下一步(如果映像已签名)是根据“拒绝”和“允许”签名者验证签名链信息。首先,将检查被拒绝的签名者。如果与前面相同的规范在此匹配,该函数将把验证状态设置为status_system_integrity_policy_violate。如果没有拒绝签名者规范匹配,代码将继续检查允许的签名者规范。在该示例中,如果存在匹配,则会清除以前的任何状态/分数。根据策略签名验证映像签名的过程主要在函数SIPolicyValidateChainAgainstSigner中完成。此函数将作为第一个参数接收映像的SI_CHAIN_INFO,并在@r8中接收POLICY_SIGNERS_DATA。

关于这个POLICY_SIGNERS_DATA结构,基本上SI_POLICY结构保留一个POLICY-SIGNERS_DATA数组。这些代表两种方案的所有Allow和Deny签名。代码知道哪些规范适用于哪个场景的方式,这意味着要使用POLICY_SIGNERS_DATA数组的哪个索引是非常聪明的。这是我之前在文件规范中没有解释的事情,所以现在是检查它的好时机。如果你返回并检查SI_POLICY_SCENARIO结构,将看到对于每个规范类型结构(file, Allow, Deny),都有一个SI_RULES结构,其中包含一个我称为IndexArray的字段。基本上,这是一个索引数组,用于指示该特定场景和规则必须使用包含数据的数组中的哪个索引。让我们看一个快速的伪代码片段,以便更好地理解这一点。

23.png

这可能不是百分之百准确的,因为我省略了很多在中间进行的检查。

为了更好地了解签名是如何验证的,接下来你可以找到POLICY_SIGNERS_DATA的原型,注意,这将适用于允许签名者和拒绝签名者。

24.png

通过查看SI_CHAIN_INFO和POLICY_SIGNERS_DATA,你可以或多或少地了解如何在SIPolicyValidateChainAgainstSigner函数中进行比较。最后,为了总结Signer规范的验证,下面是在SIPolicyValidateChainAgainstSigner条目处使用SAC强制策略验证ProcessHacker时记录的映像。

25.png

老实说,为了达到这张图片的目的,我不得不稍微修改代码流。因为在第一次签名检查时,Type将匹配,然后它将退出循环。之所以会实现这一点,是因为这个POLICY_SIGNERS_DATA中的信息比第一个检查的要多。在第一次选中时,唯一的填充值是Type(设置为0x14)。我已尝试查找有关此Type值的信息,但找不到任何信息。

因此,在为每个活动策略和补充策略运行整个过程之后,我们将返回函数CipApplySiPolicyEx,为每个BasePolicy提供一个CI_VALIDATION_RESULT。补充策略的结果将写入与BasePolicy相同的CI_VALIDATION_RESULT中。此时,该函数只会遍历验证结果,将这些结果存储在validation Context中。此外,此时SmartLocker事件将记录在函数CiLogSIPolicySmartlockerEvent中。此处可以记录四种类型的事件:

SmartlockerOperationalAudit (EventId: 3091)SmartlockerOperationalFailure (EventId: 3092)SmartlockerVerbose (EventId: 3088)SmartlockerOperationalSuccess (EventId: 3090)

26.png

我们几乎完成了,现在将进入调用堆栈,将验证状态传递到上面的函数。最后,我们将回到CI入口点CiValidateImageHeader,与之前一样,我们不会对这个函数进行过多讨论。关于SAC唯一有趣的一点是,如果SigningLevel匹配以下任何一项:

尚未检查签名级别;

文件未签名;

受Windows防御措施应用程序控制策略信任;

开发者签名代码;

SAC结果是允许执行,然后将使用函数CipInstrumentNightsWatchAllow记录操作。此函数可以为提供程序CodeIntegrity编写四个基于TraceLogging的事件。具有以下名称的NWActivityVerbose & CodeIntegrity.NWActivity。

27.png

执行此函数时,将记录QuestionableAllow或Allow。如果采用了记录QuestionableAllow的路径,那么如果所需数据可用,还将写入QuestionaleAllowSignatureInfo&OriginClaimData。

由于这些是基于跟踪日志记录的事件,我们需要使用一些特殊办法来捕获跟踪。值得庆幸的是,Matt已经做了所有艰苦的工作来研究和记录这类事件的过程。看了他的文章《Windows RE使用WPP和TraceLogging》后,我们可以使用powershell中的以下4行代码来启动ETW会话,该会话将捕获NWActivity和NWActovityVerbose提供程序。

28.png

开始跟踪并使用一些应用程序/安装程序后,你应该有一个可以用EventViewer打开的EventLog,你可以发现防御措施最终信任ProcessHacker之类的事情。

29.png

总结

就个人而言,我认为微软为提高操作系统的安全性而采取的措施是很好的,其最终目标是让用户更加安全。另一方面,我确实看到了SAC和Windows 10 S之间的一些相似之处。对于SAC,当设置为强制时,限制由具有数字签名的应用程序设置,如果没有签名,则由防御措施云认为可信的应用程序进行设置。

第一种选择,即使你知道数字签名可以很好地验证应用程序,许多开源项目或自由开发者负担不起,不幸的是,这给开发者带来了一些限制。

第二个选项,即对“智能云安全服务”的查询,这也是我希望微软提供更多信息的地方,因为基本上应用程序能否运行的决定将完全取决于微软。

下面的伪代码或多或少地展示了SmartLocker非继承属性的最后一部分是如何工作的。

12.png

注意: 根据稍后如何使用此函数中的值来填充TraceLogging字符串,我们知道防御措施将评估过程的所有这一部分视为: Is防御措施Shell。

这或多或少就是我们通过在调用之后立即双击从资源管理器启动的进程所需要的:

13.png

CipCheckSmartlockerEAandProcessToken的情况就这样了,现在再说说CipExternalAuthorizationCallback。

现在,让我们说说Intelligent Security Graph所使用的代码段,它现在已被扩展以添加一些SAC功能。首先,将再次检查策略选项Intelligent Security Graph Authorization(智能安全图授权),如果未设置,函数将使用从CipCheckSmartlockerEAandProcessToken获取的值退出。如果该值在策略中处于活动状态(SAC策略就是这种情况),该函数将使用前面讨论的IsTrustedSigning来确定它是否应该继续。如果映像可信,将执行以下检查:

如果ValidatedSigningLevel等于“由使用AMPPL(7)的产品的AV签名”,并且策略的值为VerifiedAndReputableAllowAntiMalware,则分数将用值AllowAnti Malware(0x100000)进行异或运算,函数将返回。

如果映像不可信,则函数将继续查询防御措施。如上所述,向防御措施发出查询的函数是CiCatDbSmartlockerDefenderCheck。此函数将接收两个MPFILE_TRUST_EXTRA_INFO结构,一个填充请求数据,另一个接收回复数据。代码还将从FileObject传递FileName。MPFILE_TRUST_EXTRA_INFO结构如下所示。

14.png

双方之间的通信是使用RPC实现的,CI.dll将实现客户端,服务器将在cryptcatsvc.dll中实现。为了记录,RPC存根的IID是f50aac00-c7f3-428e-a022a6b71bfb9d43。

cryptcatsvc在服务CryptSvc中运行。在用于RPC服务器的发送函数中,我们重点关注以下函数:

s_SSCatDBSmartlockerDefenderCheck (Already present in 22H1);s_SSCatDBSmartlockerDefenderCheck2 (New to 22H2);s_SSCatDBSendSmartAppControlBlockToast;s_SSCatDBSendSmartAppControlSwitchEnforceToast;

SmartLockerDefenderCheck函数的v1和v2之间的最大区别在于,在v2中,该函数接受请求和回复MPFILE_TRUST_EXTRA_INFO作为其参数的一部分。这两个函数最终都调用了助手函数CatDBSmartlockerDefenderCheckHelper。

CI将从这些函数调用s_SSCatDBSmartlockerDefenderCheck2,它将首先加载MpClient.dll。

注意:在第一次执行时,将在防御措施配置中启用SmartLocker。该函数将调用MpClient导出的函数MpSmartLockerEnable。此函数只需注册Defender ELAM证书信息(打开Wdboot.sys的句柄并调用InstallELAMCertificateInfo),然后使用RPC从MpSvc.dll调用方法ServerMpEnableSmartLocker,它将检查防御措施配置中是否设置了SmartLockerMode,如果没有,它将写入。

打开库的句柄后,该函数将使用CI.dll提供的文件名来打开一个文件句柄,该句柄将被传递给MpClient导出的函数MpQueryFileTrustByHandle2,该函数只在来自于DefenderCheck2时被调用,如果是旧版本的DefenderCheck,则将调用MpQueryFileTrustByHandle。

在MpQueryFileTrustByHandle2内部,代码将使用该文件的句柄来创建文件映射,该文件映射将被防御程序用于对其进行内存扫描。下面的InSequence函数将通过从MpClient(客户端)到MpSvc(服务器)发出RPC调用来执行。显然,我们刚才看到的所有函数调用都接受CI.dll设置的MPFILE_TRUST_EXTRA_INFO作为参数的一部分。

ServerMpRpcMemoryScanStart:设置CMpMemScanContext和CMpMemScanEngineVfz(使用GetAttributeTrustCheck作为GetAttributions函数),并进行异步扫描;

ServerMpRpcMemoryScanQueryNotification:检索扫描信息;

ServerMpRpcMemoryScanClose:关闭并清除CMpMemScanContext。

这些函数的内部结构不在本文所讲的范围,我想强调的是,当启用SAC时,防御措施将主动扫描文件并进行云查询。

从扫描检索到的信息中有三个可能的信号:

0x31001:检索到的MPTRUST_INFO(IGS);

0x31002:检索到的MPFILE_TRUST_EXTRA_INFO(SAC);

0x4005:与RSIG_VIRINFO相关;

最后完成防御措施通信,下图显示了代码到达防御措施时客户端(CI)和服务器(cryptcatsvc)堆栈。

15.png

需要注意的是,如果我们的SAC处于强制状态,并且设备中没有互联网连接,则默认操作是阻止该进程,并且将显示一条通知,提示“智能应用程序控制无法验证此应用程序,请检查您的互联网连接,然后重试”。

返回外部授权回调,如果RPC调用失败,则未设置策略设置VerifiedAndReputableAllowUnknown,并且ValidateSigningLevel不是以下任何一项:

Microsoft Store signed app PPL (Protected Process Light)Microsoft Store-signedMicrosoft signedWindows signedOnly used for signing of the .NET NGEN compilerWindows Trusted Computing Base signed

然后将验证分数与值Unattainable(0x40000)进行异或运算,函数将返回。如果RPC调用成功,则将调用函数CiHandleDefenderSignals。顾名思义,此函数将处理防御措施发送回的消息。它将遍历返回的元素数,其中每个元素的类型为MPFILE_TRUST_EXTRA_INFO。根据ReplyType字段,它将执行不同的操作。更有趣的两种情况是:首先,当返回信任结果时。在该示例中,信息将指向MP_INFO_RESULT,其中的值将复制到验证上下文:

16.png

第二个有趣的示例是信息指向MP_NW_CONTROL枚举。在该示例中,根据控制命令,该功能将被禁用或切换到强制模式。这基本上将更新VerifiedAndReputablePolicyState RegKey,并更新WorkItem中的策略。

17.png

在我们从学习模式更改为强制模式的情况下,将发出对函数s_SSCatDBSendSmartAppControlSwitchEnforceToast的RPC调用。在此函数中,DLL wldap . DLL将被加载,然后调用函数WldpSendSmartAppControlSwitchEnforceToast。

从信号处理程序回来后,有一些细微差别。如果NW控制命令设置了标志IsUnfriendlyFile,则Score将更新为值UnfriendalyFile(0x80000),函数将返回。如果未设置标志,则TrustInfo和FileObject将被传递到带有标志0x82的函数CipSetFileCache中,这意味着EA $Kernel.Purge.CIpCache将用于存储此信息。

最后,需要根据防御程序返回的信任调整分数,有5个选项:

Trust == 1:分数将使用值0x202进行异或运算,不过我对这个值不太了解;

Trust == -1 (0xFFFFFFFF):如果策略设置VerifiedAndReputableAllowUnknown被设置,则分数将使用值AllowUnderknown(0x20000)进行异或运算;

Trust == -2 (0xFFFFFFFE):分数将使用值Malicious (0x80)进行异或运算;

Trust == -3 (0xFFFFFFFD):分数将用PUA(0x100)值进行异或运算;

任何其他情况下,分数将用值0x42进行异或运算。

这几乎就是外部授权回调的全部内容,现在我们回到调用外部授权回调时的SIPolicyValidateImageInternal!

SIPolicyValidateImageInternal

在进入外部授权回调之前,我们将讨论SIPolicyObjectValidationEngine函数如何遍历策略并调用内部SIPolicy ValidateImageInternal,后者稍后将调用外部auth回调。现在,调用回调后,我们返回到SIPolicyValidateImageInternal,并返回验证分数。如果启用了SAC,则该函数将继续评估分数,并将此分数传播到验证引擎分数,并根据该得分设置相应的NTSTATUS。

18.png

如上图所示,在大多数分支中,它会将相应的NTSTATUS设置为验证状态,然后跳转到我所称为ProcessDbgAndReprieve的状态。这只不过是一种检查内核调试器是否附加到调试器控制台中以记录策略冲突的方法。

19.png

如果未遵循前一个映像中的任何分支,或者分数为Unattainable但设置了AllowUnknown,则函数将继续根据策略规范评估对象。首先检查文件规范,这将在函数SIPolicyMatchFileRules内完成。此函数将接收以下参数:

具有要评估的文件规范的策略;

OriginalFileName;InternalName;FileDescription;ProductName;

我强烈建议阅读MSDN的“理解Windows防御应用程序控制(WDAC)策略规范和文件规范”一节,以了解更多关于策略规范和可用于它们的不同选项的内容。

与我们在第1部分中看到的Policy Secure Settings类似,该函数将使用作为key传递到函数bsearch的数据建立一个结构。关键结构具有以下原型:

20.png

bsearch函数的base和num将取自SI_POLICY结构。将策略解析为SI_policy结构时,将设置一个包含两个场景的数组。每个场景都包含其特定的文件规范、允许的签名者、拒绝的签名者和异常规范。如上所述,当调用SIPolicyMatchFileRules时,要评估的场景的特定数量被传递给函数。此数字将用作函数的索引,以了解要选取Scenarios数组的哪个元素。每个场景都由以下结构表示:

21.png

如果没有FileName级别的文件规范匹配,则函数将继续计算哈希级别的文件规范:

22.png

如果FileName或Hash匹配,则SIPolicyMatchFileRules返回TRUE,验证状态将设置为status_SYSTEM_INTEGRITY_POLICY_VIOLATION。

如果对SAC策略使用的哈希和文件名感兴趣,可以查看策略的FileRule标签下的整个列表。

如果没有匹配的文件规范,则下一步(如果映像已签名)是根据“拒绝”和“允许”签名者验证签名链信息。首先,将检查被拒绝的签名者。如果与前面相同的规范在此匹配,该函数将把验证状态设置为status_system_integrity_policy_violate。如果没有拒绝签名者规范匹配,代码将继续检查允许的签名者规范。在该示例中,如果存在匹配,则会清除以前的任何状态/分数。根据策略签名验证映像签名的过程主要在函数SIPolicyValidateChainAgainstSigner中完成。此函数将作为第一个参数接收映像的SI_CHAIN_INFO,并在@r8中接收POLICY_SIGNERS_DATA。

关于这个POLICY_SIGNERS_DATA结构,基本上SI_POLICY结构保留一个POLICY-SIGNERS_DATA数组。这些代表两种方案的所有Allow和Deny签名。代码知道哪些规范适用于哪个场景的方式,这意味着要使用POLICY_SIGNERS_DATA数组的哪个索引是非常聪明的。这是我之前在文件规范中没有解释的事情,所以现在是检查它的好时机。如果你返回并检查SI_POLICY_SCENARIO结构,将看到对于每个规范类型结构(file, Allow, Deny),都有一个SI_RULES结构,其中包含一个我称为IndexArray的字段。基本上,这是一个索引数组,用于指示该特定场景和规则必须使用包含数据的数组中的哪个索引。让我们看一个快速的伪代码片段,以便更好地理解这一点。

23.png

这可能不是百分之百准确的,因为我省略了很多在中间进行的检查。

为了更好地了解签名是如何验证的,接下来你可以找到POLICY_SIGNERS_DATA的原型,注意,这将适用于允许签名者和拒绝签名者。

24.png

通过查看SI_CHAIN_INFO和POLICY_SIGNERS_DATA,你可以或多或少地了解如何在SIPolicyValidateChainAgainstSigner函数中进行比较。最后,为了总结Signer规范的验证,下面是在SIPolicyValidateChainAgainstSigner条目处使用SAC强制策略验证ProcessHacker时记录的映像。

25.png

老实说,为了达到这张图片的目的,我不得不稍微修改代码流。因为在第一次签名检查时,Type将匹配,然后它将退出循环。之所以会实现这一点,是因为这个POLICY_SIGNERS_DATA中的信息比第一个检查的要多。在第一次选中时,唯一的填充值是Type(设置为0x14)。我已尝试查找有关此Type值的信息,但找不到任何信息。

因此,在为每个活动策略和补充策略运行整个过程之后,我们将返回函数CipApplySiPolicyEx,为每个BasePolicy提供一个CI_VALIDATION_RESULT。补充策略的结果将写入与BasePolicy相同的CI_VALIDATION_RESULT中。此时,该函数只会遍历验证结果,将这些结果存储在validation Context中。此外,此时SmartLocker事件将记录在函数CiLogSIPolicySmartlockerEvent中。此处可以记录四种类型的事件:

SmartlockerOperationalAudit (EventId: 3091)SmartlockerOperationalFailure (EventId: 3092)SmartlockerVerbose (EventId: 3088)SmartlockerOperationalSuccess (EventId: 3090)

26.png

我们几乎完成了,现在将进入调用堆栈,将验证状态传递到上面的函数。最后,我们将回到CI入口点CiValidateImageHeader,与之前一样,我们不会对这个函数进行过多讨论。关于SAC唯一有趣的一点是,如果SigningLevel匹配以下任何一项:

尚未检查签名级别;

文件未签名;

受Windows防御措施应用程序控制策略信任;

开发者签名代码;

SAC结果是允许执行,然后将使用函数CipInstrumentNightsWatchAllow记录操作。此函数可以为提供程序CodeIntegrity编写四个基于TraceLogging的事件。具有以下名称的NWActivityVerbose & CodeIntegrity.NWActivity。

27.png

执行此函数时,将记录QuestionableAllow或Allow。如果采用了记录QuestionableAllow的路径,那么如果所需数据可用,还将写入QuestionaleAllowSignatureInfo&OriginClaimData。

由于这些是基于跟踪日志记录的事件,我们需要使用一些特殊办法来捕获跟踪。值得庆幸的是,Matt已经做了所有艰苦的工作来研究和记录这类事件的过程。看了他的文章《Windows RE使用WPP和TraceLogging》后,我们可以使用powershell中的以下4行代码来启动ETW会话,该会话将捕获NWActivity和NWActovityVerbose提供程序。

28.png

开始跟踪并使用一些应用程序/安装程序后,你应该有一个可以用EventViewer打开的EventLog,你可以发现防御措施最终信任ProcessHacker之类的事情。

29.png

总结

就个人而言,我认为微软为提高操作系统的安全性而采取的措施是很好的,其最终目标是让用户更加安全。另一方面,我确实看到了SAC和Windows 10 S之间的一些相似之处。对于SAC,当设置为强制时,限制由具有数字签名的应用程序设置,如果没有签名,则由防御措施云认为可信的应用程序进行设置。

第一种选择,即使你知道数字签名可以很好地验证应用程序,许多开源项目或自由开发者负担不起,不幸的是,这给开发者带来了一些限制。

第二个选项,即对“智能云安全服务”的查询,这也是我希望微软提供更多信息的地方,因为基本上应用程序能否运行的决定将完全取决于微软。

本文会详细分析Windows即将推出的最大安全功能——智能应用控制(Smart App Control,SAC)。“智能应用控制”功能是什么,为什么我认为它是 Windows 中最牛的安全功能之一。首先,SAC 会嵌入在操作系统中,启用后将阻止恶意或不受信任的应用程序。这与 AppLocker 非常相似。

在之前一篇文章中,我们看到了SAC是如何启用和初始化的。在本文中,我们将讨论SAC如何执行这些操作。即使SAC是一个新功能,该功能使用的大部分代码也已经在操作系统中了。我的意思是,在22H2之前的版本中,通过使用适当的策略规范,可以获得类似的行为。总之,SAC的最大变化是MS将激活特定的WDAC策略,类似于启用HVCI时,操作系统如何启用Driver Block Rule策略。

需要注意的是,因为我们在这篇文章中看到的很多内容在操作系统中已经存在了很长时间。AppLocker或AppID等功能利用了它。当然,有几个方面只适用于SAC,我一定会注意到这些。从好的方面来看,这篇文章的绝大多数可以推断出其他WDAC策略是如何评估的。

1.png

SAC运行

在本节中,我们将重点关注CI处理来自内核的验证请求所采取的步骤。我们将深入探讨此过程中涉及的主要例程,还将讨论CI使用的一些主要结构。正如我刚才提到的,这些步骤中的大多数并不是SAC独有的,无论启用哪种策略,都将采取这些步骤。如上图所示,我们看到有三个主要的评估来源。据我所知,这些要点与以下功能/策略规范有关,至于是选择使用一个或多个评估取决于策略规范。

OriginClaim (EAs or Token): 托管安装程序、AppLocker、SmartScreen和SAC;

Query 防御措施: Intelligent Security Graph (ISG) & SAC;

Policy FileRules: 通用于所有具有FileRule的策略。

2.png

在上一篇文章中,我们已经说过全局g_CiPolicyState具有位NW_ENABLED,这意味着SAC已启用,SAC策略(强制或评估)处于活动状态,并存储在g_SiPolicyCtx中。现在,让我们看看CI向内核提供的回调,看看内核的验证方式。以下函数建议执行某种类型的验证:

CiValidateImageHeader;
CiValidateImageData;
CiValidateFileAsImageType;
CiRevalidateImage;

在本文中,我将只关注CiValidateImageHeader。

CiValidateImageHeader

可以说,此函数是大多数CI验证的主要入口点。内核将从MiValidateSectionCreate中引用的SeValidateImageHeader调用此函数。CiValidateImageHeader将处理CI初始化的第2阶段,主要初始化minCrypt、ETW、Lookaside缓冲区等。一旦完成(只有一次),第一步是获取指定映像(CiGetActionsForImage)行为。此函数将根据诸如Requested SigningLevel之类的内容,或者如果对象来自受保护进程或系统进程,来确定将要进行的验证操作,这些操作是位字段枚举,但我不知道大多数值的含义.

操作进行后,函数就可以开始验证映像了。如果操作变量设置了位0(action_FILE_In_CACHE(0x1)),则CI将尝试获取之前为此FO设置的任何验证数据,并重新验证。

在本文中,我们不会涉及CI缓存及其验证原理。本质上,它将尝试获取内核EA:$Kernel.Purge.CIpCache或$Kernell.Purge.ESBCache(请参阅函数CipGetFileCache)。然后,它会将策略应用于CiApplyPolicyToSyntheticEa内的这些属性。这个例程最终将调用CipApplySiPolicyEx,我们稍后将详细讨论。

如果未设置“file in cache”属性,则会分配用于处理验证的主结构(CipAllocateValidationContext)。此结构用于所有类型的验证,例如,此上下文也用于HVCI验证(请参阅CiHvciSetValidationContextForHvci)。一旦分配了这个上下文,我看到UMCI验证会发生两个操作。

如果设置了位2(ACTION_PAGE_HASH(0x4)),验证函数为->CipValidatePageHash;

如果设置了位8(ACTION_FILE_HASH(0x100)),验证函数为->CipValidateFileHash。

CipValidateImageHash将接收发生操作的Validation函数作为函数指针。无论传递的是什么函数指针,PageHash还是FileHash,CipValidateImageHash最终都会调用它。在这两个验证函数中,CI都会使用被验证对象的信息更新验证上下文。诸如FileInfo(CipUpdateValidationContextWithFileInfo)、文件版本(CiGetFileResourceInformation)、嵌入签名(CipImageGetCertInfo)或对象哈希(Page CipCalculateHeaderHash或File CipCalpulateImageHash)。有了所有这些信息,代码将通过函数CipApplySiPolicyEx方法继续应用策略。

对于未签名映像的验证,验证函数将返回STATUS_INVALID_IMAGE_HASH,代码将进入CipApplySIPolicyUMCI,最终调用前面提到的CipApply SiPolicyEx。相反,对于签名文件,将从CiVerifyPageHashSignedFile或CiVerify FileHashSingedFile访问此函数。简单说明一下,这两个函数有它们的HVCI对应函数CiHvciXxx。

CipApplySiPolicyEx

顾名思义,此函数将把策略应用于正在验证的对象。该函数将首先设置两个结构,然后将其传递给验证引擎。一个结构将保存正在验证的ImageFile的信息,而另一个结构则包含“外部”授权过程所需的信息,我说“外部”授权是因为MS在验证对象的回调函数名中使用了“外部”授权这个词。

这两个结构将存储在Validation Context中,并且实际上都将被来自Validation Context的数据填充。其中一个包含映像数据,我命名为CI_VALIDATE_IMAGE_DATA,其中包含以下内容:

3.png

另一方面,外部授权结构(我将其命名为CI_EXTERNAL_AUTH)具有以下有趣的值:

4.png

在调用验证引擎例程之前,CipApplySiPolicyEx将设置一个结构数组,其中包含每个策略的验证结果,该数组的大小将等于活动策略的数量。我将此结构命名为CI_VALIDATION_RESULT,它具有以下字段:

5.png

最后,我们准备调用SIPolicyObjectValidationEngine,它具有以下原型:

6.png

这个例程将简单地遍历策略和补充策略,为每个策略调用内部例程SIPolicyValidateImageInternal。

内部验证例程的任务是调用外部授权回调,以从“外部源”获取验证分数。它将根据此分数,选择继续或不继续根据策略中的规范评估映像。我们将首先关注外部回调,设置为函数CipExternalAuthorizationCallback,然后我们将讨论如何评估策略规范。

从代码中我可以看到,这与MS在文件规范优先顺序一节中声明的有些不同。他们说“它将首先处理它找到的所有显式拒绝规范。然后,它将处理所有显式允许规范。如果不存在拒绝或允许规范,WDAC将检查托管安装程序EA。最后,如果这些集合都不存在,WDAC会回到ISG”。相反,在代码中,似乎在处理FileRule之前检查了托管安装程序和ISG(外部授权)。

CipExternalAuthorizationCallback

这个函数包含了SAC的核心功能,即使它从21H2到22H2没有太大的变化,当启用SAC时,有一些细节会造成很大的不同。尽管如此,我们将要讨论的大部分内容都将被AppLocker和ISG使用(并且已经被使用了),所以从好的方面来看,我们也将从中学习一些东西。为了概述我们是如何做到这一点的,下面是我们到达外部授权回调时的堆栈,用于验证未签名映像时的堆栈。

7.png

该函数将通过检查策略选项Intelligent Security Graph Authorization(智能安全图授权)或Managed Installer(托管安装程序)启动,如果这些选项都没有设置,则该函数将退出,SIPolicyValidateImageInternal将继续处理策略FileRule,我们将在稍后的章节中看到这一点。

如果设置了任何选项,下一步是根据签名级别确定映像是否可信。这是通过使用为映像获取的ValidatedSigningLevel,并将此值与全局变量g_CipWhichLevelComparisons内索引为0xC的位掩码进行比较来实现的。

请注意:全局变量g_CipWhichLevelComparisons存储了一个指向ulong数组的指针。每个值表示适用于此签名级别的比较级别。通常与已验证的签名级别一起使用,以确定映像的不同操作/选项。例如,对于等于“File Unsigned”(即数组中的索引1)的已验证签名级别,位掩码为0xFFFFFFFE,因此大多数情况下测试此位掩码时,结果都为正值。在其他情况下,如上所述,索引在代码中被硬编码为仅作用于与该索引的位掩码匹配的已验证签名级别。下表有望帮助理解g_CipWhichLevelComparisons和ValidatedSigningLevel之间的关系。

8.png

如上表所示,索引0xC表示位掩码0x5000,表示“Windows签名”和“Windows TCB签名”。此外,接下来的两个级别“仅用于.NET NGEN编译器的签名”和由使用AMPPL的产品的反病毒签名”也将包含在可信映像列表中。此时,函数将继续调用CipCheckSmartlockerEAandProcessToken以获得第一个验证分数。

我觉得这是一个讨论命名的好时机,希望微软的人能联系到我,并澄清命名。有人称之为Smart App Control和Nights Watch,也有人称之为AppLocker,内部名称似乎是SmartLocker。相同或非常相似的事物有4个不同的名称。这确实有点令人困惑。

该函数具有以下原型:

9.png

这个函数有两条路径,其中一条总是被执行,另一条基于boolean IsTrustedSigning。如果不受信任,那么下面的EA将被查询为正在验证的文件对象,它也试图从当前流程文件对象中获得相同的EA,但除了存储在验证上下文中,我没有看到它们在其他地方被使用。

$ Kernel.Smartlocker.Hash: 包含映像的哈希;

$ Kernel.Purge.Smartlocker.Valid: 布尔值是否有效;

$Kernel.Smartlocker.OriginClaim: 包含我命名为EA_ORIGIN_CLAIM的结构。

10.png

如果获得了有效的EA,那么将检查OriginClaim结构以确定图像的分数。Origin值将决定第一个分数,如果Origin == 0,则score |= 1,如果Origin == 1,则score |= 0x1002。

不过我对这方面了解不多。这很可能与WDAC在策略中设置托管安装程序选项时在AppLocker中使用的特殊规范集合有关。这很可能与在策略中设置托管安装程序选项时WDAC使用的AppLocker中的特殊规范集合有关。从我所看到的,我知道appid.sys确实设置了此EA,另一种设置此EA的方法是通过CI回调cisetcachedorigin声明。这个函数在发出带有标志0x2000的syscall NtSetCachedSigningLevel时被内核调用,当然不像调用这个syscall来设置EA origin声明那么容易,如果这个syscall以前的模式是UserMode,那么NtSetCachedSigningLevel2将确保请求来自一个受保护的进程。

下一步,无论我们是否检查了EA,都是获取存储在令牌对象中的OriginClaim。对于令牌对象,origin声明存储在令牌的SecurityAttributes列表中,这些属性存储为Authz SecurityAttributes,并且可以使用函数sequerysecurityattributeken按名称查询/检索。在本例中,将寻找两个安全属性:

SMARTLOCKER://ORIGINCLAIM;
SMARTLOCKER://SMARTSCREENORIGINCLAIMNOTINHERITED (New in 22H2, previously “SMARTLOCKER://SMARTSCREENORIGINCLAIM”)

首先将查找OriginClaim。如果发现,分数将相应调整。同样,我对这方面不太了解,也没有有关此声明的结构外观的信息 (appid.sys设置此值令牌)。

之后,将查询SmartScreen OriginClaim未继承属性,如果它被发现并设置标签CLAIM_DANGEROUS_EXT (0x80) (这不是官方名称),然后函数将继续检查ImageFile是否有被认为是危险扩展名。同样,在所有情况下,代码都将检查ImageFile是否具有InstallerExtension。对于安装程序扩展,它只会检查.msi,对于危险扩展的情况,这些值如下:

11.png

如果ImageFile与这些值中的任何一个匹配,则分数将设置为DangerousExtension (0x800),并通过调用CiCatDbSmartlockerDefenderCheck向防御措施发出查询,有关此函数稍后将详细讨论。

本文会详细分析Windows即将推出的最大安全功能——智能应用控制(Smart App Control,SAC)。“智能应用控制”功能是什么,为什么我认为它是 Windows 中最牛的安全功能之一。首先,SAC 会嵌入在操作系统中,启用后将阻止恶意或不受信任的应用程序。这与 AppLocker 非常相似。

在之前一篇文章中,我们看到了SAC是如何启用和初始化的。在本文中,我们将讨论SAC如何执行这些操作。即使SAC是一个新功能,该功能使用的大部分代码也已经在操作系统中了。我的意思是,在22H2之前的版本中,通过使用适当的策略规范,可以获得类似的行为。总之,SAC的最大变化是MS将激活特定的WDAC策略,类似于启用HVCI时,操作系统如何启用Driver Block Rule策略。

需要注意的是,因为我们在这篇文章中看到的很多内容在操作系统中已经存在了很长时间。AppLocker或AppID等功能利用了它。当然,有几个方面只适用于SAC,我一定会注意到这些。从好的方面来看,这篇文章的绝大多数可以推断出其他WDAC策略是如何评估的。

1.png

SAC运行

在本节中,我们将重点关注CI处理来自内核的验证请求所采取的步骤。我们将深入探讨此过程中涉及的主要例程,还将讨论CI使用的一些主要结构。正如我刚才提到的,这些步骤中的大多数并不是SAC独有的,无论启用哪种策略,都将采取这些步骤。如上图所示,我们看到有三个主要的评估来源。据我所知,这些要点与以下功能/策略规范有关,至于是选择使用一个或多个评估取决于策略规范。

OriginClaim (EAs or Token): 托管安装程序、AppLocker、SmartScreen和SAC;

Query 防御措施: Intelligent Security Graph (ISG) & SAC;

Policy FileRules: 通用于所有具有FileRule的策略。

2.png

在上一篇文章中,我们已经说过全局g_CiPolicyState具有位NW_ENABLED,这意味着SAC已启用,SAC策略(强制或评估)处于活动状态,并存储在g_SiPolicyCtx中。现在,让我们看看CI向内核提供的回调,看看内核的验证方式。以下函数建议执行某种类型的验证:

CiValidateImageHeader;
CiValidateImageData;
CiValidateFileAsImageType;
CiRevalidateImage;

在本文中,我将只关注CiValidateImageHeader。

CiValidateImageHeader

可以说,此函数是大多数CI验证的主要入口点。内核将从MiValidateSectionCreate中引用的SeValidateImageHeader调用此函数。CiValidateImageHeader将处理CI初始化的第2阶段,主要初始化minCrypt、ETW、Lookaside缓冲区等。一旦完成(只有一次),第一步是获取指定映像(CiGetActionsForImage)行为。此函数将根据诸如Requested SigningLevel之类的内容,或者如果对象来自受保护进程或系统进程,来确定将要进行的验证操作,这些操作是位字段枚举,但我不知道大多数值的含义.

操作进行后,函数就可以开始验证映像了。如果操作变量设置了位0(action_FILE_In_CACHE(0x1)),则CI将尝试获取之前为此FO设置的任何验证数据,并重新验证。

在本文中,我们不会涉及CI缓存及其验证原理。本质上,它将尝试获取内核EA:$Kernel.Purge.CIpCache或$Kernell.Purge.ESBCache(请参阅函数CipGetFileCache)。然后,它会将策略应用于CiApplyPolicyToSyntheticEa内的这些属性。这个例程最终将调用CipApplySiPolicyEx,我们稍后将详细讨论。

如果未设置“file in cache”属性,则会分配用于处理验证的主结构(CipAllocateValidationContext)。此结构用于所有类型的验证,例如,此上下文也用于HVCI验证(请参阅CiHvciSetValidationContextForHvci)。一旦分配了这个上下文,我看到UMCI验证会发生两个操作。

如果设置了位2(ACTION_PAGE_HASH(0x4)),验证函数为->CipValidatePageHash;

如果设置了位8(ACTION_FILE_HASH(0x100)),验证函数为->CipValidateFileHash。

CipValidateImageHash将接收发生操作的Validation函数作为函数指针。无论传递的是什么函数指针,PageHash还是FileHash,CipValidateImageHash最终都会调用它。在这两个验证函数中,CI都会使用被验证对象的信息更新验证上下文。诸如FileInfo(CipUpdateValidationContextWithFileInfo)、文件版本(CiGetFileResourceInformation)、嵌入签名(CipImageGetCertInfo)或对象哈希(Page CipCalculateHeaderHash或File CipCalpulateImageHash)。有了所有这些信息,代码将通过函数CipApplySiPolicyEx方法继续应用策略。

对于未签名映像的验证,验证函数将返回STATUS_INVALID_IMAGE_HASH,代码将进入CipApplySIPolicyUMCI,最终调用前面提到的CipApply SiPolicyEx。相反,对于签名文件,将从CiVerifyPageHashSignedFile或CiVerify FileHashSingedFile访问此函数。简单说明一下,这两个函数有它们的HVCI对应函数CiHvciXxx。

CipApplySiPolicyEx

顾名思义,此函数将把策略应用于正在验证的对象。该函数将首先设置两个结构,然后将其传递给验证引擎。一个结构将保存正在验证的ImageFile的信息,而另一个结构则包含“外部”授权过程所需的信息,我说“外部”授权是因为MS在验证对象的回调函数名中使用了“外部”授权这个词。

这两个结构将存储在Validation Context中,并且实际上都将被来自Validation Context的数据填充。其中一个包含映像数据,我命名为CI_VALIDATE_IMAGE_DATA,其中包含以下内容:

3.png

另一方面,外部授权结构(我将其命名为CI_EXTERNAL_AUTH)具有以下有趣的值:

4.png

在调用验证引擎例程之前,CipApplySiPolicyEx将设置一个结构数组,其中包含每个策略的验证结果,该数组的大小将等于活动策略的数量。我将此结构命名为CI_VALIDATION_RESULT,它具有以下字段:

5.png

最后,我们准备调用SIPolicyObjectValidationEngine,它具有以下原型:

6.png

这个例程将简单地遍历策略和补充策略,为每个策略调用内部例程SIPolicyValidateImageInternal。

内部验证例程的任务是调用外部授权回调,以从“外部源”获取验证分数。它将根据此分数,选择继续或不继续根据策略中的规范评估映像。我们将首先关注外部回调,设置为函数CipExternalAuthorizationCallback,然后我们将讨论如何评估策略规范。

从代码中我可以看到,这与MS在文件规范优先顺序一节中声明的有些不同。他们说“它将首先处理它找到的所有显式拒绝规范。然后,它将处理所有显式允许规范。如果不存在拒绝或允许规范,WDAC将检查托管安装程序EA。最后,如果这些集合都不存在,WDAC会回到ISG”。相反,在代码中,似乎在处理FileRule之前检查了托管安装程序和ISG(外部授权)。

CipExternalAuthorizationCallback

这个函数包含了SAC的核心功能,即使它从21H2到22H2没有太大的变化,当启用SAC时,有一些细节会造成很大的不同。尽管如此,我们将要讨论的大部分内容都将被AppLocker和ISG使用(并且已经被使用了),所以从好的方面来看,我们也将从中学习一些东西。为了概述我们是如何做到这一点的,下面是我们到达外部授权回调时的堆栈,用于验证未签名映像时的堆栈。

7.png

该函数将通过检查策略选项Intelligent Security Graph Authorization(智能安全图授权)或Managed Installer(托管安装程序)启动,如果这些选项都没有设置,则该函数将退出,SIPolicyValidateImageInternal将继续处理策略FileRule,我们将在稍后的章节中看到这一点。

如果设置了任何选项,下一步是根据签名级别确定映像是否可信。这是通过使用为映像获取的ValidatedSigningLevel,并将此值与全局变量g_CipWhichLevelComparisons内索引为0xC的位掩码进行比较来实现的。

请注意:全局变量g_CipWhichLevelComparisons存储了一个指向ulong数组的指针。每个值表示适用于此签名级别的比较级别。通常与已验证的签名级别一起使用,以确定映像的不同操作/选项。例如,对于等于“File Unsigned”(即数组中的索引1)的已验证签名级别,位掩码为0xFFFFFFFE,因此大多数情况下测试此位掩码时,结果都为正值。在其他情况下,如上所述,索引在代码中被硬编码为仅作用于与该索引的位掩码匹配的已验证签名级别。下表有望帮助理解g_CipWhichLevelComparisons和ValidatedSigningLevel之间的关系。

8.png

如上表所示,索引0xC表示位掩码0x5000,表示“Windows签名”和“Windows TCB签名”。此外,接下来的两个级别“仅用于.NET NGEN编译器的签名”和由使用AMPPL的产品的反病毒签名”也将包含在可信映像列表中。此时,函数将继续调用CipCheckSmartlockerEAandProcessToken以获得第一个验证分数。

我觉得这是一个讨论命名的好时机,希望微软的人能联系到我,并澄清命名。有人称之为Smart App Control和Nights Watch,也有人称之为AppLocker,内部名称似乎是SmartLocker。相同或非常相似的事物有4个不同的名称。这确实有点令人困惑。

该函数具有以下原型:

9.png

这个函数有两条路径,其中一条总是被执行,另一条基于boolean IsTrustedSigning。如果不受信任,那么下面的EA将被查询为正在验证的文件对象,它也试图从当前流程文件对象中获得相同的EA,但除了存储在验证上下文中,我没有看到它们在其他地方被使用。

$ Kernel.Smartlocker.Hash: 包含映像的哈希;

$ Kernel.Purge.Smartlocker.Valid: 布尔值是否有效;

$Kernel.Smartlocker.OriginClaim: 包含我命名为EA_ORIGIN_CLAIM的结构。

10.png

如果获得了有效的EA,那么将检查OriginClaim结构以确定图像的分数。Origin值将决定第一个分数,如果Origin == 0,则score |= 1,如果Origin == 1,则score |= 0x1002。

不过我对这方面了解不多。这很可能与WDAC在策略中设置托管安装程序选项时在AppLocker中使用的特殊规范集合有关。这很可能与在策略中设置托管安装程序选项时WDAC使用的AppLocker中的特殊规范集合有关。从我所看到的,我知道appid.sys确实设置了此EA,另一种设置此EA的方法是通过CI回调cisetcachedorigin声明。这个函数在发出带有标志0x2000的syscall NtSetCachedSigningLevel时被内核调用,当然不像调用这个syscall来设置EA origin声明那么容易,如果这个syscall以前的模式是UserMode,那么NtSetCachedSigningLevel2将确保请求来自一个受保护的进程。

下一步,无论我们是否检查了EA,都是获取存储在令牌对象中的OriginClaim。对于令牌对象,origin声明存储在令牌的SecurityAttributes列表中,这些属性存储为Authz SecurityAttributes,并且可以使用函数sequerysecurityattributeken按名称查询/检索。在本例中,将寻找两个安全属性:

SMARTLOCKER://ORIGINCLAIM;
SMARTLOCKER://SMARTSCREENORIGINCLAIMNOTINHERITED (New in 22H2, previously “SMARTLOCKER://SMARTSCREENORIGINCLAIM”)

首先将查找OriginClaim。如果发现,分数将相应调整。同样,我对这方面不太了解,也没有有关此声明的结构外观的信息 (appid.sys设置此值令牌)。

之后,将查询SmartScreen OriginClaim未继承属性,如果它被发现并设置标签CLAIM_DANGEROUS_EXT (0x80) (这不是官方名称),然后函数将继续检查ImageFile是否有被认为是危险扩展名。同样,在所有情况下,代码都将检查ImageFile是否具有InstallerExtension。对于安装程序扩展,它只会检查.msi,对于危险扩展的情况,这些值如下:

11.png

如果ImageFile与这些值中的任何一个匹配,则分数将设置为DangerousExtension (0x800),并通过调用CiCatDbSmartlockerDefenderCheck向防御措施发出查询,有关此函数稍后将详细讨论。

abstract_binary_brain_report-1200x600.jpg

勒索软件

季度趋势和亮点

2022年第三季度,知名勒索软件LockBit源代码被泄漏。如今,LockBit 3.0工具包已经被广泛攻击者广泛使用。与过去的其他勒索软件家族(如Babuk和Conti)类似,该勒索软件开始为与LockBit无关的其他组织提供服务。比如5月份发现的Bloody/B100dy,该组织于2022年9月将新推出的LockBit添加到了自己的武器库中。

对NAS(网络连接存储)设备的大规模攻击仍在继续。QNAP在2022年第三季度发布了关于Checkmate和Deadbolt感染的警告。Checkmate威胁通过SMB协议从互联网访问的文件,并受到弱帐户密码的保护。Deadbolt攻击了安装了Photo Station软件(一款照片管理软件)的易受攻击版本的设备。针对NAS的威胁仍然突出,因此我们建议保持这些设备无法从互联网访问,以确保数据的最大安全。

鲜为人知的AstraLocker和Yashma勒索软件的开发者发布了解密程序,并停止了这两个勒索软件的传播。黑客没有对此举做出解释,但这似乎与媒体报道的增加有关。

软件迭代

2022年第三季度,我们检测到17个新的勒索软件家族和14626个这种恶意软件类型的新修改。其中11000多人的攻击和Trojan-Ransom.Win32.Crypmod有关。

4.png

2021年第三季度至2022年第三季度软件迭代数量

被勒索软件木马攻击的用户数

2022年第三季度,卡巴斯基的产品和技术保护了72941名用户免受勒索软件攻击。

5.png

2022年第三季度被勒索软件木马攻击的用户数量

十大银行恶意软件家族

6.png

十大最常见的勒索软件木马家族

8.png

新型挖矿软件

2022年第三季度,卡巴斯基系统检测到153773个新的挖矿模式。其中超过14万个在7月和8月被发现,加上6月份的统计,这表明挖矿活动一直很猖獗。

9.png

挖矿软件攻击的用户数

在第三季度,挖矿软件攻击活动又增加了。

10.png

2022年第三季度挖矿软件攻击的用户数量

攻击者在网络攻击期间使用的易受攻击的应用程序

季度亮点

让我们从Microsoft Windows及其一些组件开始说起,研究人员发现了影响CLFS驱动程序的新漏洞:CVE-2022-30220,以及CVE-2022-25803和CVE-2022-17969,它们都是在野外被发现的。通过以特定方式操纵公共日志文件系统数据,攻击者可以使内核将自己的数据写入任意内存地址,从而允许网络攻击者劫持内核控制并提升其在系统中的特权。在Print Spooler服务中发现了几个漏洞:CVE-2022-22022、CVE-2022-30206和CVE-2022-3 0226。

这些漏洞允许在安装打印机时通过一系列操作提升系统权限。在客户端/服务器运行时子系统(CSRSS)(一个重要的Windows组件)中也发现了严重的漏洞。其中一些漏洞可用于权限升级(CVE-2022-22047、CVE-2022-2049和CVE-2022-2 2026),而CVE-20212-22038影响远程过程调用(RPC)协议,允许攻击者远程执行任意代码。在图形子系统中发现了CVE-2022-22034和CVE-2022-35750等一系列关键漏洞,也可以利用这些漏洞进行权限升级。请注意,以上大多数漏洞都需要在攻击者运行恶意软件之前在系统中进行防御。微软支持诊断工具(MSDT)被发现包含另外两个漏洞CVE-2022-34713和CVE-2022-35743,可以利用链接处理程序中的安全漏洞在系统中远程运行命令。

2022年第三季度检测到的大多数网络威胁仍然是与Microsoft SQL Server、RDP和其他服务的暴力强制密码相关的攻击。通过EternalBlue、EternalRomance和其他漏洞对Windows的脆弱版本进行网络攻击仍然很常见。通过Log4j库(CVE-2021-44228、CVE-2021-44832、CVE-2021-45046和CVE-2021-45105)中的漏洞利用网络服务和其他软件的尝试也在继续。

在Microsoft Windows网络文件系统(NFS)驱动程序中发现了几个漏洞。它们是CVE-2022-22028,它可能导致机密信息泄漏,还有CVE-2022-22029, CVE-2022-22039和CVE-2022-34715,攻击者可以使用它们在系统中(在内核上下文中)通过使用特别制作的网络数据包远程执行任意代码。发现TCP/IP栈包含关键漏洞CVE-2022-34718,该漏洞理论上允许利用IPv6协议处理程序中的错误远程利用目标系统。最后,值得一提的是CVE-2022-34724漏洞,该漏洞会影响Windows DNS Server,如果被利用,可能会导致拒绝服务。

Microsoft Exchange Server中的两个漏洞CVE-2022-41040和CVE-2022-4 1082受到了媒体的广泛报道。它们被统称为“ProxyNotShell”,指的是具有类似攻击技术的ProxyShell漏洞(目前已关闭)。研究人员在调查APT攻击时发现了ProxyNotShell漏洞:经过身份验证的用户可以利用漏洞提升其权限,并在MS Exchange服务器上运行任意代码。因此,攻击者可以窃取机密数据,加密服务器上的关键文件,以勒索受害者的钱财等。

2022年第三季度,恶意Microsoft Office文档再次成为检测最多的漏洞载体,占我们发现的漏洞的80%,尽管与第二季度相比,数量略有下降。这些检测大多是由针对以下漏洞的攻击引发的:

公式编辑器组件中的CVE-2018-0802和CVE-2017-11882,允许在处理公式时破坏应用程序内存,随后在系统中运行任意代码;

CVE-2017-0199,允许下载和运行恶意脚本文件;

CVE-2022-30190,也称为“Follina”,它利用Microsoft Windows支持诊断工具(MSDT)中的漏洞,在易受攻击的系统中运行任意程序,即使在保护模式下或宏被禁用时也是如此;

CVE-2021-40444,由于输入验证不充分,攻击者可以使用特殊的ActiveX模板部署恶意代码。

12.png

攻击者使用的漏洞情况

随后是针对浏览器的攻击,他们的份额达到6%,比第二季度高1%。我们将列出最严重的漏洞,所有漏洞都针对谷歌Chrome:

CVE-2022-2294,在WebRTC组件中,导致缓冲区溢出;

CVE-2022-2624,它利用PDF查看组件中的内存溢出漏洞;

CVE-2022-2295,一种类型混淆漏洞,允许攻击者远程攻击浏览器进程内存并在沙盒中运行任意代码;

CVE-2022-3075,一个与谷歌chrome浏览器中Mojo进程间通信组件输入验证不充分有关的漏洞,允许逃逸沙箱并在系统中运行任意命令。

由于许多现代浏览器都基于GoogleChromium,攻击者通常可以利用共享漏洞攻击其他浏览器,只要它们在一个引擎上运行。

在Microsoft Edge中发现了一系列漏洞。值得注意的是CVE-2022-33649,它允许通过绕过浏览器保护在系统中运行应用程序CVE-2022-33636和CVE-2022-3 5796,最终允许沙盒逃脱的条件漏洞CVE-2022-38012,它利用了一个应用程序内存损坏漏洞,产生了类似的结果。

Mozilla Firefox浏览器被发现包含与内存破坏相关的漏洞,这些漏洞允许在系统中运行任意代码:CVE-2022-38476,这是一个竞争条件漏洞,导致随后的自由使用场景,以及利用内存破坏的类似漏洞CVE-2022-3 8477和CVE-2022-28478。从我们的报告中可以看到,浏览器是网络攻击者的一个有吸引力的目标,因为它们被广泛使用,并允许攻击者在用户不知情的情况下远程渗透系统。也就是说,要利用浏览器漏洞并不容易,因为攻击者通常必须使用一系列漏洞来绕过现代浏览器的保护。

其余则是Android(5%),Java(4%)和Adobe Flash(3%)漏洞,其中针对Adobe Flash的漏洞是一种过时但仍在使用的技术。

对macOS的攻击

2022年第三季度出现了大量有趣的macOS恶意软件,特别是,研究人员发现了名为Operation In(ter)ception的活动,这些攻击是由 Lazarus Group 的成员实施的。Lazarus Group 是朝鲜最大的黑客组织,黑客一直在通过加密货币交易所提供诱人的工作机会来吸引macOS 用户。黑客将恶意软件伪装成来自流行的加密货币交易所的招聘信息,使用精心设计且看起来合法的诱饵PDF文档来宣传空缺职位,该恶意软件伪装成包含Coinbase和Crypto.com职位摘要的文件。

CloudMensis是一个用Objective-C编写的间谍程序,它使用云存储服务作为C&C服务器,并与ScarCruft操作的RokRAT Windows恶意软件共享一些特性。

XCSSET的创建者将他们的工具集改编为macOS Monterey,并从Python 2迁移到Python 3。

第三季度,网络黑客也开始利用开源工具进行攻击。7月份发现了两个使用虚假VPN应用程序和虚假Salesforce更新的活动,这两个活动都是基于Sliver框架构建的。

除此之外,研究人员还宣布了一项新的发现:LuckyMouse组织用中文即时通讯应用MiMi的恶意mod攻击Windows、Linux和macOS用户。

macOS的前20大威胁

13.png

与往常一样,卡巴斯基macOS安全解决方案用户遇到的最大威胁排名前20位的主要是广告软件。AdWare.OSX.Amc.e连续第二季度蝉联榜首。该应用程序显示虚假的系统漏洞消息,提供购买完整版本来修复这些漏洞。第二名和第三名分别来自adware . osx . pirit和AdWare.OSX.Agent家族。

物联网攻击

物联网威胁统计

2022年第三季度,攻击卡巴斯基蜜罐的设备中有四分之三使用了Telnet协议。

15.png

2022年第3季度,按攻击设备的唯一IP地址数量划分的受攻击服务分布

大多数针对卡巴斯基蜜罐的攻击都是通过Telnet控制的。

16.png

通过Telnet的物联网设备十大威胁

17.png

通过web资源进行的攻击

本节中的统计数据基于Web Anti-Virus,当从恶意/受感染的网页下载恶意对象时,它会保护用户。网络攻击者故意创建这些网站,他们可以用用户创建的内容(如论坛)感染被黑客入侵的合法资源以及网络资源。

2022年第三季度,卡巴斯基解决方案阻止了来自全球在线资源的956074958次攻击。共有251288987个唯一URL被Web防病毒组件识别为恶意。

abstract_binary_brain_report-1200x600.jpg

勒索软件

季度趋势和亮点

2022年第三季度,知名勒索软件LockBit源代码被泄漏。如今,LockBit 3.0工具包已经被广泛攻击者广泛使用。与过去的其他勒索软件家族(如Babuk和Conti)类似,该勒索软件开始为与LockBit无关的其他组织提供服务。比如5月份发现的Bloody/B100dy,该组织于2022年9月将新推出的LockBit添加到了自己的武器库中。

对NAS(网络连接存储)设备的大规模攻击仍在继续。QNAP在2022年第三季度发布了关于Checkmate和Deadbolt感染的警告。Checkmate威胁通过SMB协议从互联网访问的文件,并受到弱帐户密码的保护。Deadbolt攻击了安装了Photo Station软件(一款照片管理软件)的易受攻击版本的设备。针对NAS的威胁仍然突出,因此我们建议保持这些设备无法从互联网访问,以确保数据的最大安全。

鲜为人知的AstraLocker和Yashma勒索软件的开发者发布了解密程序,并停止了这两个勒索软件的传播。黑客没有对此举做出解释,但这似乎与媒体报道的增加有关。

软件迭代

2022年第三季度,我们检测到17个新的勒索软件家族和14626个这种恶意软件类型的新修改。其中11000多人的攻击和Trojan-Ransom.Win32.Crypmod有关。

4.png

2021年第三季度至2022年第三季度软件迭代数量

被勒索软件木马攻击的用户数

2022年第三季度,卡巴斯基的产品和技术保护了72941名用户免受勒索软件攻击。

5.png

2022年第三季度被勒索软件木马攻击的用户数量

十大银行恶意软件家族

6.png

十大最常见的勒索软件木马家族

8.png

新型挖矿软件

2022年第三季度,卡巴斯基系统检测到153773个新的挖矿模式。其中超过14万个在7月和8月被发现,加上6月份的统计,这表明挖矿活动一直很猖獗。

9.png

挖矿软件攻击的用户数

在第三季度,挖矿软件攻击活动又增加了。

10.png

2022年第三季度挖矿软件攻击的用户数量

攻击者在网络攻击期间使用的易受攻击的应用程序

季度亮点

让我们从Microsoft Windows及其一些组件开始说起,研究人员发现了影响CLFS驱动程序的新漏洞:CVE-2022-30220,以及CVE-2022-25803和CVE-2022-17969,它们都是在野外被发现的。通过以特定方式操纵公共日志文件系统数据,攻击者可以使内核将自己的数据写入任意内存地址,从而允许网络攻击者劫持内核控制并提升其在系统中的特权。在Print Spooler服务中发现了几个漏洞:CVE-2022-22022、CVE-2022-30206和CVE-2022-3 0226。

这些漏洞允许在安装打印机时通过一系列操作提升系统权限。在客户端/服务器运行时子系统(CSRSS)(一个重要的Windows组件)中也发现了严重的漏洞。其中一些漏洞可用于权限升级(CVE-2022-22047、CVE-2022-2049和CVE-2022-2 2026),而CVE-20212-22038影响远程过程调用(RPC)协议,允许攻击者远程执行任意代码。在图形子系统中发现了CVE-2022-22034和CVE-2022-35750等一系列关键漏洞,也可以利用这些漏洞进行权限升级。请注意,以上大多数漏洞都需要在攻击者运行恶意软件之前在系统中进行防御。微软支持诊断工具(MSDT)被发现包含另外两个漏洞CVE-2022-34713和CVE-2022-35743,可以利用链接处理程序中的安全漏洞在系统中远程运行命令。

2022年第三季度检测到的大多数网络威胁仍然是与Microsoft SQL Server、RDP和其他服务的暴力强制密码相关的攻击。通过EternalBlue、EternalRomance和其他漏洞对Windows的脆弱版本进行网络攻击仍然很常见。通过Log4j库(CVE-2021-44228、CVE-2021-44832、CVE-2021-45046和CVE-2021-45105)中的漏洞利用网络服务和其他软件的尝试也在继续。

在Microsoft Windows网络文件系统(NFS)驱动程序中发现了几个漏洞。它们是CVE-2022-22028,它可能导致机密信息泄漏,还有CVE-2022-22029, CVE-2022-22039和CVE-2022-34715,攻击者可以使用它们在系统中(在内核上下文中)通过使用特别制作的网络数据包远程执行任意代码。发现TCP/IP栈包含关键漏洞CVE-2022-34718,该漏洞理论上允许利用IPv6协议处理程序中的错误远程利用目标系统。最后,值得一提的是CVE-2022-34724漏洞,该漏洞会影响Windows DNS Server,如果被利用,可能会导致拒绝服务。

Microsoft Exchange Server中的两个漏洞CVE-2022-41040和CVE-2022-4 1082受到了媒体的广泛报道。它们被统称为“ProxyNotShell”,指的是具有类似攻击技术的ProxyShell漏洞(目前已关闭)。研究人员在调查APT攻击时发现了ProxyNotShell漏洞:经过身份验证的用户可以利用漏洞提升其权限,并在MS Exchange服务器上运行任意代码。因此,攻击者可以窃取机密数据,加密服务器上的关键文件,以勒索受害者的钱财等。

2022年第三季度,恶意Microsoft Office文档再次成为检测最多的漏洞载体,占我们发现的漏洞的80%,尽管与第二季度相比,数量略有下降。这些检测大多是由针对以下漏洞的攻击引发的:

公式编辑器组件中的CVE-2018-0802和CVE-2017-11882,允许在处理公式时破坏应用程序内存,随后在系统中运行任意代码;

CVE-2017-0199,允许下载和运行恶意脚本文件;

CVE-2022-30190,也称为“Follina”,它利用Microsoft Windows支持诊断工具(MSDT)中的漏洞,在易受攻击的系统中运行任意程序,即使在保护模式下或宏被禁用时也是如此;

CVE-2021-40444,由于输入验证不充分,攻击者可以使用特殊的ActiveX模板部署恶意代码。

12.png

攻击者使用的漏洞情况

随后是针对浏览器的攻击,他们的份额达到6%,比第二季度高1%。我们将列出最严重的漏洞,所有漏洞都针对谷歌Chrome:

CVE-2022-2294,在WebRTC组件中,导致缓冲区溢出;

CVE-2022-2624,它利用PDF查看组件中的内存溢出漏洞;

CVE-2022-2295,一种类型混淆漏洞,允许攻击者远程攻击浏览器进程内存并在沙盒中运行任意代码;

CVE-2022-3075,一个与谷歌chrome浏览器中Mojo进程间通信组件输入验证不充分有关的漏洞,允许逃逸沙箱并在系统中运行任意命令。

由于许多现代浏览器都基于GoogleChromium,攻击者通常可以利用共享漏洞攻击其他浏览器,只要它们在一个引擎上运行。

在Microsoft Edge中发现了一系列漏洞。值得注意的是CVE-2022-33649,它允许通过绕过浏览器保护在系统中运行应用程序CVE-2022-33636和CVE-2022-3 5796,最终允许沙盒逃脱的条件漏洞CVE-2022-38012,它利用了一个应用程序内存损坏漏洞,产生了类似的结果。

Mozilla Firefox浏览器被发现包含与内存破坏相关的漏洞,这些漏洞允许在系统中运行任意代码:CVE-2022-38476,这是一个竞争条件漏洞,导致随后的自由使用场景,以及利用内存破坏的类似漏洞CVE-2022-3 8477和CVE-2022-28478。从我们的报告中可以看到,浏览器是网络攻击者的一个有吸引力的目标,因为它们被广泛使用,并允许攻击者在用户不知情的情况下远程渗透系统。也就是说,要利用浏览器漏洞并不容易,因为攻击者通常必须使用一系列漏洞来绕过现代浏览器的保护。

其余则是Android(5%),Java(4%)和Adobe Flash(3%)漏洞,其中针对Adobe Flash的漏洞是一种过时但仍在使用的技术。

对macOS的攻击

2022年第三季度出现了大量有趣的macOS恶意软件,特别是,研究人员发现了名为Operation In(ter)ception的活动,这些攻击是由 Lazarus Group 的成员实施的。Lazarus Group 是朝鲜最大的黑客组织,黑客一直在通过加密货币交易所提供诱人的工作机会来吸引macOS 用户。黑客将恶意软件伪装成来自流行的加密货币交易所的招聘信息,使用精心设计且看起来合法的诱饵PDF文档来宣传空缺职位,该恶意软件伪装成包含Coinbase和Crypto.com职位摘要的文件。

CloudMensis是一个用Objective-C编写的间谍程序,它使用云存储服务作为C&C服务器,并与ScarCruft操作的RokRAT Windows恶意软件共享一些特性。

XCSSET的创建者将他们的工具集改编为macOS Monterey,并从Python 2迁移到Python 3。

第三季度,网络黑客也开始利用开源工具进行攻击。7月份发现了两个使用虚假VPN应用程序和虚假Salesforce更新的活动,这两个活动都是基于Sliver框架构建的。

除此之外,研究人员还宣布了一项新的发现:LuckyMouse组织用中文即时通讯应用MiMi的恶意mod攻击Windows、Linux和macOS用户。

macOS的前20大威胁

13.png

与往常一样,卡巴斯基macOS安全解决方案用户遇到的最大威胁排名前20位的主要是广告软件。AdWare.OSX.Amc.e连续第二季度蝉联榜首。该应用程序显示虚假的系统漏洞消息,提供购买完整版本来修复这些漏洞。第二名和第三名分别来自adware . osx . pirit和AdWare.OSX.Agent家族。

物联网攻击

物联网威胁统计

2022年第三季度,攻击卡巴斯基蜜罐的设备中有四分之三使用了Telnet协议。

15.png

2022年第3季度,按攻击设备的唯一IP地址数量划分的受攻击服务分布

大多数针对卡巴斯基蜜罐的攻击都是通过Telnet控制的。

16.png

通过Telnet的物联网设备十大威胁

17.png

通过web资源进行的攻击

本节中的统计数据基于Web Anti-Virus,当从恶意/受感染的网页下载恶意对象时,它会保护用户。网络攻击者故意创建这些网站,他们可以用用户创建的内容(如论坛)感染被黑客入侵的合法资源以及网络资源。

2022年第三季度,卡巴斯基解决方案阻止了来自全球在线资源的956074958次攻击。共有251288987个唯一URL被Web防病毒组件识别为恶意。