Files
2026-04-22 10:58:32 +03:00

34 lines
2.7 KiB
Markdown
Raw Permalink 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">ChinaOwner</h1>
<p align="center">
<img src="https://img.shields.io/badge/category-Stego-blueviolet" alt="Stego"/>
<img src="https://img.shields.io/badge/points-960-critical" alt="960 pts"/>
</p>
У нас есть архив сырых [AIS](https://gpsd.gitlab.io/gpsd/AIVDM.html)-строк формата `!AIVDM` с временными метками. Больше всего в галаза бросается судно, которое публикует в поле `destination` строки `CHINA OWNER` и `CHINA OWNER&CREW`. Эти значения - маркер правильного MMSI. Само сообщение находится в таймингах между соседними `type 5` сообщениями того же борта.
## Решение
Сообщения `type 5` в AIS длинные, в handout они поделены на две `!AIVDM`-строки. Для начала склеиваем фрагменты по `seq_id`, каналу и timestamp, декодируем armored payload обратно в биты, отфильтровываем `message type == 5`. В пятом типе лежат `MMSI`, имя судна, `destination` и `ETA`.
> **AIS `!AIVDM` / type 5.** Тип 5 — «Static and Voyage Related Data» судна: содержит MMSI, IMO, имя, тип, позывной, данные о грузе, destination и ETA. Формат payload — armored 6-bit ASCII, [gpsd AIVDM spec](https://gpsd.gitlab.io/gpsd/AIVDM.html#_types_5_and_24_static_and_voyage_related_data) описывает все поля побитно.
После декодирования всплывает один MMSI — `422451900`. У этого судна `destination` раз за разом принимает значения `CHINA OWNER` и `CHINA OWNER&CREW` — вот он, нужный канал. Дальше сортируем все его `type 5` сообщения по времени и смотрим на интервалы между соседними timestamp:
| # | Δt, сек | Δt 280 | chr() |
|---|---:|---:|:---:|
| 1 | 379 | 99 | `c` |
| 2 | 377 | 97 | `a` |
| 3 | 392 | 112 | `p` |
| 4 | 388 | 108 | `l` |
| 5 | 377 | 97 | `a` |
| 6 | 383 | 103 | `g` |
| … | … | … | … |
Схема кодирования достаточно очевидная: `chr(delta_seconds - 280)`. Прогоняем ту же операцию по всем дельтам — получаем полную строку флага.
Готовый скрипт — [`solve/decode_timing.py`](solve/decode_timing.py): `python3 solve/decode_timing.py`.
## Флаг
`caplag{watch_the_gaps_not_the_words}`