Files
simtrace-analyser/README.md
T
catarrh b900a8a3e1 Merge simtrace-analyser PWA into frontend/ (monorepo); serve it same-origin
- frontend/: simtrace-analyser PWA (index.html, sw.js, manifest.json,
  icons, tests/index.test.html) copied in fresh
- server.py: static file serving (_STATIC_MIME, _serve_static) with
  path-traversal guard; injects window.SIMTRACE_EMBEDDED='1' into
  index.html so the PWA defaults to a relative API base
- server __main__: --web-dir (default <repo>/frontend)
- frontend: embedded same-origin mode; sw.js relative precache paths +
  cache v4; GitHub link + version-warn point at simtrace2-pysniff
- version 1.1.0 everywhere (__version__, pyproject, PWA_VERSION,
  manifest); MIN_SERVER_VERSION stays 1.0.0
- README/scripts/.gitignore updated

Tests: 107.
2026-08-14 16:26:28 +03:00

205 lines
6.8 KiB
Markdown

# simtrace2-pysniff
Python-based replacement for `simtrace2-sniff` — SIM card communication sniffer
for Osmocom SIMtrace2 hardware (firmware in **trace** mode). It bundles the
**simtrace-analyser** PWA (in [`frontend/`](frontend/)) and an analysis server
that both captures APDU traffic and serves that PWA.
**Single dependency**: PyUSB (libusb wrapper). No libosmocore, no libosmosim.
## Prerequisites
- **Python 3.9+**
- **PyUSB** — `pip install pyusb`
- **libusb** — system library, present by default on Linux; on Windows the
SIMtrace2 driver must be swapped (see [USB Device Access](#usb-device-access))
- **SIMtrace2 hardware** running firmware in *trace* mode
(VID `1d50`, PID `60e3`, USB class `ff`, subclass `01`). For building and
flashing trace firmware, see the [upstream SIMtrace2 project](https://gitea.osmocom.org/sim-card/simtrace2).
No other dependencies. PCAP, GSMTAP, and hex dump output use only Python stdlib.
## Install
```sh
git clone https://github.com/anttro/simtrace2-pysniff.git
cd simtrace2-pysniff
pip install pyusb
```
Or install the package into your environment:
```sh
pip install -e .
# then run: simtrace2-pysniff [opts]
```
## Running
Two tools are provided:
### Sniffer CLI (`simtrace2-pysniff`)
Captures SIMtrace2 traffic and writes it to stdout, GSMTAP (Wireshark), or PCAP files.
### Startup script (Linux only)
`./sniff-start.sh` performs a pre-flight USB permission check (prints udev
install instructions if the SIMtrace2 device is not writable) and then
launches the Python module.
```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
```
OPTIONS can also be set via environment variables:
```sh
FORMAT=timestamp GSMTAP=127.0.0.1 ./sniff-start.sh
```
### Analysis server + PWA (`simtrace2-pysniff-server`)
Stores captured APDU traffic in SQLite and serves it over HTTP, together with
the bundled **simtrace-analyser** PWA (`frontend/`) on the same origin. Two
capture modes:
```sh
# Listen for GSMTAP from simtrace2-pysniff (or original simtrace2-sniff):
simtrace2-pysniff-server --capture gsmtap
# Capture directly from SIMtrace2 hardware (no external tool needed):
simtrace2-pysniff-server --capture direct
```
Then open **http://127.0.0.1:8081/** in a browser — the PWA is served by the
server, so the UI and the API share an origin and no CORS/Private-Network-Access
setup is involved. Use `--web-dir PATH` to serve a different PWA directory
(default: `<repo>/frontend`).
### Hosted PWA (landing page)
A standalone copy of the PWA is hosted at **https://simtrace.atroshin.ru**.
It is a pure frontend: point it (Settings → Server URL) at a locally running
`simtrace2-pysniff-server`.
> **Browser restriction:** when the PWA is served from a public HTTPS host,
> reaching a local server (`http://127.0.0.1:8081`) requires two things: the
> server must send `Access-Control-Allow-Private-Network: true` (this server
> does), and the browser must be allowed to access the local network — in
> Chrome/Edge/Vivaldi: Site settings → Local network access → allow the site
> (or accept the permission prompt). Without the browser permission, the
> request to `127.0.0.1` is blocked before any preflight is sent.
### Python module (cross-platform)
```sh
python -m simtrace2_pysniff
python -m simtrace2_pysniff --format timestamp --gsmtap 127.0.0.1:4729
python -m simtrace2_pysniff --pcap trace.pcap
```
If installed via `pip install -e .`, use the console script directly:
```sh
simtrace2-pysniff --format atr-time
```
## USB Device Access
### Linux
A udev rule is required for non-root USB access to the SIMtrace2 device.
```sh
sudo cp 70-simtrace2-pysniff.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger
```
Then reconnect the SIMtrace2 USB cable. The rule uses `TAG+="uaccess"`
(systemd-logind ACL) — no group membership or world-writable permissions needed.
### Windows
Windows does not ship a libusb-compatible driver for SIMtrace2. Use
[Zadig](https://zadig.akeo.ie/) to replace the default driver:
1. Download and run **Zadig**
2. Plug in the SIMtrace2 device
3. Select it in the dropdown (VID `1D50`, PID `60E3` — "Osmocom SIMtrace 2")
4. Choose **WinUSB** (or libusbK) as the replacement driver
5. Click **Replace Driver** (one-time operation)
After that, `python -m simtrace2_pysniff` works identically to Linux.
## CLI Options
```
python -m simtrace2_pysniff [OPTIONS]
--format, -f FORMAT Output format (default: hex)
hex — plain hex dump
timestamp — TPDU lines prefixed with [HH:MM:SS.mmm]
atr-time — TPDU lines prefixed with [SSSS.mmm] from last ATR
--gsmtap HOST[:PORT] Send ATR/TPDU as GSMTAP over UDP (default port 4729)
--pcap FILE Write sniffed data to PCAP file for Wireshark
--output, -o FILE Write hex dump to file
--no-stdout Suppress hex dump to stdout
--vendor HEX USB vendor ID (default: 0x1d50)
--product HEX USB product ID (default: auto-detect)
Recovery options:
--no-reconnect Exit on USB disconnect instead of reconnecting
--inactivity-timeout SEC Reconnect after N seconds of silence (default: disabled)
```
## Output Formats
- **`hex`** (default): plain hex dump — `ATR: 3b 9e ...`, `TPDU: a0 a4 00 00 02 3f 00`
- **`timestamp`**: TPDU lines prefixed with local time — `[14:32:05.123] TPDU: a0 a4 00 00 02 3f 00`
- **`atr-time`**: TPDU lines prefixed with seconds since last ATR — `[0001.234] TPDU: a0 a4 00 00 02 3f 00`
Non-TPDU messages (ATR, PPS, card state changes, Fi/Di) print identically in all formats.
- **GSMTAP**: ATR and APDU messages over UDP (port 4729) to Wireshark
- **PCAP**: ATR/TPDU messages as Ethernet/IP/UDP/GSMTAP packets, openable in Wireshark
## Background / Daemon
SIGHUP is automatically ignored when stdin is not a terminal (i.e. run in
background or via a pipe). Foreground terminal sessions still respond to
SIGHUP normally.
To run persistently in the background with output to files:
```sh
nohup ./sniff-start.sh --output /tmp/sniff.log &> /tmp/sniff-err.log &
# or
FORMAT=timestamp nohup python -m simtrace2_pysniff --output /tmp/sniff.log &> /tmp/sniff-err.log &
```
## Library Usage
```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()}")
```
## Recovery
The tool survives hardware resets, cable disconnects, and firmware hangs
by default — it reconnects with exponential backoff (1s → 30s cap).
Use `--inactivity-timeout` to also trigger reconnect on silent firmware hangs.
## Related
- **[simtrace2](https://gitea.osmocom.org/sim-card/simtrace2)** — the upstream
SIMtrace2 hardware/firmware project that this tool sniffs from.