
За полтора года соревнований на CTFtime — picoCTF, HackTheBox CTF, DownUnderCTF — я вывел одно рабочее правило: порядок запуска инструментов стеганоанализа важнее знания самих инструментов. Команда, которая начинает с steghide на PNG (он PNG не поддерживает в принципе), теряет десять минут на ошибку и ещё двадцать на разбирательство. Команда, которая стартует с file → exiftool → strings → формат-специфичный инструмент, закрывает таск до того, как первая допьёт кофе.
Этот алгоритм покрывает подавляющее большинство стего-тасков лёгкого и среднего уровня на forensics CTF тасках. Оставшиеся — Python-скрипты и ручной разбор битовых плоскостей. Ниже — полная последовательность с командами, таблицей совместимости и разбором типичных ловушек.
Любой таск на поиск спрятанных данных начинается одинаково. Не с Stegsolve, не с zsteg, не с steghide — с трёх универсальных команд, которые работают на любом формате.
Первая — file. Расширение файла в forensics CTF заданиях врёт через раз: challenge.txt окажется PNG, image.jpg — ZIP-архивом. Как описывает Trail of Bits CTF Field Guide: «in a CTF, part of the game is to identify the file ourselves, using a heuristic approach.» Команда file challenge.txt определяет реальный тип по магическим байтам в заголовке. Если ответ — PNG image data, 800 x 600, 8-bit/color RGBA, а расширение .txt — перед вами картинка с подменённым расширением. Две секунды на проверку экономят двадцать минут мучений с неподходящим инструментом.
Дополнение для PNG: pngcheck -v challenge.png проверяет целостность чанков. Если авторы таска модифицировали заголовок, изменили размеры в IHDR или дописали данные после IEND — pngcheck это покажет. В отличие от file, которая читает только первые байты, pngcheck валидирует весь файл и ругается на каждый битый чанк.
Вторая — exiftool. Метаданные — классическое место для сокрытия флагов или подсказок. Comment, Author, Description, GPS-координаты, пользовательские XMP-теги — всё вытаскивается одной командой: exiftool challenge.png. На простых тасках Base64-строка в поле Comment — стабильный паттерн. Нюанс: exiftool извлекает не только стандартные EXIF-поля, но и текстовые чанки PNG (tEXt, iTXt, zTXt), IPTC-блоки и даже миниатюры из JPEG. Windows через «Свойства файла» покажет жалкую часть — только CLI покрывает всё. GPS-координаты из EXIF иногда ведут к названию города, которое и оказывается флагом.
Третья — strings с фильтром. strings challenge.png | grep -iE "flag|ctf|key|{|}" вытаскивает все текстовые строки из бинарного файла и фильтрует по паттернам флагов. Тривиально, но на лёгких и средних тасках это решает задачу чаще, чем хотелось бы признавать — флаг просто дописан в конец файла, спрятан в текстовом чанке или валяется в нестандартном поле метаданных. Параметр -n 6 ограничит вывод строками длиннее 6 символов и уберёт мусор.
На этих трёх шагах заканчивается заметная часть стего-тасков. Нет результата — копаем дальше.
Следующий обязательный шаг — проверка на вложенные файлы. File carving, как описывает Trail of Bits — обнаружение файла внутри другого файла и его извлечение. В CTF это стандартный приём: ZIP-архив внутри PNG, второе изображение после маркера IEND, исполняемый файл в аудиозаписи. Матрёшка, короче.
binwalk challenge.png сканирует бинарный файл на известные сигнатуры и показывает все совпадения с их смещениями. Если в выводе есть Zip archive data или JPEG image data на ненулевом смещении — внутри спрятан другой файл. Извлечение одной командой: binwalk -e challenge.png, результат попадёт в папку _challenge.png.extracted.
Но binwalk — штука нервная. Он ищет сигнатуры по смещениям и регулярно генерирует ложные срабатывания. Сжатые данные внутри IDAT-чанков PNG или DCT-блоки JPEG случайно совпадают с заголовками ZIP или TIFF. Как отмечают на форуме Codeby: инструменту не стоит слепо верить, он просматривает только сигнатуры начала. Каждый извлечённый файл обязательно проверяйте через file и пробуйте открыть. Если «архив» не открывается — это фантом.
Если binwalk молчит — foremost -i challenge.png -o output/. Foremost ищет пары header/footer для восстановления файлов и иногда вытаскивает то, что binwalk пропускает. Для ручного извлечения фрагмента с известного смещения: dd if=challenge.png of=extracted.zip bs=1 skip=524288 скопирует данные начиная с байта 524288. Учтите: bs=1 означает побайтовое копирование и на больших файлах работает мучительно медленно; для ускорения: dd if=challenge.png of=extracted.zip bs=4096 iflag=skip_bytes skip=524288.
Главная ошибка новичков в стеганографии CTF — путать инструменты между форматами. steghide на PNG не работает. zsteg на JPEG бесполезен. Таблица ниже — не декорация, а рабочий справочник:
| Инструмент | Форматы | Метод анализа | Когда НЕ подходит |
|---|---|---|---|
| zsteg | PNG, BMP | LSB всех каналов и битовых плоскостей | JPEG, аудио, любой lossy-формат |
| steghide | JPEG, BMP, WAV, AU | Парольная стеганография (графовый алгоритм) | PNG — не поддерживает |
| stegseek | JPEG, BMP, WAV, AU | Брутфорс пароля steghide | Без словаря бесполезен |
| Stegsolve | Любые изображения | Визуальный анализ битовых плоскостей | Нет CLI, требует Java GUI |
| StegOnline | Любые изображения | Веб-аналог Stegsolve | Ограничение на размер файла |
| binwalk | Любые файлы | File carving по сигнатурам | Ложные срабатывания на сжатых данных |
| foremost | Любые файлы | File carving по header/footer | Медленнее binwalk |
| exiftool | Любые файлы | Метаданные | Не анализирует пиксели и семплы |
| Sonic Visualiser | WAV, MP3, FLAC | Спектрограмма | Только визуальный анализ |
| Audacity | WAV, MP3, FLAC | Спектрограмма | Менее тонкая настройка спектра |
| Aperi'Solve | Изображения | Агрегатор: strings, zsteg, binwalk, exiftool | Онлайн, зависит от интернета |
Алгоритм ветвления по типу файла:
convert challenge.gif frame_%03d.png (ImageMagick), анализировать каждый как PNGexiftool на метаданные → конвертировать в WAV через ffmpeg -i challenge.mp3 challenge.wav → анализ WAVLSB (Least Significant Bit) — самый распространённый метод стеганографии в CTF-задачах. Младший бит каждого цветового компонента пикселя заменяется битом скрытого сообщения. Визуально разница в один уровень из 256 неразличима для глаза, но данные полностью сохраняются в младших битах. Красивый фантик — а внутри секрет.
zsteg — инструмент на Ruby, который автоматически перебирает десятки комбинаций каналов, битовых порядков и направлений обхода. Установка: gem install zsteg. Базовый запуск и пример вывода:
$ zsteg challenge.png
b1,r,lsb,xy .. text: "FLAG{hidden_in_plain_sight}"
b1,rgb,lsb,xy .. file: Zip archive data
b2,g,msb,xy .. text: "\x00\x00\x00"
Каждая строка — комбинация параметров. b1,r,lsb,xy означает: первый бит (b1), красный канал (r), порядок от младшего бита (lsb), построчное чтение (xy). Если в выводе появился читаемый текст или файловая сигнатура (PK для ZIP, \x89PNG для PNG) — скрытые данные найдены. Для исчерпывающей проверки: zsteg -a challenge.png перебирает все комбинации, включая обход по столбцам (yx), отдельные битовые плоскости альфа-канала, MSB-порядок. Работает дольше, зато покрывает экзотику.
Ограничение zsteg: только PNG и BMP. Для JPEG не подходит принципиально — lossy-сжатие (DCT) разрушает данные в младших битах. Если дали JPEG с подозрением на LSB — автор таска использовал что-то вроде jsteg, и zsteg этого не увидит.
Stegsolve — Java-приложение для визуального анализа по отдельным битовым плоскостям. Запуск: java -jar Stegsolve.jar. Открываете файл, листаете стрелками между режимами: Red plane 0, Green plane 0, Blue plane 0, Alpha plane 0 и далее. Скрытое изображение, QR-код или текст проявляются как контрастный рисунок на одной из плоскостей. Режим «Data Extract» позволяет вручную задать каналы и порядок для извлечения данных в файл.
Веб-альтернатива — StegOnline (georgeom.net/StegOnline). Те же функции в браузере: битовые плоскости, извлечение LSB, гистограммы. Спасает, когда нет GUI-окружения или Java не установлена. Из каталога CTF-инструментов на GitHub: «big stego tool, upload image and modify/extract data.»
Отдельный момент — альфа-канал. В PNG с прозрачностью (RGBA) данные могут быть спрятаны в альфа-плоскости, которую большинство инструментов не проверяют по умолчанию. zsteg -a проверяет альфа-канал, но в Stegsolve нужно явно пролистать до Alpha plane 0–7. На тасках среднего уровня это встречающийся вектор — и пропустить его обидно.
Steghide — утилита, встраивающая данные в JPEG, BMP, WAV и AU с шифрованием паролем. Последний релиз — версия 0.5.1, 2003 год. Двадцать с лишним лет без обновлений, но входит в стандартные репозитории Kali и Debian и остаётся де-факто стандартом для CTF-задач с парольной стеганографией. Альтернатив по-прежнему нет — такой вот долгожитель.
Порядок действий на JPEG-таске:
steghide info challenge.jpg — проверить наличие встроенных данных; при запросе пароля нажать Enter (пустая строка).steghide extract -sf challenge.jpg -p "" — попробовать пустой пароль. Срабатывает на простых тасках чаще, чем вы думаете.stegseek challenge.jpg /usr/share/wordlists/rockyou.txt. Stegseek — форк steghide, заточенный под перебор. Проходит rockyou.txt (14 миллионов записей) за секунды, тогда как встроенный перебор steghide занял бы часы. На Kali: apt install stegseek, отдельно — .deb из GitHub-репозитория RickdeJager/stegseek.Критическое ограничение: steghide не поддерживает PNG. Это архитектурное ограничение, а не баг. Сообщение the file format of "challenge.png" is not supported означает именно то, что написано. Для PNG — zsteg или Stegsolve. Steghide использует графовый алгоритм выбора позиций встраивания: для JPEG модифицируются DCT-коэффициенты, для BMP — младшие биты пиксельных данных, для WAV/AU — младшие биты семплов. Поэтому zsteg не обнаружит steghide-вставку — принципиально разные методы.
Аудио-стеганография встречается реже изображений, но стабильно всплывает в категориях forensics и misc на CTF. Три основных вектора: визуальные сообщения в спектрограмме, LSB в WAV-семплах и специализированные кодировки.
Самый зрелищный приём — спрятать текст или картинку в спектрограмме аудиофайла. Ухо слышит звуки определённых частот, но не «видит» их распределение по спектру. Авторы тасков генерируют аудио, визуализация которого на спектрограмме проявляет текст флага, QR-код или координаты.
Sonic Visualiser — специализированное приложение для анализа аудио. Откройте файл, добавьте слой спектрограммы через Pane → Add Spectrogram. Настройки: FFT size 1024 или 2048, Window Type — Hann. Если скрытое сообщение есть — оно проявится как рисунок на частотном спектре.
Audacity — более распространённый вариант. Откройте файл, переключите отображение дорожки с Waveform на Spectrogram (выпадающее меню слева от трека). Через Spectrogram Settings: FFT Size 2048–4096, диапазон частот до 22 кГц. Если сообщение спрятано в высокочастотной области — стандартные настройки его обрежут, так что расширение диапазона обязательно.
На тасках среднего и высокого уровня встречаются аудиокодировки, которые не связаны с классической стеганографией, но попадают в ту же CTF-категорию:
Эти кодировки стандартные стего-инструменты не находят. Если steghide info, спектрограмма и LSB-анализ ничего не дали — просто послушайте файл. Morse, SSTV, DTMF опознаются на слух за секунды.
WAV — формат без сжатия, семплы хранятся как есть. Принцип аналогичен изображениям: младшие биты семплов заменяются битами скрытого сообщения. Steghide работает с WAV, но через собственный алгоритм. Для классической LSB стеганографии в аудио есть WavSteg. Альтернативно — Python-скрипт с модулем wave для чтения семплов напрямую и извлечения младших битов.
Когда автоматика молчит — остаётся Python. Pillow позволяет читать пиксели напрямую и визуализировать любую битовую плоскость. Ниже — скрипт визуализации LSB красного канала: каждый пиксель нового изображения становится чёрным (бит = 0) или белым (бит = 1) в зависимости от младшего бита оригинала.
from PIL import Image
img = Image.open("challenge.png")
out = Image.new("RGB", img.size)
for y in range(img.height):
for x in range(img.width):
r, g, b = img.getpixel((x, y))[:3]
val = (r & 1) * 255 # вытаскиваем младший бит
out.putpixel((x, y), (val, val, val))
out.save("lsb_red.png")
Если в lsb_red.png виден текст, QR-код или контрастный рисунок — данные спрятаны в LSB красного канала. Для других каналов замените r на g или b. Для второго бита: (r >> 1) & 1. Для альфа-канала на RGBA: img.getpixel((x, y))[3].
На продвинутых тасках данные распределяются по нескольким каналам, шифруются XOR-маской или записываются в нестандартном порядке — по столбцам, по спирали, через каждый N-й пиксель. Тут zsteg бессилен, а скрипт на Python — единственный путь. Типичный паттерн: прочитать биты из нужных каналов, собрать в байты, декодировать как ASCII или сохранить как файл. Попробуйте модифицировать скрипт под обход по столбцам (yx вместо xy) — на удивление часто это и есть разгадка.
Aperi'Solve (aperisolve.com) — онлайн-агрегатор, который за один запрос запускает strings, exiftool, binwalk, foremost, zsteg и ещё несколько утилит на загруженном файле. По описанию автора: «it gather about 9 or 10 tools at the same time.» На соревновании, когда каждая минута на счету, это экономит время на переключение между утилитами и покрывает базовый анализ одним действием. Ограничение: размер файла и зависимость от интернета. На серьёзных тасках всё равно придётся работать локально.
Ещё один полезный веб-инструмент — CyberChef (gchq.github.io/CyberChef). Не стего-инструмент напрямую, но незаменим для декодирования того, что вы нашли: Base64, hex, XOR, ROT13 и десятки других преобразований. Операция «Magic» автоматически определяет формат и декодирует — особенно спасает, когда из LSB вытащили строку непонятного вида и не ясно, что с ней делать.
Пять ошибок, которые я вижу на каждом соревновании:
1. steghide на PNG. Steghide не поддерживает PNG — архитектурное ограничение. file format not supported означает именно то, что написано. Для PNG — zsteg. Для JPEG — steghide. Путаница между этими двумя — ошибка номер один.
2. Слепое доверие binwalk. Случайное совпадение байт с заголовком ZIP или JPEG в сжатых IDAT-чанках PNG — обычное дело. Каждый извлечённый файл проверяйте через file и пробуйте открыть: если «архив» не открывается — это фантом, не тратьте на него время.
3. Пропуск метаданных. Comment в EXIF, GPS-координаты как название города, Base64 в Description — на простых тасках флаг сидит именно здесь. exiftool обязателен до запуска специализированных инструментов стеганоанализа.
4. Один инструмент на всё. zsteg не найдёт steghide-вставку. steghide не обнаружит LSB стеганографию в PNG. binwalk не увидит данные, распределённые по битовым плоскостям. У каждого инструмента свой метод и свой формат — поэтому таблица совместимости выше не для красоты.
5. Игнорирование звукового содержания аудио. Перед техническим анализом — послушайте файл. Morse-код, SSTV-сигнал, DTMF-тоны распознаются на слух за секунды. Спектрограмму это не заменит, но сузит область поиска.
Отдельная категория — таски с повреждёнными заголовками. Если file не определяет тип, а hexdump -C challenge | head показывает нестандартные первые байты — заголовок файла модифицирован. Сверьте магические байты с эталоном: PNG начинается с 89 50 4E 47 0D 0A 1A 0A, JPEG — с FF D8 FF, BMP — с 42 4D. Исправить можно через hex-редактор (hexedit на Linux, HxD на Windows) или pngcheck, который укажет на конкретный битый чанк. Восстановление сломанного IHDR (изменённые размеры изображения) — ещё один классический трюк авторов тасков: картинка открывается, но часть данных не видна, потому что заявленная высота меньше реальной. Подставляете правильные байты в IHDR — и скрытая часть изображения буйком всплывает.
Стего-категория на CTF — единственная, где порядок действий важнее глубины знаний. В pwn нужно понимать механику переполнения. В crypto — математику. В web — логику приложения. В стего достаточно знать инструменты и последовательность запуска.
Это создаёт иллюзию простоты. Просто — пока таск укладывается в стандартный чеклист. На тасках высокого уровня начинаются кастомные алгоритмы вставки, нестандартные кодировки, XOR-маски поверх LSB — и автоматика заканчивается, остаётся Python и понимание принципов.
Навык стеганоанализа выходит за пределы соревнований. В MITRE ATT&CK стеганография документирована как техника T1001.002 (Steganography, тактика command-and-control) и T1027.003 (Steganography, тактика stealth). Реальные группировки прячут payloads в PNG и JPEG, которые проходят через корпоративные файрволы как обычный веб-трафик. Тот, кто на CTF научился вытаскивать LSB из картинки за минуту, в SOC-команде быстрее обнаружит встроенный payload в подозрительном изображении из логов прокси.
Я бы потратил первые десять часов обучения не на зубрёжку флагов каждого инструмента, а на отработку алгоритма: file → exiftool → strings → формат-специфичный инструмент → Python. Инструменты меняются, последовательность — нет. На HackerLab есть лабы по стеганоанализу, где эту цепочку можно прогнать на реальных тасках — от тривиальных до тех, где без Python-скрипта никуда.
🚀 Хочешь закрепить на практике? Реши задачи по теме на HackerLab — категория «pentest-machines».
0 комментариев
Пожалуйста, войдите, чтобы оставить комментарий.
Загрузка комментариев...