← Back to BrewedIntel
otherlowCVE-2024-38193

Dec 02, 2024 • Exodus Intel VRT

Windows Sockets: From Registered I/O to SYSTEM Privileges

By Luca Ginex Overview This post discusses CVE-2024-38193, a use-after-free vulnerability in the afd.sys Windows driver. Specifically, the vulnerability is in...

Source
Exodus Intelligence
Category
other
Severity
low

Summary

By Luca Ginex Overview This post discusses CVE-2024-38193, a use-after-free vulnerability in the afd.sys Windows driver. Specifically, the vulnerability is in the Registered I/O extension for Windows sockets. The vulnerability was patched in the August 2024 Patch Tuesday. This post describes the exploitation process for the vulnerability. First, we give a general overview of the ... Read more Windows Sockets: From Registered I/O to SYSTEM Privileges The post Windows Sockets: From Registered I/O to SYSTEM Privileges appeared first on Exodus Intelligence .

Published Analysis

By Luca Ginex Overview This post discusses CVE-2024-38193, a use-after-free vulnerability in the afd.sys Windows driver. Specifically, the vulnerability is in the Registered I/O extension for Windows sockets. The vulnerability was patched in the August 2024 Patch Tuesday. This post describes the exploitation process for the vulnerability. First, we give a general overview of the ... Read more Windows Sockets: From Registered I/O to SYSTEM Privileges The post Windows Sockets: From Registered I/O to SYSTEM Privileges appeared first on Exodus Intelligence . By Luca Ginex Overview This post discusses CVE-2024-38193 , a use-after-free vulnerability in the afd.sys Windows driver. Specifically, the vulnerability is in the Registered I/O extension for Windows sockets. The vulnerability was patched in the August 2024 Patch Tuesday . This post describes the exploitation process for the vulnerability. First, we give a general overview of the registered I/O extension for Winsock, describing the driver’s internal structures. We then analyze the vulnerability and proceed to detailing the exploitation strategy. Preliminaries In this section we give a general overview of the registered I/O extension for Winsock and describe the relevant structures for registering I/O extensions. Winsock Registered I/O Extension In Windows, the Registered I/O (RIO) extension can be used in socket programming in order to reduce the amount of system calls issued by userland programs while sending and receiving packets. The RIO extension workflow is as follows: The userland program registers huge buffers. The kernel then obtains kernel mappings for them. The userland program issues send and receive requests by using the receive and send buffer slices of the registered buffers. If a userland program wants to use the Registered I/O extension for sockets, it has to create a socket via the WSASocketA() function. The function’s prototype is as follows: SOCKET WSAAPI WSASocketA( [in] int af, [in] int type, [in] int protocol, [in] LPWSAPROTOCOL_INFOA lpProtocolInfo, [in] GROUP g, [in] DWORD dwFlags ); The userland program has to specify the WSA_FLAG_REGISTERED_IO flag in the dwFlags argument of the call. The program then has to retrieve the function table for the RIO API. This table can be retrieved by issuing a WSAIoctl() call with the SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER IOCTL code. The call returns a RIO_EXTENSION_FUNCTION_TABLE structure. This table contains all the pointers to the RIO API. The definition of the structure is presented in the following code listing: typedef struct _RIO_EXTENSION_FUNCTION_TABLE { DWORD cbSize; LPFN_RIORECEIVE RIOReceive; LPFN_RIORECEIVEEX RIOReceiveEx; LPFN_RIOSEND RIOSend; LPFN_RIOSENDEX RIOSendEx; LPFN_RIOCLOSECOMPLETIONQUEUE RIOCloseCompletionQueue; LPFN_RIOCREATECOMPLETIONQUEUE RIOCreateCompletionQueue; LPFN_RIOCREATEREQUESTQUEUE RIOCreateRequestQueue; LPFN_RIODEQUEUECOMPLETION RIODequeueCompletion; LPFN_RIODEREGISTERBUFFER RIODeregisterBuffer; LPFN_RIONOTIFY RIONotify; LPFN_RIOREGISTERBUFFER RIORegisterBuffer; LPFN_RIORESIZECOMPLETIONQUEUE RIOResizeCompletionQueue; LPFN_RIORESIZEREQUESTQUEUE RIOResizeRequestQueue; } RIO_EXTENSION_FUNCTION_TABLE, *PRIO_EXTENSION_FUNCTION_TABLE; Once the function table is obtained, the program has to register the I/O buffers. These buffers will be used for all subsequent I/O operations. In order to do so, the RIORegisterBuffer() function must be called. The function’s prototype is as follows: RIO_BUFFERID RIORegisterBuffer( _In_ PCHAR DataBuffer, _In_ DWORD DataLength ); The `DataBuffer` argument is a pointer to the buffer to be used and the `DataLength` argument is the size of the buffer. The function returns a `RIO_BUFFERID` buffer descriptor, which is an opaque integer that identifies the registered buffer in the kernel. In order to send or receive data from the socket, the `RIOSend()` and the `RIOReceive()` functions can be used. These functions accept a `RIO_BUF` structure that describes a *slice* of the registered buffers to be used. The definition of the `RIO_BUF` structure is as follows: typedef struct _RIO_BUF { RIO_BUFFERID BufferId; ULONG Offset; ULONG Length; } RIO_BUF, *PRIO_BUF; Kernel Structures Structure definitions are obtained by reverse engineering and may not accurately reflect structures defined in the source code. The recovered structure definition for the registered buffer is as follows: struct RIOBuffer { PMDL AssociatedMDL; _QWORD VirtualAddressBuffer; _DWORD LengthBuffer; _DWORD RefCount; _DWORD IsInvalid; _DWORD Unknown; }; This kernel structure is used by the afd.sys driver to keep track of the registered buffer. It contains the following fields: AssociatedMDL : A pointer to the MDL that describes the userland buffer. VirtualAddressBuffer : A virtual kernel pointer that can be used by the kernel driver to write/read to the userland buffer. LengthBuffer : The size of the userland buffer. RefCount : Field that keeps track of the number of...

Linked Entities

  • CVE-2024-38193