Executive summary
Akamai researchers have created a new AI capability for instant root cause analysis. The tool is a supervised multi-agent system, dubbed PatchDiff-AI. In this blog post, we are using it for deep analysis of CVE-2025-60719, which affects almost all Windows versions.
The vulnerability: A use-after-free (UAF) vulnerability in the Windows Ancillary Function Driver (afd.sys) for Winsock caused by a race condition
The impact: Local privilege escalation; an attacker with low privileges can manipulate the kernel memory and gain system privileges
Root cause: The driver failed to prevent a socket endpoint from being unbound (freed) while other operations (like Transfer, GetInformation, or Connect) were actively dereferencing its associated objects
The fix: Microsoft added a synchronization barrier mechanism (AfdPreventUnbind / AfdReallowUnbind) to explicitly lock the endpoint state during critical operations
Keep reading to learn how the PatchDiff-AI tool can be used to quickly analyze the root cause of a high-impact Patch Tuesday vulnerability and enable security teams to better detect and mitigate one-day vulnerabilities.
The vulnerability
CVE-2025-60719 represents a significant flaw in the Windows kernel networking stack, specifically within afd.sys, the cornerstone behind the Winsock API. A successful exploitation enables a low-privilege process to gain system privileges. However, we’ve tested our exploit within an AppContainer process, and it failed because of insufficient permissions.
The vulnerability affects many Windows products, including all the following Windows versions:
Windows Server — 2008 SP2 (x86/x64), 2008 R2 SP1, 2012, 2012 R2, 2016, 2019, 2022, 2022 23H2, 2025
Windows 11 — 23H2, 24H2, 25H2
Windows 10 — versions 1607, 1809, 21H2, 22H2
Other discontinued versions
Such a wide spectrum of affected versions increases the attack surface significantly.
Root cause analysis
Using PatchDiff-AI, we can quickly analyze the security patch that, according to the vendor advisory, fixes the vulnerability. Reading the tool’s results indicates that the relevant code changes involve the methods AfdSocketTransfer*, AfdGetInformation, AfdBind, and AfdConnect.
A closer look reveals that the root cause of this vulnerability lies in the lifecycle management of the AFD Endpoint structure (named AFD_ENDPOINT) and the lack of atomicity (concurrent operations synchronization) between fetching an object pointer and using it.
Between the changes
The PatchDiff-AI tool highlighted one component directly related to the vulnerability’s core logic — the Ancillary Function Driver (afd.sys), which implements Windows’ core transport-layer networking support. It provides the Winsock interface, manages network sockets, and handles other I/O-related functionalities.
The tool analysis is based on the fixed version 10.0.26100.7171, as part of the KB5068861 security update, and tested against the vulnerable version 10.0.26100.6899, which is part of the KB5066835 security update.
There are five modified functions in total, and all of them were classified as security-related by the tool.
By analyzing the AfdGetInformation function, we can identify the code block that is now protected by blocking the unbind operation, preventing the socket from being released (Figure 1). Since we know this change refers to the socket lifecycle and interferes with its state, we can fairly assume this is related to a UAF vulnerability.
Ancillary Function Driver — quick start
There are some comprehensive articles about how Ancillary Function Driver (afd.sys) works and how to use it. In short, this is a Windows component that is responsible for serving the Winsock API. It makes it possible for low-privilege processes to use the network stack for TCP/IP and other communication protocols.
In Figure 2, we find many reference binaries that call afd.sys through input/output controls (IOCTLs). And we can understand which call is related to which interface, connecting the dots between the user-mode application calls and the kernel module logic activation. It will help us later to perform direct calls to the driver and debug the driver's behavior.
Into the logic
The vulnerability is a classic race condition that leads to a UAF scenario. It affects multiple dispatch routines, including AfdSocketTransfer*, AfdGetInformation, AfdBind, and AfdConnect.
The core issue arises when a user-mode application issues a specific IOCTL request while simultaneously closing the socket in a separate thread. In the unpatched version, the driver fetched pointers to the Endpoint, File Object, or Device Object and used them without ensuring that the underlying memory wasn't being freed by the concurrent close operation. This created a window in which the kernel operated on invalid memory, allowing a local attacker to corrupt kernel memory or gain elevated privileges.
When a process calls the afd!AfdGetInformation function for a specific information class using a handle of a bound socket (listen), it will involve checking some required conditions, such as the socket type and its protocol layer. Then, if we follow the call flow, we can find that the underlying function has a switch case for the different operations that the caller can use.
The vulnerable code block resides within the AFD_MAX_PATH_SEND_SIZE case (Figure 3). In other words, hitting the vulnerable path will require the caller to provide the correct values when calling the interface, and the socket to be in a connected state.
class AFD_INFORMATION_CLASS(IntEnum):
AFD_INLINE_MODE = 1 # s: BOOLEAN
AFD_NONBLOCKING_MODE = 2 # s: BOOLEAN
AFD_MAX_SEND_SIZE = 3 # q: ULONG
AFD_SENDS_PENDING = 4 # q: ULONG
AFD_MAX_PATH_SEND_SIZE = 5 # q: ULONG
AFD_RECEIVE_WINDOW_SIZE = 6 # q; s: ULONG
AFD_SEND_WINDOW_SIZE = 7 # q; s: ULONG
AFD_CONNECT_TIME = 8 # q: ULONG (seconds)
AFD_CIRCULAR_QUEUEING = 9 # s: BOOLEAN
AFD_GROUP_ID_AND_TYPE = 10 # q: AFD_GROUP_INFO
AFD_REPORT_PORT_UNREACHABLE = 11 # s: BOOLEAN
AFD_REPORT_NETWORK_UNREACHABLE = 12 # s: BOOLEAN
AFD_DELIVERY_STATUS = 14 # q: SIO_DELIVERY_STATUS
AFD_CANCEL_TL = 15 # s: void
In Figure 4, you can find a decompiled version of the vulnerable code (before) compared with the patched code (after).
The race condition
The afd.sys driver maintains the lifecycle of the endpoint, and the Endpoint object can be accessed concurrently from multiple threads. In Figure 5, the m_Endpoint->State represents the state of the socket.
To keep the socket in a valid state, the kernel module should handle it with extreme care. In this case, there is a window during which the state can be changed through another thread, and eventually free the endpoint altogether using the unbind control command.
A local attacker can exploit this by creating a "race" between two threads:
Thread A: Repeatedly sends a vulnerable IOCTL (e.g., IOCTL_AFD_GET_INFORMATION)
Thread B: Repeatedly binds and unbinds the socket handle
If Thread B wins the race after Thread A has fetched the pointer but before Thread A uses it, Thread A will dereference freed memory.
Crashing the party
Using the PatchDiff-AI report and the other resources, we can understand how to use the afd!AfdGetInformation function, and call it with the correct arguments to win the race (Figure 6).
Fig. 6: Proof of concept code that triggers the vulnerability
In Figure 7, you can find the call stack of the crash when it calls AfdGetInformation to the point where there is a PageFault exception.
Attack vector
This is a local privilege escalation bug that only affects the local system. An attacker who can execute arbitrary code from a low-privilege local process can exploit the race condition and gain higher privileges.
Although the PatchDiff-AI tool is not intended for creating an exploit, it can help with understanding the alleged exploit procedure.
Initialization: The attacker opens a valid AfdSocket using NtCreateFile().
Grooming/spraying: While not strictly necessary for the crash, reliable exploitation for EoP often involves heap spraying to replace the freed AFD_ENDPOINT with a fake structure controlled by the attacker.
Triggering: The attacker spawns two threads. Thread 1 loops on NtDeviceIoControlFile with the vulnerable IOCTL (e.g., IOCTL_AFD_GET_INFORMATION). Thread 2 loops on consecutive IOCTL_AFD_BIND and IOCTL_AFD_UNBIND.
Execution: When the race is won, the kernel executes a call (like IoGetRelatedDeviceObject) on the attacker's fake object, leading to kernel memory manipulation.
How to secure your system
Apply the patch: The only effective protection is to install the relevant Windows security update. The patch hardens afd.sys by strictly enforcing the unbind barrier.
Mitigation: Using a SIGMA or YARA rule set to identify the interaction with AFD that could indicate an exploitation attempt may reduce the threat. Tracing processes that initiate the IOCTL calls to the afd driver, and trying to spray the kernel pool memory using repeated calls, may be sufficient in most cases (Figure 8).
Detection: Since the AFD endpoint (socket) is ultimately exposed through the Windows I/O subsystem as a file handle, we can intercept the IRP calls and monitor for suspicious activities, especially of disconnected endpoints.
import "pe"
rule CVE_2025_60719 {
meta:
description = "Detects exploits for CVE-2025-60719 targeting afd.sys"
author = "Maor Dahan"
date = "2025-12-01"
reference = "https://github.com/akamai/CVE-2025-60719-AFD.SYS"
strings:
// Core Indicators - The specific device name is strong indicator
$str_device = "\\Device\\Afd\\Endpoint" ascii wide
$str_device_double = "\\\\Device\\\\Afd\\\\Endpoint" ascii
// Specific IOCTL constants used in the exploit
// 0x12003 = IOCTL_AFD_BIND
$ioctl_str_bind = "0x12003" ascii
$ioctl_hex_bind = { 03 20 01 00 }
// 0x12113 = IOCTL_AFD_UNBIND
$ioctl_str_unbind = "0x12113" ascii
$ioctl_hex_unbind = { 13 21 01 00 }
// 0x1207B = IOCTL_AFD_GET_INFORMATION
$ioctl_str_info = "0x1207B" ascii
$ioctl_hex_info = { 7B 20 01 00 }
condition:
($str_device or $str_device_double) and
(
(
pe.is_pe and
pe.imports("ntdll.dll", "NtDeviceIoControlFile") and
all of ($ioctl_hex_*)
)
or
(
not pe.is_pe and
(
(
all of ($ioctl_str_*) or
3 of ($ioctl_*)
)
)
)
)
}
Final thoughts
By using PatchDiff-AI you can automate the correlation between binary changes and security logic, and rapidly pinpoint the root cause without getting lost in the noise of irrelevant code modifications. This allows security teams to act quickly to prevent one-day exploits.
The CVE-2025-60719 case study highlights the complexity of patch management in kernel drivers and how the PatchDiff-AI tool’s analysis can provide insightful details for various purposes.
Tags