/Разборы задач
27 октября 2026
Райтап на задачу «Шахматы с Момо»
Я хотел спрятать флаг на самом видном месте, а спрятал на невидимом.9
21

Stegano
Задача «Really deep bzzz»
В эту странную игру про пчёлок кто-то напихал пасхалок, может, даже флаг где-то спрятал.
Дисклеймер: автор крайне не рекомендует запускать любые исполняемые файлы в основной рабочей среде, т. к. они могут нести в себе действующие malware или иные угрозы безопасности ваших данных
В качестве отправной точки нам дан .exe-файл. Посмотрим, чем он собран, с помощью утилиты Detect-It-Easy:
Написана игра на питоне, а значит, скорее всего, упакована PyInstaller. Распакуем, воспользуемся pyinstxtractor (оговорюсь, что существует сборка и для Windows):
Эх, как же хорошо, что у нас не реверс, а стега, поэтому декомпилить и ковыряться в коде пока точно не будем. Лучше, наконец, поиграем:
Геймплей тут насыщенный и увлекательный, а саундтрек-то какой... Рекомендую играть СТРОГО в наушниках. Немного пощупав игру, обнаруживаем небольшую пасхалочку по клику на улей:
Начнём уже решать стегу! А она тут может быть где угодно. У нас есть графические ассеты:
И аудиоассеты:
На то, чтобы проверить всё даже на базовые приёмы стеганографии, уйдёт немало времени. Если автор задачи не хотел, чтобы мы впустую страдали над каждой картинкой и звуком, он бы точно оставил нам подсказку... На самом деле их тут сразу две.
Размер файла bee_boo.wav намного больше всех остальных файлов, что делает его хорошим первым кандидатом для проверки.
Картинка ниже
Тут и проявляется сложность задачи. Люди, знакомые с методами стеганографии, могут сразу понять, о чём идёт речь, новичкам придётся посложнее. По запросу deep steganography Google уводит нас в сторону метода сокрытия изображений, описанного в 2017 году в статье:
Но bzzz больше намекает на звук, да и размер файла указывает туда же. И вот тут, если загуглить deep sound steganography, мы уже попадаем куда надо:
Скачиваем и устанавливаем DeepSound и закидываем нашего подозреваемого:
Есть! Скрытая картинка. Попробуем извлечь, ведь DeepSound позволяет шифровать файлы, поэтому для их извлечения часто нужен пароль, но это, к счастью, не наш случай. Изображение извлечено:
Картинка есть — флага нет. Продолжаем. Закидываем в https://aperi.bug-makers.ru/ и ищем, за что зацепиться. В EXIF ничего, PNG целый, данных после IEND нет, IDAT-чанки одинаковые по размеру, визуально все bit planes и альфа выглядят нормально. Тут мы натыкаемся на новую ловушку автора. Все, кто решает стеганографию, постоянно видят ложные срабатывания Zsteg по сигнатурам — достаточно дать ему любое объёмное изображение и в нём, с большой долей вероятности, найдётся:
Весь трюк в том, что Zsteg по умолчанию передаёт извлеченные данные утилите file, которая смотрит сигнатуры, а для определения OpenPGP Public Key достаточно всего 2 совпавших байт (99 00) в начале файла. Поэтому строчка OpenPGP Public Key для многих уже привычный шум, на который никто не обращает внимания. Aperi'Solve, которым мы воспользовались для быстрого анализа изображения, запускает Zsteg без ключа --no-file и в результате Zsteg выводит всё подряд: и найденный текст, который он посчитал читабельным, и файлы, выявленные по сигнатурам:
Но если запустить его вручную с ключом --no-file, легко заметить:
И вот это тут лежит не случайно — это не срабатывание file по сигнатуре, а вписанный в LSB ASCII-текст! В общей картине с Aperi эта строчка просто теряется:
b1,b,lsb,xy .. text: "OpenPGP Public Key"
b2,b,lsb,xy .. file: OpenPGP Public Key
b3,g,msb,xy .. file: OpenPGP Secret Key
b3,abgr,msb,xy .. file: OpenPGP Secret KeyПоработаем с этой находкой, сперва извлечём данные:
Посмотрим в хексе:
Отрежем непосредственно текст — первые 18 байт и посмотрим, что у нас получится:
Окак — зашифрованные данные! Воспользуемся утилитой gpg, чтобы выяснить, что по нагрузке, не забываем, что мы сейчас смотрим на все данные из LSB b1 — начало пакета мы нашли, а конец — ещё нет.
Видим два валидных OpenPGP-пакета на офсетах 0 и 15. Первый пакет имеет длину заголовка hlen=2 и длину пакета plen=13, второй — hlen=2 и plen=124, можно сделать вывод, что корректный зашифрованный поток занимает 2+13+2+124=141 байт. Отрежем всё лишнее и оставим ровно 141 байт полезной нагрузки.
Получили корректное зашифрованное сообщение. Главный вопрос — что дальше? В ходе решения мы не сталкивались с паролем. Конечно, всегда есть шанс, что мы что-то упустили (учитывая, что мы не осматривали графические ассеты и остальные аудио), но предположим, что это не так. Тогда в голову приходит краеугольный камень любой задачи, где есть неизвестный пароль — rockyou. Сперва извлечём хэш в формате, который поймёт JohnTheRipper:
Дальше — только перебор, бессмысленный и беспощадный. Скорость этого перебора не сильно радует, но могу сказать, что успех рано или поздно будет достигнут :). Однако если очень хочется побыстрее, можно подрезать словарь до пчелиных паролей
И получить столь желанный пароль максимально быстро:
Пытаемся расшифровать, вводим пароль и, наконец, забираем флаг!