- the header title drops its "UICC" prefix — "GSMTAP trace analyser" is enough - the trace topbar's search input is half its previous width (flex basis 33.333% -> 16.667%); the session name now ellipsizes instead of wrapping the tighter row - the side-panel view selector moved out of the scrollable side panel into the trace topbar: right-aligned over the panel at the panel's width (--side-panel-w: 260px, the negative right margin cancelling the topbar's 16px padding so the edges line up), so it stays visible at all times while the panel scrolls - tests: the topbar/selector position pins (the Files-view wiring test and style.test.js), the shared width variable, the halved search basis and the title; 527 Python + 61 Node tests - README/README_RUS: the selector's new place; PWA_VERSION/pyproject/ version.py 2.6.3, SW cache simtrace-analyser-v77
446 lines
31 KiB
Markdown
446 lines
31 KiB
Markdown
# SIMtrace Analyser
|
||
|
||
[English](README.md) | Русский
|
||
|
||
Анализатор APDU-трассировок в формате GSMTAP-SIM — захватывает обмен с
|
||
SIM/UICC из UDP-потока GSMTAP (или импортирует файлы PCAP/PCAPNG),
|
||
декодирует его и отдаёт устанавливаемое веб-приложение для просмотра.
|
||
В репозиторий также включён **simtrace2-pysniff** — замена `simtrace2-sniff`
|
||
на Python, которая захватывает трафик с оборудования Osmocom SIMtrace2
|
||
и может передавать GSMTAP этому анализатору.
|
||
|
||

|
||
|
||
## Компоненты
|
||
|
||
- **Анализирующий сервер + 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), поиск и фильтрация по типу
|
||
- Устанавливаемая PWA, тёмная тема, интерфейс на английском/русском
|
||
|
||
## Требования
|
||
|
||
- **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.
|
||
|
||
## Установка
|
||
|
||
```sh
|
||
git clone https://github.com/anttro/simtrace-analyser.git
|
||
cd simtrace-analyser
|
||
pip install pyusb
|
||
```
|
||
|
||
Или установите пакет в своё окружение:
|
||
|
||
```sh
|
||
pip install -e .
|
||
# затем запуск: simtrace-analyser-server [opts]
|
||
# или: simtrace2-pysniff [opts]
|
||
```
|
||
|
||
## Запуск
|
||
|
||
### Анализирующий сервер + PWA (`simtrace-analyser-server`)
|
||
|
||
Сохраняет захваченный APDU-трафик в SQLite и отдаёт его по HTTP вместе
|
||
со встроенной PWA **SIMtrace Analyser** (`frontend/`) на том же origin.
|
||
Три режима захвата:
|
||
|
||
```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** и **Changed on card** показывают те же имена файлов, что и вид Map,
|
||
а щелчок по строке переходит прямо к APDU в трассе и оставляет его
|
||
выделенным, пока не выбран другой (список APDU сохраняет позицию читателя:
|
||
новые сообщения прижимают вид к низу, только пока читатель уже внизу,
|
||
поэтому переход не срывается живым опросом и не снимает выделение). У строк с записанным изменением
|
||
(изменение со стороны карты либо запись, изменившая или впервые показавшая
|
||
байты) есть кнопка **Details**: окно показывает полный путь файла (`MF/EF_ICCID (2FE2)`,
|
||
`ADF/EF_IMSI (6F07)`, `DF_GSM_ACCESS/EF_KcGPRS (4F52)`, `AID …/4F09` — DF
|
||
называется по меткам из EF.DIR, если они есть) и затронутую единицу — файл
|
||
целиком или изменившуюся запись — **до и после** изменения в виде hex-вида
|
||
(16 байт в строке, никогда не наблюдавшиеся байты — `--`), причём изменённые
|
||
байты подсвечены одним цветом, а впервые наблюдаемые — другим; ниже —
|
||
счётчики изменённых/новых байт, ссылка на APDU и легенда цветов под
|
||
представлениями.
|
||
|
||
Изображения отдаёт `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)
|
||
--web-dir PATH каталог статических файлов PWA (по умолчанию: <repo>/frontend)
|
||
```
|
||
|
||
Затем откройте **http://127.0.0.1:8081/** в браузере — PWA отдаётся
|
||
сервером, поэтому UI и API используют один origin, и настройка
|
||
CORS/Private-Network-Access не требуется. Используйте `--web-dir PATH`,
|
||
чтобы отдавать другой каталог 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
|
||
```
|
||
|
||
## Доступ к 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.
|
||
|
||
## Параметры 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`, чтобы также переподключаться
|
||
при «тихих» зависаниях прошивки.
|
||
|
||
## Связанные проекты
|
||
|
||
- **[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-листенером этого проекта).
|