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

3.4 KiB
Raw Blame History

LeaseMesh

PWN medium

LeaseMesh позволяет создавать, просматривать, закрывать и пересылать «аренды» маршрутов. В раздатке есть ELF lease-mesh с PIE и сохранёнными символами. Для получения флага нужно узнать адрес flag_export и подменить обработчик маршрута.

Решение

У маршрута размер 144 байта. Для атаки важны следующие поля:

Смещение Поле Назначение
0 magic, 8 байт 0x4c454153454d4553
8 name[24] Имя маршрута
32 generation, 8 байт Поколение объекта
40 handler, 8 байт Указатель на обработчик
48 approved, 4 байта Для экспорта нужно 0x51524f4b
52 memo_len, 4 байта Длина заметки
56 memo[88] Сама заметка

Открываем маршрут в слоте 0 через 1) open route lease, имя и заметка любые. В пункте 4) inspect route выбираем слот 0. Из handler=%p получаем адрес route_status в запущенном процессе и сохраняем его числом в leaked_handler. Через readelf -sW public/lease-mesh находим значения символов route_status и flag_export. Смещения относительно базы PIE обозначим offset_route_status и offset_flag_export. Вычитаем первое из утечки и прибавляем второе:

pie_base = leaked_handler - offset_route_status
target = pie_base + offset_flag_export

Теперь освобождаем маршрут через 2) close route lease, указывая слот 0. В close_route есть free(routes[idx]), но нет обнуления routes[idx]. Значит, слот продолжает ссылаться на освобождённую память.

Пункт 3) import raw decoder packet выделяет ровно sizeof(struct route) и заполняет блок переданными байтами. Собираем подделку:

import struct

payload = struct.pack("<Q", 0x4c454153454d4553)
payload += b"export-reclaim".ljust(24, b"\x00")
payload += struct.pack("<QQII", 0x2605061337, target, 0x51524f4b, 0)
payload = payload.ljust(144, b"\x00")

Выбираем 3) import raw decoder packet. На запрос raw packet bytes: отправляем строку 144, затем на packet payload: передаём 144 байта payload без добавленного перевода строки.

После переиспользования блока routes[0] указывает на этот пакет как на настоящий маршрут. Вызываем 5) dispatch route, слот 0. Поля magic и approved содержат ожидаемые значения, а handler указывает на flag_export.

Солвер.

Флаг

caplag{stale_handle_reclaimed_the_route}