
На одном из CTF задание из категории Stego казалось тривиальным: JPEG-картинка с текстом на немецком языке. Тридцать минут ушло на steghide, stegsolve, strings — ноль результатов. Флаг был в ZIP-архиве, склеенном с концом JPEG-файла, причём первый байт magic-сигнатуры ZIP 50 4B 03 04 оказался намеренно заменён с 0x50 на 0xFF, превратив начало в FF 4B 03 04. binwalk находил конец архива, но не начало. Задача решилась за минуту — один байт в hex-редакторе, unzip, готово. Этот кейс (подробно разобранный в writeup на dominicbreuker.com) показывает главное: стего-таски решаются не перебором инструментов, а системным чек-листом, где каждый шаг сужает область поиска.
Русскоязычные гайды по стеганографии в CTF обычно дают список утилит: «вот steghide, вот binwalk, вот exiftool». Проблема в том, что новичок не понимает порядок запуска и момент перехода к следующему инструменту. Вот порядок, который я использую сам.
Шаг 1 — определение реального типа файла. Расширение .png в задании не гарантирует PNG. Команда file mystery.png покажет реальный формат по magic bytes. Если file возвращает «JPEG image data» при расширении .png — уже подсказка: автор задания маскирует формат.
Шаг 2 — поиск текстовых строк. strings mystery.png | grep -iE "flag|ctf|key" — грубый, но неожиданно эффективный фильтр. Иногда флаг лежит прямо в бинарных данных открытым текстом. Для фильтрации мусора полезен флаг длины: strings -n 10 mystery.png показывает только строки от десяти символов.
Шаг 3 — метаданные. exiftool mystery.png извлекает EXIF, IPTC, XMP и прочие метаполя. В CTF флаги прячут в Comment, Artist, Copyright, а GPS-координаты дают подсказку для геолокационных тасков.
Шаг 4 — поиск вложенных файлов. binwalk mystery.png сканирует файл на сигнатуры других форматов: ZIP, RAR, gzip, PDF, ELF. Найденное вложение извлекается через binwalk -e mystery.png в отдельную директорию.
Шаг 5 — LSB-анализ. Для PNG и BMP — zsteg mystery.png проверяет младшие биты всех каналов. Визуальный анализ битовых плоскостей — через Stegsolve (Java-приложение с GUI).
Шаг 6 — password-based стеганография. steghide extract -sf mystery.jpg пытается извлечь данные из JPEG или WAV. При наличии пароля — брутфорс через stegseek или stegcracker со словарём rockyou.txt.
Порядок не случаен: каждый следующий шаг дороже по времени. file и strings — секунды. exiftool — секунды. binwalk — секунды. zsteg — секунды. А вот брутфорс steghide с rockyou.txt — часы. Запускать его первым — пустая трата времени на CTF, где каждая минута на счету.
exiftool — рабочая лошадка для чтения метаданных из файлов практически любого формата. В forensics CTF заданиях он делает две вещи: находит флаг, спрятанный в метаполях, и даёт подсказки для дальнейшего анализа.
Расширенный вызов exiftool -v2 target.jpg включает вывод всех тегов, включая нестандартные. В CTF данные прячут в полях, которые не отображаются в обычном просмотрщике:
50 deg 27' 4.68" N, 30 deg 31' 24.12" E (для десятичного формата: exiftool -c '%.6f' target.jpg; вбить в Google Maps — получить название города-флага)Нюанс, на котором спотыкаются многие: PNG формально не поддерживает EXIF в классическом понимании (в отличие от JPEG), но хранит метаданные в текстовых чанках — tEXt, zTXt, iTXt. exiftool читает и их. Если Windows через стандартные «Свойства» показывает пустые поля для PNG — это не значит, что метаданных нет. На root-me.org есть классическая задача уровня 5 баллов, где GPS-координаты из метаданных PNG ведут к городу-флагу, а Windows-свойства файла при этом выглядят пустыми.
Ещё один диагностический приём — анализ несоответствий. Если exiftool показывает Software: Adobe Photoshop для файла, который по легенде задания «снят на телефон» — это маркер модификации. Аномальный размер тоже информативен: PNG 100×100 пикселей весом 2 МБ почти наверняка содержит дополнительные скрытые данные в файлах. Картинка 100 на 100 не может столько весить — значит, внутри что-то лишнее.
binwalk изначально создавался для анализа прошивок IoT-устройств, но прижился в CTF-стеганографии благодаря обширной базе файловых сигнатур. Его задача проста — найти внутри одного файла сигнатуры других форматов.
Базовый сценарий: binwalk target.png сканирует файл и выводит таблицу найденных сигнатур со смещениями. Когда внутри картинки спрятан архив, вывод выглядит примерно так:
DECIMAL HEXADECIMAL DESCRIPTION
0 0x0 PNG image, 800 x 600, 8-bit RGBA
1024567 0xFA037 Zip archive data, v2.0 to extract
1025891 0xFA563 End of Zip archive
Обнаруженное вложение извлекается командой binwalk -e target.png в директорию _target.png.extracted/. Для рекурсивного извлечения (архив внутри картинки, внутри архива — другая картинка, матрёшка) есть флаг -M: binwalk -eM target.png проходит все уровни вложенности.
Самый частый приём авторов CTF-заданий — конкатенация файлов. Берётся JPEG и к нему командой cat image.jpg archive.rar > challenge.jpg дописывается RAR-архив. Просмотрщик отображает нормальную картинку (он читает данные до маркера конца JPEG 0xFFD9 и игнорирует остаток), а binwalk видит обе сигнатуры.
Но у binwalk есть слабое место: если magic bytes вложенного файла намеренно повреждены (как в кейсе из вступления — замена 0x50 на 0xFF в первом байте ZIP-сигнатуры), сканер не обнаружит начало архива. В таких случаях binwalk покажет только «End of Zip archive» без начала. Это сигнал для ручного анализа hex-дампа — подробнее в разделе про appended data.
LSB (Least Significant Bit) — самый распространённый метод стеганографии в CTF-заданиях. Принцип: в каждом пикселе изображения младший бит цветового канала заменяется битом секретного сообщения. Визуальная разница неразличима (изменение яркости на 1 из 255), но данные извлекаются программно.
zsteg — мой первый выбор для обнаружения LSB-стеганографии в PNG и BMP. Установка через gem install zsteg, запуск: zsteg target.png. Утилита автоматически проверяет все комбинации каналов (R, G, B, A) и порядков бит (MSB/LSB). Когда данные найдены, вывод выглядит так:
b1,rgb,lsb,xy .. text: "flag{hidden_in_plain_sight}"
b1,r,lsb,xy .. text: "flag{hidden_in_plain_sight}"
b2,bgr,msb,xy .. file: data
Обозначение b1,rgb,lsb,xy расшифровывается: бит 1 (младший), каналы RGB, порядок LSB, обход пикселей по X затем Y. Это самая стандартная конфигурация LSB-стеганографии в CTF.
Если zsteg не даёт результата — берём Stegsolve. Это графическое Java-приложение для ручного просмотра битовых плоскостей каждого канала. Иногда в красном канале (Red plane 0) спрятан QR-код или текст, который zsteg не распознал как строку, но глаз видит мгновенно. Stegsolve скачивается с GitHub (репозиторий eugenekolo/sec-tools) и запускается через java -jar stegsolve.jar.
Принципиальное ограничение: zsteg работает только с PNG и BMP. Для JPEG LSB-стеганография применяется крайне редко — сжатие с потерями разрушает младшие биты при каждом сохранении. Если задание даёт JPEG и намекает на LSB — проверьте file, возможно реальный формат другой.
Для нестандартных случаев (данные записаны в один канал, в обратном порядке бит или с произвольным смещением) пригодится ручной скрипт на Python с Pillow:
from PIL import Image
img = Image.open('target.png').convert('RGB') # convert ensures RGB mode for P/L/RGBA images
px = img.load()
bits = []
for y in range(img.height):
for x in range(img.width):
r, g, b = px[x, y]
bits.extend([r & 1, g & 1, b & 1])
bits = bits[:len(bits) - len(bits) % 8] # trim to multiple of 8
data = bytes(int(''.join(map(str, bits[i:i+8])), 2)
for i in range(0, len(bits), 8))
print(data[:200])
Скрипт извлекает LSB только из каналов RGB. Если данные спрятаны в альфа-канале (который zsteg проверяет автоматически), замените convert('RGB') на convert('RGBA') и добавьте обработку четвёртого значения. Это отправная точка — дальше экспериментируйте с комбинациями каналов и порядком обхода пикселей.
steghide — старый добрый инструмент для стеганографии, работающий с четырьмя форматами: JPEG, BMP, WAV и AU. В отличие от LSB-методов, steghide использует собственный алгоритм встраивания с шифрованием, и без пароля данные просто так не вытащить.
Базовая команда: steghide extract -sf target.jpg. Если данные встроены без пароля — достаточно нажать Enter при запросе passphrase. По данным hoppersroppers.org, steghide в связке со stegsolve решает до 90% стего-тасков начального уровня — авторы заданий часто не устанавливают пароль или используют пустую строку. Не нажать Enter на запрос passphrase — одна из самых частых ошибок новичков. Серьёзно, я видел это на каждом втором CTF.
Когда пароль установлен, остаётся брутфорс. Два инструмента на выбор:
stegcracker — обёртка над steghide для словарных атак. Команда: stegcracker target.jpg /usr/share/wordlists/rockyou.txt. Минус — скорость: steghide выполняет полную расшифровку при каждой попытке, поэтому перебор rockyou.txt (порядка 14 миллионов записей) растягивается на часы. В write-up на TryHackMe (CTF-BasicSteganography) отдельно предупреждают: «This specific action can take several hours».
stegseek — быстрая альтернатива, работающая на порядки быстрее за счёт прямого разбора формата steghide без полного вызова утилиты на каждую попытку. Тот же rockyou.txt обрабатывается за минуты вместо часов. Запуск аналогичен: stegseek target.jpg rockyou.txt. На Kali ставится через apt, для других дистрибутивов — сборка из исходников на GitHub. Если есть выбор между stegcracker и stegseek — берите stegseek, не пожалеете.
Частая ловушка: задание даёт PNG, а участник пытается запустить steghide. Утилита не поддерживает PNG — только JPEG, BMP, WAV и AU. Для PNG нужны zsteg, stegsolve или openstego. Эта ошибка стоит минут отладки на каждом втором CTF.
Аудио-стеганография в CTF — отдельная категория, где визуальные инструменты важнее слуховых. Два основных вектора: изображение, закодированное в спектрограмму, и LSB-данные в WAV-сэмплах.
Спектрограмма — самый «классический» аудио-стего. Автор таска кодирует текст или QR-код в высокочастотный диапазон WAV-файла. На слух — тишина или лёгкий шум. На спектрограмме — читаемое сообщение. Красиво, когда видишь это в первый раз.
Инструменты: Sonic Visualiser (больше контроля над параметрами — рекомендую для CTF) или Audacity (переключить вид трека на «Спектрограмму»). Ключевые настройки для обнаружения: увеличить верхнюю границу частоты до 20-22 кГц (флаги часто прячут в диапазоне 18-20 кГц, неслышном для большинства людей) и выбрать логарифмическую шкалу. Без этих настроек сообщение будет незаметным даже на спектрограмме — я сам первый раз потратил полчаса, пока не догадался крутануть верхнюю границу.
LSB в WAV. WAV — несжатый формат, каждый аудиосэмпл хранится как 16-битное число. Младший бит каждого сэмпла может нести полезные данные. WavSteg (pip install WavSteg) извлекает LSB: python3 -m WavSteg -r -i target.wav -o output.txt -n 1 забирает по одному младшему биту из каждого сэмпла.
MP3 и сжатые форматы. Сжатие с потерями разрушает LSB-данные, поэтому для MP3 используются другие методы: метаданные ID3 (проверяются через exiftool target.mp3), скрытые фреймы или стеганография на уровне параметров кодирования. В CTF MP3-стеганография встречается заметно реже WAV.
Практическая подсказка: если задание даёт аудиофайл подозрительно малой длительности (1-3 секунды) при большом размере — данные, вероятно, спрятаны не в аудио, а приклеены к файлу. Запускайте binwalk и strings прежде, чем открывать аудиоредактор.
Этот приём встречается на CTF регулярно, и он же вызывает больше всего ступора у новичков. Браузеры и просмотрщики изображений читают файл до маркера конца формата (для JPEG — 0xFFD9, для PNG — чанк IEND) и игнорируют всё что после. Автор задания дописывает архив, текст или другое изображение после маркера конца — визуально файл выглядит нормально.
Обнаружение: binwalk покажет вторую сигнатуру. Если binwalk видит только «End of Zip archive» без начала — magic bytes повреждены. В writeup на dominicbreuker.com описан характерный случай: ZIP приклеен к JPEG, первый байт PK (hex 50 4B 03 04) заменён на FF 4B 03 04. Утилита stegdetect сигнализирует: appended(227)<[nonrandom][data]>, а stegoVeritas печатает сырые байты trailing data, в которых дважды читается строка flag.txt.
Алгоритм при подозрении на appended data с повреждёнными сигнатурами:
xxd target.jpg | tail -30FF D9) и проверить байты после него50 4B 03 04, RAR — с 52 61 72 21, gzip — с 1F 8Bhexedit target.jpgdd if=target.jpg of=extracted.zip bs=1 skip=<offset> или автоматически через foremost -i target.jpgДля PNG есть ещё один хитрый метод сокрытия — занижение высоты в заголовке IHDR. Реальная картинка содержит больше строк пикселей, чем указано в заголовке, и нижняя часть просто не отрисовывается. Обнаружение: pngcheck -v target.png покажет предупреждение о несоответствии между заявленным размером и реальным объёмом IDAT-данных. Исправление: увеличить высоту в байтах 4-7 блока IHDR и пересчитать CRC блока. Звучит страшно, но на практике — пара минут в hex-редакторе.
Доверие расширению файла. Файл flag.png может оказаться JPEG, ZIP, ELF-бинарником или текстовым файлом. Первая команда — всегда file. Без исключений. Это не рекомендация, это правило.
Один инструмент на все случаи. steghide работает только с JPEG, BMP, WAV и AU. zsteg — только с PNG и BMP. Stegsolve — только визуальный анализ. Ни один инструмент для стеганографии не покрывает все форматы и методы. Чек-лист из начала статьи существует именно чтобы не застревать на одном шаге.
Игнорирование strings. Кажется слишком примитивным, но strings обнаруживает флаг примерно в каждом пятом стего-таске начального уровня. Авторы CTF-заданий прячут флаг в comment-секциях бинарного формата или тупо конкатенируют текст с бинарными данными.
Пропуск пустого пароля в steghide. При запросе passphrase нужно нажать Enter. Часто данные встроены без пароля, а участник решает, что «steghide не работает», и уходит к другому инструменту. Минута проверки экономит часы.
Незнание бинарной структуры форматов. Если вы не понимаете архитектуру PNG (сигнатура 89 50 4E 47 0D 0A 1A 0A → IHDR → tEXt → IDAT → IEND), то не заметите занижение высоты в IHDR или данные после IEND. Базовое знание структуры основных форматов — необходимость для категории Forensics и Stego.
Брутфорс до анализа. Запустить stegcracker с rockyou.txt и уйти ждать — соблазнительно, но неэффективно. Сначала все быстрые шаги. Часто подсказка к паролю лежит в метаданных (Comment или Description в EXIF), в имени файла или в описании задания на CTF-платформе.
Навыки стегоанализа применимы далеко за пределами CTF. Реальные вредоносные программы используют стеганографию для маскировки C2-коммуникаций — техника Steganography (T1001.002, тактика Command and Control по MITRE ATT&CK) и обфускации полезной нагрузки (T1027.003, тактика Stealth). Некоторые семейства малвари, по данным отчётов ИБ-вендоров, прячут команды C2-серверу прямо в картинках, выложенных на легитимных хостингах. Инструменты обнаружения — binwalk, strings, hex-анализ — те же самые, что разобраны в этой статье.
Разбираю стего-таски не первый год и вижу устойчивый паттерн: 80% заданий ломаются первыми четырьмя шагами чек-листа (file → strings → exiftool → binwalk). Оставшиеся 20% делятся примерно поровну между LSB-стеганографией и password-based steghide. Экзотика вроде PNG column padding или Unicode zero-width characters попадается на финалах — но к тому моменту интуиция уже наработана десятками решённых тасков. Категория Stego раздражает многих CTF-игроков именно потому, что нет серебряной пули — одного инструмента на все случаи. Но в этом и ценность: стеганография в CTF учит системному мышлению, а не нажиманию кнопок. Не коллекционируйте утилиты — отрабатывайте чек-лист, пока порядок действий не станет рефлексом. Writeup'ы дают понимание, но навык формируется только на практике с прогрессией по уровням — если хочешь не просто читать разборы, а проходить каждый вектор самому, на codeby.school есть WAPT с лабой на каждый кейс и ментором при затыке.
🚀 Хочешь закрепить на практике? Реши задачи по теме на HackerLab — категория «pentest-machines».
0 комментариев
Пожалуйста, войдите, чтобы оставить комментарий.
Загрузка комментариев...