Tuesday, May 14, 2013

Как уронить Windows шестью строчками кода

Inline image 1

Однажды один знакомый рассказал мне про одну уязвимость в Windows. А именно из-за нее можно легко вызвать синий экран смерти шестью строчками кода на Си. Причем программа не требует никаких прав администратора и вызывает только одну функцию масштабирования окна.

...
...

Ядро Windows

В ядре Windows принято не использовать переменные с плавающей точкой. Прямо вообще-вообще не использовать. Поэтому когда приходится работать с чем-то нецелым, используют две целочисленные переменные: числитель и знаменатель.
Также для увеличения производительности некоторые WinAPI функции, вызываемые программой, выполняются в ядре системы. Пример такой функции — ScaleWindowExtEx. Она ничего особенного не делает — функция масштабирует окно.
Прототип функции:
BOOL ScaleWindowExtEx(
  _In_   HDC hdc,
  _In_   int Xnum,
  _In_   int Xdenom,
  _In_   int Ynum,
  _In_   int Ydenom,
  _Out_  LPSIZE lpSize
);


Сама программа

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

Xnum / Xdenom — масштабирование по x.
Ynum / Ydenom — масштабирование по y.

Но функция не всегда делит одно число на другое. Функция будет делить одно число на другое в случае, если разметка контекста рисования (device context) располагается справа налево. В противном случае она, видимо, будет перед делением как-то менять эти числа. Чтобы поменять разметку контекста, есть функция SetLayout.

Значит, создаем контекст рисования вызовом CreateCompatibleDC (NULL). Устанавливаем разметку контекста с помощью SetLayout. После чего вызываем функцию ScaleWindowExtEx с нужными параметрами.

Конечно, программисты Майкрософт не полные дебилы проверяют деление на ноль, и передачей третьим параметром числа ноль Windows не уронишь.
Но вот деление INT_MIN на -1 они не проверяют. Из-за чего происходит необработанное исключение в ядре системе, что приводит к синему экрану.

Такой код программы при добавлении библиотеки gdi32.lib уронит Windows:

#include <windows.h>
#include <limits.h>

int main()
{
    HDC dc = CreateCompatibleDC (NULL);
    SetLayout (dc, LAYOUT_RTL);
    ScaleWindowExtEx (dc, INT_MIN, -1, 1, 1, NULL);
}

Read more: Habrahabr.ru
QR: Inline image 2