Files
Tajna-tretej-stolicy/pwn-бортовой-журнал/WRITEUP.md
2026-04-22 10:58:32 +03:00

55 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<h1 align="center">Бортовой Журнал</h1>
<p align="center">
<img src="https://img.shields.io/badge/category-PWN-blueviolet" alt="PWN"/>
<img src="https://img.shields.io/badge/points-1000-critical" alt="1000 pts"/>
</p>
Сервис принимает JSON-программы и выполняет над буферами операции в стиле мини-VM: `alloc`, `write`, `read`, `compute`, `typeof`, `free`, `realloc`. Вычислительные функции (`xor`, `rot`, `rev`) лежат внутри C-таблицы указателей `dispatch_table` — и это уже подозрительно, потому что в бинарнике есть скрытая функция победы `win_fn`, читающая `/tmp/flag`. Нужно подложить её адрес в `dispatch_table` и вызвать обычным `compute`.
## Решение
Атака склеивается из двух багов:
| Баг | Что делает |
|---|---|
| `typeof` сливает адреса | Возвращает `data_ptr` буфера, адрес `dispatch_table` и адрес `_emergency_nav` (= `win_fn`) |
| `write` не проверяет `offset` | `dest = buffer.DataPtr + offset` — можно писать куда угодно относительно буфера |
Подбираем `offset = dispatch_table - data_ptr`, и запись в буфер улетает прямиком в таблицу указателей. По сути, воспроизводится тот же принцип, что и классический [GOT overwrite](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got), просто вместо Global Offset Table — user-space jump table.
Эксплуатация в два раунда. В первом — выделяем два буфера и снимаем адреса через `typeof`:
```json
{
"program": [
{"op": "alloc", "id": "a", "size": 256},
{"op": "alloc", "id": "b", "size": 256},
{"op": "typeof", "id": "a"}
]
}
```
Из ответа забираем три адреса:
```text
data_ptr — адрес буфера a
dispatch — адрес dispatch_table
_emergency_nav — адрес win_fn
```
Во втором раунде считаем `offset = dispatch - data_ptr`, пишем в буфер `a` по этому смещению `p64(win_addr)` — и переписываем `dispatch_table[0]` (слот `xor`) адресом `win_fn`. Дальше `compute("b", "xor")` вместо честной xor-функции вызывает `win_fn`, та кладёт флаг в буфер `b`, и обычный `read` с base64-декодом выдаёт результат:
```json
{
"program": [
{"op": "write", "id": "a", "data": "<p64(win)>", "offset": "<dispatch-data_ptr>"},
{"op": "compute", "id": "b", "func": "xor"},
{"op": "read", "id": "b", "count": 256}
]
}
```
## Флаг
`caplag{p3g4s_d1sp4tch_t4bl3_3xpl01t3d}`