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,60 @@
<h1 align="center">Mirror Trace</h1>
<p align="center">
<img src="https://img.shields.io/badge/category-OSINT-blueviolet" alt="OSINT"/>
<img src="https://img.shields.io/badge/points-866-orange" alt="866 pts"/>
</p>
На старте у нас есть `mirrortrace_casebundle.zip`, внутри которого dataset'ы и артефакты. Опираемся на seed domain из `00_brief/case_brief.txt` или `10_datasets/seeds.txt`.
## Решение
Берём стартовый домен `panel.mirrortrace-help.example`, смотрим сертификат, и через общий `cert-ms441` разворачивается кластер из шести доменов:
```text
panel.mirrortrace-help.example
status.mirrortrace-help.example
cdn.mirrortrace-help.example
docs.mercury-sustain.example
git.mercury-sustain.example
helpdesk.mercury-sustain.example
```
Внутри кластера довольно быстро проявляются две ветки с людьми:
| Персона | Роль |
|---|---|
| `Viktor Korolev` | Корректный операторский трек |
| `Anton Smirnov` | Правдоподобный same-cluster decoy |
`negotiation_excerpt.txt` и `capture_02.html` указывают, что нужный материал относится к responder baseline, а routing worksheets — это отдельная ветка. То есть правильный путь идёт не через `helpdesk.mercury-sustain.example`, а по responder-цепочке:
```mermaid
flowchart LR
S[status.mirrortrace-help.example] --> D[docs.mercury-sustain.example]
D --> P[doc_01.pdf]
P --> G[git.mercury-sustain.example]
G --> V[vkorolev-dev.example]
```
Фрагменты контрольной фразы получаем в процессе:
| Источник | Фрагмент | Сопутствующие артефакты |
|---|:---:|---|
| `capture_02.html` | `R3TAIN` | retained copy mention |
| `doc_01.pdf` | `ED-C0` | metadata author `vkorolev` |
| `capture_04.html` | `PY-71E` | email, handle, `vkorolev-dev.example` |
| `capture_05.html` | `64DB` | полное имя `Viktor Korolev` |
`capture_04.html` попутно упоминает `helpdesk.mercury-sustain.example` как routing mirror — это не другая цепочка, а decoy-шум внутри уже известного кластера. `capture_03.html` тоже отдаёт не фрагмент, а наводку: legal retained copy note лежит внутри mirrored advisory.
Склеиваем куски в pivot-порядке:
```text
R3TAIN + ED-C0 + PY-71E + 64DB → R3TAINED-C0PY-71E64DB
```
Эта строка — пароль к `20_artifacts/retained_copy.zip`. Внутри архива лежит `final_flag.txt` с ответом.
## Флаг
`caplag{retained_copy_6d8f21c4e9ab}`

View File

@@ -0,0 +1,104 @@
from __future__ import annotations
import csv
import json
import subprocess
import sys
import zipfile
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
CONFIG = json.loads((ROOT / "src" / "task_config.json").read_text(encoding="utf-8"))
def require(path: Path) -> None:
if not path.exists():
raise SystemExit(f"missing required file: {path}")
def assert_contains(path: Path, needle: str, error: str) -> None:
if needle not in path.read_text(encoding="utf-8"):
raise SystemExit(error)
def main() -> int:
archive_path = ROOT / "public" / CONFIG["archive_name"]
bundle_dir = ROOT / "public" / "mirrortrace_casebundle"
retained_copy = bundle_dir / "20_artifacts" / CONFIG["retained_copy_name"]
require(ROOT / "public" / "case_brief.txt")
require(ROOT / "public" / "negotiation_excerpt.txt")
require(archive_path)
require(bundle_dir / "10_datasets" / "graph_nodes.csv")
require(bundle_dir / "10_datasets" / "graph_edges.csv")
require(bundle_dir / "20_artifacts" / "doc_01.pdf")
require(bundle_dir / "20_artifacts" / "doc_03.pdf")
require(bundle_dir / "20_artifacts" / "capture_05.html")
require(bundle_dir / "20_artifacts" / "capture_11.html")
require(retained_copy)
assert_contains(
ROOT / "public" / "case_brief.txt",
CONFIG["retained_copy_name"],
"case_brief.txt is missing retained copy reference",
)
doc_01_bytes = (bundle_dir / "20_artifacts" / "doc_01.pdf").read_bytes()
if f"/Author ({CONFIG['correct']['pdf_author']})".encode("ascii") not in doc_01_bytes:
raise SystemExit("doc_01.pdf is missing expected metadata author")
if b"Retained legal copy marker: ED-C0" not in doc_01_bytes:
raise SystemExit("doc_01.pdf is missing expected retained copy marker")
doc_03_bytes = (bundle_dir / "20_artifacts" / "doc_03.pdf").read_bytes()
if f"/Author ({CONFIG['same_cluster_decoy']['pdf_author']})".encode("ascii") not in doc_03_bytes:
raise SystemExit("doc_03.pdf is missing expected same-cluster decoy author")
capture_05 = (bundle_dir / "20_artifacts" / "capture_05.html").read_text(encoding="utf-8")
if CONFIG["correct"]["full_name"] not in capture_05:
raise SystemExit("capture_05.html is missing expected identity")
capture_11 = (bundle_dir / "20_artifacts" / "capture_11.html").read_text(encoding="utf-8")
if CONFIG["same_cluster_decoy"]["personal_domain"] not in capture_11:
raise SystemExit("capture_11.html is missing expected same-cluster decoy pivot")
with (bundle_dir / "10_datasets" / "graph_edges.csv").open(encoding="utf-8", newline="") as fh:
rows = list(csv.DictReader(fh))
expected_edges = {
("panel", "cert_ms441"),
("helpdesk_mercury", "doc_03"),
("git_mercury", "personal_vk"),
("helpdesk_mercury", "personal_as"),
}
actual_edges = {(row["source"], row["target"]) for row in rows}
if not expected_edges.issubset(actual_edges):
raise SystemExit("graph_edges.csv is missing expected hard-mode relations")
subprocess.run(
["unzip", "-P", CONFIG["passphrase"], "-t", str(retained_copy)],
check=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
with zipfile.ZipFile(archive_path) as zf:
expected = {
"mirrortrace_casebundle/00_brief/case_brief.txt",
"mirrortrace_casebundle/10_datasets/graph_nodes.csv",
"mirrortrace_casebundle/10_datasets/graph_edges.csv",
"mirrortrace_casebundle/20_artifacts/doc_01.pdf",
"mirrortrace_casebundle/20_artifacts/doc_03.pdf",
"mirrortrace_casebundle/20_artifacts/capture_05.html",
"mirrortrace_casebundle/20_artifacts/capture_11.html",
f"mirrortrace_casebundle/20_artifacts/{CONFIG['retained_copy_name']}",
}
names = set(zf.namelist())
if not expected.issubset(names):
raise SystemExit("participant archive is missing expected hard-mode files")
print("MirrorTrace offline release check passed.")
return 0
if __name__ == "__main__":
sys.exit(main())