
Scanner Bluetooth Low Energy (BLE) con risoluzione degli indirizzi privati risolvibili (RPA) mediante Identity Resolving Keys (IRKs)
Scansione Bluetooth Low Energy (BLE) con risoluzione avanzata degli Indirizzi Privati Risolvibili (RPA). Scopri i dispositivi BLE nelle vicinanze, traccia un dispositivo specifico tramite indirizzo MAC o risolvi gli indirizzi randomizzati per la privacy utilizzando una chiave di risoluzione dell'identità (IRK).
Scritto da: David Kennedy (@HackingDave) Azienda: TrustedSec
-o -)La marcatura della posizione GPS richiede che il daemon gpsd sia in esecuzione con un ricevitore GPS collegato. Se gpsd non è in esecuzione, btrpa-scan continua normalmente senza GPS.
Per verificare che gpsd funzioni:
# Controlla che gpsd sia in ascolto
gpspipe -w -n 5
# Oppure usa il monitor curses
cgps
Questo progetto usa pyproject.toml (PEP 621), lo standard moderno di packaging Python. Definisce il progetto come pacchetto installabile con un comando CLI registrato: non è necessario eseguire i file .py direttamente.
uvx btrpa-scan --all
uvx --from git+https://github.com/hackingdave/btrpa-scan.git btrpa-scan --all
uv tool install btrpa-scan
Oppure direttamente da GitHub:
uv tool install git+https://github.com/hackingdave/btrpa-scan.git
pip install btrpa-scan
Per il supporto GUI (interfaccia radar basata su Flask):
pip install btrpa-scan[gui]
git clone https://github.com/hackingdave/btrpa-scan.git
cd btrpa-scan
pip install .
usage: btrpa-scan [-h] [-a] [--irk HEX] [--irk-file PATH] [-t TIMEOUT]
[--output {csv,json,jsonl}] [-o FILE] [--log FILE]
[-v | -q] [--min-rssi DBM] [--rssi-window N] [--active]
[--environment {free_space,indoor,outdoor}]
[--ref-rssi DBM] [--name-filter PATTERN]
[--alert-within METERS] [--tui] [--gui] [--gui-port PORT]
[--no-gps] [--adapters LIST] [mac]
BLE Scanner — scopri tutti i dispositivi o cerca uno specifico
positional arguments:
mac Indirizzo MAC del dispositivo da cercare (ometti per scansionare tutto)
optional arguments:
-h, --help mostra questo messaggio di aiuto ed esce
-a, --all Scansiona tutti i dispositivi che trasmettono
--irk HEX Risolvi le RPA usando questa chiave di risoluzione dell'identità (32 caratteri hex)
--irk-file PATH Leggi una o più IRK da un file (una per riga, formato hex)
-t, --timeout TIMEOUT Timeout di scansione in secondi (default: 30, o infinito per --irk)
--output {csv,json,jsonl}
Formato di output batch scritto al termine della scansione
-o, --output-file FILE
Percorso del file di output (default: btrpa-scan-results.<formato>;
usa - per stdout)
--log FILE Trasmette i rilevamenti a un file CSV in tempo reale
-v, --verbose Modalità verbose — mostra dettagli aggiuntivi
-q, --quiet Modalità quiet — sopprime l'output per dispositivo, mostra solo il riepilogo
--min-rssi DBM Soglia RSSI minima (es. -70) — ignora i segnali più deboli
--rssi-window N Dimensione della finestra scorrevole RSSI per la media (default: 1 = nessuna media)
--active Usa la scansione attiva (invia SCAN_REQ per dati aggiuntivi)
--environment {free_space,indoor,outdoor}
Modello di attenuazione per la stima della distanza (default: free_space)
--ref-rssi DBM RSSI calibrata a 1 metro per la stima della distanza
--name-filter PATTERN Filtra i dispositivi per nome (corrispondenza di sottostringa senza distinzione maiuscole/minuscole)
--alert-within METERS Avviso di prossimità quando il dispositivo è entro questa distanza
--tui Tabella del terminale ad aggiornamento live invece dell'output scorrevole
--gui Avvia l'interfaccia radar basata su browser
--gui-port PORT Porta per il server web della GUI (default: 5000)
--no-gps Disabilita la marcatura della posizione GPS (il GPS è attivo per impostazione predefinita tramite gpsd)
--adapters LIST Nomi degli adattatori Bluetooth separati da virgola (es. hci0,hci1)
Scansiona tutti i dispositivi BLE che trasmettono (timeout predefinito di 30 secondi):
btrpa-scan --all
Con un timeout personalizzato:
btrpa-scan --all -t 60
Cerca un dispositivo specifico tramite indirizzo MAC:
btrpa-scan AA:BB:CC:DD:EE:FF
Risolvi gli Indirizzi Privati Risolvibili usando una chiave di risoluzione dell'identità. Questa modalità viene eseguita indefinitamente per impostazione predefinita fino a quando non viene interrotta con Ctrl+C:
btrpa-scan --irk 0123456789ABCDEF0123456789ABCDEF
L'IRK può essere fornita in diversi formati:
| Formato | Esempio |
|---|---|
| Hex semplice | 0123456789ABCDEF0123456789ABCDEF |
| Separato da due punti |
Carica una o più IRK da un file. Ogni riga deve contenere una IRK in qualsiasi formato hex supportato. Le righe che iniziano con # sono trattate come commenti:
btrpa-scan --irk-file keys.txt
Esempio di keys.txt:
# Il telefono di Alice
0123456789ABCDEF0123456789ABCDEF
# L'orologio di Bob
FEDCBA9876543210FEDCBA9876543210
Quando vengono caricate più IRK, ogni RPA rilevata viene controllata contro tutte le chiavi. Il riepilogo mostra il totale delle corrispondenze su tutte le chiavi.
Imposta la variabile d'ambiente BTRPA_IRK per evitare di passare la chiave sulla riga di comando:
export BTRPA_IRK=0123456789ABCDEF0123456789ABCDEF
btrpa-scan
Priorità: --irk > --irk-file > BTRPA_IRK
Mostra solo i dispositivi con intensità del segnale superiore a una soglia:
btrpa-scan --all --min-rssi -70
L'RSSI BLE è intrinsecamente rumoroso. Usa una media a finestra scorrevole per stime di distanza più stabili e per filtrare i rilevamenti deboli spuri:
btrpa-scan --all --rssi-window 5
Quando la finestratura è attiva, la visualizzazione mostra sia l'RSSI grezzo che quello mediato (es. RSSI: -65 dBm (avg: -62 dBm over 5 readings)), e la stima della distanza usa il valore mediato. Il filtro --min-rssi si applica anche all'RSSI mediato, impedendo a un singolo picco rumoroso di far sparire un dispositivo.
Filtra i dispositivi per nome usando una corrispondenza di sottostringa senza distinzione tra maiuscole e minuscole:
btrpa-scan --all --name-filter "AirPods"
Vengono mostrati solo i dispositivi il cui nome pubblicizzato contiene il pattern indicato. I dispositivi senza nome vengono esclusi quando è attivo un filtro per nome.
La scansione passiva (predefinita) vede solo gli advertisement. La scansione attiva invia SCAN_REQ e riceve SCAN_RSP, che può rivelare UUID di servizi aggiuntivi e nomi di dispositivo:
btrpa-scan --all --active
Nota: Su macOS, CoreBluetooth esegue sempre scansioni attive indipendentemente da questo flag. Su Linux/BlueZ, la scansione attiva può richiedere root o
CAP_NET_ADMIN.
La stima della distanza usa un esponente di attenuazione del percorso che varia in base all'ambiente. Il default (free_space, n=2.0) presuppone l'assenza di ostacoli. Per stime più realistiche in ambienti interni:
btrpa-scan --all --environment indoor
| Preset | Esponente di attenuazione (n) | Caso d'uso |
|---|---|---|
free_space | 2.0 | Aria aperta, linea di vista |
Valori di n più alti producono stime di distanza maggiori per lo stesso RSSI, riflettendo l'attenuazione del segnale dovuta a muri e ostacoli.
Per impostazione predefinita btrpa-scan ricava l'RSSI attesa a 1 metro dalla TX Power pubblicizzata usando un offset di 59 dB convalidato empiricamente (lo standard iBeacon). Per una precisione ancora maggiore puoi fornire un valore calibrato misurato nel tuo ambiente:
--ref-rssi:btrpa-scan --all --ref-rssi -55
Quando viene impostato --ref-rssi, la TX Power viene completamente ignorata. Questo abilita anche le stime di distanza per i dispositivi che non pubblicizzano la TX Power.
Attiva un campanello acustico e un avviso visivo quando un dispositivo viene stimato entro una data distanza. Richiede che il dispositivo target pubblichi la TX Power:
btrpa-scan AA:BB:CC:DD:EE:FF --alert-within 5.0
Funziona in tutte le modalità, inclusa la risoluzione IRK:
btrpa-scan --irk <key> --alert-within 3.0
Sostituisci l'output scorrevole con una tabella del terminale ad aggiornamento live, ordinata per intensità del segnale:
btrpa-scan --all --tui
La TUI mostra tutti i dispositivi rilevati in una tabella compatta con indirizzo, nome, RSSI, RSSI mediata, distanza stimata, conteggio dei rilevamenti e ora dell'ultima visualizzazione. Le corrispondenze IRK risolte sono mostrate in grassetto e i dispositivi entro la soglia --alert-within sono evidenziati.
Combinabile con altri flag:
btrpa-scan --irk <key> --tui --rssi-window 5 --environment indoor --alert-within 5.0
Avvia un'interfaccia radar basata su browser con spazzata animata, tracciamento dei dispositivi in tempo reale e mappa GPS:
btrpa-scan --all --gui
La GUI include:
La modalità GUI esegue la scansione in continuo per impostazione predefinita (nessun timeout di 30 secondi). Premi Ctrl+C per fermarla. Usa -t per impostare una durata di scansione specifica:
# Scansiona per 60 secondi con il modello di attenuazione indoor
btrpa-scan --all --gui -t 60 --environment indoor
# Porta personalizzata
btrpa-scan --all --gui --gui-port 8080
# Combinazione con media RSSI e avvisi di prossimità
btrpa-scan --all --gui --rssi-window 5 --alert-within 5.0
Nota:
--guirichiede Flask e flask-socketio (pip install btrpa-scan[gui]). Non può essere combinato con--tuio--quiet.
Trasmette ogni rilevamento a un file CSV in tempo reale (utile per scansioni di lunga durata in cui si vogliono dati incrementali):
btrpa-scan --all --log scan.csv
Può essere combinato con --output per un'esportazione batch separata:
btrpa-scan --all --log live.csv --output json -o results.json
Esporta tutti i risultati al termine della scansione in formato CSV, JSON o JSONL (JSON Lines):
btrpa-scan --all --output json -o results.json -t 30
btrpa-scan --all --output csv -t 30
btrpa-scan --all --output jsonl -o results.jsonl -t 30
JSONL scrive un oggetto JSON per riga, semplificando il passaggio attraverso jq:
btrpa-scan --all --output jsonl -o results.jsonl -t 10
cat results.jsonl | jq .
Scrivi l'output su stdout per il piping:
btrpa-scan --all --output json -o - -t 10 -q | jq .
Scansiona con più adattatori Bluetooth contemporaneamente per una copertura più ampia:
btrpa-scan --all --adapters hci0,hci1
Ogni adattatore esegue la propria istanza di scansione che condivide lo stesso callback di rilevamento. Tutti i rilevamenti vengono uniti in un unico output.
Il GPS è attivo per impostazione predefinita. Ogni rilevamento viene etichettato con le coordinate GPS correnti da gpsd. Lo scanner tiene anche traccia della migliore posizione GPS per dispositivo: le coordinate del rilevamento con l'RSSI più forte (prossimità più vicina = posizione più accurata).
Se gpsd non è in esecuzione, lo scanner stampa una nota e continua normalmente senza GPS:
# Con gpsd in esecuzione — i rilevamenti includono lat/lon
btrpa-scan --all --output json
# Senza gpsd — funziona comunque, i campi GPS sono vuoti
btrpa-scan --all
# Disabilita esplicitamente il GPS (salta il tentativo di connessione)
btrpa-scan --all --no-gps
Le coordinate GPS compaiono in:
latitude, longitude, gps_altitudeEsegui in modalità quiet (solo riepilogo, nessun output per dispositivo — utile con --output o --log):
btrpa-scan --all -q --output json -t 30
Esegui in modalità verbose (mostra le RPA non corrispondenti in modalità IRK):
btrpa-scan --irk 0123456789ABCDEF0123456789ABCDEF -v
I dispositivi Bluetooth Low Energy usano gli Indirizzi Privati Risolvibili (RPA) per prevenire il tracciamento. Un RPA è un indirizzo MAC temporaneo che cambia periodicamente, ma può essere risolto da chiunque possieda la chiave di risoluzione dell'identità (IRK) del dispositivo.
Un RPA è composto da:
01AES-128-ECB(IRK, padding || prand) troncato a 3 bytebtrpa-scan implementa la funzione ah() della Specifica Bluetooth Core (Vol 3, Part H, Section 2.2.2) per risolvere questi indirizzi in tempo reale.
Nota su AES-ECB: L'uso di AES in modalità ECB per la funzione
ah()è imposto dalla Specifica Bluetooth Core. Poiché viene sempre crittografato un unico blocco da 16 byte, la mancanza di diffusione tra blocchi dell'ECB è irrilevante: non si tratta di una vulnerabilità.
ps. Per evitare di esporre l'IRK, usa --irk-file per leggerla da un file oppure imposta la variabile d'ambiente BTRPA_IRK. L'output della console maschera le IRK per impostazione predefinita (mostrando solo i primi e gli ultimi 4 caratteri hex).--no-gps per disabilitare completamente il GPS.--output-file e --log scrivono nel percorso specificato. Assicurati che la destinazione abbia i permessi appropriati per il tuo caso d'uso.pip install pytest
python -m pytest test_btrpa_scan.py -v
Mode: DISCOVER ALL - showing every broadcasting device
Scanning: passive
GPS: connected (37.774929, -122.419418)
Timeout: 30s | Press Ctrl+C to stop
------------------------------------------------------------
============================================================
DEVICE #1 - seen 1x
============================================================
Address : AA:BB:CC:DD:EE:FF
Name : MyDevice
RSSI : -45 dBm
TX Power : -59 dBm
Est. Distance: ~0.4 m
Manufacturer : 0x004C -> 0215abcdef
Best GPS : 37.774929, -122.419418
Timestamp : 14:32:07
============================================================
------------------------------------------------------------
Scan complete - 30.0s elapsed
Total detections : 142
Unique devices : 12
Results written to btrpa-scan-results.json
Premi Ctrl+C in qualsiasi momento per interrompere la scansione in modo pulito e visualizzare le statistiche di riepilogo.
| Piattaforma | Installazione | Avvio |
|---|
| macOS | brew install gpsd | gpsd -n /dev/tty.usbserial-* |
| Debian/Ubuntu | sudo apt install gpsd gpsd-clients | sudo systemctl start gpsd |
| Fedora/RHEL | sudo dnf install gpsd gpsd-clients | sudo systemctl start gpsd |
| Arch | sudo pacman -S gpsd | sudo systemctl start gpsd |
| Windows | Usa gpsd tramite WSL o MSYS2 | Vedi le istruzioni WSL sopra |
| Piattaforma | Note |
|---|
| macOS | Usa CoreBluetooth. La modalità IRK sfrutta un'API non documentata per recuperare i veri indirizzi Bluetooth invece degli UUID. --active non ha effetto: CoreBluetooth esegue sempre scansioni attive. |
| Linux | Può richiedere la capacità root o CAP_NET_ADMIN per la scansione. |
| Windows | API Bluetooth WinRT nativa: i veri indirizzi MAC sono disponibili in modo nativo. La TUI richiede pip install windows-curses. |
01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF| Separato da trattini | 01-23-45-67-89-AB-CD-EF-01-23-45-67-89-AB-CD-EF |
| Prefisso 0x | 0x0123456789ABCDEF0123456789ABCDEF |
outdoor | 2.2 | Parchi, parcheggi |
indoor | 3.0 | Uffici, case, edifici |