APNG — Just A PNG: текст в задержках кадров

стеганография · задача 07   pngapngcrcroot-me

Анимированный PNG ch21.apng, 13 кадров. Картинка как картинка.

Платформа
Root-Me
Носитель
APNG
Приём
коды символов в числителях задержек кадров
Инструменты
pngcheck, Python (разбор чанков)
Статус
решено

Аномалия

pngcheck ругается на CRC error в чанках fcTL, а один из кадров показывается 7 секунд, что для анимации нелепо. У каждого чанка PNG своя контрольная сумма. Если она не сходится, значит, байты меняли вручную и не пересчитали CRC.

Чанк fcTL описывает кадр APNG: номер, размер, смещение и задержку как дробь delay_num/delay_den.

Разбор чанков

import sys, struct, zlib
d = open(sys.argv[1], 'rb').read(); pos = 8
while pos < len(d):
    ln, = struct.unpack('>I', d[pos:pos+4]); t = d[pos+4:pos+8]
    body = d[pos+8:pos+8+ln]; crc, = struct.unpack('>I', d[pos+8+ln:pos+12+ln])
    bad = (zlib.crc32(t + body) & 0xffffffff) != crc
    if t == b'fcTL':
        seq, w, h, x, y, dn, dd, di, bl = struct.unpack('>IIIIIHHBB', body)
        print(f'fcTL seq={seq} {w}x{h} delay={dn}/{dd} {"CRC BAD" if bad else ""}')
    pos += 12 + ln
КадрЗадержкаCRCЧислитель как ASCII
070/10CRC error70 → F
176/10CRC error76 → L
265/10CRC error65 → A
371/10CRC error71 → G
458/10CRC error58 → :
… ещё 8 кадров, они и есть ответ

Проверка гипотезы через старую CRC

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

# body — тело fcTL, crc — записанная в файле контрольная сумма
for dn in range(65536):
    test = body[:20] + struct.pack('>H', dn) + body[22:]   # delay_num лежит по смещению 20
    if zlib.crc32(b'fcTL' + test) & 0xffffffff == crc:
        print('исходный числитель:', dn)

У всех кадров получилось 1, то есть исходно задержка была 1/10. Значит, автор менял только числитель, и гипотеза подтверждена.

[ответ скрыт] Это задача с Root-Me, а правила платформы просят не выкладывать ответы. Метод выше полный: по нему ответ получается за пару минут.

Что вынести

  • CRC error означает «здесь копались». Старая CRC позволяет восстановить, что было до правки.
  • Любые числа из файла (задержки, размеры, цвета) в диапазоне 32–126 стоит пробовать как ASCII.