
На рейтинговом CTF в прошлом сезоне наша команда убила два часа на один stego-таск. PNG с котиком, внутри которого binwalk нашёл ZIP-архив, а пароль к нему лежал в LSB красного канала второй картинки из того же задания. Два часа вместо десяти минут — потому что запускали инструменты наугад, пропускали тривиальные проверки и возвращались к началу. Классическая стего-матрёшка, а мы ковыряли её как первоклассники.
После того случая я собрал алгоритм, который с тех пор закрывает типовые forensics CTF задания за 5-15 минут. Ниже — тот самый workflow: от первого взгляда на файл до извлечения флага. С конкретными командами, разбором вывода и ловушками, на которых обжигается каждая вторая команда.
Главная ошибка при решении заданий на стеганографию в CTF — хаотичный перебор инструментов. Запускаешь steghide на PNG (он не поддерживает PNG), потом zsteg на JPEG (он не поддерживает JPEG), теряешь время и нервы. Знакомо?
Workflow, который я использую на каждом стего-таске:
file — определяем реальный формат (расширение может врать)strings | grep -i flag — ищем флаг в открытом текстеexiftool — проверяем метаданные на скрытые комментарииbinwalk — ищем вложенные файлыzsteg для PNG/BMP, steghide для JPEG/WAV, спектрограмма для аудиоПорядок не случаен. Шаги 1-3 занимают секунды и решают простейшие задания. Шаг 4 ловит файлы-матрёшки. И только если ничего не всплыло — переходим к тяжёлой артиллерии. Согласно Trail of Bits CTF Field Guide, для forensics-тасков нужны три навыка: распознавание форматов, работа с бинарными данными и знание Python. Алгоритм выше построен на них.
Первое правило стеганографии CTF — не доверяй расширению файла. На соревнованиях я встречал JPEG, переименованные в .txt, PNG с расширением .docx и ELF-бинарники под видом картинок. Утилита file читает magic bytes — сигнатурные байты в заголовке — и показывает настоящий формат.
file suspicious.png может вернуть JPEG image data, JFIF standard 1.01 — и сразу ясно, что расширение подменено. Дальше работать нужно с JPEG-инструментами, а не с PNG.
Следующий шаг — strings. Утилита вытаскивает все читаемые ASCII-последовательности из бинарного файла. Комбинация strings image.png | grep -i flag ловит флаги, которые автор таска спрятал в конце файла или в текстовых чанках PNG. Параметр -o добавляет смещение: strings -o screenshot.png — пригодится для ручного извлечения через dd.
Отдельно стоит проверить base64. Если среди вывода strings попалась длинная алфавитно-цифровая строка с = или == на конце — пробуйте echo "строка" | base64 -d. Бывает, что весь таск сводится к этому.
Метаданные — частый кандидат на хранение скрытого сообщения в файле. Exiftool читает EXIF, IPTC, XMP и текстовые чанки PNG (tEXt, zTXt, iTXt). В forensics CTF заданиях флаги прячут в полях Comment, Artist, Copyright, Description и даже в GPS-координатах (да, и такое бывает).
Запуск: exiftool image.jpg. Если вывод объёмный — фильтруйте: exiftool image.jpg | grep -i -E "comment|flag|hint|description".
Нюанс с PNG: Windows не показывает EXIF-данные PNG через стандартные свойства файла. Формат PNG технически не поддерживает EXIF-стандарт (в отличие от JPEG), но может хранить метаданные в текстовых чанках. Exiftool корректно читает эти чанки на любой платформе — не полагайтесь на «Свойства файла» в проводнике.
Для полноты картины стоит запустить pngcheck -v file.png. Утилита проверяет целостность всех чанков и покажет ошибки CRC — верный признак модифицированного заголовка IHDR (техника PNG-padding, о ней ниже).
Least Significant Bit — самая распространённая техника стеганографии в CTF. Суть: младший бит каждого байта цветового канала заменяется битом скрытого сообщения. Визуально изменение незаметно — разница в цвете пикселя составляет 1 из 256 градаций. Но если собрать все младшие биты вместе — получим спрятанные данные.
Как отмечает SANReN CSC в forensics-руководстве, LSB стеганография работает потому, что значения 255 (11111111) и 254 (11111110) для человеческого глаза неразличимы, а в последнем бите уже содержится другая информация. Один бит на пиксель — мало. Но в картинке 1920×1080 это 2 073 600 бит, то есть около 253 КБ скрытых данных. Хватит за глаза.
zsteg — Ruby-утилита, которая автоматически проверяет PNG и BMP на LSB-стеганографию по всем каналам и bit planes. Это первое, что стоит запускать на PNG-файле после базовой разведки.
Базовый вызов: zsteg image.png — проверяет стандартные LSB-комбинации (RGB, BGR, обход по строкам и столбцам). Расширенный анализ: zsteg image.png --all — перебирает все возможные комбинации каналов, порядков битов и направлений обхода.
Пример реального вывода:
b1,r,lsb,xy .. text: "flag{lsb_is_easy_peasy}"
b1,rgb,lsb,xy .. file: PNG image data, 200 x 50
b2,g,msb,xy .. text: "\x03\x8a random noise"
Читаем: b1,r,lsb,xy — первый бит, красный канал, least significant bit, обход по строкам (xy). Обращайте внимание на строки с осмысленным текстом или сигнатурами файлов. file: PNG image data — признак вложенного изображения в LSB.
Ловушка: zsteg --all на зашумлённых изображениях генерирует десятки ложных срабатываний. Фильтруйте: zsteg image.png --all | grep -v "^b[2-8]" — отсекает старшие битовые плоскости, где данные прячут редко. Ещё вариант — направить вывод в файл (zsteg --all image.png > results.txt) и искать осмысленное руками.
Stegsolve — Java-приложение с GUI, которое показывает изображение по отдельным битовым плоскостям каждого канала. Где zsteg ищет текст автоматически, Stegsolve визуализирует результат — иногда скрытое сообщение буквально нарисовано в одном из слоёв.
Запуск: java -jar Stegsolve.jar, затем File → Open. Стрелками переключайте фильтры: Red plane 0, Green plane 0, Blue plane 0 — это LSB каждого канала.
Три режима, которые нужно знать:
Data Extract — выбираете конкретные биты конкретных каналов для извлечения данных. Если zsteg показал, что данные в b1,rgb,lsb — отмечаете бит 0 в каналах R, G, B и получаете файл.
Image Combiner — накладывает два изображения с операциями XOR, AND, SUB. Применяется когда в задании дают оригинал и модифицированную копию: XOR двух картинок покажет только изменённые пиксели.
Frame Browser — разбирает GIF и APNG на отдельные кадры. Символы флага могут быть раскиданы по разным кадрам анимации.
Когда zsteg не находит ничего осмысленного, а задание явно указывает на LSB — открывайте Stegsolve и перебирайте плоскости вручную. Автоматика не всегда ловит данные, записанные в нестандартном порядке (по столбцам вместо строк или в альфа-канале).
steghide — один из самых популярных инструментов для стеганографии в CTF. Работает с JPEG, BMP, WAV и AU. В отличие от LSB-утилит, steghide использует собственный алгоритм встраивания с опциональной защитой паролем.
Основные команды: steghide info cover.jpg — проверяет наличие вложенных данных и показывает размер. steghide extract -sf cover.jpg — извлекает. Если пароль не установлен (пустой passphrase, просто Enter) — данные достаются мгновенно.
И вот тут граблями уложена целая аллея: steghide НЕ работает с PNG. Если у вас PNG — используйте zsteg или Stegsolve. Запускаешь steghide extract -sf image.png, получаешь ошибку формата и теряешь время. На каждом втором CTF кто-то из команды на это наступает.
Когда steghide требует пароль, а хинт в задании не помогает — два пути.
Первый — ручной перебор очевидного: пустой пароль (Enter), имя файла, слова из описания задания, «password», «123456». В CTF авторы часто прячут пароль прямо в условии таска — читайте внимательнее.
Второй — автоматический перебор. stegcracker (pip install stegcracker) — обёртка над steghide, перебирающая пароли из словаря:
stegcracker cover.jpg /usr/share/wordlists/rockyou.txt
На типовых CTF-тасках среднего уровня пароль обычно находится за минуту — авторы используют словарные слова.
Если stegcracker не установлен — минимальный bash-скрипт:
while read pass; do
steghide extract -sf cover.jpg -p "$pass" -xf out.txt 2>/dev/null
if [ $? -eq 0 ]; then
echo "Found: $pass"
break
fi
done < wordlist.txt
Не самый быстрый способ, но работает без зависимостей.
binwalk сканирует файл на наличие сигнатур известных форматов внутри него. Это ключевой инструмент для заданий типа «файл-матрёшка» — когда внутри картинки спрятан ZIP-архив, внутри архива другая картинка, а в ней флаг. По данным Trail of Bits CTF Field Guide, files-within-files — одна из самых частых конструкций в forensics-тасках.
Сканирование: binwalk image.jpg покажет список сигнатур с их смещениями. Если в выводе появились строки вроде «Zip archive data» или «gzip compressed data» со смещением больше нуля — внутри файла сидит другой файл.
Извлечение: binwalk -e image.jpg автоматически достанет найденное в директорию _image.jpg.extracted/. После извлечения проверьте содержимое через ls -la и каждый файл через file — убедитесь, что извлечённое не побилось.
Ручное извлечение через dd: если -e не справляется — dd if=image.jpg of=extracted.zip bs=1 skip=45678, где 45678 — смещение из вывода binwalk (столбец DECIMAL).
Первая ловушка: binwalk распознаёт только сигнатуры заголовков. Если автор таска вставил файл без стандартного заголовка или с побитой сигнатурой — binwalk его пропустит. Тут спасает hex-редактор (xxd, HxD, Bless) и ручной поиск характерных байтов.
Вторая: вложенные архивы. Флаг binwalk -e вытаскивает первый уровень, но внутри могут быть ещё архивы. Прогоняйте каждый извлечённый файл через весь алгоритм заново — file, strings, binwalk. Не ленитесь.
Третья: ложные сигнатуры. binwalk может принять случайную последовательность байт за заголовок gzip или LZMA. Если извлечённый файл оказался мусором (нулевой размер, нечитаемое содержимое) — это фантом. Не тратьте время.
Альтернатива — утилита foremost, которая извлекает файлы по заголовкам и футерам. Иногда foremost находит то, что binwalk пропускает. Держите оба в арсенале.
Аудио-стеганография в CTF встречается реже картинок, но задания на неё стабильно попадаются в категории forensics. Основные форматы — WAV и MP3. Две главные техники — спектрограммы и LSB в WAV-сэмплах.
Самый распространённый приём стеганографии в аудио файлах на CTF — текст или изображение, нарисованные в спектрограмме. Файл звучит как шум или искажённая музыка, но открываешь его в спектральном анализаторе — и видишь флаг. Красиво, когда знаешь, куда смотреть.
Audacity — бесплатный аудиоредактор. Откройте файл, кликните на имя дорожки слева и выберите Spectrogram. По умолчанию отображается диапазон до 8 кГц — этого часто мало. В настройках спектрограммы увеличьте максимальную частоту до 22050 Гц, а Window Size до 2048 или 4096 для лучшего разрешения. Иногда сообщение спрятано выше 16 кГц — без корректных настроек вы его просто не увидите.
Sonic Visualiser — специализированный инструмент для анализа аудио. Layer → Add Spectrogram — и вы получаете спектрограмму с более гибкими настройками. Для сложных аудио-тасков он удобнее Audacity.
Базовые проверки для аудио те же: strings audio.wav | grep flag, exiftool audio.wav, binwalk audio.wav — флаг может быть в метаданных или дописан после аудиоданных простым текстом. steghide работает с WAV и AU: steghide extract -sf audio.wav — не забывайте попробовать пустой пароль.
Аналогично изображениям, данные можно записать в младшие биты аудио-сэмплов. Для WAV нет универсального инструмента вроде zsteg — часто приходится писать короткий Python-скрипт:
from scipy.io.wavfile import read
rate, samples = read('stego.wav')
bits = [s & 1 for s in samples.flatten()]
msg = ''.join(chr(int(''.join(map(str, bits[i:i+8])), 2))
for i in range(0, min(len(bits), 800), 8))
print(msg)
Скрипт вытаскивает LSB из каждого сэмпла, собирает биты в байты и декодирует как ASCII. Ограничение до 800 бит (100 символов) — чтобы не ждать обработки всего файла. На реальном таске может потребоваться адаптация: стерео vs моно, 16-bit vs 8-bit сэмплы, другой порядок битов. Но для старта хватит за глаза.
Таблица ниже — компактная шпаргалка. Формат файла определяет стартовый набор инструментов для извлечения данных из PNG, JPG, WAV и других форматов.
| Формат | Инструмент | Команда | Что ищет |
|---|---|---|---|
| PNG/BMP | zsteg | zsteg file.png |
LSB данные во всех каналах |
| PNG/BMP | Stegsolve | GUI, Data Extract | Визуальный анализ битовых плоскостей |
| JPEG/BMP | steghide | steghide extract -sf file.jpg |
Встроенные данные (с паролем или без) |
| WAV/AU | steghide | steghide extract -sf file.wav |
Встроенные данные |
| WAV/MP3 | Audacity | Spectrogram view | Текст/изображение в спектре |
| GIF/APNG | Stegsolve | Frame Browser | Данные в отдельных кадрах |
| Любой | binwalk | binwalk -e file |
Вложенные файлы |
| Любой | exiftool | exiftool file |
Скрытые метаданные |
| Любой | strings | strings file \| grep flag |
Текст в открытом виде |
| Любой | file | file unknown_file |
Реальный формат файла |
Порядок в таблице — приоритет: сначала формат-специфичный инструмент, затем универсальные.
Подменённое расширение. Файл назван image.png, а file показывает JPEG image data. Частая ловушка лёгкого уровня. Решение: всегда начинать с file. Если формат не совпадает — переименуйте файл и работайте с инструментами для реального формата.
Пустой пароль steghide. Новички вводят случайные пароли, когда steghide запрашивает passphrase. Первое действие — нажать Enter. По моим наблюдениям, примерно в трети CTF-тасков с steghide пароль пустой.
Данные после EOF. После маркера конца формата (IEND в PNG, FFD9 в JPEG) дописан текст или другой файл. binwalk это обычно ловит, но strings надёжнее для текстовых вставок — флаг может быть тупо приписан в конец файла.
Альфа-канал PNG. Канал прозрачности (Alpha в RGBA) может хранить скрытые данные. Если zsteg ничего не нашёл в RGB — проверьте альфа-канал через Stegsolve (Alpha plane 0). Отдельный подвох: пиксели с alpha=0 (полная прозрачность), у которых RGB-значения игнорируются при отображении, но содержат данные.
PNG-padding за границами картинки. Техника, при которой уменьшают значение высоты в заголовке IHDR: нижняя часть изображения перестаёт отображаться, но данные остаются в файле. Обнаруживается через pngcheck -v file.png — если CRC блока IHDR не совпадает, высота была изменена. Восстановление: откройте файл в hex-редакторе, найдите 4 байта высоты в IHDR (смещение 0x14-0x17) и увеличьте значение. После изменения пересчитайте CRC или используйте скрипт для автоматического исправления.
Стего в стего. Извлечённый файл из binwalk сам содержит стеганографию. Не останавливайтесь на первом уровне: прогоняйте каждый извлечённый файл через весь алгоритм с начала. На одном CTF я трижды распаковывал матрёшку, прежде чем добрался до флага.
QR-код в битовой плоскости. Отдельный подвид LSB-заданий: в младших битах спрятан не текст, а QR-код. Stegsolve покажет его при переключении на Red/Green/Blue plane 0, после чего нужно сделать скриншот и отсканировать QR любым ридером.
Стеганография в CTF — это ещё и тренировочная площадка для навыков digital forensics. Техники отсюда напрямую связаны с реальными TTP атакующих. В MITRE ATT&CK техника Steganography (T1001.002, Command and Control) описывает использование стеганографии для сокрытия C2-коммуникаций: команды малвари прячутся в пикселях PNG-изображений, загружаемых с легитимных хостингов. Техника T1027.003 (Defense Evasion) — обфускация вредоносной нагрузки внутри медиафайлов. Те же binwalk и zsteg, которые вы запускаете на CTF-тасках, пригодятся при анализе подозрительных файлов в реальных инцидентах.
Девять из десяти стего-тасков среднего уровня решаются за пять минут при наличии чёткого алгоритма. Проблема не в инструментах — их хватает. Проблема в хаосе: запускаешь всё подряд, тонешь в выводе zsteg --all, забываешь проверить strings. На каждом соревновании вижу команды, которые тратят полчаса на таск, решаемый через strings image.png | grep flag.
Мне кажется, стего-категория сильно недооценена. Навыки анализа бинарных форматов, работы с hex-данными, написания Python-парсеров — всё это переносится в форензику, анализ малвари и реверс. Те, кто отмахивается от stego как от «нетехнической» категории, упускают практику, которая пригодится при разборе реальных инцидентов.
Единственное, что раздражает — зависимость от конкретного инструмента встраивания. Если автор таска использовал кастомный скрипт, стандартные утилиты молчат. И тут приходит понимание: инструменты — стартовая точка, а не финишная. Настоящая сила — в способности написать свой парсер на 20 строк Python, когда готовый тул молчит. Если хочешь не просто writeup, а пройти всю атаку самому — на WAPT есть лаба на каждый такой кейс.
🚀 Хочешь закрепить на практике? Реши задачи по теме на HackerLab — категория «pentest-machines».
0 комментариев
Пожалуйста, войдите, чтобы оставить комментарий.
Загрузка комментариев...