Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2023-21768 — Эксплойт с доказательством концепции для CVE-2023-21768, уязвимость произвольной записи в ядро драйвера вспомогательных функций Windows (AFD.sys), позволяющая локальное повышение привилегий через кольцо ввода-вывода. | Kitploit
Инструменты/GitHubGitHub/h1bana/cve-2023-21768
Повышение привилегийАнализ уязвимостейЭксплуатацияЭксплуатация Бинарных Файлов
GitHubh1bana/cve-2023-21768

CVE-2023-21768

Эксплойт с доказательством концепции для CVE-2023-21768, уязвимость произвольной записи в ядро драйвера вспомогательных функций Windows (AFD.sys), позволяющая локальное повышение привилегий через кольцо ввода-вывода.

Репозиторий
33 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2023-21768

Windows Ancillary Function Driver for WinSock

Согласно подробному описанию CVE-2023-21768, опубликованному Microsoft Security Response Center (MSRC), уязвимость существует в Ancillary Function Driver (AFD), файл которого в системе называется afd.sys. AFD модуль является kernel entry point для WinSock API. В этом анализе я буду использовать его для повышения привилегий в Windows 11.

Patch Diff and Root Cause Analysis

Скачиваем две версии afd.sys из Winbindex: одну – самую последнюю до исправления, и одну – после исправления. Затем используем Bindiff для сравнения этих версий. bindiff

Сравнивая две версии в целом, видим, что только одна функция имеет различия – AfdNotifyRemoveIoCompletion. Посмотрим подробнее на различия этой функции между двумя версиями. bindiff

Различий не так много. В версии после исправления добавлены инструкции ассемблера для установки параметров и вызова функции ProbeForWrite. Согласно документации Microsoft, эта функция проверяет, что адрес действительно принадлежит user-mode, имеет права на запись и правильно выровнен. Детальный анализ этого кода:

  • до исправления afd.sys version 10.0.22621.608 code1

  • после исправления afd.sys version 10.0.22621.1105 code2

Обе версии проверяют значение r15_1, если равно 0, записывают значение var_304 по указателю, заданному в поле struct_1. Если не равно 0, вызывается ProbeForWrite, чтобы убедиться, что указатель указывает на корректный адрес. В версии до исправления затем запись значения var_304 по указателю происходит без проверки. Из этого исправления можно предположить, что мы можем вызвать этот код с контролируемым значением arg3_1->field_18. Если можно установить адрес ядра в field_18, то мы сможем записать var_304 в область памяти ядра.

=> bug type: arbitrary kernel Write-Where

Теперь нужно найти способ вызвать баг. Функция AfdNotifyRemoveIoCompletion вызывается непосредственно в функции AfdNotifySock. crossRef

Аналогично, ищем перекрёстные ссылки на AfdNotifySock – она не вызывается напрямую ни из какой другой функции, но её адрес хранится по адресу в .rdata. cross2

Этот адрес находится непосредственно перед AfdIrpCallDispatch. cross3

Чтобы вызвать баг, я вызову DeviceIoControl с IOCTL_AFD_NOTIFY_SOCK, и будет вызвана 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

Для каждого драйвера в ядре создаётся объект DRIVER_OBJECT, который определяется так:

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;

Последний элемент MajorFunction – это массив функций диспетчеризации драйвера для обработки взаимодействий между ядром и user-mode. Функция диспетчеризации, соответствующая вызову DeviceIoControl, хранится в MajorFunction[IRP_MJ_DEVICE_CONTROL].

#define IRP_MJ_DEVICE_CONTROL           0x0e

Из функции DriverEntry afd.sys видно, что драйвер создаёт объект устройства "\Device\Afd": code3

Присваивает MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatchDeviceControl, поэтому при вызове DeviceIoControl для взаимодействия с ядром будет вызвана эта функция. code4

В AFD есть две диспетчерские таблицы: AfdIrpCallDispatch и AfdImmediateCallDispatch. dispatchtable1 dispatchtable2

Легко заметить, что AfdDispatchDeviceIoControl вычисляет индекс по IoControlCode и берёт соответствующее значение из AfdIoctlTable для проверки по IoControlCode. 1

По расстоянию от начального адреса AfdImmediateCallDispatch до адреса хранения AfdNotifySock вычисляем индекс 73, что даёт управляющий код 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

Как было сказано в начале, уязвимость возникает, когда мы можем передать непроверенный указатель через структуру. Эта структура передаётся непосредственно из user-mode через lpInBuffer в DeviceIoControl. Затем она передаётся в AfdNotifySock как четвёртый параметр и в AfdNotifyRemoveIoCompletion как третий параметр.

para1 para2 para3

Скачать инструмент