Райтап на задачу «Блендер.png»

musa2ap

Автор:

musa2ap

6 ноября 2026

14

06.11.2026
Блендер.png
Категория:

Forensic

Задача «Блендер.png»

LastTeamLead

Автор:

LastTeamLead

Первая кровь:
velvetway
Сложность:
easy
Дата публикации:
28.03.2026
Решений:
45
Рейтинг:
4.91/5
Ссылка:
Решать

Открываем изображение, прикреплённое к нашему заданию, и видим полностью чёрный квадрат. Смотрим на размер и понимаем, что обычный чёрный квадрат не может весить 1 МБ, значит, изображение есть, но оно закрыто для нас. Открываем любой hex-редактор, чтобы посмотреть все данные. Заголовок: 1728 на 2304 пикселя (синий и фиолетовый цвета), 8 бит на пиксель (розовый), тип цвета 3 (красный). Тип 3 — в файле лежит палитра на 256 цветов, а в самих данных хранятся только номера цветов из неё. Все цвета вполне нормальные. Если бы изображение было действительно полностью чёрным, то все байты с 0x29 и до 0x328 были бы одинаковыми. Делаем вывод о том, что проблема в представлении данных пикселей.

Решение задачи «Блендер.png»: иллюстрация 1

Дальше вытаскиваем список чанков. У PNG структура простая: 8 байт сигнатуры, а потом куски вида «длина, тип, данные, CRC». Получается IHDR, PLTE, пять штук IDAT и IEND. Проверяем это с помощью ввода в PowerShell скрипта, который читает нужные нам данные. Вот тут и становится интересно. IDAT — это сами пиксели, сжатые zlib. Обычно это один большой чанк или несколько подряд идущих кусков одного потока. У нас их пять, и размеры почти одинаковые: 226 102, 226 103, 226 102, 226 103, 226 103 байта. Ровные куски по 226 КБ — это явно один поток, который нарезали на равные части. А раз задание называется Blender, логично предположить, что эти куски ещё и перемешали между собой.

Проверить гипотезу легко по первому чанку. Поток zlib в PNG всегда начинается с двух байт вида 78 9C, 78 DA или 78 01. Смотрим начала всех пяти:

Решение задачи «Блендер.png»: иллюстрация 2

Нормальный заголовок только у второго. Значит, именно он должен идти первым, а остальные стоят не на своих местах. Осталось понять, в каком порядке их сложить.

Восстанавливаем порядок

Перебирать 24 варианта руками — сомнительное удовольствие, поэтому идём жадно. Берём второй чанк как первый, дальше по очереди пробуем дописать к нему каждый из оставшихся и смотрим, сколько байт удаётся распаковать. Правильный кусок продолжает поток и даёт нормальный прирост, неправильный либо падает с ошибкой, либо распаковывается заметно меньше.

Скрипт на PowerShell, который делает эту работу:

$z = (IDAT в текущем порядке) -join
$raw = Inflate $z          # снимаем 2 байта zlib-заголовка и 4 байта adler32
while ($rest.Count -gt 0) {
    foreach ($c in $rest) {
        $try = $seq + $c
        "{0} -> {1} байт" -f ($try -join ','), (Inflate $try).Length
    }
    $best = (перебираем и берём вариант с максимальной длиной)
    $seq += $best
    $rest = $rest | Where-Object { $_ -ne $best }
}

Результат подбора получится такой:

2        -> 1618215
2,4      -> 2306002
2,4,5    -> 3108242
2,4,5,1  -> 3983616

Последнее число — 3 983 616 — это ровно (1728 + 1) * 2304, то есть полный объём данных картинки вместе с байтами фильтров в начале каждой строки. Значит поток собран полностью и без ошибок. Итоговый порядок чанков: 2, 4, 5, 1, 3.

Собираем PNG обратно. CRC пересчитывать не нужно: он считается от типа и данных конкретного чанка, а не от его положения в файле. Поэтому просто копируем байты как есть, включая старые CRC.

$ms = New-Object IO.MemoryStream
$ms.Write($signature, 0, 8)
foreach ($c in $pre)  { $ms.Write($c, 0, $c.Length) }
$order = 1, 3, 4, 0, 2
foreach ($i in $order) { $ms.Write($idat[$i], 0, $idat[$i].Length) }
$ms.Write($iend, 0, $iend.Length)
[IO.File]::WriteAllBytes("blender_restored.png", $ms.ToArray())

Файл открывается без проблем, и на нём видно Пикси с табличкой.

Решение задачи «Блендер.png»: иллюстрация 3
Если вы нашли опечатку или ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter

Также по теме:

Райтап на задачу «Слив флагов»

/Разборы задач

Райтап на задачу «Слив флагов»

Исследуем WIM-образ через 7-Zip, находим альтернативный поток flag_404.txt и декодируем спрятанную строку Base64.
Прочитать

8

Райтап на задачу «CTF-ер, который смог»

/Разборы задач

Райтап на задачу «CTF-ер, который смог»

Исследуем повреждённый ZIP в HxD и восстанавливаем изображение с помощью Take bytes и Raw Inflate в CyberChef.
Прочитать

6