
PoC для CVE-2018-7249
Проблема была обнаружена в secdrv.sys, поставляемом в Microsoft Windows Vista, Windows 7, Windows 8 и Windows 8.1 до KB3086255, а также в Macrovision SafeDisc. Два правильно синхронизированных вызова IOCTL 0xCA002813 могут вызвать состояние гонки, приводящее к use-after-free. При эксплуатации непривилегированный злоумышленник может выполнить произвольный код в режиме ядра.
Уязвимость была сообщена Microsoft, и, поскольку она не затрагивает обновлённые системы Windows (только версии до KB3086255), они не будут принимать никаких мер. Была протестирована и успешно эксплуатирована на Windows 7 x86.
Также связана с CVE-2018-7250.

Этот документ описывает моё небольшое исследование драйвера secdrv.sys. Все описанные поведения драйвера были получены с помощью реверс-инжиниринга и могут быть неверными или неточными.
Смещение 0x4 входного буфера IOCTL (0x0CA002813) содержит число, которое я буду называть TYPE. Основная функция-обработчик этого IOCTL (0x0CA002813), sub_11A88, принимает 3 различных типа: 0x96, 0x97 и 0x98.
После того, как IOCTL типа 0x96 выделил новый блок и инициализировал его, но не полностью, он копирует блок в пользовательский режим. 16 бит в новом выделенном блоке не были инициализированы и содержат данные от предыдущих выделений PagedPool. Эти неинициализированные биты затем копируются в пользовательский режим по адресу .text:00011BE9 инструкцией REP MOVSD. PoC-код здесь.
Когда вызывается IOCTL типа 0x97, он находит нужный блок, ранее выделенный с типом 0x96, по его тегу. Если блок уже освобождён IOCTL типа 0x97, DeviceIoControl возвращает ошибку. Уязвимость в том, что блок, используемый типом 0x97, может быть освобождён ВО ВРЕМЯ его работы (поскольку не используются механизмы синхронизации), что приводит к использованию после освобождения, если гонка будет выиграна. Если злоумышленнику удастся освободить блок во время работы IOCTL типа 0x97 (используя тип 0x98) и выделить новый блок, контролируемый им, в точно то же место в памяти, он может перезаписать указатель на другую структуру, содержащую указатель на функцию, который может быть использован для перехвата потока выполнения драйвера и выполнения произвольного кода в ring 0. Поскольку процедура шифрования выполняется над пользовательским буфером, который может быть огромного размера, шифрование может выполняться долго, что даёт идеальное временное окно для IOCTL типа 0x98, чтобы освободить блок, пока он ещё используется. Временное окно может быть настолько большим (более 1 секунды!), что гонка может быть надёжно выиграна с первой попытки. Use-after-free начинается по адресу .text:00011B68, а фактический вызов, который будет перехвачен для перехода к shellcode, происходит по адресу .text:00011B86.
Шаги для успешной эксплуатации этой уязвимости следующие:
ОС: Windows 7 Kernel Version 7600 MP (1 procs) Free x86 compatible Built by: 7600.16385.x86fre.win7_rtm.090713-1255 ВМ: 4GB RAM, 1 CPU Оборудование: Windows 10 Pro 64 bit, Motherboard Gigabyte Z370 HD3, 16GB RAM, Intel i5-8400 2.80GHz (6 CPUs)