ShadowFight2: байты прямо в RGBA
Картинка 9 × 9 пикселей, 195 байт. Структура чистая: только IHDR, pHYs, IDAT, IEND, без ошибок CRC и хвостов.
- Платформа
- CTF (флаги вида DUCKERZ{…})
- Носитель
- PNG RGBA
- Приём
- коды символов прямо в каналах, включая альфа
- Инструменты
- Python (Pillow), ImageMagick +
xxd - Статус
- решено
Метод исключения
Структура чистая, метаданных нет, strings пусто. А находки zsteg — «файлы» Atari и PlayStation с абсурдными размерами: на 81 пикселе слишком мало бит, и случайные куски легко похожи на чьи-то заголовки. Остаётся одно место: сами значения пикселей. 81 пиксель × 4 канала = 324 байта, на флаг хватает с запасом.
Название ShadowFight («бой с тенью»): тень намекает на альфа-канал, прозрачность, которую просмотрщик не показывает как цвет.
Вывести все числа
import sys
from PIL import Image
im = Image.open(sys.argv[1]).convert('RGBA')
raw = im.tobytes() # R,G,B,A,R,G,B,A,...
asc = lambda vals: ''.join(chr(v) if 32 <= v < 127 else '.' for v in vals)
for y in range(im.height): # таблица, чтобы увидеть глазами
print(' '.join('%3d,%3d,%3d,%3d' % tuple(raw[(y*im.width + x)*4:][:4]) for x in range(im.width)))
for i, name in enumerate('RGBA'): # каждый канал отдельно
print(name, asc(raw[i::4]))
print('RGBA подряд:', asc(raw))
Или вообще без Python: ImageMagick распаковывает пиксели в голые байты, а xxd их показывает.
convert ShadowFight2.png RGBA:raw.bin && xxd raw.bin
Как это выглядит
Я сделал такую же картинку 3 × 3 со своей строкой. На шахматке видно, что пиксели полупрозрачные: альфа тоже несёт буквы.

| Пиксель | R G B A | Как ASCII |
|---|---|---|
| 0 | 68 69 77 79 | DEMO |
| 1 | 123 52 108 112 | {4lp |
| 2 | 104 52 95 99 | h4_c |
| 3 | 52 114 114 49 | 4rr1 |
| 4 | 51 115 95 100 | 3s_d |
| 5 | 52 116 52 125 | 4t4} |
Без альфа-канала теряется каждая четвёртая буква. Именно поэтому важно .convert('RGBA'), а не 'RGB'.
показать флаг (спойлер)
DUCKERZ{Sh4d3OfC0l0r2_4nsw3r}Сколько букв помещается в пиксель
| Формат пикселя | Букв в пикселе | Где встречалось |
|---|---|---|
| палитра / серый, 8 бит | 1 | BMP с Гамлетом |
| RGB | 3 | Три в одном |
| RGBA | 4 | эта задача |
| LSB в RGB | 3 бита, то есть ~⅜ буквы | Зачарованный лес |
Прямая запись вмещает в 8–10 раз больше, чем LSB, но картинка сразу выглядит странно. LSB глазу незаметен.