Init. commit
This commit is contained in:
109
reverse-umbrella-os-lab/WRITEUP.md
Normal file
109
reverse-umbrella-os-lab/WRITEUP.md
Normal file
@@ -0,0 +1,109 @@
|
||||
<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}`
|
||||
Reference in New Issue
Block a user