Init. Commit
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
<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}`
|
||||
Reference in New Issue
Block a user