Sumário executivo
Os pesquisadores da Akamai criaram um novo recurso de IA para análise instantânea da causa raiz. A ferramenta é um sistema supervisionado de vários agentes, chamado PatchDiff-AI. Nesta publicação do blog, estamos usando-a para análise profunda da CVE-2025-60719, que afeta quase todas as versões do Windows.
A vulnerabilidade: uma vulnerabilidade UAF (Use-After-Free) no Driver de Função Auxiliar do Windows (afd.sys) para Winsock causada por uma condição de corrida
O impacto: escalonamento de privilégios locais; um invasor com privilégios baixos pode manipular a memória do kernel e obter privilégios do sistema
Causa raiz: o driver não conseguiu impedir que um endpoint de soquete fosse desvinculado (liberado) enquanto outras operações (como Transfer, GetInformation ou Connect) estavam desfazendo a referência a seus objetos associados
A correção: a Microsoft adicionou um mecanismo de barreira de sincronização (AfdPreventUnbind/AfdReallowUnbind) para bloquear explicitamente o estado do endpoint durante operações críticas
Continue lendo para saber como a ferramenta PatchDiff-AI pode ser usada para analisar rapidamente a causa raiz de uma vulnerabilidade da Patch Tuesday de alto impacto e permitir que as equipes de segurança detectem e atenuem melhor as vulnerabilidades de um dia.
A vulnerabilidade
A CVE-2025-60719 representa uma falha significativa no stack de rede do kernel do Windows, especificamente no afd.sys, a pedra angular por trás da API Winsock. Uma exploração bem-sucedida permite que um processo de baixo privilégio obtenha privilégios do sistema. No entanto, testamos nossa exploração dentro de um processo do AppContainer e ela falhou por causa de permissões insuficientes.
A vulnerabilidade afeta muitos produtos Windows, incluindo todas as seguintes versões do Windows:
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 — versões 1607, 1809, 21H2, 22H2
Outras versões descontinuadas
Um espectro tão amplo de versões afetadas aumenta significativamente a superfície de ataque.
Análise de causa raiz
Usando o PatchDiff-AI, podemos analisar rapidamente o patch de segurança que, de acordo com o comunicado do fornecedor, corrige a vulnerabilidade. A leitura dos resultados da ferramenta indica que as alterações de código relevantes envolvem os métodos AfdSocketTransfer*, AfdGetInformation, AfdBind e AfdConnect.
Um olhar mais atento revela que a causa raiz dessa vulnerabilidade está no gerenciamento do ciclo de vida da estrutura de endpoint AFD (chamada AFD_ENDPOINT) e a falta de atomicidade (sincronização de operações simultâneas) entre buscar um indicador de objeto e usá-lo.
Entre as mudanças
A ferramenta PatchDiff-AI destacou um componente diretamente relacionado à lógica principal da vulnerabilidade: o driver de função auxiliar (afd.sys), que implementa o suporte de rede de camada de transporte principal do Windows. Ele fornece a interface Winsock, gerencia soquetes de rede e lida com outras funcionalidades relacionadas a E/S.
A análise da ferramenta é baseada na versão fixa 10.0.26100.7171, como parte da atualização de segurança KB5068861, e testada em relação à versão vulnerável 10.0.26100.6899, que faz parte da atualização de segurança KB5066835.
Há cinco funções modificadas no total, e todas elas foram classificadas como relacionadas à segurança pela ferramenta.
Ao analisar a função AfdGetInformation, podemos identificar o bloco de código que agora está protegido bloqueando a operação de desvinculação, impedindo que o soquete seja liberado (Figura 1). Como sabemos que essa mudança se refere ao ciclo de vida do soquete e interfere com seu estado, podemos supor que isso esteja relacionado a uma vulnerabilidade de UAF.
Driver de função auxiliar — inicialização rápida
Existem alguns artigos abrangentes sobre como o driver de função auxiliar (afd.sys) funciona e como usá-lo. Em suma, este é um componente do Windows que é responsável por servir a API Winsock. Ele possibilita que processos de baixo privilégio usem o stack de rede de TCP/IP e outros protocolos de comunicação.
Na Figura 2, encontramos muitos binários de referência que chamam afd.sys por meio de controles de entrada/saída (IOCTLs). E podemos entender qual chamada está relacionada a qual interface, conectando os pontos entre as chamadas de aplicação no modo de usuário e a ativação lógica do módulo kernel. Isso nos ajudará mais tarde a realizar chamadas diretas para o driver e depurar o comportamento do driver.
Dentro da lógica
A vulnerabilidade é uma condição de corrida clássica que leva a um cenário de UAF. Ela afeta várias rotinas de despacho, incluindo AfdSocketTransfer*, AfdGetInformation, AfdBind e AfdConnect.
O problema principal surge quando uma aplicação em modo de usuário emite uma solicitação IOCTL específica ao fechar simultaneamente o soquete em uma thread separada. Na versão sem patch, o driver procurou indicadores para o Endpoint, Objeto de arquivo ou Objeto de dispositivo e os usou sem garantir que a memória subjacente não estivesse sendo liberada pela operação de fechamento simultâneo. Isso criou uma janela na qual o kernel operava em memória inválida, permitindo que um invasor local corrompesse a memória do kernel ou ganhasse privilégios elevados.
Quando um processo chama a função afd!AfdGetInformation de uma classe de informação específica usando o handle de um soquete vinculado (listen), isso envolverá a verificação de algumas condições necessárias, como o tipo de soquete e sua camada de protocolo. Então, se seguirmos o fluxo de chamadas, podemos descobrir que a função subjacente tem um caso de switch para as diferentes operações que o chamador pode usar.
O bloco de código vulnerável está no caso AFD_MAX_PATH_SEND_SIZE (Figura 3). Em outras palavras, chegar no caminho vulnerável exigirá que o chamador forneça os valores corretos ao chamar a interface e o soquete esteja em um estado conectado.
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
Na Figura 4, você pode encontrar uma versão descompilada do código vulnerável (antes) em comparação com o código corrigido (depois).
A condição de corrida
O driver afd.sys mantém o ciclo de vida do endpoint, e o objeto Endpoint pode ser acessado simultaneamente a partir de vários threads. Na Figura 5, o m_Endpoint->State representa o estado do soquete.
Para manter o soquete em um estado válido, o módulo do kernel deve lidar com ele com extremo cuidado. Nesse caso, há uma janela durante a qual o estado pode ser alterado através de outro thread e, eventualmente, liberar o endpoint completamente usando o comando de controle unbind.
Um invasor local pode explorar isso criando uma "corrida" entre dois threads:
Thread A: envia repetidamente um IOCTL vulnerável (por exemplo, IOCTL_AFD_GET_INFORMATION)
Thread B: vincula e desvincula repetidamente o handle do soquete
Se o Thread B ganhar a corrida após o Thread A ter buscado o indicador, mas antes que o Thread A o use, o Thread A fará a desreferência da memória liberada.
Invadindo a festa
Usando o relatório do PatchDiff-AI e os outros recursos, podemos entender como usar a função afd!AfdGetInformation e chamá-la com os argumentos corretos para vencer a corrida (Figura 6).
Fig. 6: Código da prova de conceito que aciona a vulnerabilidade
Na Figura 7, você pode encontrar o stack de chamadas da falha quando ela chama AfdGetInformation para o ponto em que há uma exceção PageFault.
Vetor de ataque
Este é um bug de escalonamento de privilégios local que afeta apenas o sistema local. Um invasor que pode executar código arbitrário de um processo local de baixo privilégio pode explorar a condição de corrida e obter privilégios mais altos.
Embora a ferramenta PatchDiff-AI não seja destinada à criação de um exploit, ela pode ajudar a entender o suposto procedimento de exploit.
Inicialização: o invasor abre um AfdSocket válido usando NtCreateFile().
Grooming/pulverização: embora não seja estritamente necessário para a falha, a exploração confiável do EoP geralmente envolve a pulverização de heap para substituir o AFD_ENDPOINT liberado por uma estrutura falsa controlada pelo invasor.
Acionamento: o invasor gera dois threads. O Thread 1 fica em loop em NtDeviceIoControlFile com o IOCTL vulnerável (como IOCTL_AFD_GET_INFORMATION). O Thread 2 fica em loop consecutivo em IOCTL_AFD_BIND e IOCTL_AFD_UNBIND.
Execução: quando a corrida é ganha, o kernel executa uma chamada (como IoGetRelatedDeviceObject) no objeto falso do invasor, levando à manipulação de memória do kernel.
Como proteger seu sistema
Aplique o patch: a única proteção eficaz é instalar a atualização de segurança relevante do Windows. O patch protege afd.sys aplicando estritamente a barreira de desvinculação.
Mitigação: usar um conjunto de regras SIGMA ou YARA para identificar a interação com AFD que poderia indicar uma tentativa de exploração pode reduzir a ameaça. O rastreamento de processos que iniciam as chamadas IOCTL para o driver afd e tentar pulverizar a memória do pool do kernel usando chamadas repetidas pode ser suficiente na maioria dos casos (Figura 8).
Detecção: Como o endpoint AFD (soquete) é exposto por meio do subsistema de E/S do Windows como um identificador de arquivo, podemos interceptar as chamadas IRP e monitorar atividades suspeitas, especialmente de endpoints desconectados.
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_*)
)
)
)
)
}
Considerações finais
Ao usar o PatchDiff-AI, você pode automatizar a correlação entre alterações binárias e lógica de segurança e identificar rapidamente a causa raiz sem se perder no ruído de modificações irrelevantes de código. Isso permite que as equipes de segurança ajam rapidamente para evitar explorações de um dia.
O estudo de caso da CVE-2025-60719 destaca a complexidade do gerenciamento de patches em drivers de kernel e como a análise da ferramenta PatchDiff-AI pode fornecer detalhes perspicazes para vários fins.
Tags