43 lines
2.7 KiB
Markdown
43 lines
2.7 KiB
Markdown
<h1 align="center">RailAnnot</h1>
|
||
|
||
<p align="center">
|
||
<img src="https://img.shields.io/badge/category-PWN-blueviolet" alt="PWN"/>
|
||
<img src="https://img.shields.io/badge/difficulty-medium-orange" alt="medium"/>
|
||
</p>
|
||
|
||
RailAnnot обрабатывает служебные аннотации PDF-нарядов. В раздатке есть ELF `railannot`. У объекта аннотации 16-битный счётчик ссылок, а у страницы — отдельный указатель на него. Если счётчик обнулится при переполнении, объект освободится, но указатель страницы продолжит ссылаться на него.
|
||
|
||
## Решение
|
||
|
||
Создаём аннотацию через `1) load annotation`: `refs = 1`. Затем `2) attach annotation to page` добавляет вторую ссылку, и `refs` становится равен `2`.
|
||
|
||
Пункт `3) replay stream references` прибавляет произвольное `n`:
|
||
|
||
```c
|
||
ann->refs = (uint16_t)(ann->refs + n);
|
||
```
|
||
|
||
При нуле объект освобождается, но `page_ref` не обнуляется. Передаём `65534` и получаем `2 + 65534 = 65536`, что в `uint16_t` превращается в `0`. Аннотация удалена, страница продолжает держать висячий указатель.
|
||
|
||
В `4) allocate replacement cache object` выделяется блок того же размера. Заполняем его поддельной аннотацией:
|
||
|
||
```python
|
||
import struct
|
||
|
||
payload = struct.pack("<HHI", 0, 7, 0x414e4e52)
|
||
payload += b"sealed depot note".ljust(64, b"\x00")
|
||
payload += struct.pack("<I", 0x5241494c)
|
||
```
|
||
|
||
Первые два поля — `refs` и `id`, затем `magic`, 64 байта текста и `sealed`. Размер получается 76 байт, а `sealed` стоит на смещении `72`.
|
||
|
||
Выбираем `4) allocate replacement cache object`. На запрос `replacement bytes:` отправляем строку `76`, затем на `payload:` передаём 76 байт поддельной аннотации без добавленного перевода строки.
|
||
|
||
Освобождённый блок переиспользуется, и `page_ref` указывает на поддельную структуру. При выборе `5) render sealed annotation` сервис проверяет поля `magic` и `sealed`. Они содержат ожидаемые значения, поэтому сервис выводит флаг.
|
||
|
||
[Солвер](solve/solve.py).
|
||
|
||
## Флаг
|
||
|
||
`caplag{annotation_refcount_wrapped_into_the_depot_note}`
|