APNG — Just A PNG: текст в задержках кадров
Анимированный 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 |
|---|---|---|---|
| 0 | 70/10 | CRC error | 70 → F |
| 1 | 76/10 | CRC error | 76 → L |
| 2 | 65/10 | CRC error | 65 → A |
| 3 | 71/10 | CRC error | 71 → G |
| 4 | 58/10 | CRC error | 58 → : |
| … ещё 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.