Skip to content
KitploitKITPLOIT
HerramientasBlog
Log in
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/h1bana/cve-2023-21768
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónExplotación de Binarios
GitHubh1bana/cve-2023-21768

CVE-2023-21768

Prueba de concepto de exploit para CVE-2023-21768, una vulnerabilidad de escritura arbitraria en el kernel del controlador de función auxiliar de Windows (AFD.sys) que permite la escalada local de privilegios mediante el anillo de E/S.

Ver Repositorio
3hace 3 añosAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2023-21768

Windows Ancillary Function Driver for WinSock

Según la descripción detallada de CVE-2023-21768 publicada por Microsoft Security Response Center (MSRC), la vulnerabilidad existe en el Ancillary Function Driver (AFD), cuyo nombre de archivo en el sistema es afd.sys. El módulo AFD es el punto de entrada del kernel de WinSock API. En este análisis, lo usaremos para explotar la escalada de privilegios en Windows 11.

Patch Diff and Root Cause Analysis

Descargue dos versiones de afd.sys desde Winbindex, una versión cercana anterior al parche y una versión posterior al parche. Luego use Bindiff para comparar estas dos versiones. bindiff

Comparando las dos versiones en general, vemos que solo una función tiene diferencias: AfdNotifyRemoveIoCompletion. Vea más detalles sobre las diferencias de esta función entre las dos versiones. bindiff

No hay muchas diferencias entre las dos versiones. En la versión posterior al parche, se agregan instrucciones assembly para establecer parámetros y llamar a la función ProbeForWrite. Según la documentación de Microsoft, esta función se usa para verificar si una dirección realmente pertenece al modo usuario, tiene permiso de escritura y está alineada correctamente. Analicemos más en detalle este código:

  • Pre-patch afd.sys version 10.0.22621.608 code1

  • Post-patch afd.sys version 10.0.22621.1105 code2

Ambas verifican el valor de r15_1, si es 0 escriben el valor de var_304 en el puntero indicado en un campo de struct_1. Si es distinto de 0, se llama a ProbeForWrite para asegurar que el puntero apunte a una dirección válida. En la versión pre-patch, luego se escribe el valor de var_304 en el puntero, esta verificación falta. A partir de este parche, podemos suponer que podemos llamar a este código con el valor de arg3_1->field_18 controlado. Si podemos establecer un valor de dirección del kernel en field_18, entonces podemos escribir var_304 en una dirección de memoria del kernel.

=> tipo de bug: escritura-Where arbitraria en el kernel

Ahora necesitamos encontrar cómo provocar el bug. La función AfdNotifyRemoveIoCompletion se llama directamente dentro de la función AfdNotifySock. crossRef

De manera similar, al buscar la referencia cruzada de AfdNotifySock, vemos que no se llama directamente desde ninguna otra función, pero la dirección de la función se almacena en una dirección en .rdata. cross2

Esta dirección se encuentra justo antes de AfdIrpCallDispatch. cross3

Para provocar el bug, llamaré a DeviceIoControl con IOCTL_AFD_NOTIFY_SOCK y se llamará a AfdNotifySock.

BOOL DeviceIoControl(
  [in]                HANDLE       hDevice,
  [in]                DWORD        dwIoControlCode,
  [in, optional]      LPVOID       lpInBuffer,
  [in]                DWORD        nInBufferSize,
  [out, optional]     LPVOID       lpOutBuffer,
  [in]                DWORD        nOutBufferSize,
  [out, optional]     LPDWORD      lpBytesReturned,
  [in, out, optional] LPOVERLAPPED lpOverlapped
);

reverse and debug

Para cada driver, se crea un objeto DRIVER_OBJECT en el kernel, definido así:

typedef struct _DRIVER_OBJECT {
  CSHORT             Type;
  CSHORT             Size;
  PDEVICE_OBJECT     DeviceObject;
  ULONG              Flags;
  PVOID              DriverStart;
  ULONG              DriverSize;
  PVOID              DriverSection;
  PDRIVER_EXTENSION  DriverExtension;
  UNICODE_STRING     DriverName;
  PUNICODE_STRING    HardwareDatabase;
  PFAST_IO_DISPATCH  FastIoDispatch;
  PDRIVER_INITIALIZE DriverInit;
  PDRIVER_STARTIO    DriverStartIo;
  PDRIVER_UNLOAD     DriverUnload;
  PDRIVER_DISPATCH   MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
} DRIVER_OBJECT, *PDRIVER_OBJECT;

El último componente, MajorFunction, es un array que contiene las funciones de dispatch del driver para manejar la comunicación entre kernel y modo usuario. La función dispatch correspondiente a la llamada a DeviceIoControl se almacena en MajorFunction[IRP_MJ_DEVICE_CONTROL].

#define IRP_MJ_DEVICE_CONTROL           0x0e

Desde la función DriverEntry de afd.sys, podemos ver que el driver creó el objeto de dispositivo "\Device\Afd": code3

Asigna MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatchDeviceControl, por lo que al llamar a DeviceIoControl para comunicarse con el kernel, se llamará a esta función. code4

En AFD hay dos tablas de dispatch: AfdIrpCallDispatch y AfdImmediateCallDispatch. dispatchtable1 dispatchtable2

Se puede ver fácilmente que AfdDispatchDeviceIoControl calcula un subíndice mediante IoControlCode y obtiene el valor correspondiente al subíndice de AfdIoctlTable para verificarlo con IoControlCode. 1

Desde la distancia entre la dirección de inicio de AfdImmediateCallDispatch y la dirección donde se almacena AfdNotifySock, calculamos el índice como 73, con el código de control 0x12127. ioctl

int main() {
    WSADATA WSAData;
    SOCKET s;
    SOCKADDR_IN sa;
    int ierr;

    WSAStartup(0x2, &WSAData);
    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    memset(&sa, 0, sizeof(sa));
    sa.sin_port = htons(135);
    sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    sa.sin_family = AF_INET;
    ierr = connect(s, (const struct sockaddr*)&sa, sizeof(sa));

    char outBuf[100];
    DWORD bytesRet;
    DWORD inbuf1[100];

    memset(inbuf1, 0, sizeof(inbuf1));

    DeviceIoControl((HANDLE)s, 0x12127, (LPVOID)inbuf1, 0x30, outBuf, 0, &bytesRet, NULL);
    return 0;
}

it works!

bp1

Como se dijo al principio, la vulnerabilidad ocurre cuando podemos pasar un puntero no validado a través de una estructura. Esta estructura se pasa directamente desde el modo usuario mediante lpInBuffer de DeviceIoControl. Luego se pasa a AfdNotifySock como el cuarto parámetro y se pasa a AfdNotifyRemoveIoCompletion como el tercer parámetro.

Descargar herramienta