[翻译] 星期二补丁- 星期三利用:24 小时内破解 WinSock (afd.sys) 的 Windows 辅助功
时间:2023-07-03 21:13:37来源:哔哩哔哩

原文地址:/posts/patch-tuesday-exploit-wednesday-pwning-windows-ancillary-function-driver-winsock/


(资料图)

“星期二补丁,星期三利用” 是一句古老的黑客格言,指的是每月安全补丁公开后的第二天,漏洞就被武器化。随着安全性的提高和漏洞缓解措施变得更加复杂,制作武器化漏洞所需的研究和开发量也随之增加。这与内存损坏漏洞尤其相关。

补丁差异和根本原因分析

根据微软安全响应中心(MSRC)发布的CVE-2023-21768的详细信息,该漏洞存在于辅助功能驱动程序(AFD)中,其二进制文件名为 。AFD 模块是 Winsock API 的内核入口点。利用这些信息,我们分析了 2022 年 12 月的驱动程序版本,并将其与 2023 年 1 月新发布的版本进行了比较。这些样本可以从 Winbindex 单独获取,无需从 Microsoft 补丁中提取更改的耗时过程。分析的两个版本如下所示。

/ Windows 11 22H2 / (December 2022)

/ Windows 11 22H2 / (January 2023)

Ghidra 用于为这两个文件创建二进制导出,以便可以在 BinDiff 中对它们进行比较。匹配功能的概述如下所示。

似乎只有一个函数发生了变化,afd!AfdNotifyRemoveIoCompletion。这大大加快了我们对漏洞的分析速度。然后我们比较了这两个功能。下面的屏幕截图显示了在 Binary Ninja 中查看反编译代码时修补前后代码的变化。

Pre-patch version .

Post-patch version .

上面显示的此更改是对已识别功能的唯一更新。一些快速分析表明,正在根据以下内容执行检查

PreviousMode 。 如果 PreviousMode为 0 (表明调用源自内核),则将值写入由未知结构中的字段指定的指针。另一方面,如果 PreviousMode 不为零,则 ProbeForWrite函数被调用确保该字段中设置的指针是驻留在用户模式中的有效地址。

补丁前版本的驱动程序中缺少此检查。由于该函数有一个针对 PreviousMode的特定 switch 语句,因此假设开发人员打算添加此检查但忘记了(我们有时都缺咖啡☕!)。

从这次更新中,我们可以推断攻击者可以通过未知结构的 field_0x18处的受控值到达此代码路径。如果攻击者能够使用内核地址填充此字段,则可以创建任意内核 Write-Where 原语。此时,尚不清楚正在写入什么值,但任何值都可能用于本地权限升级原语。

函数原型本身包含 PreviousMode值和指向未知结构的指针,分别作为第一个和第三个参数。

逆向工程

我们现在知道漏洞的位置,但不知道如何触发有漏洞的代码路径的执行。在开始进行概念验证 (PoC) 之前,我们将进行一些逆向工程。

首先,交叉引用易受攻击的函数以了解其使用地点和方式。

在 afd!AfdNotifySock中对易受攻击的函数进行了一次调用。

我们重复该过程,寻找对 AfdNotifySock的交叉引用。我们发现没有对该函数的直接调用,但其地址出现在名为 AfdIrpCallDispatch的函数指针表上方。

该表包含 AFD 驱动程序的调度例程。调度例程用于通过调用来处理来自 Win32 应用程序的请求 DeviceIoControl. 每个函数的控制代码可在 AfdIoctlTable中找到。

然而,上面的指针并不像我们预期的那样位于 AfdIrpCallDispatch表中。从 Steven Vittitoe 的 Recon 谈话幻灯片中,我们发现 AFD 实际上有两个调度表。第二个是 AfdImmediateCallDispatch。通过计算该表的开头与存储 AfdNotifySock 的指针之间的距离,我们可以计算 AfdIoctlTable 的索引,该索引显示该函数的控制代码是 0x12127

值得注意的是,它是表中最后一个输入/输出控制(IOCTL)代码,表明 AfdNotifySock很可能是最近添加到 AFD 驱动程序中的新调度函数。

此时,我们有几个选择。我们可以在用户空间对相应的 Winsock API进行逆向工程,以更好地了解底层内核函数是如何调用的,或者对内核代码进行逆向工程并直接调用它。我们实际上并不知道哪个 Winsock 函数对应于 AfdNotifySock,因此我们选择了后者。

我们发现 x86matthew 发布的一些代码通过直接调用 AFD 驱动程序来执行套接字操作,放弃了 Winsock 库。从隐秘的角度来看,这很有趣,但就我们的目的而言,它是一个很好的模板,可以创建 TCP 套接字的句柄以向 AFD 驱动程序发出 IOCTL 请求。从那里,我们能够到达目标函数,正如在内核调试时到达 WinDbg 中设置的断点所证明的那样。

