CVE-2024-21338 是微软于 2024 年 2 月的周二补丁日披露的 Windows 内核权限提升高危漏洞,CVSS 3.1 评分为 7.8(高危),存在于 Windows 内置的 AppLocker 应用白名单驱动 appid.sys 中。该漏洞的核心危害在于:攻击者可通过精心构造的 IOCTL 请求,在内核态触发任意函数调用,最终从用户模式突破至内核模式执行代码,实现完整的系统控制。更值得关注的是,该0day漏洞在补丁发布前已被朝鲜国家级黑客组织 Lazarus 利用长达半年的时间,用于其 FudModule Rootkit 的内核权限获取,彻底替代了此前易被检测的 BYOVD(自带漏洞驱动) 攻击模式。该漏洞已于 2024 年 2 月 13 日 修复,建议使用 Windows 10 1709 等微软在 2024 年 2 月 13 日 之前停止支持的 Windows 系统版本进行测试。在 Windows 系统中,需要开启 Application Identity 服务,才能利用该漏洞。在 services.msc 中,找到 Application Identity 服务并手动启动。通过拆解0x22A018控制码可知,该控制码需要具有写入权限的句柄,才能成功触发。我们打开 WinObj 工具,找到 AppID,如图所示:可以看出,管理员无权限对设备对象进行写操作,只有在 LOCAL SERVICE 的权限上下文中才具备对设备对象的写操作权限。漏洞的核心缺陷位于appid.sys对 IOCTL 控制码0x22A018的处理函数中,本质是对用户态传入的指针完全缺乏合法性校验,导致任意内核函数调用能力。在(*a2)(userBuffer, v42)中,第一个参数正是内核态从用户态拷贝过来的缓冲区基址。而a2则是userBuffer的0x10偏移,指向一个函数指针,用于调用用户态传入的函数地址。整体调用如下:总的结构体定义如下:注意事项由于appid.sys的设备仅允许 Local Service 进行写访问,攻击者需要获取该身份的模拟令牌管理员无法直接复制 svchost.exe 进程的令牌,所以先获取 SYSTEM 权限。代码如下:通过复制 Winlogon.exe 进程中的 SYSTEM 令牌并模拟权限上下文,再遍历 svchost 进程比对对应 Local Service 的 SID 并复制 LOCAL SERVICE 令牌,最后模拟 LOCAL SERVICE 权限上下文。比对 Local Service SID 的代码如下:我们并不能直接找碎片化的gadget作为原语,因为 KCFG 会验证回调函数的地址是否为合法的内核函数地址,如果不是合法函数地址,执行时就会导致蓝屏。虽然 KCFG 和 SMEP 极大地限制了攻击者通过漏洞执行任意代码的难度,但实际上并不能阻止我们利用漏洞进行提权。因为攻击者只需找到一个符合 KCFG 的合法内核写原语作为我们的回调函数,那这些安全机制自然就被绕过了。在nero22k的这篇文章里讲过可以使用ExpProfileDelete进行内核写操作,将自己线程里的PreviousMode字段通过ObfDereferenceObject将其递减为0,从而将当前线程的权限提升为内核态。虽然这是一个符合 KCFG 的函数,但实际上极力不推荐使用此函数,我通过 IDA 将其反汇编如下:在ExpProfileDelete中,我们发现该函数会检查a1+0x30处是否为0,若为非零值,就会执行该分支。a1是我们传入到内核的缓冲区基址,而我们最多也就传入了0x18或者0x20字节,而a1+0x30处的内存地址不属于我们传入的缓冲区,当对a1+0x30处的内存地址进行解映射操作时,会触发蓝屏。我们用 WinDbg 给ExpProfileDelete函数下个断点:在rcx+0x30处,我们发现该地址的值为0,说明该分支不会执行。会继续执行ObfDereferenceObjectWithTag函数。但当rcx+0x30处的内存地址不为0时,情况就不一样了:如果我们再往下,就会执行第一个分支里面的代码,从而将rcx+0x30处的内存地址解映射,导致蓝屏。值得庆幸的是,我找到了另一个相对更安全的内核写原语,那就是ObpDirectoryTeardownCallback函数,它同样也会调用ObfDereferenceObjectWithTag函数,将其递减为0,从而将当前线程的权限提升为内核态。在找到ObpDirectoryTeardownCallback函数后,我们就可以顺理成章地将(*a2)(userBuffer, v42)的地址指向该函数,从而触发漏洞。你以为这样就完事了吗?那就大错特错了,你确实成功触发了漏洞,但也因此导致了蓝屏或者永远留在了死循环中。请看以下反 C 代码:我们需要给((__int64 (__fastcall *)(__int64, __int64 *, _QWORD, PVOID))v39[1])(v40, &v32, cbInput, pbInput)找一个合适的回调函数地址,使其返回的值小于0,从而跳出这个死循环。我觉得ZwQuerySystemInformation是一个很好的的选择,这个函数指针第一个参数传的就是地址值,而ZwQuerySystemInformation的第一个参数是枚举值,远小于地址值,若第一个参数是无效的枚举值,函数便会直接返回失败,也就是小于0的值,然后直接跳出循环。以我对 Windows 内核的了解,ObfDereferenceObjectWithTag会对目标对象体对应的OBJECT_HEADER结构体中的PointerCount字段也就是在对象体的0x30负偏移处进行递减操作。所以我们在APPID_KERNEL_EXPLOIT第一个字段填写目标PreviousMode字段的地址加上0x30即可将PreviousMode字段递减为0,从而将当前线程的权限提升为内核态。尽管ObpDirectoryTeardownCallback利用方式相对稳健,但仍存在内存篡改风险——具体表现为破坏自身ETHREAD结构体的特定字段。该影响在初始阶段可能不明显,但为实现可靠的权限提升,建议采用双线程架构:主线程首先创建跳板线程(线程A) 和 攻击线程(线程B)线程A 触发漏洞修改自身PreviousMode字段完成内核态提升后,再通过NtWriteVirtualMemory将线程B的PreviousMode字段置为0。线程A 随即退出,隔离内存篡改带来的不稳定因素。调度 线程B 执行后续操作,此时其所有系统调用将被内核判定 为内核模式发起,从而绕过用户态安全检查。 伪代码如下:本文配套的 CVE-2024-21338 Exploit代码,全程由本人独立逆向分析、自主编写实现,无任何开源项目复刻、无第三方代码搬运;其中双线程稳定利用架构、内核原语优化方案等均为个人原创研究成果,完整源码已开源至个人 GitHub仓库 。通过利用 CVE-2024-21338 漏洞,我们可以将自身进程的Protection字段修改为任何值,从而实现进程保护
...(已截断)
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-290662.htm
[原创]被 Lazarus 组织 长期利用的漏洞:Windows AppLocker 权限提升内核漏洞复现
180 浏览
17 回复
2024年的,早被补了吧
dd
牛逼
岚沐
非管理员下似乎没办法直接用sc启动,这个是需要先有管理员权限然后再提升到system权限吗
不是,这个漏洞利用以管理员提升到内核权限为主,并非标准用户提升为管理员
非管理员下似乎没办法直接用sc启动,这个是需要先有管理员权限然后再提升到system权限吗
不是,这个漏洞利用以管理员提升到内核权限为主,并非标准用户提升为管理员
漫雾.
攻击者也可以通过sc命令自动启用该服务,并非只能手动启用
非管理员下似乎没办法直接用sc启动,这个是需要先有管理员权限然后再提升到system权限吗
攻击者也可以通过sc命令自动启用该服务,并非只能手动启用
非管理员下似乎没办法直接用sc启动,这个是需要先有管理员权限然后再提升到system权限吗
岚沐
攻击场景是不是多用于企业PC,一般用户电脑上不会启用 Application Identity 服务吧,需要手动启用感觉攻击门槛还是太高了
攻击者也可以通过sc命令自动启用该服务,并非只能手动启用
攻击场景是不是多用于企业PC,一般用户电脑上不会启用 Application Identity 服务吧,需要手动启用感觉攻击门槛还是太高了
攻击者也可以通过sc命令自动启用该服务,并非只能手动启用
攻击场景是不是多用于企业PC,一般用户电脑上不会启用 Application Identity 服务吧,需要手动启用感觉攻击门槛还是太高了
你的帖子非常有用,感谢分享!
dayang
2024年的,早被补了吧
我在文中已经介绍过该补丁了
2024年的,早被补了吧
我在文中已经介绍过该补丁了
牛逼牛逼
牛逼牛逼
好像还挺牛逼的
感谢分享
好像还挺牛逼的
我看看是怎么个回事