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

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

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

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

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

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/piotrflorczyk/cve-2019-1458_poc
Анализ уязвимостейЭксплуатацияОбратная инженерияОбучение и ОбразованиеЭксплуатация Бинарных Файлов
GitHubpiotrflorczyk/cve-2019-1458_poc

cve-2019-1458_POC

POC для cve-2019-1458

Репозиторий
1815394 лет назадПроверено Kitploit

Популярное

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

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

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

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

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

CVE-2019-1458: от «отчёта об эксплуатации в дикой природе» до POC

Введение

В декабре Лаборатория Касперского опубликовала пост в блоге об [используемом в дикой природе 0day-эксплойте][1]. Это заинтересовало меня, потому что, хотя они описали, как работает эксплойт, они не предоставили никакого POC в своём анализе. Поэтому я решил попробовать написать POC для этой уязвимости на основе поста Лаборатории Касперского и анализа патча.
Этот пост описывает мой путь в этом деле.

Сбор информации

Первым делом нужно было собрать как можно больше информации об этой уязвимости. Читая упомянутый пост в блоге, я извлёк следующую информацию:

  • Уязвимость связана с функциональностью переключения окон
  • Для срабатывания требуется имитация нажатий клавиши ALT
  • Необходимы два вызова недокументированного API NtUserMessageCall
  • Нужно создать специальное окно переключения
  • Была некая ссылка на функцию ядра win32k!DrawSwitchWndHilite

Кроме того, есть отличный скриншот декомпилированного кода, показывающий некоторые из перечисленных выше вещей. Если быть точным, он показывает: создание окна переключения, вызов функции с именем toggle_alt_key и множественные вызовы NtUserMessageCall.

Part of decompiled exploit code [Источник изображения][1]

Много полезной информации, но она всё ещё не описывает, как именно работает эта уязвимость и как её вызвать.

Диффинг патча

[Затронутым модулем был win32k.sys][2]. Я скачал пропатченную и непропатченную версии этого модуля.
Для win7 x64 это были:

  • пропатченная: KB4530692
  • непропатченная: KB4525233

Их можно скачать из [Microsoft Update Catalog][3]

Вот результат bindiff при сравнении обеих версий

win32k comparison

После исключения функций, связанных с функциональностью DebugHook, у нас фактически остаётся эта слегка изменённая функция InitFunctionTables()

InitFunctionTables changes

Определённо не самый большой патч.
Это не поможет сразу выявить корневую причину этой уязвимости. Но стоит отметить, что были добавлены некоторые начальные значения для переменных в *(gpsi+0x14E), *(gpsi+0x154), *(gpsi+0x180). Так что это может быть ошибка, связанная с неинициализированной переменной.

Создание POC - шаг за шагом

В этом разделе я покажу, как я постепенно создавал POC, который вызывает эту уязвимость, одновременно выясняя, чем на самом деле является эта уязвимость.

С чего начать

На начальном этапе диффинг патча не дал слишком много полезной информации, поэтому на первой стадии разработки я в основном полагался на пост в блоге Лаборатории Касперского.
Чтобы иметь хорошую тестовую среду, я подготовил VM с Win7 SP1 x64 и последней уязвимой версией win32k. Кроме того, я подключил Windbg к этой VM для отладки ядра и заодно настроил путь к серверу символов.
Я начал исследование с изучения win32k!DrawSwitchWndHilite, которая упоминалась в посте в блоге. Она вызывается из двух мест: xxxMoveSwitchWndHilite и xxxPaintSwitchWindow; последнее сразу привлекло моё внимание из-за окружающих вызовов GetKeyState/GetAsyncKeyState, упомянутых в исходном отчёте. Более того, эти вызовы проверяют, нажата ли клавиша ALT.

Interesting callsite to DrawSwitchWndHilite
Вызов DrawSwitchWndHilite из xxxPaintSwitchWindow

Продолжая прослеживать перекрёстные ссылки вызовов (xxxWrapSwitchWndProc->xxxSwitchWndProc->xxxPaintSwitchWindow->DrawSwitchWndHilite), я обнаружил, что на первый элемент этой цепочки есть ссылка в InitFunctionTables, функции, которая была исправлена в патче.

Затем я обратился к NtUserMessageCall со скриншота декомпилированного кода. Вот объявление этой функции```cpp NtUserMessageCall(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ResultInfo, DWORD dwType, BOOLEAN bAnsi)

Эксплойт вызывает его с `msg = 0x14` и `dwType = 0xE0`. Посмотрим, что он делает.```cpp
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASSEX wcx;
ZeroMemory(&wcx, sizeof(wcx));
wcx.hInstance = hInstance;
wcx.cbSize = sizeof(wcx);
wcx.lpszClassName = L"SploitWnd";
wcx.lpfnWndProc = DefWindowProc;

printf("[*] Registering window\n");
ATOM wndAtom = RegisterClassEx(&wcx);
if (wndAtom == INVALID_ATOM) {
    printf("[-] Failed registering SploitWnd window class\n");
    exit(-1);
}

printf("[*] Creating instance of this window\n");
HWND sploitWnd = CreateWindowEx(0, L"SploitWnd", L"", 0, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);
if (sploitWnd == INVALID_HANDLE_VALUE) {
    printf("[-] Failed to create SploitWnd window\n");
    exit(-1);
}
NtUserMessageCall(sploitWnd, WM_ERASEBKGND, 0, 0, 0, 0xE0, 1);

Здесь я зарегистрировал простой оконный класс и создал окно этого класса. Затем вызвал NtUserMessageCall с теми же параметрами, что и в эксплойте. Чтобы увидеть, что происходит под капотом, я установил точку останова kd> ba e 1 win32k!NtUserMessageCall и запустил код. К этой функции выполняется довольно много вызовов, поэтому мне пришлось поймать нужный, но это было не так сложно — это был вызов с очень коротким стеком вызовов.

NtUserMessageCall
NtUserMessageCall

Проход по коду показал, что она вызывает функцию из массива gapfnMessageCall; индекс вычисляется на основе значения msg и равен 0, поэтому вызов направляется к NtUserfnDWORD.

NtUserfnDWORD
NtUserfnDWORD

Следующий вызов выполняется с использованием значения dwType, и теперь смещение gpsi равно 0x40, а вызов ведёт к xxxWrapSwitchWndProc (эта функция уже появлялась, когда я проверял цепочку вызовов DrawSwitchWndHilite).
xxxWrapSwitchWndProc просто вызывает xxxSwitchWndProc.

xxxSwitchWndProc
xxxSwitchWndProc

И это конец: код падает здесь и не идёт дальше к xxxPaintSwitchWindow, а именно туда мы хотим попасть исходя из значения msg (0x14). Давайте разберёмся, почему.

Запуск правильного пути

На этом этапе код падает, потому что, как показано на предыдущем изображении, fnid нашего окна не равен 0x2A0 (FNID_SWITCH), а отправляемое сообщение не равно 1, поэтому мы попадаем в xxxDefWindowProc. Чтобы избежать этого сценария, нам нужно вызвать xxxSwitchWndProc с fnid, установленным в FNID_SWITCH, чтобы перейти сразу к конструкции switch, а затем к xxxPaintSwitchWindow.
Как установить правильный fnid? Вообще-то та же функция делает это в первом блоке if, нам просто нужно провалить все проверки внутри него, чтобы добраться до инструкции, устанавливающей fnid.

Вот условия, которые нужно выполнить, чтобы провалить все три проверки if:

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