В статье упоминаются 9 слоев zip файлов, поэтому это не простой случай скрепления кучей нулей. Почему 9, почему 10 файлов в каждом?
Во-первых, статья Википедии в настоящее время говорит о 5 слоях по 16 файлов. Не знаете, где происходит несоответствие, но это не все, что уместно. Реальный вопрос в том, почему использование гнездования в первую очередь.
DEFLATE, единственный поддерживаемый метод сжатия для zip файлов *, имеет максимальную степень сжатия 1032. Это может быть достигнуто асимптотически для любой повторяющейся последовательности 1-3 байта. Независимо от того, что вы делаете с zip файлом, до тех пор, пока он используется только с помощью DEFLATE, размер распакованного файла будет не более чем в 1032 раза больше размера исходного zip файла.
Поэтому для достижения действительно возмутительных коэффициентов сжатия необходимо использовать вложенные zip файлы. Если у вас есть 2 слоя сжатия, максимальное отношение равно 1032 ^ 2 = 1065024. Для 3, это 1099104768 и так далее. Для 5 слоев, используемых в 42.zip, теоретическая максимальная степень сжатия составляет 1170572956434432. Как вы можете видеть, фактический размер 42.zip далек от этого уровня. Часть этого является накладными расходами формата zip, а часть его заключается в том, что им просто все равно.
Если бы я должен был догадаться, я бы сказал, что 42.zip был сформирован путем создания большого пустого файла и многократного копирования и копирования. Невозможно нажимать пределы формата или максимизировать сжатие или что-то еще - они просто произвольно выбрали 16 копий на слой. Суть заключалась в том, чтобы создать большую полезную нагрузку без особых усилий.
Примечание. Другие форматы сжатия, такие как bzip2, предлагают намного, намного, намного большие максимальные коэффициенты сжатия. Однако большинство zip-парсеров их не принимают.
P.S. Можно создать zip файл, который будет распаковывать копию самого себя (quine). Вы также можете сделать тот, который распаковывает несколько копий. Поэтому, если вы рекурсивно распаковываете файл навсегда, максимально возможный размер бесконечен. Единственное ограничение состоит в том, что он может увеличиться не более чем на 1032 на каждой итерации.
P.P.S. Значение 1032 предполагает, что данные файла в zip не пересекаются. Одна из особенностей формата zip файла состоит в том, что он имеет центральный каталог, в котором перечислены файлы в архиве и смещения данных файла. Если вы создаете несколько записей в файлах, указывающих на одни и те же данные, вы можете достичь гораздо более высоких коэффициентов сжатия даже при отсутствии вложенности, но такой zip файл, скорее всего, будет отклонен парсерами.
Что за штука такая - ZIP-бомба?
Как выяснилось, сжатие ZIP великолепно справляется с повторяющимися данными, так что если у вас имеется гигантский текстовый файл, заполненный повторяющимися данными вроде всех нулей, он очень хорошо сожмётся. В смысле, ОЧЕНЬ хорошо.
Как показал 42.zip , можно сжать 4,5 петабайта (4 500 000 гигабайт) в 42 килобайта. Когда вы попытаетесь посмотреть содержимое архива (извлечь или разархивировать его), то у вас, вероятно, израсходуется всё дисковое пространство или оперативная память.
Как сделать ZIP-бомбу?
Первым делом создадим 10-гигибайтный файл ZIP, заполненный нулями. Можно сделать много вложенных сжатий, но начнём с простого.
В линуксе можно сделать очень просто, командой dd:
Dd if=/dev/zero bs=1M count=10240 >> 10
Получим файлик с именем "10" и 10-ть гигов...:)
Zip -r 10.zip 10
Получим файлик с именем "10.zip", у меня он весит всего пять мегабайт! :)
Как сбросить ZIP-бомбу на жертву?
Ну можно просто дать ему такой файлик на распаковку! :)
Но давайте рассмотрим более прикольный способ:
К сожалению, веб-браузеры не понимают ZIP, но зато они понимают GZIP.
Так что первым делом создадим 10-гигибайтный файл GZIP, заполненный нулями.
Dd if=/dev/zero bs=1M count=10240 | gzip > 10G.gzip
Как видите, её размер 10 МБ. Можно было сжать и получше, но пока хватит.
Теперь установим PHP-скрипт, который доставит её клиенту.
Всё браузер прочитает такой файлик и сдохнет! :)
Можно использовать для борьбы с хакерами и сканерами на уязвимости, пример:
Данный скрипт проверяет заголовки популярных сканеров на уязвимости и выдаёт этот файлик на чтение вместо самого сайта! :)
Итак… Что будет, если запустить этот скрипт?
IE 11
- Память расходуется, IE падает.
Chrome
- Память расходуется, демонстрируется ошибка.
Edge -
Память расходуется, утекает, грузится вечно.
Nikto -
Как будто нормально сканирует, но не выдаёт результат.
SQLmap
- Большой расход памяти, затем падает.
Safari -
Большой расход памяти, затем падает и перезагружается, затем опять большой расход памяти и так далее...
Chrome (Android) -
Память расходуется, демонстрируется ошибка.
Тестирование декомпрессионной бомбы
Декомпрессионная бомба является файлом, разработанным для того, чтобы сбивать или удалять бесполезную программу или систему, считывающую её, т.е. отказывать в обслуживании. Файлы этого проекта могут использоваться для проверки уязвимости приложения для данного типа атаки.
Zip бомба, также известная как как zip of death или декомпрессионная бомба, является вредоносным файлом архива, разработанным для того, чтобы сбивать или удалять бесполезную программу или систему, считывающую её. Он часто используется для отключения антивирусного программного обеспечения, чтобы создать отверстие для более традиционных вирусов. Вместо того, чтобы перехватывать нормальную работу программы, zip бомба позволяет программе работать должным образом, но архив тщательно обрабатывается так, что его распаковка (например, с помощью антивирусного сканера для поиска вирусов) требует слишком много времени, дискового пространства или памяти.
Zip бомба представляет собой небольшой файл для упрощения его передачи и избегания подозрений. Однако, при попытке распаковки данного файла, его содержимое запрашивает большего, чем система может обработать. Еще одним примером zip бомбы является файл 42.zip
, который представляет собой zip файл, содержащий 42 килобайта сжатых данных, содержащий пять уровней вложенных ZIP-файлов в наборах по 16, каждый архив нижнего уровня, содержащий 4,3 гигабайта (4 294 967 295 байт, ~ 3,99 GiB), в общей сложности 4,5 петабайта (4 503 599 626 321 920 байт, ~ 3,99 PiB) несжатых данных. Подобные файлы все еще можно скачать с различных вебсайтов на просторах интернета. Во многих антивирусных сканерах в архивах выполняется только несколько уровней рекурсии, чтобы предотвратить атаки, которые могли бы вызвать переполнение буфера, состояние нехватки памяти или превысить приемлемое время выполнения программы. Zip-бомбы часто (если не всегда) полагаются на повторение идентичных файлов, чтобы достичь своих предельных коэффициентов сжатия. Методы динамического программирования можно использовать для ограничения обхода таких файлов, так что на каждом уровне рекурсивно выполняется только один файл, эффективно преобразуя их экспоненциальный рост в линейный.
При тестировании всегда лучше начинать с малого и продолжать работать на повышение. Начиная работать с самым большим файлом можно серьезно навредить приложению или системе – пользуйтесь этими бомбами с большой осторожностью.
Все файлы были сжаты (bzipped), чтобы обойти ограничение загрузки файлов GitMub 50 МБ. Группы файлов были заархивированы, а затем снова сжаты (bzipped). Удалите эти дополнительные предварительные кодировки перед сканированием.
Дополнительные источники
Zip-бомбы должны преодолеть тот факт, что наиболее часто поддерживаемый парсерами алгоритм сжатия DEFLATE не может превысить степень сжатия 1032 к 1. По этой причине zip-бомбы обычно полагаются на рекурсивную декомпрессию, вкладывая zip-файлы в zip-файлы, чтобы получить дополнительный коэффициент 1032 с каждым слоем. Но трюк работает только в реализациях, которые распаковывают рекурсивно, а большинство этого не делают. Самая известная бомба 42.zip расширяется до грозных 4,5 ПБ, если все шесть слоёв рекурсивно распаковать, но на верхнем слое у неё пустяковые 0,6 МБ. Zip-квайны, как у Кокса и Эллингсена , выдают копию самих себя и, таким образом, расширяются бесконечно при рекурсивной распаковке. Но они тоже совершенно безопасны при распаковке один раз.
В этой статье показано, как создать нерекурсивную zip-бомбу, степень сжатия которой превышает предел DEFLATE в 1032. Она работает путём перекрытия файлов внутри zip-контейнера, чтобы ссылаться на «ядро» сильно сжатых данных в нескольких файлах, не делая несколько копий. Выходной размер zip-бомбы растёт квадратично от входного размера; т. е. степень сжатия улучшается при увеличении размера бомбы. Конструкция зависит от особенностей zip и DEFLATE: она не переносится напрямую на другие форматы файлов или алгоритмы сжатия. Бомба совместима с большинством zip-парсеров, кроме «потоковых», которые анализируют файлы в один проход, не проверяя центральный каталог zip-файла. Мы стараемся сбалансировать две противоречивые цели:
Центральный каталог находится в конце файла zip. Это список заголовков центрального каталога . Каждый заголовок центрального каталога содержит метаданные одного файла, такие как имя файла и контрольная сумма CRC-32, а также обратный указатель на заголовок локального файла. У заголовка центрального каталога длина 46 байт плюс длина имени файла.
Файл состоит из заголовка локального файла, за которым следуют сжатые данные файла. Длина заголовка локального файла - 30 байт плюс длина имени файла. Он содержит избыточную копию метаданных из заголовка центрального каталога, а также размеров сжатого и несжатого файлов данных за ним. Zip - это формат контейнера, а не алгоритм сжатия. Данные каждого файла сжимаются с помощью алгоритма, указанного в метаданных, - обычно DEFLATE .
Это описание формата zip опускает много деталей, которые не нужны для понимания zip-бомбы. Для получения полной информации см. раздел 4.3 APPNOTE.TXT или «Структуру файла PKZip» Флориана Бухгольца, или см. .
Значительная избыточность и много двусмысленностей в формате zip открывают возможности для озорства разных видов. Zip-бомба - это лишь верхушка айсберга. Ссылки для дальнейшего чтения:
$ python3 -m zipfile -e overlap.zip .
Traceback (most recent call last):
...
__main__.BadZipFile: File name in directory "B" and header b"A" differ.
Далее мы рассмотрим, как изменить конструкцию для согласованности имён файлов, сохранив при этом большинство преимуществ перекрывающихся файлов.
Поток DEFLATE представляет собой последовательность блоков , где каждый блок может быть сжатым или несжатым. Мы обычно думаем только о сжатых блоках, например, ядро - это один большой сжатый блок. Но есть и несжатые, которые начинаются с 5-байтового заголовка с полем длины, что означает просто: «выведите следующие n байтов дословно». Распаковка несжатого блока означает только удаление 5-байтового заголовка. Сжатые и несжатые блоки могут свободно смешиваться в потоке DEFLATE. На выходе получается конкатенация результатов распаковки всех блоков по порядку. Понятие «несжатый» имеет значение только на уровне DEFLATE; данные файла по-прежнему считаются «сжатыми» на уровне zip, независимо от того, какие блоки используются.
Проще всего представить эту конструкцию как внутреннее перекрытие, от последнего файла к первому. Начинаем со вставки ядра, которое будет формировать конец файла данных для каждого файла. Добавляем заголовок локального файла LFH N и заголовок центрального каталога CDH N , который указывает на него. Устанавливаем поле метаданных «сжатый размер» в LFH N и CDH N на сжатый размер ядра. Теперь добавляем 5-байтовый заголовок несжатого блока (зелёным цветом на диаграмме), поле длины которого равно размеру LFH N . Добавляем второй заголовок локального файла LFH N −1 и заголовок центрального каталога CDH N −1 , который указывает на него. Устанавливаем поле метаданных «сжатый размер» как новый заголовок сжатого размера ядра плюс размер несжатого заголовка блока (5 байт) плюс размер LFH N .
На данный момент zip-файл содержит два файла с именами Y и Z. Давайте пройдёмся, что увидит парсер при разборе. Предположим, что сжатый размер ядра 1000 байт, а размер LFH N - 31 байт. Начинаем с CDH N −1 и следуем указателю на LFH N −1 . Имя первого файла Y, а сжатый размер его файла данных 1036 байт. Интерпретируя следующие 1036 байт как поток DEFLATE, мы сначала сталкиваемся с 5-байтовым заголовком несжатого блока, который говорит скопировать следующие 31 байт. Записываем следующие 31 байт, которые являются LFH N , которые мы распаковываем и добавляем в файл Y. Двигаясь дальше в потоке DEFLATE, находим сжатый блок (ядро), который распаковываем в файл Y. Теперь мы достигли конца сжатых данных и закончили с файлом Y.
Переходя к следующему файлу, мы следуем указателю от CDH N к LFH N и находим файл с именем Z, сжатый размер которого составляет 1000 байт. Интерпретируя эти 1000 байт как поток DEFLATE, мы сразу же сталкиваемся со сжатым блоком (снова ядро) и распаковываем его в файл Z. Теперь мы достигли конца финального файла и закончили. Выходной файл Z содержит распакованное ядро; выходной файл Y тот же, но дополнительно с префиксом 31 байт LFH N .
Завершаем конструкцию, повторяя процедуру цитирования, пока zip-архив не будет включать нужное количество файлов. Каждый новый файл добавляет заголовок центрального каталога, заголовок локального файла и несжатый блок для цитирования непосредственно следующего заголовка локального файла. Сжатые файловые данные, как правило, представляют собой цепочку несжатых блоков DEFLATE (процитированных заголовков локальных файлов), за которыми следует сжатое ядро. Каждый байт в ядре вносит около 1032N в выходной размер, потому что каждый байт является частью всех N файлов. Выходные файлы тоже разного размера: более ранние больше, чем более поздние, потому что больше цитируют заголовки локальных файлов. Содержимое выходных файлов не имеет особого смысла, но никто не говорил, что оно должно иметь смысл.
У этой конструкции цитирования с перехлёстом лучше совместимость, чем у конструкции полного перекрытия из предыдущего раздела, но совместимость достигается за счёт степени сжатия. Там каждый добавленный файл стоил только заголовка центрального каталога, здесь он стоит заголовка центрального каталога, заголовка локального файла и ещё 5 байт для заголовка цитирования.
Все приличные архиваторы DEFLATE приближаются к степени сжатия 1032 на бесконечном потоке повторяющихся байтов, но нас волнует конкретный размер. В наш размер архива bulk_deflate вмещает больше данных, чем архиваторы общего назначения: примерно на 26 КБ больше, чем zlib и Info-ZIP, и примерно на 15 КБ больше, чем Zopfli , который жертвует скоростью ради качества сжатия.
Цена высокой степени сжатия bulk_deflate - отсутствие универсальности. Он может сжимать только строки из повторяющихся байт и только определённой длины, а именно 517 + 258 k для целого числа k ≥ 0. Кроме хорошего сжатия, bulk_deflate работает быстро, выполняя работу практически за одно и то же время независимо от размера входных данных, не считая работу по фактической записи сжатой строки.
Каждый байт, потраченный на имя файла, означает два байта, не потраченных на ядро (два, потому что каждое имя файла появляется дважды: в заголовке центрального каталога и в заголовке локального файла). Байт имени файла приводит в среднем только к (N + 1) / 4 байта вывода, в то время как байт в ядре считается как 1032 N . Примеры: , , .
Первым соображением совместимости является кодировка. В спецификации формата zip указано, что имена файлов должны интерпретироваться как CP 437 или UTF-8 , если установлен определённый бит флага (APPNOTE.TXT, приложение D). Это основной момент несовместимости между парсерами zip, которые могут интерпретировать имена файлов в некоторой фиксированной или специфичной для локали кодировке. Поэтому для совместимости лучше ограничиться символами с одинаковой кодировкой как в CP 437, так и в UTF-8. А именно, это 95 печатаемых символов US-ASCII.
Мы также связаны ограничениями именования файловой системы. Некоторые файловые системы нечувствительны к регистру, поэтому "a" и "А" не считаются разными именами. Распространённые файловые системы, такие как FAT32, запрещают определённые символы , такие как "*" и "?".
В качестве безопасного, но не обязательно оптимального компромисса, наша zip-бомба будет использовать имена файлов из 36-символьного алфавита, который не включает специальные символы и символы разного регистра:
0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Имена файлов генерируются очевидным образом, все позиции по очереди, с добавлением позиции в конце цикла:
"0", "1", "2", …, "Z",
"00", "01", "02", …, "0Z",
…,
"Z0", "Z1", "Z2", …, "ZZ",
"000", "001", "002", …
Существует 36 имён файлов длиной в один символ, 36² имён длиной два символа и так далее. Четырёх байтов достаточно для 1 727 604 различных имён файлов.
Учитывая, что у имён файлов в архиве обычно будет разная длина, как их лучше упорядочить: от самого короткого к самому длинному или наоборот? Если немного подумать, то лучше ставить самые длинные имена последними. Такое упорядочение добавляет более 900 МБ вывода в zblg.zip , по сравнению с упорядочением от самого длинного к самому короткому. Впрочем, это незначительная оптимизация, потому что 900 МБ - всего 0,0003% от общего размера выдачи.
Чтобы найти оптимальный баланс, нужно оптимизировать только одну переменную N , количество файлов в zip-архиве. Каждое значение N требует определённого объёма накладных расходов для заголовков центрального каталога, заголовков локальных файлов, заголовков блоков цитирования и имён файлов. Всё остальное пространство будет занято ядром. Поскольку N должно быть целым числом, а вы можете поместить только определённое количество файлов, прежде чем размер ядра упадёт до нуля, достаточно проверить каждое возможное значение N и выбрать то, что даёт наибольшую выдачу.
Применение процедуры оптимизации к X = 42 374 для 42.zip находит максимум при N = 250. Эти 250 файлов требуют 21 195 байт служебных данных, оставляя 21 179 байт для ядра. Ядро такого размера распаковывается в 21 841 249 байт (соотношение 1031,3 к 1). 250 копий распакованного ядра плюс немного процитированных заголовков локальных файлов даёт общий распакованный выход 5 461 307 620 байт и степень сжатия 129 000.
CRC-32 можно смоделировать как машину состояний, обновляющую 32-разрядный регистр состояния для каждого входного бита. Основные операции обновления для битов 0 и 1 такие:
Uint32 crc32_update_0(uint32 state) {
// Shift out the least significant bit.
bit b = state & 1;
state = state >> 1;
// If the shifted-out bit was 1, XOR with the CRC-32 constant.
if (b == 1)
state = state ^ 0xedb88320;
return state;
}
uint32 crc32_update_1(uint32 state) {
// Do as for a 0 bit, then XOR with the CRC-32 constant.
return crc32_update_0(state) ^ 0xedb88320;
}
Если вы представляете регистр состояния как 32-элементный двоичный вектор и используете XOR для сложения и умножения, то crc32_update_0 является линейным отображением ; т. е. его можно представить как умножение на бинарную матрицу перехода 32×32. Чтобы понять, почему, обратите внимание, что умножение матрицы на вектор - это просто суммирование столбцов матрицы после умножения каждого столбца на соответствующий элемент вектора. Операция сдвига state >> 1 просто берёт каждый бит i
вектора состояния и умножает его на вектор, который равен нулю везде, кроме бита i
− 1 (нумерация битов справа налево). Условно говоря, конечное XOR state ^ 0xedb88320 происходит только тогда, когда бит b равен единице. Это можно представить как первое умножение b на 0xedb88320, а затем XORинг в данное состояние.
Кроме того, crc32_update_1 - это просто crc32_update_0 плюс (XOR) константа. Это делает crc32_update_1 аффинным преобразованием : умножение матрицы с последующим отображением (т. е., векторное сложение). Мы можем представить умножение матрицы и отображение за один шаг, если увеличим размеры матрицы преобразования до 33×33 и добавим дополнительный элемент к вектору состояния, который всегда равен 1 (такое представление называется однородными координатами).
Матрицы преобразования 33×33 M 0 и M 1 , которые вычисляют изменение состояния CRC-32, выполненное битами 0 и 1, соответственно. Векторы столбцов хранятся с наиболее значащим битом внизу: читая первый столбец снизу вверх, вы видите полиномиальную константу CRC-32 edb8832016 = 111
011
011
0111
0001
0000011
001
00000 2 . Эти две матрицы различаются только в конечном столбце, который представляет вектор трансляции в однородных координатах. В M 0 трансляция равна нулю, а в M 1 - edb88320 16 , полиномиальная константа CRC-32. Единицы сразу над диагональю представляют состояние операции state >> 1
Обе операции crc32_update_0 и crc32_update_1 можно представить матрицей перехода 33×33. Показаны матрицы M 0 и M 1 . Преимущество матричного представления состоит в том, что матрицы можно умножать. Предположим, мы хотим увидеть изменение состояния, произведённое обработкой ASCII-символа "a", двоичное представление которого равно 01100001 2 . Мы можем представить совокупное изменение состояния CRC-32 этих восьми бит в одной матрице преобразования:
Предположим, нам нужна zip-бомба, которая расширяется до 4,5 ПБ, как 42.zip. Насколько большим должен быть архив? С помощью двоичного поиска мы находим, что минимальный размер такого файла составляет 46 МБ.
С Zip64 уже практически неинтересно рассматривать максимальную степень сжатия, потому что мы можем просто продолжать увеличивать размер zip-файла и степень сжатия вместе с ним, пока даже сжатый zip-файл не станет непомерно большим. Интересный порог, однако, составляет 2 64 байта (18 EB или 16 EiB) - столько данных не поместится в большинстве файловых систем. Двоичный поиск находит самую маленькую zip-бомбу, которая производит по крайней мере столько выходных данных: она содержит 12 миллионов файлов и сжатое ядро 1,5 ГБ. Общий размер zip-файла составляет 2,9 ГБ, и он распаковывается в 2 64 +11 727 895 877 байт со степенью сжатия более 6,2 млрд к одному. Я не выкладывал этот файл для скачивания, но вы можете сгенерировать его самостоятельно, используя . У него файлы такого размера, что выявился даже баг в Info-ZIP UnZip 6.0.
Zipbomb --mode=quoted_overlap --num-files=12056313 --compressed-size=1482284040 --zip64 > zbxxl.zip
Bzip2 первым делом кодирует «шаг выполнения» (run-length encoding), уменьшая длину строки повторяющихся байтов в 51 раз. Затем данные разделяются на блоки по 900 КБ и каждый блок сжимается отдельно. Теоретически, один блок может сжаться до 32 байт. 900 000 × 51 / 32 = 1 434 375.
Не обращая внимания на потери совместимости, позволяет ли bzip2 сделать более эффективную бомбу?
Да - но только для небольших файлов. Проблема в том, что в bzip2 нет ничего похожего на несжатые блоки DEFLATE, которые мы использовали для цитирования заголовков локальных файлов. Таким образом, невозможно перекрывать файлы и повторно использовать ядро - для каждого файла нужно записывать собственную копию, поэтому общая степень сжатия будет не лучше, чем коэффициент для любого отдельно взятого файла. На графике внизу мы видим, что без перекрытия bzip2 превосходит DEFLATE только для файлов размером около мегабайта.
Остаётся надежда только на альтернативное средство цитирования заголовков в bzip2, что обсуждается в следующем разделе. Кроме того, если вы знаете, что определённый zip-парсер поддерживает bzip2 и допускает несоответствие имён файлов, вы можете использовать конструкцию полного перекрытия, которая не нуждается в цитировании.
Сравнение коэффициента сжатия у разных zip-бомб. Обратите внимание на логарифмические оси. Каждая конструкция показана с и без Zip64. У конструкций без перекрытия линейная скорость роста, что видно по постоянному соотношению осей. Вертикальное смещение графика bzip2 означает, что степень сжатия bzip2 примерно в тысячу раз больше, чем у DEFLATE. У конструкций DEFLATE с цитированием квадратичная скорость роста, о чём свидетельствует наклон к осям 2:1. Вариант Zip64 немного менее эффективен, но позволяет выдавать более 281 ТБ. Графики для bzip2 с цитированием через дополнительное поле переходят из квадратичных в линейные при достижении либо максимального размера файла (2 32 −2 байта), либо максимально разрешённого количества файлов
В конце структуры заголовка локального файла есть дополнительное поле переменной длины для хранения информации, которая не вписывается в обычные поля заголовка (APPNOTE.TXT, раздел 4.3.7). Дополнительная информация может включать в себя, например, метку точного времени или uid/gid из Unix. Информация Zip64 тоже хранится в дополнительном поле. Дополнительное поле представлено в виде структуры length-value; если увеличить длину без добавления значения, то дополнительное поле включит то, что находится за ним в zip-файле, а именно следующий заголовок локального файла. Используя этот метод, каждый заголовок локального файла может «цитировать» следующие заголовки, заключая их в собственное дополнительное поле. По сравнению с DEFLATE здесь три преимущества:
Предыдущая диаграмма иллюстрирует возможность использования дополнительных полей в bzip2, c и без Zip64. На обоих графиках есть точка перелома, когда рост переходит от квадратичного к линейному. Без Zip64 это происходит там, где достигается максимальный размер несжатого файла (2 32 −2 байта); затем можно увеличить только количество файлов, но не их размер. График полностью заканчивается, когда количество файлов достигает 1809, тогда у нас заканчивается место в дополнительном поле для цитирования дополнительных заголовков. С Zip64 перелом происходит на 1171 файле, после чего может быть увеличен только размер файлов, но не их количество. Дополнительное поле помогает и в случае DEFLATE, но разница настолько мала, что визуально не заметна. Она увеличивает степень сжатия zbsm.zip на 1,2%; zblg.zip на 0,019%; и zbxl.zip на 0,0025%.
Мы разработали конструкцию zip-бомбы с перехлёстом цитирования с учётом совместимости - ряда различий в реализациях, некоторые из которых показаны в таблице ниже. Полученная конструкция совместима с zip-парсерами, которые работают обычным способом, то есть сначала проверяя центральный каталог и используя его в качестве индекса файлов. Среди них уникальный zip-парсер из Nail , который автоматически генерируется из формальной грамматики. Однако конструкция несовместима с «потоковыми» парсерами, которые анализируют zip-файл от начала до конца за один проход без предварительного чтения центрального каталога. По своей природе потоковые парсеры не допускают перекрытия файлов ни в каком виде. Скорее всего, они извлекут только первый файл. Кроме того, они могут даже выдать ошибку, как в случае с