Files
simtrace-analyser/README_RUS.md
T
catarrh cbeeed3608 File names: the DF-scoped spec dictionary + refreshed EF/SFI tables (v2.5.0)
- the file/DF/SFI dictionaries move to simtrace_analyser/ef_tables.py and are
  extracted from the pinned specs: TS 102 221 (MF, Annex H.1), TS 31.102
  (ADF USIM 4.2 and the child DFs 4.3/4.4/4.6, the H.1-H.12 SFI annexes, the
  Annex L.6 Relay Node/certificate files; Annex A/E as the ADF/DF file
  completeness cross-check), TS 31.103 and TS 51.011 - 20 DF tables (~370
  entries) and 14 SFI tables, up from ~180 flat names and 3 SFI tables
- names are DF-scoped: a FID reused across DFs resolves to the file its DF
  context names - 4F09 is EF_SUPI_NAI under DF_5GS but EF_PROSE_GC under
  DF_ProSe, 6F07 is EF_IMSI in the USIM/SIM but EF_IST in the ISIM, 6F4E is
  EF_EXT4 in DF_TELECOM but EF_EXT5 in the USIM ADF; the flat table keeps
  only names that are identical everywhere and is the fallback when no DF is
  known (the two names the old table had wrong there are fixed: 6F0A is
  EF_AC_GBAUAPI, 6F53 EF_LOCIGPRS)
- the SELECT-path decoder resolves the 7FFF children against the USIM ADF
  table, and the Files view names files DF-first - including files first seen
  only via their FCP (a select-only file used to keep the bare FID, e.g.
  ADF/6F3C is now ADF/EF_SMS (6F3C))
- tests/data/spec_files.json pins the extracted tables; tests/test_decode.py
  asserts the DF/ADF tables cover them, the SFI tables match them exactly and
  every flat name is a spec name for that FID; tests/extract_spec_tables.py
  regenerates the fixture from the PDFs and --check re-verifies the tables
- README/README_RUS document the dictionary and its sources; PWA_VERSION and
  pyproject/version.py 2.5.0, SW cache simtrace-analyser-v71
2026-10-17 22:11:47 +03:00

29 KiB
Raw Blame History

SIMtrace Analyser

English | Русский

Анализатор APDU-трассировок в формате GSMTAP-SIM — захватывает обмен с SIM/UICC из UDP-потока GSMTAP (или импортирует файлы PCAP/PCAPNG), декодирует его и отдаёт устанавливаемое веб-приложение для просмотра. В репозиторий также включён simtrace2-pysniff — замена simtrace2-sniff на Python, которая захватывает трафик с оборудования Osmocom SIMtrace2 и может передавать GSMTAP этому анализатору.

PWA SIMtrace Analyser

Компоненты

  • Анализирующий сервер + PWA (simtrace-analyser-server) — сохраняет захваченный трафик в SQLite, декодирует его и отдаёт PWA (frontend/) вместе с HTTP API на одном origin. Три режима захвата: GSMTAP-листенер, захват напрямую с оборудования SIMtrace2 или отключённый захват (только просмотр существующих записей).
  • Утилита захвата (simtrace2-pysniff) — захватывает трафик оборудования SIMtrace2 и выводит его в stdout, GSMTAP (Wireshark) или PCAP-файлы. Это один из нескольких источников GSMTAP, которые принимает анализатор (см. также sigrok_iso7816_stream).
  • PWA (frontend/) — окно трассировки с декодированными APDU, SIM Toolkit, SMS и SCP80 OTA; сессии, импорт PCAP и трасс COMPRION, интерфейс EN/RU.

Возможности

Декодер APDU (на стороне сервера, отображается в PWA):

  • Полное декодирование APDU — CLA по ISO 7816-4 / ETSI (логический канал, secure messaging, chaining команд), имена INS из таблицы спецификаций, учёт SFI в P1/P2 для READ/UPDATE BINARY и команд с записями
  • Статусные слова — полный набор 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) и FCP/FCI TLV

PWA SIMtrace Analyser (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-устройству)
  • Оборудование SIMtrace2 с прошивкой в режиме trace (только для прямого захвата; VID 1d50, PID 60e3, USB class ff, subclass 01). О сборке и прошивке trace-прошивки см. проект SIMtrace2.

Других зависимостей нет. Вывод PCAP, GSMTAP и hex dump использует только стандартную библиотеку Python.

Установка

git clone https://github.com/anttro/simtrace-analyser.git
cd simtrace-analyser
pip install pyusb

Или установите пакет в своё окружение:

pip install -e .
# затем запуск: simtrace-analyser-server [opts]
# или:          simtrace2-pysniff [opts]

Запуск

Анализирующий сервер + PWA (simtrace-analyser-server)

Сохраняет захваченный APDU-трафик в SQLite и отдаёт его по HTTP вместе со встроенной PWA SIMtrace Analyser (frontend/) на том же origin. Три режима захвата:

# Слушать 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 и Capture stopped (либо ERROR: capture thread stopped on error …, если поток захвата неожиданно умер). Неверно сформированные или не-SIM датаграммы GSMTAP отбрасываются и считаются (dropped), а не молча убивают захват. Интервал 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 в трассе. У строк с записанным изменением (изменение со стороны карты либо запись, изменившая или впервые показавшая байты) есть кнопка 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 с теми же параметрами (проверка прав не требуется).

./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

Параметры также можно задавать через переменные окружения:

FORMAT=timestamp GSMTAP=127.0.0.1 ./sniff-start.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 ., используйте консольный скрипт напрямую:

simtrace2-pysniff --format atr-time

Доступ к USB-устройству

Нужен для захвата с оборудования SIMtrace2 (утилита и режим --capture direct сервера); для источников GSMTAP и PCAP не требуется.

Linux

Для доступа к устройству SIMtrace2 без root нужно udev-правило.

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, чтобы заменить драйвер по умолчанию:

  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 обычным образом.

Для постоянной работы в фоне с выводом в файлы:

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 &

Использование как библиотеки

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 — вышестоящий проект оборудования/прошивки SIMtrace2, с которого утилита захвата снимает трафик.
  • sigrok_iso7816_stream — пассивный ISO 7816 сниффер на базе FX2LP, выдающий такой же поток GSMTAP-SIM на UDP 4729 (принимается GSMTAP-листенером этого проекта).