Files
Tajna-tretej-stolicy/reverse-umbrella-os-lab/WRITEUP.md
2026-04-22 10:58:32 +03:00

109 lines
5.7 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">Alpha Centauri</h1>
<p align="center">
<img src="https://img.shields.io/badge/category-Reverse-blueviolet" alt="Reverse"/>
<img src="https://img.shields.io/badge/points-Σ_6991-critical" alt="Σ 6991 pts"/>
</p>
<p align="center"><sub><b>этапы:</b> 996 · 998 · 999 · 999 · 999 · 1000 · 1000</sub></p>
Вспоминаем нашу любимую вселенную с бессмертным Леоном (ну реально, у тебя совесть то есть в таком возрасте в такой физ. форме находиться?). Всего у очередной лаборатории корпорации *будет 7 уровней*: артефакты каждого шага содержат ключевой материал для следующего:
```mermaid
flowchart LR
T1(["1 · Surface<br/><i>web</i>"])
T2(["2 · Capsule<br/><i>forensics</i>"])
T3(["3 · Auth<br/><i>reverse</i>"])
T4(["4 · USB Key<br/><i>forensics</i>"])
T5(["5 · Audit<br/><i>crypto</i>"])
T6(["6 · Nemesis<br/><i>proto</i>"])
T7(["7 · Uplink<br/><i>pwn</i>"])
T1 --> T2 --> T3 --> T4 -->|seed_tail| T5 -->|tokens| T6 -->|ticket| T7
T3 -. seed_head .-> T5
classDef web fill:#dbeafe,stroke:#3b82f6,color:#1e3a8a
classDef forensics fill:#fce7f3,stroke:#ec4899,color:#831843
classDef reverse fill:#fef3c7,stroke:#f59e0b,color:#78350f
classDef crypto fill:#d1fae5,stroke:#10b981,color:#064e3b
classDef proto fill:#ede9fe,stroke:#8b5cf6,color:#312e81
classDef pwn fill:#fee2e2,stroke:#ef4444,color:#7f1d1d
class T1 web
class T2,T4 forensics
class T3 reverse
class T5 crypto
class T6 proto
class T7 pwn
```
## Решение
**Таск 1 — Surface (Web).** В глаза сразу бросается подозрительный эндпоинт `/api/internal/cache-check?url=` — классический SSRF. Есть фильтрация по `127.0.0.1`, но ее легко обойти путем перевода IP в десятичный формат:
```text
http://2130706433:18091/bootstrap/creds
```
В ответе лежит `admin:UmbrellaNode7`. Под этими кредами заходим в админку, дальше находим другой весёлый эндпоинт — `/api/files?name=...`. При помощи незамысловатого path traversal `../private/exports/flag.txt` получаем флаг для первого этапа.
**Таск 2 — Capsule (Forensics).** Распаковываем `capsule.tar`, внутри `manifest.json` описано 40 чанков, из которых склеивается 10 МБ образа. Сигнатурным поиском (`ACIX` = `0x58494341` LE) находится orphaned ACIX-контейнер. Бинарники из OS подсказывают, чем он шифровался:
```text
byte ^= (i * 0x3F + 0x17) & 0xFF
```
Снимаем маску, прогоняем `gunzip` — на выходе JSON с `flag2`, auth_ploicy и метаданными сида.
**Таск 3 — Auth Reverse.** Из `AlphaCentauri-ctf.img` парсится кастомная UmbrellaFS, внутри лежит `/ops/operator.note.enc` (341 байт). `auth_policy` из таска 2 задаёт формат пароля `<word>-<word>-<word>-<3digits>`. Словарь из 12 слов даёт $12^3 \cdot 1000 = 1\,728\,000$ кандидатов — брутим, пароль находится на попытке `#41 408` примерно за 3 секунды:
```text
relay-mirror-lattice-407
```
После расшифровки получаем `flag3`, `audit_seed_head=43656e7461757269` и координату USB-образа.
**Таск 4 — USB Key Reverse.** `ops-usb.img` маленький — 32 КБ, 64 сектора:
| LBA | Содержимое |
|---|---|
| `32` | `usb_keyfile_t` с magic `UMBK`, оператор |
| `33` | Vendor trailer `UMBX`: `flag4`, `seed_tail=536565644b657931` |
**Таск 5 — Audit Crypto.** Склеиваем полный seed из тасков 3 и 4:
```text
43656e7461757269 + 536565644b657931 → CentauriSeedKey1
```
Ключ выводится из сида по формуле `seed[i] ^ (i * 0x1f + 5)` — 16 байт. Этим ключом через кастомный `umbrella_ctr` расшифровывается `audit.log` (672 байта, 6 записей), и из них достаются `flag5`, `cluster_key`, `node_id`, `operator_token` и TCP endpoint для следующего этапа.
**Таск 6 — Nemesis Proto.** Подключаемся к `nemesisd --mode proto` на порту 24062, делаем handshake с `cluster_key` и `node_id` из таска 5, шлём `msg_type=0x31` с `operator_token` в payload. В ответе приходят:
```text
flag6
ticket = 53414d504c455f5449434b45545f3031
hint = upload_sample
msg = 0x41
```
**Таск 7 — Uplink Pwn.** В паблик-бинарнике `nemesisd` через `nm nemesisd | grep win` находим `win()` по адресу `0x4043e0`. Уязвимость — `memcpy(ctx.name, payload+4, name_len)` без проверки `name_len <= 64`. Готовим payload с `name_len=72`:
```mermaid
block-beta
columns 4
H["header<br/>4 B"]
P["A × 64<br/>64 B<br/>→ ctx.name[64]"]
W["p64(win)<br/>8 B<br/>→ ctx.dispatch"]
T["ticket<br/>16 B"]
classDef base fill:#e0e7ff,stroke:#6366f1,color:#312e81
classDef hit fill:#fee2e2,stroke:#dc2626,color:#7f1d1d
class H,P,T base
class W hit
```
92 байта уходят через `nemesis_client --msg-type 0x41`, и сервер отдаёт финальный флаг.
## Флаг
`caplag{alpha_centauri_uplink_overflow}`