
recreating exp for cve-2023-21768.
Root Cause: Comparing the AFD.sys between the 202209 and 202307 versions, in the function AfdNotifyRemoveIOCompletion, both the 202209 and 202307 Windows versions include a step that uses the ProbeForWrite function to check whether a memory region is in user mode. However, the buffer address checked differs by 0x8 bytes. Before this vulnerability was patched, there was no such check. It can be speculated that the buffer check address in the 202209 version might be incorrect and therefore ineffective. This buffer check is related to an intermediate assignment: **(_DWORD **)(a3 + 24) = v20; where the buffer that should be checked is a3+24, and the value of v20 is related to v8 = IoRemoveIoCompletion(v25, Pool2, v4, (unsigned int)v6, &v20, a1, v13, 0). At least Pool2, v4, and v13 appear to be determined by the unknown struct passed from user mode, so it is speculated that the value of v20 is also related to that struct from user mode. (Looking at the writeup, it seems to be the return value of IoRemoveIoCompletion calling KeRemoveQueueEx.)
If a3+24 stores a kernel-mode address, it may result in a kernel arbitrary write primitive, which can then be exploited using IORING. (Exploitation method: https://windows-internals.com/one-i-o-ring-to-rule-them-all-a-full-read-write-exploit-primitive-on-windows-11/)
Reproduction Environment: Compiled source code with Visual Studio 2022 + Windows 11 202209 (running on Hyper-V). The compilation option is x64 Release. Due to the missing vcruntime140.dll issue in Hyper-V, static linking was used.
Function call chain in AFD.sys: AfdFastIOdeviceControl -> AfdNotifySock -> AfdNotifyRemoveIOCompletion. It assigns a field of an unknown struct to an address determined by user mode, thereby creating an arbitrary kernel Write-Where primitive, which is then exploited by IORing.
Exploit Implementation: The arbitrary write is achieved through the ArbitraryKernelWrite0x1 function. In the exploit, the main part of this function reuses a wheel from x86matthew to bypass Winsock and interact directly with AFD.sys (the original purpose of the wheel was to directly create a TCP socket) (https://www.x86matthew.com/view_post?id=ntsockets)
The struct implementing the arbitrary address write in the above text is struct AFD_NOTIFYSOCK_DATA, i.e., the unknown struct mentioned earlier. Its various components are mainly designed to bypass the various checks in the function call chain.
The first parameter, the handle, is created using the undocumented NT function NtCreateIoCompletion (https://securityintelligence.com/x-force/patch-tuesday-exploit-wednesday-pwning-windows-ancillary-function-driver-winsock/)
Update with debugging experience: Code that looks very similar in appearance can still get stuck in strange places during debugging.
For example, when first calling _NtCreateFile, the first parameter was hSocket, and in the original function, __imp_ObReferenceObjectByHandle kept returning negative values. After looking into it, a handle was defined as the parameter for both _NtCreateFile and _NtDeviceIoControlFile (these two functions mainly interact with afd.sys, refer to the x86matthew article).
Also, initially NtSetIOCompletion was not called, so the IORemoveIOCompletion check failed. So a reference was made to the approach in https://securityintelligence.com/x-force/patch-tuesday-exploit-wednesday-pwning-windows-ancillary-function-driver-winsock/.
Then, in the shadow group, I asked for help with the symbol table not loading. The reason turned out to be that the computer running Windbg did not have a proxy enabled, so it could not connect to the online symbol server.
Finally, debugging the program on Hyper-V with Windbg is not as complicated as described in Microsoft Learn. Roughly, just enter bcdedit /debug on; bcdedit /dbgsettings net hostip:(IPv4 address of the Ethernet default switch on the host) port:50001 key:1.2.3.4 into the Hyper-V command line.
The zip file contains the complete Visual Studio project used for reproduction.
Finally, special thanks to Sister Tingting and Brother Mimi who helped troubleshoot Windbg.