37 lines
2.5 KiB
Markdown
37 lines
2.5 KiB
Markdown
<h1 align="center">Allocator War</h1>
|
||
|
||
<p align="center">
|
||
<img src="https://img.shields.io/badge/category-PWN-blueviolet" alt="PWN"/>
|
||
<img src="https://img.shields.io/badge/points-996-critical" alt="996 pts"/>
|
||
</p>
|
||
|
||
С первого взгляда обычный каталог: создать запись, изменить описание, посмотреть, удалить. Косяк опять с памятью, там самописный аллокатор с кешем. При старте сервис кладёт флаг в 64-байтный буфер, сохраняет указатель в глобальной `last_freed_ptr` — и этот буфер никогда не чистится.
|
||
|
||
Создание записи идёт через обычный `malloc`, а вот изменение — через `alloc_or_reuse()`. Если в `edit` попросить буфер ровно такого же размера, как лежит в кеше, аллокатор без проблем отдаст старый буфер с флагом.
|
||
|
||
## Решение
|
||
|
||
Первая подсказка скрыта прямо в интерфейсе — в меню есть недокументированная диагностическая команда `9`:
|
||
|
||
```text
|
||
cache: last_freed_size=64, flag_cache_size=64
|
||
```
|
||
|
||
Значит, чтобы выдернуть флаг, надо заставить сервис переиспользовать именно 64-байтный блок, и сделать это на этапе `edit`.
|
||
|
||
План:
|
||
|
||
1. Создаём любую запись произвольного размера (лишь бы жила).
|
||
2. Редактируем её, просим новый размер `64`.
|
||
3. На ввод описания отправляем **пустую строку**.
|
||
4. Смотрим запись.
|
||
|
||
>Сервис сначала выделит буфер из кеша, а потом запишет в него ровно столько байт, сколько пришло от пользователя. Ноль байт = ноль записи, и старое содержимое буфера (флаг) остаётся на месте.
|
||
|
||
При просмотре сервис печатает и описание, и *hex*-дамп содержимого. В дампе и светится флаг.
|
||
|
||
Минимальный [солвер](./solve/solver.py).
|
||
|
||
## Флаг
|
||
`caplag{Some_thing_is_here_not_there}`
|