Задача была простая: передать архив с конфигами на виртуальную машину через RocketChat. Файловые вложения — заблокированы. Только картинки проходили без вопросов.
Так появился png-zip — утилита, которая прячет произвольные файлы внутри PNG-изображений тремя разными способами.
Append: просто дописать
Самый простой режим — append: полезная нагрузка дописывается после маркера IEND в конце PNG-файла. Декодеры картинок игнорируют всё, что идёт после него, поэтому изображение остаётся валидным и открываемым.
python3 pack.py cover.png secret.tar.gz -o output.pngChunk: кастомные блоки
Данные кладутся в кастомный чанк pnZp, что соответствует спецификации PNG. Если файл больше 2 МБ, он автоматически разбивается на пронумерованные чанки.
python3 pack.py -m chunk cover.png secret.tar.gz -o output.pngLSB: в биты пикселей
Данные записываются в младшие биты каналов пикселей. Изменение — плюс-минус единица на канал, невидимое глазу. Ёмкость зависит от размера картинки: width × height × channels / 8 байт.
python3 pack.py -m lsb cover.png secret.tar.gz -o output.pngЕсть ещё bootstrap-режим — изображение со встроенным скриптом распаковки, которое само себя распаковывает без отдельного unpack.py.
Что ломается
Append и chunk не переживают пересжатие PNG. Если сервис обрабатывает картинки через ImageMagick или перекодирует их при загрузке — данные теряются. LSB пережатие переносит нормально, но конвертация в JPEG съедает весь стеганографический слой (потери в формате).
Данные не шифруются по умолчанию. Если содержимое чувствительное, архив стоит пропустить через GPG ещё перед упаковкой. Append-режим заметен утилите file — она видит данные после IEND. Весь payload грузится в память целиком, поэтому файлы больше 500 МБ потребуют соответствующего RAM.
Честно: я не проверял поведение с очень большими изображениями (больше 10K × 10K). Теоретически всё должно работать, но в реальности там может быть своя подводный камень.
Распаковка и исходники
Python 3.6+, только стандартная библиотека. Есть PowerShell-версия для Windows.
python3 unpack.py output.pngкод и документация
Комментарии