Files
Serdtse-Sysoly/qualifiers/heiftrack-pwn-medium/WRITEUP.md
T
2026-09-17 00:50:07 +03:00

2.6 KiB

HeifTrack

PWN medium

HeifTrack проверяет последовательности кадров с камер. Он загружает chunk, привязывает его к воспроизведению и сверяет таблицы. В ELF heiftrack обнаруживаем, что ошибочный chunk удаляется, но воспроизведение продолжает ссылаться на него.

Решение

Chunk занимает 108 байт:

struct chunk {
    uint32_t magic;
    uint32_t frames;
    char label[32];
    uint32_t approved;
    char pad[64];
};

Экспорт проверяет два поля по указателю playback: magic == 0x48454946 и approved == 0x54524143. У обычного загруженного объекта approved равен нулю.

Сначала выбираем 1) load chunk, затем 2) bind track. Теперь и chunk0, и playback указывают на один объект. В 3) validate tables вводим несовпадающие значения 1, 2, 3. Валидация делает free(chunk0) и обнуляет chunk0, но про playback забывает. Получаем use-after-free.

Остаётся занять освободившуюся память своими данными. Пункт 4) add metadata item выделяет блок того же размера, 108 байт. Готовим поддельный chunk:

import struct

payload = struct.pack("<II", 0x48454946, 9)
payload += b"approved-track".ljust(32, b"\x00")
payload += struct.pack("<I", 0x54524143)
payload = payload.ljust(108, b"\x00")

Поле approved оказывается на смещении 40, как и у настоящего объекта. Выбираем 4) add metadata item, на запрос metadata bytes: передаём строку 108, затем на payload: отправляем 108 байт payload без добавленного перевода строки. Аллокатор переиспользует освобождённый блок, поэтому висячий playback теперь указывает на поддельный объект.

Выбираем 5) verify playback. Обе проверки проходят, и сервис выводит флаг.

Солвер.

Флаг

caplag{conflicting_track_tables_kept_the_chunk_alive}