Files
simtrace-analyser/README_RUS.md
T
catarrh 5809092175 Files view: the change-details modal shows the full file path (v2.4.2)
- the modal header showed only the flat name (EF_ICCID, 4F09); it now shows the
  path built from data already available: the tracker's DF identity named via
  KNOWN_FIDS (MF, DF_GSM_ACCESS, DF_TELECOM, …), 'ADF' for the current
  application (7FFF), DF_CHILDREN for DF-qualified EF names (4F52 →
  EF_KcGPRS) and the EF.DIR labels for AID-selected applications —
  e.g. `MF/EF_ICCID (2FE2)`, `ADF/EF_IMSI (6F07)`,
  `DF_GSM_ACCESS/EF_KcGPRS (4F52)`, `AID A00000015141434C00/4F09`
- exposed as `path` in the change-details payload and in the files entries
  (the timeline rows keep the short name — they have no room)
- the colour legend (changed / newly observed / never observed) moved below
  the two hex views
- tests: `_file_path` cases (MF, ADF, DF-qualified EF, AID with and without an
  EF.DIR label, FID-as-name) plus the payload field, and the Node modal test
  asserts the path header and that the legend follows the views
- v2.4.2; SW cache simtrace-analyser-v68
2026-10-17 21:35:41 +03:00

28 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 берутся из нормативных таблиц (TS 102 221 Annex H, TS 31.102 Annex H) и из каждого показанного 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 отдаёт, но в этом виде пока не показываются.

Параметры сервера:

--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-листенером этого проекта).