Компиляторная бомба: 29 байт кода → 16 ГБ .exe

    Достойный наследник ZIP-бомбы и PNG-бомбы (которая в своё время положила Хабр) — компиляторная бомба, которая генерирует огромный бинарник из нескольких строчек кода. Наилучший на сегодня вариант предложил в 2016 году пользователь StackExchange под ником Digital Trauma (последняя версия протестирована в 2020 году). Код на C:

    main[-1u]={1};

    Это 14 байт. По условиям конкурса к результату добавляется 15 обязательных байт (дополнительный параметр для компилятора).

    Данный код определяет функцию main как большой массив и инициализирует его первый элемент. Такое поведение заставляет компилятор GCC хранить весь массив в результирующем исполняемом файле.

    Поскольку массив больше двух гигабайт, при компиляции следует указать флаг -mcmodel=medium.

    Компиляция следующей командой:

    gcc -mcmodel=medium cbomb.c -o cbomb

    Не каждая машина осилит такую компиляцию. Эксперименты показали, что с ней справляется виртуальная машина RedHat 5.6 с 10 ГБ RAM, свопом на 12 ГБ и большим локальным разделом в /tmp. GCC версии 4.1.2. Общее время компиляции около 27 минут.

    Компилировать на продакшн-машине не рекомендуется.

    В итоге получается исполняемый файл размером 17 179 875 837 байт (16 гигабайт).

    Конкурс на лучшую бомбу не закончен.

    ZIP и PNG


    Напомним, оптимальная нерекурсивная zip-бомба обеспечивает высокую степень сжатия путём перекрытия файлов внутри zip-контейнера. «Нерекурсивная» означает, что она не зависит от рекурсивной распаковки декомпрессорами файлов, вложенных в zip-архивы: здесь всего один раунд. Выходной размер увеличивается квадратично от входного, достигая степени сжатия более 28 миллионов (10 МБ → 281 ТБ) в пределах формата zip. Ещё большее расширение возможно с помощью 64-разрядных расширений. Конструкция использует только наиболее распространённый алгоритм сжатия DEFLATE и совместима с большинством парсеров zip.

    • zbsm.zip 42 kB → 5.5 GB
    • zblg.zip 10 MB → 281 TB
    • zbxl.zip 46 MB → 4.5 PB (Zip64, менее совместима с парсерами)

    Исходный код:
    git clone https://www.bamsoftware.com/git/zipbomb.git
    zipbomb-20190702.zip

    В графическом формате PNG тоже используется алгоритм сжатия DEFLATE в библиотеке zlib. Таким образом, был создан файл spark.png.bz2 (420 байт). Сначала алгоритм DEFLATE заменяет повторяющиеся строки указателями (LZ77), при этом каждая пара бит кодирует 258 одинаковых байтов с нулями. Степень компрессии составляет 1032 к 1. Затем за дело берётся bzip2, который сжимает длинный набор одинаковых значений в максимально компактный вид. В архиве на 420 байт — файл PNG размером 6 132 534 байт (5,8 МБ) и изображением 225 000 × 225 000  пикселей (50,625 гигапикселей). В пиксельном буфере с тремя байтами на пиксель картинка займёт примерно 141,4 ГБ. Картинка почти полностью состоит из нулей, с секретным сообщением в центре. Закачка такой картинки на Habrastorage приводила к падению сервера, а установка в качестве аватары на Хабре привела к падению сайта. После этого на сайте были установлены противобомбовые ограничения.
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

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

      +2

      Придумано в 2016 году!


      "Конкурс не закончен" — потому что это stackoverflow, там отвечать можно когда угодно. Подсайт code golf, на котором как раз изощряются в "напиши странную штуку за минимальное количество байт".

        +9
        Это alizar, ему можно
        +11

        Немного напомнило «оператор подергивания» ++i--

          –3
          while !terminated {
          ++i--;
          }
          0
          Компилировать на продакшн-машине не рекомендуется.
          «Достаточно одной таблетки.» — «Доктор, а можно две?» — «Не рекомендуется, но можно.» — «А три?» — "… Можно, но не рекомендуется." «72 метра»
          +3
          Проверил на gcc 10.1 в MSYS. Не работает.
          ttldt@DESKTOP-FT9USOD MINGW64 /c/w/cpp/bmb
          $ time gcc -mcmodel=medium main.c -o cbomb
          main.c:1:1: warning: data definition has no type or storage class
              1 | main[-1u]={1};
                | ^~~~
          main.c:1:1: warning: type defaults to 'int' in declaration of 'main' [-Wimplicit-int]
          
          real    3m38,529s
          user    0m0,000s
          sys     0m0,015s


          ttldt@DESKTOP-FT9USOD MINGW64 /c/w/cpp/bmb
          $ ls -al
          итого 125
          drwxr-xr-x 1 ttldt ttldt      0 июл  7 13:35 .
          drwxr-xr-x 1 ttldt ttldt      0 июл  7 13:23 ..
          -rwxr-xr-x 1 ttldt ttldt 126395 июл  7 13:35 cbomb.exe
          -rw-r--r-- 1 ttldt ttldt     14 июл  7 13:24 main.c
            +1
            Вероятно, зависит от платформы. У меня (Arch, GCC 10.1.0 со включённым LTO) виновником торжества отказалось линковка, отожравшая всю оперативную память, хотя сама компиляция слишком долго не длилась.
            「 dvrpd@lptp 」 ~/test % time gcc -mcmodel=medium bomb.c -o bomb
            bomb.c:1:1: предупреждение: определение данных не содержит ни типа, ни класса хранения
            1 | main[-1u]={1};
            | ^~~~
            bomb.c:1:1: предупреждение: в декларации «main» по умолчанию установлен тип «int» [-Wimplicit-int]
            gcc -mcmodel=medium bomb.c -o bomb 46,30s user 62,75s system 95% cpu 1:53,73 total
            「 dvrpd@lptp 」 ~/test % ls -l bomb
            -rwxr-xr-x 1 dvrpd users 17179885600 июл 7 17:36 bomb
            А вот clang собирать отказался.
            bomb.c:1:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
            main[-1u]={1};
            ^
            bomb.c:1:1: warning: variable named 'main' with external linkage has undefined behavior [-Wmain]
            fatal error: error in backend: invalid number of bytes
              0
              clang норм, в отличие от, мягко говоря, сомнительного gcc.
            0
            Не каждая машина осилит такую компиляцию

            Нда, это уж точно.
            fatal error: error in backend: invalid number of byte
              0
              1:1: error: 'main' does not name a type
                0

                Еще один отличный пример, показывающий необходимость огораживать CI (либо не допуская в него кого попало, либо используя одноразовые виртуалки или контейнеры с ограничениями на ресурсы).

                  +7
                  Это не наилучший вариант, а самый заплюсованный.
                  Если проскролить ниже, есть варианты и с петабайтами готового бинаря.
                    0
                    Там потом сменили условие на «минимальный код, создающий файл больше 4 гигабайт»
                      0
                      Питонячий вариант и по этому критерию лучше получается, там всего 16 байт исходник.
                        0
                        А как его скомпилировать правильно? Пробовал вот так, на выходе 1Кб файл:
                        python -m compileall file.py
                        python -m py_compile file.py
                    0
                    Компиляторная бомба: 29 байт кода → 16 ГБ .exe

                    Но разве формат .exe не ограничен 2ГБ?

                      +1
                      С чего бы?
                      image

                      Ну или формулируйте вопрос более внятно. Может, в какой-то среде/компиляторе и ограничен.
                        +8

                        Речь о формате .exe, а не файле с расширением exe, заполненном нулями.

                          +1
                          Самораспаковывающиеся архивы легко могут больше 4 гигов
                            +3
                            Насколько я знаю самораспаковывающиеся архивы состоят из 2-х частей первая часть exe file который не очень большой, и вторая часть это сам архив читается как внешний ресурс.
                            Играет другое ограничение что 32-х битная программа может адресовать только 4Gb памяти, из них как правило 2Gb это адресное пространство ОС(включая порты вводы вывода и т.д.) а 2GB остается на программу где будет куча и стеки всех запущенных потоков. Для 64-х битной программы такого ограничения нету.
                              +3
                              Для 64-х битной программы такого ограничения нету.

                              Из описания формата PE на сайте MS:


                              PE32+ images allow for a 64-bit address space while limiting the image size to 2 gigabytes.

                              Или это относится к чему-то другому?


                              Насколько я помню, ещё есть "забавные особенности" винды в виде ограничения размера стека в 1GB, с которыми тоже мало кто сталкивается.


                              Но суть в том, что в заголовке статьи .exe, а в тексте статьи — RedHat.

                      +2
                      Стало интересно, решил попробовать — скомпилилось за 1.5 минуты, получился файл 17 179 885 752 байт (16 ГБ).
                        0
                        Аналогично, с точностью до байта.
                        +1
                        Компилировать на продакшн-машине не рекомендуется.
                        продакшн-машина грустит в стороне
                          +1
                          А что это делает в новостях?
                            +2
                            План по количеству новостей в единицу времени горит, премия в опасности!
                            0
                            На приличных компиляторах ничего подобного нет

                            Пример:

                            $ gcc cbomb.c -o cbomb.o
                            cbomb.c:1:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
                            main[-1u]={1};
                            ^
                            cbomb.c:1:1: warning: variable named 'main' with external linkage has undefined behavior [-Wmain]
                            fatal error: error in backend: invalid number of bytes
                            $ gcc -mcmodel=medium cbomb.c -o cbomb.o
                            cbomb.c:1:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
                            main[-1u]={1};
                            ^
                            cbomb.c:1:1: warning: variable named 'main' with external linkage has undefined behavior [-Wmain]
                            fatal error: error in backend: invalid number of bytes
                            $ gcc --version
                            Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
                            Apple clang version 11.0.0 (clang-1100.0.33.17)
                            Target: x86_64-apple-darwin18.7.0
                            Thread model: posix
                            InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
                            
                              0
                              PNG-бомбы (которая в своё время положила Хабр)

                              … до слез. Вмятины от укладываний остались? Фото в студию.
                              main[-1u]={1};
                              Очень эмоционально написано. Это не бомба, это протест! Если помочь этому блоку в volatile, то можно унести в кармане облако.
                                0
                                Должно быть — Данный код определяет функцию main как большой массив и инициализирует его ПОСЛЕДНИЙ элемент (а не первый)

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

                                Самое читаемое