现在,回顾一下 DeviceIoControl的函数原型,通过它我们从用户空间调用 AFD 驱动程序。参数之一 lpInBuffer 是用户模式缓冲区。如上一节所述,该漏洞的发生是因为用户能够在未知数据结构中将未经验证的指针传递给驱动程序。该结构是通过 lpInBuffer参数直接从我们的用户模式应用程序传入的。它作为第四个参数传递到 AfdNotifySock 中,并作为第三个参数传递到 AfdNotifyRemoveIoCompletion中。

此时,我们不知道如何填充 lpInBuffer中的数据(我们将其称为 AFD_NOTIFYSOCK_STRUCT),以便通过到达 AfdNotifyRemoveIoCompletion中易受攻击的代码路径所需的检查。我们逆向工程过程的其余部分包括遵循执行流程并检查如何访问易受攻击的代码。

让我们逐一检查一下。

我们遇到的第一个检查是在 AfdNotifySock的开头:

此检查告诉我们 AFD_NOTIFYSOCK_STRUCT的大小应等于 0x30 字节,否则函数会失败并显示 STATUS_INFO_LENGTH_MISMATCH

下一个检查验证结构中各个字段中的值:

当时我们不知道这些字段对应什么,所以我们传入一个 0x30字节数组,其中填充了 0x41字节(AAAAAAAAA...)。

我们遇到的下一个检查是在调用之后 ObReferenceObjectByHandle. 该函数将输入结构的第一个字段作为其第一个参数。

该调用必须返回成功才能继续到正确的代码执行路径,这意味着我们必须将有效的句柄传递给 IoCompletionObject。没有正式记录的方法可以通过 Win32 API 创建该类型的对象。然而,经过一番搜索,我们发现了一个未记录的 NT 函数 NtCreateIoCompletion 之后,我们到达一个循环,其计数器是结构中的值之一:

该循环检查结构中的一个字段,以验证它包含有效的用户模式指针并将数据复制到其中。每次循环迭代后指针都会递增。我们用有效地址填充了指针,并将计数器设置为 1。从这里,我们最终能够到达存在漏洞的函数 AfdNotifyRemoveIoCompletion

进入 AfdNotifyRemoveIoCompletion后,第一个检查是结构中的另一个字段。它必须是非零的。然后将其乘以 0x20,并与结构体中的另一个字段一起作为指针参数传递到 ProbeForWrite。从这里,我们可以使用有效的用户模式指针 (pData2) 和字段 dwLen = 1进一步填充结构(以便传递给 ProbeForWrite的总大小等于 0x20),并且检查通过。

最后,在到达目标代码之前要通过的最后一个检查是对 IoRemoveCompletion的调用,它必须返回 0 (STATUS_SUCCESS)。

该函数将阻塞,直到:

完成记录可用于 IoCompletionObject参数

超时到期,作为函数的参数传入

我们通过结构控制超时值,但简单地将超时设置为 0 不足以让函数返回成功。为了使该函数无错误地返回,必须至少有一个可用的完成记录。经过一番研究,我们发现了未记录的功能 NtSetIoCompletion 它手动增加 IoCompletionObject上的 I/O 挂起计数器。在我们之前创建的 IoCompletionObject上调用此函数可确保对 IoRemoveCompletion的调用返回 STATUS_SUCCESS

触发任意写位置

现在我们可以到达易受攻击的代码,我们可以用任意要写入的地址填充结构中的适当字段。我们写入该地址的值来自一个整数,该整数的指针被传递到对 IoRemoveIoCompletion的调用中。 IoRemoveIoCompletion将此整数的值设置为调用 KeRemoveQueueEx的返回值。

在我们的概念验证中,该写入值始终等于 0x1。我们推测 KeRemoveQueueEx的返回值是从队列中删除的项目数,但没有进一步调查。此时,我们已经有了所需的原语,并继续完成漏洞利用链。我们后来证实了这个猜测是正确的,并且可以通过对 IoCompletionObject上的 NtSetIoCompletion进行额外调用来任意增加写入值。

LPE with IORING

由于能够在任意内核地址写入固定值 (0x1),我们继续将其转换为完整的任意内核读/写。由于此漏洞影响最新版本的 Windows 11(22H2),因此我们选择利用 Windows I/O 环对象损坏来创建我们的原语。Yarden Shafir 撰写了许多关于 Windows I/O 环的优秀文章,并且还开发并披露了我们在漏洞利用链中利用的原语。据我们所知,这是该原语首次被用于公共漏洞利用。 当用户初始化 I/O 环时,会创建两个独立的结构,一个在用户空间,一个在内核空间。 这些结构如下所示。

内核对象映射到 nt!_IORING_OBJECT,如下所示。

