
recriando exp para cve-2023-21768.
Causa: comparando o AFD.sys de 202209 com o de 202307, na função AfdNotifyRemoveIOCompletion, tanto o Windows de 202209 quanto o de 202307 têm uma etapa que usa a função ProbeForWrite para verificar se uma região de memória está no modo usuário, mas o endereço do buffer verificado difere em 0x8 bytes. Antes do patch dessa vulnerabilidade, essa verificação não existia; pode-se supor que o endereço de verificação do buffer da versão 202209 não estava correto e, portanto, podia ser ineficaz. O buffer dessa verificação está relacionado a uma atribuição intermediária: **(_DWORD **)(a3 + 24) = v20;, em que o buffer que deveria ser verificado é a3+24, e o valor de v20 está relacionado a v8 = IoRemoveIoCompletion(v25, Pool2, v4, (unsigned int)v6, &v20, a1, v13, 0), em que pelo menos Pool2, v4 e v13 parecem ser determinados pelo struct desconhecido passado pelo modo usuário. Portanto, supõe-se que o valor de v20 também esteja relacionado ao struct passado pelo modo usuário~ (olhando o writeup, deve ser o valor de retorno da chamada de KeRemoveQueueEx por IoRemoveIoCompletion)
E se a3+24 armazenar um endereço do modo kernel, pode causar uma primitiva de kernel_arbituary_write, que pode então ser explorada com IORING~ (método de exploração: https://windows-internals.com/one-i-o-ring-to-rule-them-all-a-full-read-write-exploit-primitive-on-windows-11/)
Ambiente de reprodução: Visual Studio 2022 para compilar o código-fonte + Windows 11 202209 (executado no Hyper-V). A opção de compilação é x64 Release; como há o problema de vcruntime140.dll ausente no Hyper-V, foi usada a vinculação estática.
Cadeia de funções do AFD.sys usadas na exploração: AfdFastIOdeviceControl -> AfdNotifySock -> AfdNotifyRemoveIOCompletion, que atribui a um campo de um struct desconhecido um endereço determinado pelo modo usuário, criando assim uma primitiva arbitrary kernel Write-Where que posteriormente é usada pelo IORing
Implementação do exploit: a escrita arbitrária é realizada por meio da função ArbitraryKernelWrite0x1. A parte principal dessa função no exploit reutiliza uma ferramenta do mestre x86matthew para contornar o Winsock e interagir diretamente com o AFD.sys (a função original da ferramenta era criar sockets TCP diretamente) (https://www.x86matthew.com/view_post?id=ntsockets)
O que implementa a escrita em endereço arbitrário mencionada acima é o struct AFD_NOTIFYSOCK_DATA, ou seja, o struct desconhecido citado anteriormente; seus vários campos existem principalmente para contornar as diversas verificações na cadeia de chamadas de função.
O primeiro parâmetro, o handle, é criado por meio da função NT não documentada NtCreateIoCompletion (https://securityintelligence.com/x-force/patch-tuesday-exploit-wednesday-pwning-windows-ancillary-function-driver-winsock/).
Atualizando as impressões da depuração: códigos que parecem muito semelhantes ainda travam em lugares estranhos durante a depuração.
Por exemplo, no início, ao chamar _NtCreateFile, o primeiro parâmetro passado era hSocket, e então __imp_ObReferenceObjectByHandle na função original ficava retornando valores negativos. Depois de dar uma olhada, defini outro handle para ser usado como parâmetro de _NtCreateFile e _NtDeviceIoControlFile (essas duas funções parecem ser usadas principalmente para interagir com o afd.sys; pode-se consultar aquele artigo do x86matthew).
Além disso, no início eu não chamava NtSetIOCompletion e a verificação de IORemoveIOCompletion não passava.. então também consultei a abordagem de https://securityintelligence.com/x-force/patch-tuesday-exploit-wednesday-pwning-windows-ancillary-function-driver-winsock/..
Depois, pedi ajuda no grupo shadow sobre a impossibilidade de carregar a tabela de símbolos, e a causa acabou sendo que o computador que rodava o Windbg não estava com o proxy/VPN ativado, então não conseguia se conectar à tabela de símbolos online.
Por fim, para o Windbg depurar o programa no Hyper-V, não é preciso ser tão complicado quanto no Microsoft Learn~; basta inserir no prompt de comando do Hyper-V algo como bcdedit /debug on; bcdedit /dbgsettings net hostip:(endereço ipv4 do Ethernet default switch no host) port:50001 key:1.2.3.4.
No zip está o projeto completo do Visual Studio usado para a reprodução.
Para finalizar, um agradecimento especial à Tingting e ao veterano mimi, que ajudou a solucionar os problemas do windbg~