tykawaii98/CVE-2024-30088

GitHub: tykawaii98/CVE-2024-30088

针对 CVE-2024-30088 的内核 TOCTOU 漏洞分析与利用验证工具。

Stars: 288 | Forks: 60

# CVE-2024-30088 ## 错误 (Bug): - 错误存在于函数 *AuthzBasepCopyoutInternalSecurityAttributes* 中,当内核将当前令牌对象的 **_AUTHZBASEP_SECURITY_ATTRIBUTES_INFORMATION** 复制到用户模式时,其结构如下所示: ``` //0x30 bytes (sizeof) struct _AUTHZBASEP_SECURITY_ATTRIBUTES_INFORMATION { ULONG SecurityAttributeCount; //0x0 struct _LIST_ENTRY SecurityAttributesList; //0x8 ULONG WorkingSecurityAttributeCount; //0x18 struct _LIST_ENTRY WorkingSecurityAttributesList; //0x20 }; ``` - 在执行 **SecurityAttributesList** 的复制时,内核直接将 **SecurityAttribute** 结构体的列表 \**直接*\* 设置为用户提供的指针。随后,它调用 *RtlCopyUnicodeString* 和 *AuthzBasepCopyoutInternalSecurityAttributeValues* 函数来复制 **SecurityAttribute** 结构体的名称和值,导致该函数中存在多个 TOCTOU(检查时间与使用时间竞争)漏洞。 - 通过一个简单的竞争线程,在调用 *RtlCopyUnicodeString* 之前修改属性名称的 **Buffer** 指针 [*],我可以轻易地实现一个任意地址写入,并控制固定值和大小。 ![](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/aeddba004f153515.png) - 注意,还有其他利用此漏洞的方法,但在本例中,我选择利用 *RtlCopyUnicodeString*。 ## 触发错误: - 通过调用 *NtQueryInformationToken* 并使用 **TokenAccesInformation** 类别,可以轻松触发此错误。 ## 补丁: - 补丁使用内核栈上的局部变量(下方代码块中的 **v18**)作为缓冲区,在从用户模式调用时,先复制安全属性名称,然后再写回用户缓冲区。 ``` [...] p_SecurityAttributesList = &a1->SecurityAttributesList; Flink = a1->SecurityAttributesList.Flink; if ( Flink == p_SecurityAttributesList ) return (unsigned int)inserted; v13 = a2 + 0x98; while ( 1 ) { if ( (unsigned int)Feature_2516935995__private_IsEnabledDeviceUsage() ) { inserted = AuthzBasepProbeAndInsertTailList(a2 + 8, v13 - 0x68); if ( inserted < 0 ) goto LABEL_24; } else { [...] } ++*(_DWORD *)a2; *(_WORD *)(v13 - 56) = Flink[3].Flink; *(_DWORD *)(v13 - 52) = HIDWORD(Flink[3].Flink); *(_QWORD *)(v13 - 24) = v13 - 32; *(_QWORD *)(v13 - 32) = v13 - 32; *(_QWORD *)v13 = v13 - 8; *(_QWORD *)(v13 - 8) = v13 - 8; *(_QWORD *)(v13 - 48) = 0i64; *(_DWORD *)(v13 - 40) = 0; *(_DWORD *)(v13 - 16) = 0; Flink_low = LOWORD(Flink[2].Flink); v19 = Flink_low; v17 = (wchar_t *)((v10 + 1) & 0xFFFFFFFFFFFFFFFEui64); v15 = (unsigned __int64)v17 + Flink_low; if ( (unsigned __int64)v17 + Flink_low > v6 ) break; if ( (unsigned int)Feature_3391791421__private_IsEnabledDeviceUsage() ) { *(_QWORD *)&v18.Length = 0i64; v18.MaximumLength = Flink_low; v18.Buffer = v17; RtlCopyUnicodeString(&v18.Length, (unsigned __int16 *)&Flink[2]); *(_UNICODE_STRING *)(v13 - 0x48) = v18; } else { [...] } inserted = AuthzBasepCopyoutInternalSecurityAttributeValues( (__int64)Flink, v13 - 104, v15, (int)v6 - (int)v15, &v19); [...] ``` - 在调试会话中,我们可以看到 **rcx** 是补丁后的内核地址: ``` 5: kd> nt!AuthzBasepCopyoutInternalSecurityAttributes+0x1aa: fffff803`5dbcf14a e8810fa5ff call nt!RtlCopyUnicodeString (fffff803`5d6200d0) 5: kd> r rax=0000025a81d006a0 rbx=0000025a81d00590 rcx=ffffe20697c4f778 rdx=ffffa609c7a101a0 rsi=0000025a81d00598 rdi=0000025a81d00628 rip=fffff8035dbcf14a rsp=ffffe20697c4f740 rbp=0000025a81d006c0 r8=0000000000000003 r9=0000025a81d00590 r10=ffffa609c816ef78 r11=ffffe20697c4f7d0 r12=0000000000000a70 r13=ffffa609ca9b1118 r14=ffffa609c7a10180 r15=0000025a81d01000 iopl=0 nv up ei pl nz na pe nc cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00040202 nt!AuthzBasepCopyoutInternalSecurityAttributes+0x1aa: fffff803`5dbcf14a e8810fa5ff call nt!RtlCopyUnicodeString (fffff803`5d6200d0) ``` ## POC: - https://youtu.be/y5LnlHjzA64
标签:CVE-2024-30088, NtQueryInformationToken, RtlCopyUnicodeString, TOCTOU, TokenAccessInformation, Windows 内核, 任意地址写, 内核态到用户态拷贝, 内核栈缓冲区, 内核漏洞, 协议分析, 安全属性复制, 指针操控, 权限提升, 漏洞分析, 补丁分析, 赛车攻击, 路径探测