请注意,内核对象有两个字段:RegBuffersCount和 RegBuffers,它们在初始化时被清零。该计数指示有多少 I/O 操作可以在 I/O 环中排队。另一个参数是指向当前排队操作列表的指针。

在用户空间端,调用 kernelbase!CreateIoRing时,如果成功,您将返回一个 I/O 环句柄。该句柄是指向未记录结构 (HIORING) 的指针。我们对这种结构的定义是从 Yarden Shafir 所做的研究中获得的。

如果某个漏洞(例如本博文中提到的漏洞)允许您更新 RegBuffersCount和 RegBuffers字段,则可以使用标准 I/O Ring API 来读取和写入内核内存。

正如我们在上面看到的,我们可以利用该漏洞在我们喜欢的任何内核地址写入 0x1。要设置 I/O 环原语,我们只需触发该漏洞两次即可。

在第二个触发器中,我们将 RegBuffers设置为可以在用户空间中分配的地址(例如 0x0000000100000000)。

备注:需要验证两次的原因就是 RegBuffersCount和 RegBuffers分别验证是否能通过带有缺陷的驱动写入。

下面的屏幕截图显示了这样一个 nt!_IOP_MC_BUFFER_ENTRY。请注意,操作的目标是内核地址 (0xfffff8052831da20),并且在本例中操作的大小为 0x8字节。从结构中无法判断这是读操作还是写操作。操作的方向取决于使用哪个 API 对 I/O 请求进行排队。利用 kernelbase!BuildIoRingReadFile 导致任意内核写入,kernelbase!BuildIoRingWriteFile导致任意内核读取。

为了执行任意写入,I/O 操作的任务是从文件句柄读取数据并将该数据写入内核地址。

相反,为了执行任意读取,I/O 操作的任务是读取内核地址处的数据并将该数据写入文件句柄。

Demo

设置原语后,剩下的就是使用一些标准内核后利用技术来泄漏系统(PID 4)等提升进程的令牌并覆盖不同进程的令牌。

视频地址:/M3IPsKAsxvQ

在野利用

在我们的漏洞代码公开后,来自360 Icesword Lab的Xiaoliang Liu(@flame36987044)首次公开披露,他们在今年早些时候发现了利用该漏洞的样本(ITW)。 ITW 样本使用的技术与我们的不同。攻击者使用相应的 Winsock API 函数 ProcessSocketNotifications触发漏洞,而不是像我们的漏洞利用那样直接调用 驱动程序。

360冰剑实验室官方声明如下:

“360冰剑实验室专注于APT检测与防御。基于我们的0day漏洞雷达系统,今年1月份我们在野外发现了CVE-2023-21768的利用样本,该样本与 @chompie1337 和 @FuzzySec 公布的利用样本不同,它是通过系统机制和漏洞特征进行利用的。该漏洞与 NtSetIoCompletion和 ProcessSocketNotifications有关, ProcessSocketNotifications获取调用 NtSetIoCompletion的次数,因此我们使用它来更改权限计数。”

结论和最终反思

您可能会注意到,在逆向工程的某些部分,我们的分析是肤浅的。有时,仅观察一些相关的状态变化并将程序的某些部分视为黑匣子是有帮助的,以避免陷入不相关的兔子洞。这使我们能够快速扭转漏洞,尽管最大化完成速度不是我们的目标。此外,我们对 中所有报告的漏洞进行了补丁差异审查,这些漏洞被标记为“利用可能性更大”。我们的审查显示,除了两个漏洞之外,所有漏洞都是由于对从用户模式传入的指针验证不当造成的。这表明,了解过去的漏洞(尤其是特定目标内的漏洞)的历史知识,对于发现新漏洞可能会卓有成效。当代码库扩展时,同样的错误很可能会重复。请记住,新的 C 代码 == 新的 bug 。正如发现上述漏洞在野外被利用所证明的那样,可以肯定地说,攻击者也在密切监视新的代码库添加。

Windows 内核中缺乏对管理员模式访问保护 (SMAP) 的支持,这给我们提供了丰富的选项来构建新的纯数据利用原语。这些原语在支持 SMAP 的其他操作系统中不可行。例如,考虑 CVE-2021-41073,这是 Linux 的 I/O 环预注册缓冲区实现中的一个漏洞(我们在 Windows 中滥用相同的功能用于 R/W 原语)。此漏洞可以允许覆盖已注册缓冲区的内核指针,但不能用于构造任意 R/W 原语,因为如果该指针被替换为用户指针,并且内核尝试在那里读取或写入,系统将崩溃。

尽管微软尽了最大努力来消除人们喜爱的漏洞利用原语,但肯定会发现新的原语来取代它们。我们能够利用最新版本的 Windows 11 22H2,而不会遇到 HVCI(内存完整性和基于虚拟化的安全性) 等基于虚拟化的安全功能的任何缓解或限制。

