The startup instructions were buried after Components/Features and mixed release/download variants with runtime detail; a reader had to scroll through the usage guide to find how to launch it, and the start scripts were only mentioned in passing. Both READMEs now lead with Prerequisites then a Quick start with three clear paths - wheel (pip), runtime zip (start.bat / ./start.sh) and a git clone (launchers, optional pip install -e .) - followed by First run (URL, capture modes, Ctrl+C). The detailed runtime guide moves under `Usage`: the server and PWA, COMPRION import, the Files view, the hosted PWA, the capture utility, the utility CLI options, output formats, the daemon, library usage and recovery. Components and Features follow the usage guide; USB device access keeps its anchor. Only the Analysis server intro gained the launcher note; every moved section is byte-identical (checked old vs new). 557 Python + 80 Node tests.
561 lines
38 KiB
Markdown
561 lines
38 KiB
Markdown
# SIMtrace Analyser
|
||
|
||
[English](README.md) | Русский
|
||
|
||
Анализатор APDU-трассировок в формате GSMTAP-SIM — захватывает обмен с
|
||
SIM/UICC из UDP-потока GSMTAP (или импортирует файлы PCAP/PCAPNG),
|
||
декодирует его и отдаёт устанавливаемое веб-приложение для просмотра.
|
||
В репозиторий также включён **simtrace2-pysniff** — замена `simtrace2-sniff`
|
||
на Python, которая захватывает трафик с оборудования Osmocom SIMtrace2
|
||
и может передавать GSMTAP этому анализатору.
|
||
|
||
📢 Новости и обновления проекта: [atroshin.ru](https://atroshin.ru) | [Telegram-канал](https://t.me/youeyeseesee)
|
||
|
||

|
||
|
||
## Требования
|
||
|
||
- **Python 3.9+**
|
||
- **PyUSB** — `pip install pyusb` (нужен только для захвата с оборудования
|
||
SIMtrace2; захват GSMTAP/UDP и импорт PCAP работают без него)
|
||
- **libusb** — системная библиотека, обычно уже есть в Linux; в Windows
|
||
нужно заменить драйвер SIMtrace2
|
||
(см. [Доступ к USB-устройству](#доступ-к-usb-устройству))
|
||
- **Оборудование SIMtrace2** с прошивкой в режиме *trace* (только для
|
||
прямого захвата; VID `1d50`, PID `60e3`, USB class `ff`, subclass `01`).
|
||
О сборке и прошивке trace-прошивки см.
|
||
[проект SIMtrace2](https://gitea.osmocom.org/sim-card/simtrace2).
|
||
|
||
Других зависимостей нет. Вывод PCAP, GSMTAP и hex dump использует только
|
||
стандартную библиотеку Python.
|
||
|
||
## Быстрый старт
|
||
|
||
Три способа запустить анализатор; все они отдают одну и ту же PWA на
|
||
http://127.0.0.1:8081/.
|
||
|
||
### 1. Wheel (pip)
|
||
|
||
Wheel содержит PWA внутри пакета, поэтому сервер отдаёт интерфейс сам:
|
||
|
||
```sh
|
||
pip install ./simtrace_analyser-2.7.13-py3-none-any.whl
|
||
simtrace-analyser-server --capture gsmtap
|
||
```
|
||
|
||
Если системный Python управляется извне (PEP 668 — обычное дело в Arch и
|
||
Fedora), сначала создайте виртуальное окружение:
|
||
`python3 -m venv .venv && . .venv/bin/activate`.
|
||
|
||
Все артефакты лежат на странице
|
||
[последнего релиза](https://github.com/anttro/simtrace-analyser/releases/latest).
|
||
`pip` может скачать wheel напрямую (подставьте версию со страницы), а GitHub
|
||
CLI — выбрать последнюю:
|
||
|
||
```sh
|
||
pip install https://github.com/anttro/simtrace-analyser/releases/download/v2.7.13/simtrace_analyser-2.7.13-py3-none-any.whl
|
||
# или:
|
||
gh release download --pattern '*.whl'
|
||
pip install ./simtrace_analyser-*.whl
|
||
```
|
||
|
||
### 2. Zip (для Windows, без установки)
|
||
|
||
Скачайте `simtrace-analyser-2.7.13.zip` со страницы релиза и распакуйте в любое
|
||
место: это рабочее дерево (пакеты Python, PWA, скрипты запуска и документация —
|
||
без тестов и git). Затем запустите.
|
||
|
||
Windows:
|
||
|
||
```bat
|
||
start.bat
|
||
```
|
||
|
||
Linux/macOS:
|
||
|
||
```sh
|
||
./start.sh
|
||
```
|
||
|
||
Python 3 должен быть в `PATH`; `pip install pyusb` нужен только для прямого
|
||
захвата с SIMtrace2. Скрипты принимают параметры сервера
|
||
(`start.bat --capture direct`, `./start.sh --capture direct --port 8080`).
|
||
(Архив *Source code* из релиза — это полное дерево вместе с тестами; он
|
||
работает так же, как клон ниже.)
|
||
|
||
### 3. Клон репозитория (для разработки)
|
||
|
||
```sh
|
||
git clone https://github.com/anttro/simtrace-analyser.git
|
||
cd simtrace-analyser
|
||
./start.sh # Linux/macOS; в Windows: start.bat
|
||
```
|
||
|
||
Скрипты запуска добавляют каталог в `PYTHONPATH` и запускают
|
||
`python -m simtrace_analyser`, поэтому для просмотра и захвата GSMTAP ничего
|
||
устанавливать не нужно; их параметры — это параметры сервера
|
||
(`./start.sh --capture direct --port 8080`). Для прямого захвата с
|
||
оборудования нужен **PyUSB** (`pip install pyusb`). Чтобы получить консольные
|
||
команды (`simtrace-analyser-server`, `simtrace2-pysniff`), установите пакет:
|
||
|
||
```sh
|
||
pip install -e .
|
||
simtrace-analyser-server --capture gsmtap
|
||
```
|
||
|
||
### Первый запуск
|
||
|
||
Откройте **http://127.0.0.1:8081/** — PWA отдаёт сервер, поэтому интерфейс и
|
||
API находятся на одном origin (настройка CORS/Private-Network-Access не нужна).
|
||
`Ctrl+C` останавливает сервер.
|
||
|
||
- `--capture gsmtap` (по умолчанию) — слушать GSMTAP-SIM на UDP 4729,
|
||
например от `simtrace2-pysniff` или `sigrok_iso7816_stream`;
|
||
- `--capture direct` — читать оборудование SIMtrace2 напрямую (нужен PyUSB; в
|
||
Windows также нужна замена драйвера, см.
|
||
[Доступ к USB-устройству](#доступ-к-usb-устройству));
|
||
- `--capture disabled` — только просмотр сохранённых захватов.
|
||
|
||
Полное руководство по работе (параметры сервера, экраны PWA, утилита захвата)
|
||
находится в разделе [Использование](#использование).
|
||
|
||
## Использование
|
||
|
||
### Анализирующий сервер + PWA (`simtrace-analyser-server`)
|
||
|
||
Сохраняет захваченный APDU-трафик в SQLite и отдаёт его по HTTP вместе
|
||
со встроенной PWA **SIMtrace Analyser** (`frontend/` в исходном клоне, при
|
||
установке — внутри пакета) на том же origin.
|
||
Команды ниже — консольная команда; при запуске из клона скрипты принимают те
|
||
же параметры (`./start.sh --capture gsmtap`, `start.bat --capture gsmtap`).
|
||
Три режима захвата:
|
||
|
||
```sh
|
||
# Слушать GSMTAP от simtrace2-pysniff (или оригинального simtrace2-sniff):
|
||
simtrace-analyser-server --capture gsmtap
|
||
|
||
# Захват напрямую с оборудования SIMtrace2 (внешний инструмент не нужен):
|
||
simtrace-analyser-server --capture direct
|
||
|
||
# Просмотр/анализ существующих записей без бэкенда захвата:
|
||
simtrace-analyser-server --capture disabled
|
||
```
|
||
|
||
Сервер пишет в stderr информацию о жизненном цикле захвата (каждая строка
|
||
с локальным временем): `Capture started` при старте, периодический
|
||
heartbeat `Capture alive: session=N messages=M bytes=B dropped=D skipped=S`
|
||
и `Capture stopped` (либо `ERROR: capture thread stopped on error …`,
|
||
если поток захвата неожиданно умер). Неверно сформированные или не-SIM
|
||
датаграммы GSMTAP отбрасываются и считаются (`dropped`), а не молча
|
||
убивают захват; `tpdu`-пакет, вовсе не похожий на APDU (короче заголовка,
|
||
недопустимый CLA `FF` или зарезервированный ISO класс `001x`),
|
||
пропускается и считается (`skipped`) — посимвольный или миссемплированный
|
||
поток больше не засоряет декодирование. Интервал heartbeat по умолчанию
|
||
60 с, настраивается через `--log-interval SECONDS`.
|
||
|
||
GSMTAP-листенер также принимает декодер **sigrok-iso7816-stream**
|
||
(https://github.com/anttro/sigrok_iso7816_stream) — пассивный SIM-сниффер
|
||
на базе FX2-логического анализатора, выдающий тот же формат GSMTAP-SIM
|
||
на UDP 4729. Его стандартные подтипы PPS-запроса/ответа (`0x02`/`0x03`)
|
||
декодируются как PPS, а пользовательские подтипы для событий линий RST/VCC
|
||
(`0x10`/`0x11`, добавлены для совместимости с тем проектом) — как временные
|
||
маркеры `RESET ASSERTED` / `RST de-asserted — ATR follows` и `VCC ON/OFF`;
|
||
сброс или пропадание питания корректно сбрасывает отслеживание выбранного
|
||
файла. Когда событие
|
||
RST несёт измеренную частоту CLK (декодер v1.9.0+, опциональное расширение
|
||
полезной нагрузки), следующий ATR получает частоту CLK, скорость передачи
|
||
данных и ETU, вычисленные из его TA1 Fi/Di
|
||
(`data_rate = clk_hz × D / F`); измерение потребляется ATR, поэтому
|
||
следующий ATR без сброса не получит устаревшую скорость (поздно пришедшее
|
||
измерение восстанавливается для «своего» ATR). GSMTAP-пакеты с флагом
|
||
десинхронизации `GSMTAP_FLAG_BAD_FCS` (устанавливается тем декодером при
|
||
нарушении кадрирования) отображаются в таймлайне как
|
||
помеченная/десинхронизированная запись, чтобы такие артефакты было легко
|
||
заметить при разборе, а не молча искажали декодирование.
|
||
|
||
### Импорт текстового экспорта COMPRION
|
||
|
||
Кнопка **Import COMPRION trace** принимает экспорт **ISO Protocol Layer**
|
||
(табулированный текст) из COMPRION Device Manager — байтовое представление
|
||
протокола (ATR, PPS, APDU с кодами возврата). Экспорт *ISO Application
|
||
Layer* не содержит необработанных байтов ответов и не нужен; при его выборе
|
||
выводится указание на файл Protocol Layer (та же проверка выполняется в PWA
|
||
до загрузки и на сервере — для вызовов API).
|
||
|
||
Обмены перекодируются в такие же «проводные» TPDU, какие несёт захват
|
||
GSMTAP (обмен case 4 превращается в команду, статусное слово `61 xx` и GET
|
||
RESPONSE с данными ответа и итоговым SW), поэтому связывание
|
||
команда/ответ, декодирование FCP и файлов и фильтры работают так же, как
|
||
для живого захвата.
|
||
|
||
**Точные метки времени:** диалог импорта запрашивает экспорт *ISO Protocol
|
||
Layer* (обязательный) и, при наличии, соответствующий экспорт *ISO
|
||
Application Layer* — два отдельных поля выбора, имена выбранных файлов
|
||
видны, а ошибка остаётся в диалоге до исправления или отмены. С обоими
|
||
файлами метки времени Application Layer по обменам становятся таймлайном
|
||
трассы: окно сессии и интервалы между APDU точные; без него таймлайн —
|
||
оценка, описанная ниже. Перед импортом проверяется, что файлы относятся к
|
||
одной сессии (`Session Name`, при отсутствии — `Working directory`; метки
|
||
времени экспорта у слоёв различаются и не сравниваются) и что число обменов
|
||
совпадает (экспорты должны покрывать один и тот же набор обменов) — при
|
||
несовпадении импорт отклоняется, а не смешивает сессии. У ATR и обмена PPS
|
||
блоков в Application Layer нет, поэтому они получают метку времени
|
||
предыдущего обмена.
|
||
|
||
**Только Protocol Layer:** столбец `Delay` измеряет лишь активность
|
||
карты/линии — паузы хоста между сериями APDU в него не входят — поэтому
|
||
таймлайн сохраняет порядок сообщений и короткие интервалы, но заметно
|
||
короче реальной сессии. Его единица измерения задаётся предполагаемой
|
||
тактовой частотой 3,8 МГц (`CLK_HZ` в `simtrace_analyser/comprion.py`) —
|
||
это масштаб, а не измерение: в экспорте нет CLK, и импорт намеренно его не
|
||
выдумывает (ATR показывает F/D из файла, без аннотации скорости/ETU, в
|
||
отличие от захвата сниффером sigrok-iso7816-stream). Окно настенных часов
|
||
сессии берётся из метки времени `Session Name` в файле, если она там есть.
|
||
|
||
Обмены длиннее 255 байт (APDU с расширенной длиной) невозможно представить
|
||
в хранимом «проводном» виде — они пропускаются с пометкой в отчёте импорта.
|
||
|
||
### Просмотр файлов (сопровождение состояния файлов)
|
||
|
||
В верхней панели вкладки «Трассировка» появился выбор вида (*Map* / *Stats* /
|
||
**Files**) — он выровнен по правому краю над боковой панелью и имеет её
|
||
ширину, поэтому виден всё время, пока панель прокручивается (выпадающий
|
||
список, три подписи-вкладки уже не помещались). Вид
|
||
Files — это таймлайн файловых операций по всей трассе: строки **Read** и
|
||
**Update** показывают те же имена файлов, что и вид Map (изменение со стороны
|
||
карты выглядит как чтение со ссылкой **Изменено на карте!**, открывающей
|
||
подробности), а щелчок по строке переходит прямо к APDU в трассе и оставляет
|
||
его выделенным, пока не выбран другой (список APDU сохраняет позицию читателя:
|
||
новые сообщения прижимают вид к низу, только пока читатель уже внизу,
|
||
поэтому переход не срывается живым опросом и не снимает выделение). У строк с записанным изменением
|
||
(изменение со стороны карты либо запись, изменившая или впервые показавшая
|
||
байты) есть кнопка **Show diff** («Изменения»): окно показывает полный путь файла (`MF/EF_ICCID (2FE2)`,
|
||
`ADF/EF_IMSI (6F07)`, `DF_TELECOM/DF_PHONEBOOK/4FA1`, `AID …/4F09` — вся
|
||
цепочка DF из пути выбора в трассе, каждый DF назван по словарю
|
||
спецификаций, а AID — по меткам из EF.DIR, если они есть) и затронутую
|
||
единицу — файл
|
||
целиком или изменившуюся запись — **до и после** изменения в виде hex-вида
|
||
(до 16 байт в строке: короткий файл/запись заканчивает строку, а не
|
||
дополняется `--`, и столбец смещений появляется, только когда представление
|
||
занимает больше одной строки), причём изменённые
|
||
байты подсвечены одним цветом, а впервые наблюдаемые — другим; ниже —
|
||
счётчики изменённых/новых байт, ссылка на APDU и легенда цветов под
|
||
представлениями, перечисляющая только реально показанные пометки.
|
||
|
||
У файлов телефонной книги FID назначает карта, поэтому словарь их не
|
||
знает: если в трассе есть записи **EF_PBR**, они разбираются
|
||
(TS 31.102 §4.4.2.1 — группы типов `A8`/`A9`/`AA` и примитивные теги `C0`…`CC`
|
||
с FID и, для трёхбайтового объекта, SFI), и Files называет файлы по
|
||
объявлению самой карты — например
|
||
`DF_TELECOM/DF_PHONEBOOK/EF_PBC (4FA1)` — а объявленные SFI пополняют карту
|
||
SFI→FID этого DF (правило «SFI = 5 младших бит FID» из TS 102 221 §11.1.1.4.8
|
||
для остальных файлов остаётся).
|
||
|
||
Изображения отдаёт `GET /api/sessions/<id>/files/image?key=…&change=…`; они
|
||
восстанавливаются из текущего образа отменой более поздних изменений
|
||
(`filetrack.FileTracker.change_images`) — поэтому ничего не дублируется по
|
||
событиям. Каждое изменение значения записывается, так что значения точны;
|
||
байт, который был лишь *впервые показан* после выбранного изменения, может
|
||
отображаться известным в обоих видах.
|
||
|
||
Данные даёт `simtrace_analyser/filetrack.py` (`GET /api/sessions/<id>/files`) —
|
||
однопроходный анализатор сессии, который ведёт по ключу (DF, FID) и **через
|
||
сбросы карты**: счётчики доступа (`select`/`read`/`update`, только успешные
|
||
операции), разреженный образ наблюдаемого содержимого и журнал изменений.
|
||
Изменения со стороны устройства — это операции UPDATE из трассы; изменения со
|
||
стороны карты выводятся, когда чтение возвращает байты, отличающиеся от уже
|
||
известных образу (никогда не виденные байты просто заполняют образ — это
|
||
наблюдение, а не изменение). Файлы, доступные по SFI, попадают в ту же
|
||
запись, что и доступ по пути/FID: соответствия SFI ↔ FID берутся из
|
||
нормативных таблиц (анекс H.1 TS 102 221 и анексы H.1–H.12 TS 31.102;
|
||
строки SFI ISIM — из TS 31.103) и из каждого
|
||
показанного FCP с DO `88`, включая правило спецификации «SFI = 5 младших бит
|
||
FID» при отсутствии DO; SFI, использованный до того, как связь выучена,
|
||
остаётся предварительным и сливается с разрешённой записью. Контекст DF
|
||
следует TS 102 221 §8.4/Table 8.2 (выбор EF оставляет текущим его родительский
|
||
DF, включая выбор по пути); приложения, выбранные по неизвестному AID,
|
||
получают в качестве идентичности DF сам AID и имя из EF.DIR, если он
|
||
показан в трассе. Ограничения: образ замораживается после 64 КБ
|
||
наблюдаемых байт на файл (`image_truncated`), журнал изменений хранит
|
||
последние 1000 событий на файл (`changes_total` продолжает считать).
|
||
Счётчики API отдаёт, но в этом виде пока не показываются.
|
||
|
||
Имена файлов **привязаны к DF**: `simtrace_analyser/ef_tables.py` содержит
|
||
полные таблицы файлов и SFI по каждому DF, извлечённые из закреплённых
|
||
спецификаций (TS 102 221, TS 31.102 включая анексы SFI H.1–H.12, TS 31.103,
|
||
TS 51.011), поэтому FID, повторно используемый в разных DF, разрешается в имя
|
||
своего контекста — `4F09` это EF_SUPI_NAI в DF_5GS, но EF_PROSE_GC в DF_ProSe;
|
||
`6F07` — EF_IMSI в USIM/SIM, но EF_IST в ISIM; `6F4E` — EF_EXT4 в DF_TELECOM,
|
||
но EF_EXT5 в ADF USIM, — а плоская таблица служит запасным вариантом, когда DF
|
||
неизвестен. `tests/extract_spec_tables.py` пересобирает закреплённый фикстур
|
||
(`tests/data/spec_files.json`), `--check` повторно сверяет таблицы с PDF.
|
||
|
||
Параметры сервера:
|
||
|
||
```
|
||
--host ADDR адрес привязки HTTP (по умолчанию: 127.0.0.1)
|
||
--port PORT порт HTTP-сервера (по умолчанию: 8081)
|
||
--db FILE путь к базе SQLite (по умолчанию: ~/.simtrace-analyser/sessions.db)
|
||
--capture MODE gsmtap | direct | disabled (по умолчанию: gsmtap)
|
||
--gsmtap-port PORT UDP-порт листенера GSMTAP (по умолчанию: 4729)
|
||
--gsmtap-bind ADDR UDP-адрес привязки листенера GSMTAP (по умолчанию: 127.0.0.1;
|
||
используйте 0.0.0.0, чтобы принимать из Docker-сети или с другого хоста)
|
||
--web-dir PATH каталог статических файлов PWA (по умолчанию: PWA внутри
|
||
установленного пакета или <repo>/frontend при запуске из исходников)
|
||
```
|
||
|
||
Затем откройте **http://127.0.0.1:8081/** в браузере — PWA отдаётся
|
||
сервером, поэтому UI и API используют один origin, и настройка
|
||
CORS/Private-Network-Access не требуется. Используйте `--web-dir PATH`,
|
||
чтобы отдавать другой каталог PWA (по умолчанию: PWA внутри пакета или
|
||
`<repo>/frontend` при запуске из исходников).
|
||
|
||
### Размещённая PWA (лендинг)
|
||
|
||
Автономная копия PWA размещена на **https://simtrace.atroshin.ru**.
|
||
Это чистый фронтенд: укажите в нём (Settings → Server URL) адрес
|
||
локально запущенного `simtrace-analyser-server`.
|
||
|
||
> **Ограничение браузера:** когда PWA отдаётся с публичного HTTPS-хоста,
|
||
> доступ к локальному серверу (`http://127.0.0.1:8081`) требует двух
|
||
> вещей: сервер должен отправлять
|
||
> `Access-Control-Allow-Private-Network: true` (этот сервер отправляет),
|
||
> и браузер должен иметь разрешение на доступ к локальной сети —
|
||
> в Chrome/Edge/Vivaldi: Настройки сайта → Доступ к локальной сети →
|
||
> разрешить сайту (или принять запрос разрешения). Без разрешения
|
||
> браузера запрос к `127.0.0.1` блокируется ещё до отправки preflight.
|
||
|
||
### Утилита захвата (`simtrace2-pysniff`)
|
||
|
||
Захватывает трафик оборудования SIMtrace2 и выводит его в stdout, GSMTAP
|
||
(Wireshark) или PCAP-файлы. Это встроенная замена оригинального
|
||
инструмента Osmocom `simtrace2-sniff`.
|
||
|
||
Скрипт запуска `./sniff-start.sh` выполняет предварительную проверку прав
|
||
доступа к USB (при неудаче печатает инструкцию по установке udev-правила)
|
||
и затем запускает модуль Python. В Windows используйте `sniff-start.bat`
|
||
с теми же параметрами (проверка прав не требуется).
|
||
|
||
```sh
|
||
./sniff-start.sh
|
||
./sniff-start.sh --format timestamp
|
||
./sniff-start.sh --gsmtap 127.0.0.1:4729
|
||
./sniff-start.sh --pcap trace.pcap --format atr-time
|
||
```
|
||
|
||
Параметры также можно задавать через переменные окружения:
|
||
|
||
```sh
|
||
FORMAT=timestamp GSMTAP=127.0.0.1 ./sniff-start.sh
|
||
```
|
||
|
||
Кроссплатформенный запуск модуля:
|
||
|
||
```sh
|
||
python -m simtrace2_pysniff
|
||
python -m simtrace2_pysniff --format timestamp --gsmtap 127.0.0.1:4729
|
||
python -m simtrace2_pysniff --pcap trace.pcap
|
||
```
|
||
|
||
Если пакет установлен через `pip install -e .`, используйте консольный
|
||
скрипт напрямую:
|
||
|
||
```sh
|
||
simtrace2-pysniff --format atr-time
|
||
```
|
||
|
||
### Параметры CLI утилиты
|
||
|
||
```
|
||
python -m simtrace2_pysniff [OPTIONS]
|
||
|
||
--format, -f FORMAT Формат вывода (по умолчанию: hex)
|
||
hex — обычный hex-дамп
|
||
timestamp — строки TPDU с префиксом [ЧЧ:ММ:СС.мс]
|
||
atr-time — строки TPDU с префиксом [СССС.мс] от последнего ATR
|
||
--gsmtap HOST[:PORT] Отправлять ATR/TPDU как GSMTAP по UDP (порт по умолчанию 4729)
|
||
--pcap FILE Записывать перехваченные данные в PCAP для Wireshark
|
||
--output, -o FILE Записывать hex-дамп в файл
|
||
--no-stdout Не выводить hex-дамп в stdout
|
||
--vendor HEX USB vendor ID (по умолчанию: 0x1d50)
|
||
--product HEX USB product ID (по умолчанию: автоопределение)
|
||
|
||
Параметры восстановления:
|
||
--no-reconnect Выходить при отключении USB вместо переподключения
|
||
--reconnect-delay-min SEC Минимальная задержка переподключения (по умолчанию: 1.0)
|
||
--reconnect-delay-max SEC Максимальная задержка переподключения (по умолчанию: 30.0)
|
||
--backoff-factor N Множитель экспоненциальной задержки (по умолчанию: 1.5)
|
||
--inactivity-timeout SEC Переподключаться после N секунд тишины (по умолчанию: выключено)
|
||
```
|
||
|
||
### Форматы вывода
|
||
|
||
- **`hex`** (по умолчанию): обычный hex-дамп — `ATR: 3b 9e ...`,
|
||
`TPDU: a0 a4 00 00 02 3f 00`
|
||
- **`timestamp`**: строки TPDU с локальным временем —
|
||
`[14:32:05.123] TPDU: a0 a4 00 00 02 3f 00`
|
||
- **`atr-time`**: строки TPDU с секундами от последнего ATR —
|
||
`[0001.234] TPDU: a0 a4 00 00 02 3f 00`
|
||
|
||
Сообщения, не являющиеся TPDU (ATR, PPS, изменения состояния карты, Fi/Di),
|
||
выводятся одинаково во всех форматах.
|
||
|
||
- **GSMTAP**: сообщения ATR и APDU по UDP (порт 4729) в Wireshark
|
||
- **PCAP**: сообщения ATR/TPDU как пакеты Ethernet/IP/UDP/GSMTAP,
|
||
открываются в Wireshark
|
||
|
||
### Фоновый режим / демон
|
||
|
||
SIGHUP автоматически игнорируется, когда stdin не является терминалом
|
||
(т.е. при запуске в фоне или через канал). Сессии в терминале на переднем
|
||
плане по-прежнему обрабатывают SIGHUP обычным образом.
|
||
|
||
Для постоянной работы в фоне с выводом в файлы:
|
||
|
||
```sh
|
||
nohup ./sniff-start.sh --output /tmp/sniff.log &> /tmp/sniff-err.log &
|
||
# или
|
||
FORMAT=timestamp nohup python -m simtrace2_pysniff --output /tmp/sniff.log &> /tmp/sniff-err.log &
|
||
```
|
||
|
||
### Использование как библиотеки
|
||
|
||
```python
|
||
from simtrace2_pysniff import SniffSession
|
||
|
||
session = SniffSession(inactivity_timeout=30.0)
|
||
for msg in session.iter_messages():
|
||
print(f"{msg.type}: {msg.data.hex()}")
|
||
```
|
||
|
||
### Восстановление
|
||
|
||
Утилита по умолчанию переживает сбросы оборудования, отключения кабеля
|
||
и зависания прошивки — она переподключается с экспоненциальной задержкой
|
||
(1с → 30с). Используйте `--inactivity-timeout`, чтобы также переподключаться
|
||
при «тихих» зависаниях прошивки.
|
||
|
||
## Доступ к USB-устройству
|
||
|
||
Нужен для захвата с оборудования SIMtrace2 (утилита и режим
|
||
`--capture direct` сервера); для источников GSMTAP и PCAP не требуется.
|
||
|
||
### Linux
|
||
|
||
Для доступа к устройству SIMtrace2 без root нужно udev-правило.
|
||
|
||
```sh
|
||
sudo cp 70-simtrace2-pysniff.rules /etc/udev/rules.d/
|
||
sudo udevadm control --reload-rules
|
||
sudo udevadm trigger
|
||
```
|
||
|
||
Затем переподключите USB-кабель SIMtrace2. Правило использует
|
||
`TAG+="uaccess"` (ACL systemd-logind) — членство в группе и права на
|
||
запись для всех не нужны.
|
||
|
||
### Windows
|
||
|
||
В Windows нет libusb-совместимого драйвера для SIMtrace2. Используйте
|
||
[Zadig](https://zadig.akeo.ie/), чтобы заменить драйвер по умолчанию:
|
||
|
||
1. Скачайте и запустите **Zadig**
|
||
2. Подключите устройство SIMtrace2
|
||
3. Выберите его в выпадающем списке (VID `1D50`, PID `60E3` — "Osmocom SIMtrace 2")
|
||
4. Выберите **WinUSB** (или libusbK) как драйвер замены
|
||
5. Нажмите **Replace Driver** (однократная операция)
|
||
|
||
После этого `python -m simtrace2_pysniff` работает так же, как в Linux.
|
||
|
||
Скрипты запуска для Windows соответствуют shell-версиям и передают все
|
||
параметры: `start.bat --capture direct` запускает сервер анализатора, а
|
||
`sniff-start.bat` — утилиту захвата. Оба вызывают команду `python`, поэтому
|
||
Python 3 должен быть в `PATH` (проверьте `python --version` в новом окне
|
||
команды).
|
||
|
||
## Компоненты
|
||
|
||
- **Анализирующий сервер + PWA** (`simtrace-analyser-server`) — сохраняет
|
||
захваченный трафик в SQLite, декодирует его и отдаёт PWA
|
||
([`frontend/`](frontend/)) вместе с HTTP API на одном origin. Три режима
|
||
захвата: GSMTAP-листенер, захват напрямую с оборудования SIMtrace2 или
|
||
отключённый захват (только просмотр существующих записей).
|
||
- **Утилита захвата** (`simtrace2-pysniff`) — захватывает трафик
|
||
оборудования SIMtrace2 и выводит его в stdout, GSMTAP (Wireshark) или
|
||
PCAP-файлы. Это один из нескольких источников GSMTAP, которые принимает
|
||
анализатор (см. также
|
||
[sigrok_iso7816_stream](https://github.com/anttro/sigrok_iso7816_stream)).
|
||
- **PWA** ([`frontend/`](frontend/)) — окно трассировки с декодированными
|
||
APDU, SIM Toolkit, SMS и SCP80 OTA; сессии, импорт PCAP и трасс COMPRION,
|
||
интерфейс EN/RU.
|
||
|
||
## Возможности
|
||
|
||
**Декодер APDU** (на стороне сервера, отображается в PWA):
|
||
|
||
- Полное декодирование APDU — CLA по ISO 7816-4 / ETSI с **логическим
|
||
каналом 0-19** (стандартные каналы из b2-b1, расширенные 4-19 из b4-b1
|
||
по TS 102 221 §10.3), secure messaging и chaining команд, имена INS из
|
||
таблицы спецификаций, учёт SFI в P1/P2 для READ/UPDATE BINARY и команд
|
||
с записями; ответ MANAGE CHANNEL показывает назначенный картой канал
|
||
- Статусные слова — полный набор ISO 7816-4 плюс специфичные для UICC
|
||
значения: `91XX` (ожидается proactive-команда), `62F1/F2/F3`,
|
||
`63F1/F2` (больше данных), `9300` (SAT busy), `9850`, `9862–64`
|
||
- SIM Toolkit — SAT (GSM 11.14), CAT (TS 102 223) и USAT (TS 31.111):
|
||
proactive-команды с декодированными квалификаторами, TERMINAL RESPONSE,
|
||
ENVELOPE (Menu Selection, Call Control, SMS-PP download…); учитываются
|
||
известные несоответствия старых карт, нераспознанные TLV сохраняются
|
||
- TERMINAL CAPABILITY (TS 102 221 §11.1.19) — питание терминала (класс
|
||
напряжения, максимальный ток, тактовая частота), расширенные логические
|
||
каналы, дополнительные интерфейсы (UICC-CLF) и возможности eUICC
|
||
(SGP.22/SGP.32)
|
||
- SMS TPDU — SMS-DELIVER/SUBMIT, метки времени SCTS, информационные
|
||
элементы UDH
|
||
- SCP80 OTA secured packets — биты SPI (шифрование, требование/режим PoR,
|
||
RC/CC/DS, счётчик), алгоритм KIc/KID + набор ключей, TAR, CNTR/PCNTR;
|
||
декодирование Response Packet (PoR) по GET RESPONSE; **опциональная
|
||
расшифровка на клиенте** зашифрованных пакетов — вставьте 3DES/AES-ключ
|
||
карты в панели деталей, чтобы увидеть настоящие CNTR и защищённые данные
|
||
приложения (ключ остаётся в браузере, только в памяти; зашифрованные
|
||
в эфире CNTR/PCNTR/RC — это шифротекст, и они так и помечены); защищённое
|
||
сообщение приложения декодируется как поток **C-APDU** (SELECT,
|
||
UPDATE BINARY, …) с полной разбивкой CLA/INS/P1/P2/Lc/Le — сразу для
|
||
открытого текста или после расшифровки для зашифрованных пакетов
|
||
- Разбор ATR (пересчёт тактовой частоты, Fi/Di, битовая маска T,
|
||
безопасен для усечённых ATR) и FCP/FCI TLV; исторические байты
|
||
разбираются как COMPACT-TLV объекты UICC (TS 102 221 §6.3.1) — card
|
||
service data, **card capabilities** (ISO 7816-4 §8.1.1.2.7 таблица 88:
|
||
способы назначения и заявленное максимальное число логических каналов,
|
||
`8 or more` у карт с расширенными каналами) и завершающий индикатор
|
||
состояния (LCS/SW)
|
||
|
||
**PWA SIMtrace Analyser** ([`frontend/`](frontend/)):
|
||
|
||
- Окно трассировки с режимами «Карта»/«Список» — proactive,
|
||
TERMINAL RESPONSE, ENVELOPE и AUTH-команды выделяются в режиме карты
|
||
- Сессии с прямыми ссылками (`#session=N`), импорт PCAP
|
||
(`.pcap/.pcapng/.cap`), импорт трасс COMPRION (текстовый экспорт
|
||
«ISO Protocol Layer» из Device Manager), поиск и **фильтр команд с
|
||
множественным выбором** — любые команды и/или готовые пресеты («Проактивные
|
||
сессии»: FETCH, TERMINAL PROFILE и все команды с ответом SW 91xx;
|
||
«Файловые операции»: SELECT,
|
||
READ/UPDATE BINARY и READ/UPDATE RECORD, вместе с GET RESPONSE, несущим
|
||
данные выбранной команды)
|
||
- Устанавливаемая PWA, тёмная тема, интерфейс на английском/русском
|
||
|
||
## Связанные проекты
|
||
|
||
- **[simtrace2](https://gitea.osmocom.org/sim-card/simtrace2)** — вышестоящий
|
||
проект оборудования/прошивки SIMtrace2, с которого утилита захвата
|
||
снимает трафик.
|
||
- **[sigrok_iso7816_stream](https://github.com/anttro/sigrok_iso7816_stream)** —
|
||
пассивный ISO 7816 сниффер на базе FX2LP, выдающий такой же поток
|
||
GSMTAP-SIM на UDP 4729 (принимается GSMTAP-листенером этого проекта).
|
||
|
||
## Лицензия
|
||
|
||
MIT — см. [LICENSE](LICENSE). Декодеры и реализация DES/3DES в PWA написаны
|
||
самостоятельно по спецификациям ISO 7816, ETSI и 3GPP; сторонний код в проект
|
||
не включён. PyUSB (BSD-3-Clause) — зависимость для прямого захвата с
|
||
оборудования.
|