
Scanner Bluetooth Low Energy (BLE) avec résolution des adresses privées résolvables (RPA) à l'aide des clés de résolution d'identité (IRK)
Un scanner Bluetooth Low Energy (BLE) doté d'une résolution avancée des adresses privées résolubles (RPA). Découvrez les appareils BLE à proximité, suivez un appareil spécifique par adresse MAC ou résolvez les adresses randomisées pour la confidentialité à l'aide d'une clé de résolution d'identité (IRK).
Écrit par : David Kennedy (@HackingDave) Société : TrustedSec
-o -)L'horodatage de localisation GPS nécessite que le démon gpsd soit en cours d'exécution avec un récepteur GPS connecté. Si gpsd ne fonctionne pas, btrpa-scan continue normalement sans GPS.
Pour vérifier que gpsd fonctionne :
# Vérifie que gpsd écoute
gpspipe -w -n 5
# Ou utilise le moniteur curses
cgps
Ce projet utilise pyproject.toml (PEP 621), la norme moderne d'empaquetage Python. Il définit le projet comme un paquet installable doté d'une commande CLI enregistrée — nul besoin d'exécuter les fichiers .py directement.
uvx btrpa-scan --all
uvx --from git+https://github.com/hackingdave/btrpa-scan.git btrpa-scan --all
uv tool install btrpa-scan
Ou directement depuis GitHub :
uv tool install git+https://github.com/hackingdave/btrpa-scan.git
pip install btrpa-scan
Pour la prise en charge de l'interface graphique (interface radar basée sur Flask) :
pip install btrpa-scan[gui]
git clone https://github.com/hackingdave/btrpa-scan.git
cd btrpa-scan
pip install .
utilisation : 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 — découvrez tous les appareils ou traquez un appareil spécifique
arguments positionnels :
mac Adresse MAC cible à rechercher (omettre pour analyser tout)
arguments optionnels :
-h, --help Affiche ce message d'aide et quitte
-a, --all Analyse tous les appareils diffusant
--irk HEX Résout les RPA à l'aide de cette clé de résolution d'identité (32 caractères hexadécimaux)
--irk-file PATH Lit la ou les IRK depuis un fichier (une par ligne, format hexadécimal)
-t, --timeout TIMEOUT Délai d'analyse en secondes (défaut : 30, ou infini pour --irk)
--output {csv,json,jsonl}
Format de sortie par lot écrit à la fin de l'analyse
-o, --output-file FILE
Chemin du fichier de sortie (défaut : btrpa-scan-results.<format> ;
utiliser - pour la sortie standard)
--log FILE Diffuse les détections vers un fichier CSV en temps réel
-v, --verbose Mode verbeux — affiche des détails supplémentaires
-q, --quiet Mode silencieux — supprime la sortie par appareil, résumé uniquement
--min-rssi DBM Seuil RSSI minimum (par ex. -70) — ignore les signaux plus faibles
--rssi-window N Taille de la fenêtre glissante RSSI pour la moyenne (défaut : 1 = pas de moyenne)
--active Utilise l'analyse active (envoie SCAN_REQ pour des données supplémentaires)
--environment {free_space,indoor,outdoor}
Modèle d'affaiblissement pour l'estimation de distance (défaut : free_space)
--ref-rssi DBM RSSI calibré à 1 mètre pour l'estimation de distance
--name-filter PATTERN Filtre les appareils par nom (correspondance de sous-chaîne insensible à la casse)
--alert-within METERS Alerte de proximité lorsque l'appareil se trouve à cette distance
--tui Tableau de terminal mis à jour en direct au lieu d'une sortie défilante
--gui Lance l'interface radar web dans le navigateur
--gui-port PORT Port du serveur web de l'interface graphique (défaut : 5000)
--no-gps Désactive l'horodatage de localisation GPS (GPS activé par défaut via gpsd)
--adapters LIST Noms des adaptateurs Bluetooth séparés par des virgules (par ex. hci0,hci1)
Analyse tous les appareils BLE diffusant (délai d'expiration par défaut de 30 secondes) :
btrpa-scan --all
Avec un délai d'expiration personnalisé :
btrpa-scan --all -t 60
Recherche un appareil spécifique par adresse MAC :
btrpa-scan AA:BB:CC:DD:EE:FF
Résout les adresses privées résolubles à l'aide d'une clé de résolution d'identité. Ce mode s'exécute indéfiniment par défaut jusqu'à son arrêt avec Ctrl+C :
btrpa-scan --irk 0123456789ABCDEF0123456789ABCDEF
L'IRK peut être fournie dans plusieurs formats :
| Format | Exemple |
|---|---|
| Hexadécimal simple | 0123456789ABCDEF0123456789ABCDEF |
| Séparé par deux-points |
Charge une ou plusieurs IRK depuis un fichier. Chaque ligne doit contenir une IRK dans n'importe quel format hexadécimal pris en charge. Les lignes commençant par # sont considérées comme des commentaires :
btrpa-scan --irk-file keys.txt
Exemple de keys.txt :
# Le téléphone d'Alice
0123456789ABCDEF0123456789ABCDEF
# La montre de Bob
FEDCBA9876543210FEDCBA9876543210
Lorsque plusieurs IRK sont chargées, chaque RPA détectée est vérifiée par rapport à toutes les clés. Le résumé affiche le nombre total de correspondances pour toutes les clés.
Définissez la variable d'environnement BTRPA_IRK pour éviter de passer la clé en ligne de commande :
export BTRPA_IRK=0123456789ABCDEF0123456789ABCDEF
btrpa-scan
Priorité : --irk > --irk-file > BTRPA_IRK
Affiche uniquement les appareils dont l'intensité du signal est supérieure à un seuil :
btrpa-scan --all --min-rssi -70
Le RSSI BLE est intrinsèquement bruité. Utilisez une moyenne glissante pour des estimations de distance plus stables et pour éliminer les détections faibles erronées :
btrpa-scan --all --rssi-window 5
Lorsque le fenêtrage est actif, l'affichage montre à la fois le RSSI brut et le RSSI moyenné (par ex. RSSI: -65 dBm (avg: -62 dBm over 5 readings)), et l'estimation de distance utilise la valeur moyennée. Le filtre --min-rssi s'applique également au RSSI moyenné, empêchant qu'un seul pic bruité fasse disparaître un appareil.
Filtre les appareils par nom à l'aide d'une correspondance de sous-chaîne insensible à la casse :
btrpa-scan --all --name-filter "AirPods"
Seuls les appareils dont le nom diffusé contient le motif donné seront affichés. Les appareils sans nom sont exclus lorsqu'un filtre par nom est actif.
L'analyse passive (par défaut) ne voit que les publicités. L'analyse active envoie SCAN_REQ et reçoit SCAN_RSP, ce qui peut révéler des UUID de services et des noms d'appareils supplémentaires :
btrpa-scan --all --active
Remarque : Sur macOS, CoreBluetooth analyse toujours activement quel que soit ce drapeau. Sur Linux/BlueZ, l'analyse active peut nécessiter les droits root ou la capacité
CAP_NET_ADMIN.
L'estimation de distance utilise un exposant d'affaiblissement de propagation qui varie selon l'environnement. La valeur par défaut (free_space, n=2.0) suppose une absence d'obstacles. Pour des estimations plus réalistes en intérieur :
btrpa-scan --all --environment indoor
| Préréglage | Exposant d'affaiblissement (n) | Cas d'utilisation |
|---|---|---|
free_space | 2.0 |
Des valeurs n plus élevées produisent des estimations de distance plus grandes pour le même RSSI, ce qui reflète l'atténuation du signal par les murs et les obstacles.
Par défaut, btrpa-scan déduit le RSSI attendu à 1 mètre de la puissance TX diffusée à l'aide d'un décalage de 59 dB validé empiriquement (la norme iBeacon). Pour une précision encore meilleure, vous pouvez fournir une valeur calibrée mesurée dans votre propre environnement :
--ref-rssi :btrpa-scan --all --ref-rssi -55
Lorsque --ref-rssi est défini, la puissance TX est entièrement ignorée. Cela permet également les estimations de distance pour les appareils qui ne diffusent pas de puissance TX.
Déclenche une sonnerie et une alerte visuelle lorsqu'un appareil est estimé à une distance donnée. Nécessite que l'appareil cible diffuse la puissance TX :
btrpa-scan AA:BB:CC:DD:EE:FF --alert-within 5.0
Fonctionne dans tous les modes, y compris la résolution IRK :
btrpa-scan --irk <key> --alert-within 3.0
Remplace la sortie défilante par un tableau de terminal mis à jour en direct, trié par intensité du signal :
btrpa-scan --all --tui
La TUI affiche tous les appareils détectés dans un tableau compact avec l'adresse, le nom, le RSSI, le RSSI moyenné, la distance estimée, le nombre de détections et l'heure de dernière apparition. Les correspondances IRK résolues sont affichées en gras et les appareils situés dans le seuil --alert-within sont mis en évidence.
À combiner avec d'autres drapeaux :
btrpa-scan --irk <key> --tui --rssi-window 5 --environment indoor --alert-within 5.0
Lance une interface radar dans le navigateur avec balayage animé, suivi des appareils en temps réel et carte GPS :
btrpa-scan --all --gui
L'interface graphique comprend :
Le mode interface graphique analyse en continu par défaut (aucun délai d'expiration de 30 secondes). Appuyez sur Ctrl+C pour arrêter. Utilisez -t pour définir une durée d'analyse spécifique :
# Analyse pendant 60 secondes avec le modèle d'affaiblissement intérieur
btrpa-scan --all --gui -t 60 --environment indoor
# Port personnalisé
btrpa-scan --all --gui --gui-port 8080
# À combiner avec la moyenne RSSI et les alertes de proximité
btrpa-scan --all --gui --rssi-window 5 --alert-within 5.0
Remarque :
--guinécessite Flask et flask-socketio (pip install btrpa-scan[gui]). Ne peut pas être combiné avec--tuiou--quiet.
Diffuse chaque détection vers un fichier CSV au fur et à mesure (utile pour les analyses de longue durée lorsque vous souhaitez des données incrémentales) :
btrpa-scan --all --log scan.csv
Cela peut être combiné avec --output pour un export par lot séparé :
btrpa-scan --all --log live.csv --output json -o results.json
Exporte tous les résultats à la fin de l'analyse au format CSV, JSON ou 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 écrit un objet JSON par ligne, ce qui permet de le transmettre facilement à jq :
btrpa-scan --all --output jsonl -o results.jsonl -t 10
cat results.jsonl | jq .
Écrivez la sortie sur stdout pour l'utiliser dans un pipeline :
btrpa-scan --all --output json -o - -t 10 -q | jq .
Analysez avec plusieurs adaptateurs Bluetooth simultanément pour une couverture plus large :
btrpa-scan --all --adapters hci0,hci1
Chaque adaptateur exécute sa propre instance de scanner partageant le même rappel de détection. Toutes les détections sont fusionnées dans une seule sortie.
Le GPS est activé par défaut. Chaque détection est marquée avec les coordonnées GPS actuelles provenant de gpsd. Le scanner suit également la meilleure position GPS par appareil — les coordonnées de la détection avec le RSSI le plus fort (proximité la plus proche = position la plus précise).
Si gpsd ne fonctionne pas, le scanner affiche une note et continue normalement sans GPS :
# Avec gpsd en cours d'exécution — les détections incluent lat/lon
btrpa-scan --all --output json
# Sans gpsd — fonctionne parfaitement, les champs GPS sont vides
btrpa-scan --all
# Désactive explicitement le GPS (ignore la tentative de connexion)
btrpa-scan --all --no-gps
Les coordonnées GPS apparaissent dans :
latitude, longitude, gps_altitudeExécution en mode silencieux (résumé uniquement, aucune sortie par appareil — utile avec --output ou --log) :
btrpa-scan --all -q --output json -t 30
Exécution en mode verbeux (affiche les RPA non correspondantes en mode IRK) :
btrpa-scan --irk 0123456789ABCDEF0123456789ABCDEF -v
Les appareils Bluetooth Low Energy utilisent des adresses privées résolubles (RPA) pour empêcher le suivi. Une RPA est une adresse MAC temporaire qui change périodiquement, mais qui peut être résolue par quiconque possède la clé de résolution d'identité (IRK) de l'appareil.
Une RPA se compose de :
01AES-128-ECB(IRK, padding || prand) tronqué à 3 octetsbtrpa-scan implémente la fonction ah() de la spécification Bluetooth Core (Vol 3, Part H, Section 2.2.2) pour résoudre ces adresses en temps réel.
Remarque sur AES-ECB : L'utilisation d'AES en mode ECB pour la fonction
ah()est imposée par la spécification Bluetooth Core. Comme un seul bloc de 16 octets est toujours chiffré, l'absence de diffusion d'ECB entre les blocs est sans importance — il ne s'agit pas d'une vulnérabilité.
ps. Pour éviter d'exposer l'IRK, utilisez --irk-file pour la lire depuis un fichier, ou définissez la variable d'environnement BTRPA_IRK. La sortie console masque les IRK par défaut (n'affichant que les 4 premiers et 4 derniers caractères hexadécimaux).--no-gps pour désactiver entièrement le GPS.--output-file et --log écrivent dans le chemin spécifié. Assurez-vous que la destination dispose des autorisations appropriées pour votre cas d'utilisation.pip install pytest
python -m pytest test_btrpa_scan.py -v
Mode : DÉCOUVERTE DE TOUS - affiche chaque appareil diffusant
Analyse : passive
GPS : connecté (37.774929, -122.419418)
Délai : 30s | Appuyez sur Ctrl+C pour arrêter
------------------------------------------------------------
============================================================
APPAREIL #1 - vu 1x
============================================================
Adresse : AA:BB:CC:DD:EE:FF
Nom : MyDevice
RSSI : -45 dBm
TX Power : -59 dBm
Dist. estimée: ~0.4 m
Fabricant : 0x004C -> 0215abcdef
Meilleur GPS : 37.774929, -122.419418
Horodatage : 14:32:07
============================================================
------------------------------------------------------------
Analyse terminée - 30.0s écoulées
Total des détections : 142
Appareils uniques : 12
Résultats écrits dans btrpa-scan-results.json
Appuyez sur Ctrl+C à tout moment pour arrêter proprement l'analyse et afficher les statistiques récapitulatives.
| Plateforme | Installation | Démarrage |
|---|
| 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 | Utilisez gpsd via WSL ou MSYS2 | Voir les instructions WSL ci-dessus |
| Plateforme | Remarques |
|---|
| macOS | Utilise CoreBluetooth. Le mode IRK exploite une API non documentée pour récupérer les véritables adresses Bluetooth au lieu des UUID. --active n'a aucun effet — CoreBluetooth analyse toujours activement. |
| Linux | Peut nécessiter les droits root ou la capacité CAP_NET_ADMIN pour l'analyse. |
| Windows | API Bluetooth WinRT native — les véritables adresses MAC sont disponibles nativement. La TUI nécessite pip install windows-curses. |
01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF |
| Séparé par tirets | 01-23-45-67-89-AB-CD-EF-01-23-45-67-89-AB-CD-EF |
| Préfixé par 0x | 0x0123456789ABCDEF0123456789ABCDEF |
| Espace ouvert, ligne de vue |
outdoor | 2.2 | Parcs, parkings |
indoor | 3.0 | Bureaux, logements, bâtiments |