首页
社区
课程
招聘
[原创]被 Lazarus 组织 长期利用的漏洞:Windows AppLocker 权限提升内核漏洞复现
发表于: 3天前 1306

[原创]被 Lazarus 组织 长期利用的漏洞:Windows AppLocker 权限提升内核漏洞复现

3天前
1306

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 服务并手动启动。alt text

通过拆解0x22A018控制码可知,该控制码需要具有写入权限的句柄,才能成功触发。我们打开 WinObj 工具,找到 AppID,如图所示:alt textalt text可以看出,管理员无权限对设备对象进行写操作,只有在 LOCAL SERVICE 的权限上下文中才具备对设备对象的写操作权限。

漏洞的核心缺陷位于appid.sys对 IOCTL 控制码0x22A018的处理函数中,本质是对用户态传入的指针完全缺乏合法性校验,导致任意内核函数调用能力。

(*a2)(userBuffer, v42)中,第一个参数正是内核态从用户态拷贝过来的缓冲区基址。

a2则是userBuffer0x10偏移,指向一个函数指针,用于调用用户态传入的函数地址。整体调用如下:

总的结构体定义如下:

注意事项

由于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函数下个断点:alt textrcx+0x30处,我们发现该地址的值为0,说明该分支不会执行。会继续执行ObfDereferenceObjectWithTag函数。

但当rcx+0x30处的内存地址不为0时,情况就不一样了:alt text

如果我们再往下,就会执行第一个分支里面的代码,从而将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线程BPreviousMode字段置为0。

线程A 随即退出,隔离内存篡改带来的不稳定因素。

调度 线程B 执行后续操作,此时其所有系统调用将被内核判定 为内核模式发起,从而绕过用户态安全检查。 伪代码如下:

本文配套的 CVE-2024-21338 Exploit代码,全程由本人独立逆向分析、自主编写实现,无任何开源项目复刻、无第三方代码搬运;其中双线程稳定利用架构、内核原语优化方案等均为个人原创研究成果,完整源码已开源至个人 GitHub仓库

通过利用 CVE-2024-21338 漏洞,我们可以将自身进程的Protection字段修改为任何值,从而实现进程保护:

CVE-2024-21338 漏洞的核心在于 AppLocker 驱动对用户态输入的校验缺失,导致攻击者可通过构造特定 IOCTL 请求实现内核态任意函数调用。尽管存在 SMEP 和 KCFG 等安全机制的限制,攻击者仍可通过寻找合法的内核写原语(如ObpDirectoryTeardownCallback)来实现权限提升。

双线程提权方案通过隔离内存篡改风险,显著提高了利用的稳定性,展示了攻击者如何在现代 Windows 安全机制下实现权限提升。该漏洞的发现和利用也提醒我们,内核驱动的输入校验至关重要,任何微小的疏忽都可能被攻击者利用来获取系统控制权。

更新到最新版本的 Windows 操作系统,微软在最新的appid.sys中的0x22A018处添加了ExGetPreviousMode函数进行验证,判断当前线程是否为用户模式线程,如果当前线程为用户模式线程,就会直接返回错误,而不是执行,如图所示:alt textalt textalt text


[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 2天前 被漫雾.编辑 ,原因:
收藏
免费 12
支持
分享
最新回复 (8)
雪    币: 3110
活跃值: (6888)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
牛逼牛逼
2天前
0
雪    币: 540
活跃值: (1254)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
666666
18小时前
0
雪    币: 746
活跃值: (3247)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
金将军不喜欢这则贴文
13小时前
0
雪    币: 105
活跃值: (55)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
这么吊。
11小时前
0
雪    币: 2
活跃值: (748)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
我看看是怎么个回事
11小时前
0
雪    币: 4338
活跃值: (5005)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
6
9小时前
0
雪    币: 209
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
8小时前
0
雪    币: 206
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
好像还挺牛逼的
8小时前
0
游客
登录 | 注册 方可回帖
返回