引用

1.MSRC (CVE-2023-21768) (/update-guide/en-US/vulnerability/CVE-2023-21768)

2. I/O Rings – When One I/O Operation is Not Enough  (@yarden_shafir) (/i-o-rings-when-one-i-o-operation-is-not-enough/)

3.IoRing vs. io_uring: a comparison of Windows and Linux implementations  (@yarden_shafir) (/ioring-vs-io_uring-a-comparison-of-windows-and-linux-implementations/)

4.One Year to I/O Ring: What Changed? (@yarden_shafir)(/one-year-to-i-o-ring-what-changed/)

5. One I/O Ring to Rule Them All: A Full Read/Write Exploit Primitive on Windows 11 (@yarden_shafir)(/one-i-o-ring-to-rule-them-all-a-full-read-write-exploit-primitive-on-windows-11/)

6. Arbitrary Kernel RW using IORING’s (@FuzzySec) (/Posts/Arbitrary+Kernel+RW+using+IORING's)

7.NTSockets – Downloading a file via HTTP using the NtCreateFile and NtDeviceIoControlFile syscalls (@x86matthew)(/view_post?id=ntsockets)

8. Reverse Engineering (@bool101)(/2015/slides/r)

9. Microsoft Windows Ancillary Function Driver for WinSock privilege escalation CVE-2023-21768 Vulnerability Report(/vulnerabilities/243235)

标签:

生活指南
  • e招贷不上征信吗?招商银行e招贷上不上征信?-全球信息

    e招贷不上征信吗?e招贷是招商银行推出的贷款产品,招商银行是正规的

  • 环球资讯:杞菊地黄丸巧搭配,效果翻倍!1. 杞菊地黄W逍遥丸功效:滋补肝

    杞菊地黄丸巧搭配,效果翻倍!1 杞菊地黄W➕逍遥丸功效:滋补肝肾

  • 2023中级会计财务管理答疑精华:风险收益率 焦点快看

    2023年中级会计职称备考已经开始啦!为帮助大家备考,正保会计网校特从

  • 全球快讯:六安市叶集区:暖心助餐饭让老年生活有“知”有“味”

    “这里的饭软和,菜味道也好,不仅花样多,还好吃便宜,感谢政府对我们

  • 平谷区夏各庄镇举办土特产推介会

    本报讯(记者马超)胖嘟嘟的赤松茸,品种多样的红薯系列产品,鲜嫩多汁

  • 山东43人名单曝光,终生禁驾!

    近日,山东省公安厅交通管理局发布6月份重点交通违法企业、车辆及驾驶

  • 全球最大水光互补电站——柯拉光伏电站投产发电 黄强宣布电站投产发电

    6月25日上午,来自川西海拔4600米扎拉托桑雪山上的“阳光”,一路“跋

  • 高考查分的心情你还记得吗?一起沉浸式体验

    近日,各地高考成绩陆续公布。当年查分的心情你还记得么?高考终章,只

  • 京津冀出现极端高温天气 6月底高温还将再度加强

    25日、26日,京津冀地区的高温天气将略有减弱,但从6月27日开始,新一

  • 天天最资讯丨六成购房者延后/取消买房计划 《2023年中购房意愿白皮书》发布

    摘要通过线上调研问卷我们发现,6518份有效问卷中,有62 08%的人不打算

  • 世界排名487位黑马爆发!19岁天才成新武器,刘国梁打造新奇兵

    对中国乒乓球队来说,巴黎奥运会的竞争将会非常激烈,我们会面对很多的

  • 全国少年冰球邀请赛在河北唐山闭幕|世界今热点

    中新网唐山6月25日电(白云水韩伟孟潮)24日,2023“瑞翔”杯,最终,北

  • 软壳蟹和硬壳蟹有什么区别_软壳蟹|世界热讯

    1、软壳蟹是一种生长在海里的螃蟹,软壳蟹是蟹褪壳后不久的一个短暂形

  • 每日速读!保护知识产权激发创新活力

    前不久,一则关于西安市获中国专利奖再创历史新高的消息引发关注。积极

  • 世界看点:旧梦一场歌词含义 旧梦一场歌词

    今天来聊聊梦一场歌词含义,旧梦一场歌词的文章,现在就为大家来简单介

  • 范丞丞的“自私”,让观众看清白鹿的为人,《跑男》因此话题出圈_世界视讯

    正片还没播出便能掀起舆论大战,《跑男》向来是综艺界的话题中心。作为

  • 民生
    • 黄山旅游精彩亮相联合国特展

    • 如何检查wifi无线网络密码

    • 灯花 | 限塑之“他山石” 实时焦点

    • 承德避暑山庄门票价格多少?承德避暑山庄游玩需要多长时间?|每日热议