Init. commit

This commit is contained in:
Caplag
2026-04-22 10:42:16 +03:00
commit 98e51ca58b
35 changed files with 2371 additions and 0 deletions

View 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}`