Всем привет! Продолжаем разбирать задачки по стеганографии. Так как это задания из базового курса по стеганографии, они достаточно простые, но именно за счет этого хорошо подходят для понимания основ. Материал будет также будет полезен форензикам: форензика и стеганография тесно пересекаются, делят многие инструменты и более того, вторая, по сути, является часть первой. Именно поэтому я добавил тег forensics.
Итак, нам дана картинка 8.png, которая не открывается. Название задания прозрачно намекает, что изображение «обрезали» – скорее всего, искусственно уменьшили его высоту. На первый взгляд может показаться, что нижнюю часть просто отрезали, но скорее всего, данные остались и их там все еще столько же, сколько было изначально.
Но предположим, что название задания мы проигнорировали и не знаем, в какую сторону копать. Начнем с базовой быстрой аналитики и воспользуемся удобными инструментами – например, pngcheck. Это утилита для анализа PNG-файлов и их chunks (грубо говоря, структурных блоков данных внутри PNG).
Bash:
Код:
pngcheck -vtp7
8
.png
# Вывод:
zlib warning: different version
(
expected
1.2
.13, using
1.3
.1
)
File:
8
.png
(
2844192
bytes
)
chunk IHDR at offset 0x0000c, length
13
1535
x
950
image,
32
-bit RGB+alpha, non-interlaced
CRC error
in
chunk IHDR
(
computed 56e0edb1, expected 8df7c7e7
)
ERRORS DETECTED
in
8
.png
У некоторых может возникнуть вопрос, почему используется именно комбинация флагов -vtp7. Для stegano/forensics это почти стандартный набор: подробный вывод (-v), проверка CRC (-t) и вывод всех текстовых chunks (-p7). Никогда не знаешь, где спрятан флаг – может в битых chunk'ах, а может в текстовых метаданных.
Сразу становится понятно, что с изображением что-то не так – pngcheck находит ошибки. В частности, речь идет о неверной CRC-сумме (контрольная сумма, а если точнее – код для проверки целостности данных). В рамках CTF это почти всегда указывает на преднамеренное редактирование IHDR – типичный прием для сокрытия информации. Значение expected 8df7c7e7 – это оригинальная CRC, которая все еще хранится в файле. Предупреждение про версию zlib можно смело игнорировать – на решение задачи оно не влияет. Теперь стало ясно, почему картинка не открывается – большинство современных просмотрщиков отказываются открывать PNG, у которого некорректная CRC.
Дальше возникает закономерный вопрос: как восстановить исходную высоту изображения? В описании автор аккуратно подсказывает, что стоит заглянуть в шестнадцатеричный дамп файла. То есть мы откроем PNG в hex-редакторе, найдем поле высоты и подправим его вручную. Я воспользовался онлайн-инструментом:
https://hexed.it/
(подчеркну, что при работе с чувствительными данными необходимо использовать офлайн-редакторы!)
Для решения подобных заданий нужно хотя бы базово понимать структуру PNG. Чтобы не перегружать разбор теорией, которая может быть многим не интересна, ограничимся самым необходимым. Нас интересует только chunk IHDR, который идет сразу после сигнатуры PNG (8 байт: 89 50 4E 47 0D 0A 1A 0A).
В рамках этого задания достаточно знать, что высота изображения хранится в виде 4 байт в формате big-endian. В нашем случае это 00 00 03 B6. Старшие два байта нулевые, и эти четыре байта легко найти во второй строке – сразу после строки IHDR и четырех байт ширины.
Теперь переводим 03 B6 из hex в десятичную систему и получаем 950 – ровно ту высоту, которую показал pngcheck. Но нас интересует исходное значение. В рамках CTF можно задать высоту с запасом и подобрать ее эмпирически, но в общем случае корректная высота важна (в общем случае корректную высоту можно вычислить, но для соревнований быстрее просто задать заведомо большое значение и посмотреть результат). Я задал высоту с запасом – 1500, что в шестнадцатеричной системе счисления будет 05 DC. Итого: было 00 00 03 B6, стало 00 00 05 DC.
Сохраняем файл (Export) и пробуем открыть – изображение все еще не открывается. Проверяем снова:
Bash:
Код:
pngcheck redacted.png
# Вывод:
zlib warning: different version
(
expected
1.2
.13, using
1.3
.1
)
File: redacted.png
(
2844192
bytes
)
chunk IHDR at offset 0x0000c, length
13
1535
x
1500
image,
32
-bit RGB+alpha, non-interlaced
CRC error
in
chunk IHDR
(
computed 9c5ff4b7, expected 8df7c7e7
)
ERRORS DETECTED
in
redacted.png
Все ожидаемо: pngcheck снова ругается на CRC. Мы вручную изменили данные, и CRC-сумма в связи с этим сломалась. Что делать дальше? Безусловно, было бы неплохо понимать алгоритм пересчета CRC-суммы, но если нет желания в этом разбираться, задачу легко автоматизировать. На мой взгляд, самый простой путь – воспользоваться готовым инструментом pngcsum, который берет измененный PNG-файл, пересчитывает CRC и сохраняет его уже как корректный PNG:
Bash:
Код:
pngcsum redacted.png flag.png
После этого изображение наконец открывается, и внизу – за пределами исходной высоты – мы видим флаг.