Comment hacker une voiture - cours rapide

Kenny KUCHERA

Cet article est la traduction d'un article américain qui explique comment réaliser une intrusion sur un véhicule.

Il a été publié sur Medium le 21 Juin 2017 par Kenny KUCHERA.

Test simplifié pour systèmes CAN

Mini-cours sur comment hacker une voiture

Source : 21 Juin 2017 – Kenny KUCHERA, Car enthousiast.

Image tachymètre

On a trompé le tachymètre qui croit que le moteur n'est pas en marche.

Envie d'aller vite ?

Le but de cet article est de vous faire démarrer dans l'art de "hacker" des voitures - rapidement, pas cher, facilement - pour y arriver, nous allons démontrer comment tromper le compteur de vitesse et de tours par minutes du moteur.

Ce qui suit n'est en aucun cas un tutoriel exhaustif ni une formation. C'est plutôt un moyen de donner juste assez d'information pour que vous soyez capables de démarrer vous même des tests. Si vous souhaitez aller plus loin, libre à vous de lire les références à la fin de l'article !

Si vous décidez de tester vous-même ce tutoriel dans la "vraie vie", vous aurez besoin d'un PC sous Linux (ou une machine virtuelle Linux), et un dispositif vous permettant de communiquer avec le bus CAN (Exemple CAN-vers-USB sera présenté plus tard).

Une voiture ... c'est un réseau !

Une voiture est constituée de nombreux calculateurs qui contrôlent le moteur, la transmission, les fenêtres, la fermeture des portes, les lumières, etc ...

Ces calculateurs/ordinateurs sont appelés des ECU 2 et communiquent les uns avec les autres à travers un réseau ...

Par exemple, si vous appuyez sur le bouton de votre volant pour augmenter le colume de la radio, l'ECU du volant va envoyer une commande sur le réseau pour "augmenter le volume"; l'ECU de la radio voit passer la demande et réagit en fonction.

Donc il y a de multiples réseaux dans les voitures, en général au moins deux :

  • Un pour les informations critiques comme le moteur ou le système de freinage,
  • Et un pour les systèmes moins critiques comme la radio et la fermeture des portes.

Le réseau critique utilise un protocole rapide et fiable alors que le réseau non critique utilise un protocole plus lent, moins fiable et moins cher.

Le nombre de réseaux ainsi que la façon dont les ECUs sont en réseau entre elles dépent du constructeur automobile, du modèle, de l'année de fabrication.

Un ECU peut être potentiellement connecté à de nombreux réseaux.

Connexion à un réseau

Certains réseaux peuvent être accédés par le port OBD-II (1).

Ce port est obligatoire sur toutes les voitures et camions construits aux USA après 1996 et en Europe après 2004.

Le connecteur est à portée de mains du siège du condusteur. Vous pourriez avoir besoin de retirer des caches plastique mais ce port est accessible ... sans aucun outil.

Connecteur OBD-II

Le connecteur OBD-II

Le standard OBD-II permet de travailler sur 5 protocoles de signaux différents. Il appartient au fabricant de systèmes de décider lequel utiliser.

  • Le protocole CAN est le plus populaire et celui dont nous parlerons ci-dessous, Accessible sur les pins 6 et 14 du connecteur OBD-II. Si votre voiture a un bus CAN, vous verrez des fiches métal sur les pinds comme sur l'image ci-dessous.
  • Le bus CAN est un bus fiable, haute vitesse, utilisé pour envoyer des informations critiques,
  • Malheureusemet, les packets de données sur ce bus ne sont pas standardisés, vous devrez faire de l'ingénierie inversée pour comprendre ce qu'ils veulent dire.
  • Le standard OBD-II laisse également la porte ouverte pour des implémentations spécifiques (sur les différents pins) par fabricant qui peuvent être utilisées pour des protocoles spécifiques. Ca rend plus facile de diagnostic pour le fabricant ...

Sur ma voiture (fabriques par GM=Général Motors), j'ai un CAN bus standard sur les pins 6 et 14, et un une implémentation spécifique du fabricant sur l'unique pin 1 du bus CAN. Le bus CAN est fiable, permet un protocole de connexion rapide (500 kbps) également appelé CAN haute vitesse (HS-CAN). Il est utilisé pour les données critiques.

Le bus CAN sur un seul fil (SW-CAN) ou GMLAN est plus lent (33.3 kbps) et moins fiable mais également moins cher puisqu'il n'utilise qu'un seul cable. Ce bus est utilisé pour les données non critiques.

Si vous découvrez une broche (pin) spécifiques et que vous ne savez pas quel protocole est utilisé, utilisez la recherche Google " OBD pinout”.

Vous pourrez également découvrir du CAN basse vitesse (LS-CAN) ou moyenne vitesse (MS-CAN). MS-CAN se trouve généralement sur les broches 3 et 11 et "tourne" à 125 kbps pour les véhicules Ford et Volvo.

Outils

Vous aurez besoin aussi bien d'équipements permettant d'interfacer avec le bus CAN que de logiciels pour analyser les données.

Hardware

Afin de recevoir et envoyer des trames CAN vous aurez besoin d'un dispositif capable de communiquer sur un bus CAN ...

Vous trouverez souvent des dispositifs basés sur des systèmes ELM327.

Si ces systèmes peuvent être utiles pour des actions licites, ... on peut également les utiliser pour du hacking. Mais ce sont des dispositifs souvent trop lents pour monitorer le bus CAN.

Il y a aussi des dispositifs avancés comme Kvaser, Peak ou EMS Wünsche. Ces équipements nous permettraient de réaliser le hack mais ont beaucoup trop de fonctionnalités et sont vraiment trop chers.

Quelques systèmes appropriés demandent que vous achetiez également des logiciels pour pouvoir fonctionner. Le système USB2CAN est une interface CAN native pour Linux qui vaut l'investissement ...

Vous pourrez aussi utiliser Cantact ou CANUSB. Cependant, il n'y a pas de dispositif CAN natifs pour Linux et qui puissent utiliser des protocoles ASCII. Ce qui veut dire qu'ils sont plus compliqués à implémenter et qu'ils ont des performances moindres.

A contrario, ils sont bien supportés par des systèmes d'opération divers et variés.

J'utilise CANalyze que j'ai adapté à mes besoins. Cet outil est similaire à USB2CAN dans le sens où il est un outils d'interface CAN accessible mais qui utilise un micro-controlleur très moderne, open-source et qui peut être complilé à partir de logiciels open source.

La suite de ce tutorial considère que vous êtes familier avec cette interface CAN native.

Logiciel

Afin de communiquer avec le système sous test, vous avez besoin d'installer le packetage "can-utils" sur votre machine Linux. Ce qui peut se faire avec les commandes suivantes en ligne de commande :

sudo apt-get install can-utils

Test simplifié pour systèmes CAN

Le packetage Can-utils rend extrêmement simpte la transmission, la réception et l'analyse de trames CAN. Les commandes suivantes vont être utilisées :

  • cansniffer pour afficher seulement les trames qui changent,
  • candump pour afficher toutes les trames échangées,
  • cansend pour envoyer une trame.

Linux supporte nativement le protocole CAN en mode noyau via SocketCAN. Ceci rend très simple l'écriture de vos propres programmes pour ce protocole. Vous pouvez interagir directement avec le bus CAN de la même façon que vous seriez en interaction avec n'importe quel type de réseau i.e. via sockets.

CAN bus

Avant de vous lancer dans de la rétro-ingénierie, vous devez avoir une bonne connaissance de comment un bus CAN fonctionne. Ce bus est constitué de 2 câbles et utilise un signal différentiel. Comme c'est un bus, de multiples systèmes peuvent se connecter sur ces deux câbles. Quand une trame CAN est transmise sur le bus elle est reçue par tous les ECU 2 mais est uniquement traitée si elle est utile pour l'ECU. Si des trames multiples sont envoyées en même temps, celle avec la priorité la plus haute "l'emporte".

Une trame CAN est subdivisée en 3 parties qui nous intéressent :

  • Arbitration IDentifier : l'identifiant du message. L'ECU l'utilise pour décider s'il traite ou s'il ignore la trame reçue. On y trouve également la priorité de la trame. Un nombre faible représente une priorité haute. Par exemple si vous étiez l'ingénieur en charge d'implémenter le réseau, vous donneriez une priorité haute ("Arbitration ID" le plus faible) pour le déploiement des airbags. D'un autre côté, vous donneriez une priorité faible ("Arbitration ID" élevé) pour la fermeture des portes,
  • Data Length Code (DLC) : donne la taille du champs data de la trame calculés en octets (une trame CAN peut contenir au plus 8 octets de données),
  • Data Field : contient jusqu'à 8 octets de données.

Rétro-ingénierie sur bus CAN

L'approche générale pour faire une rétro-ingénierie des trames CAN consiste à écouter le traffic contenant la fonction que vous souhaitez "mimer" puis retrouver le message qui pilote la fonction. Par exemple, supposons que la fonction d'assistance au franchissement de lignes blanches (LKAS) ne vous plaise pas et que vous ayez écrit la votre.

Afin que votre LKAS puisse contrôller la direction, vous devez savoir quels messages envoyer. Pour celà, vous allez faire fonctionner votre LKAS, écouter le bus CAN et devoir identifier les trames qui demandent à tourner le volant. Une fois que vous avez identifié ces trames, vous pourrez écrire votre propre fonction LKAS pour donner des ordres au volant.

Dans notre cas, nous souhaitons déterminer comment on change change la valeur du nombre de tours par minute (RPM) du tachymètre. Nous allons mettre notre levier de vitesse au point mort (position neutre), appuyer sur l'accélérateur et ensuite chercher la trame qui sur laquelle circule le nombre de tours par minute.

Mise en place

Connectez votre analyseur CAN sur la prise OBD-II d'un côté, sur le port USB de votre ordinateur de l'autre. Lancez 'interface CAN avec la commande suivante sur votre Linux :

sudo ip link set can0 up type can bitrate 500000

Ce qui va faire monter l'interface can0 (ce sera toujours can0i vous avez seulement un système CAN connecté) avec une liaison à 500 kbps, qui est la valeur standard.

Identification

Quand la voiture est éteinte, les calculateurs ECU sont en général en mode "sleeping". Il est nécessaire d'allumer la voiture ou de passer en mode "accessoires".

Vous pouvez examiner les trames dans ces modes en tapant la commande :

candump can0

Cette commande affiche les données du bus CAN à l'écran au fur et à mesure où elles sont reçues. Ce format est difficile à lire et il est difficile de savoir quelle trame correspond à un évènement particulier. Appuyez sur pour arrêter le programme.

Afin de rendre les données plus lisibles, nous allons utiliser un sniffer qui va rendre les trames plus lisibles en les regroupant par "Arbitration ID" et nous montrera seulement les trames quand il y a des changements.

Au prompt Linux, tapez la commande :

cansniffer -c can0

L'option -c met en couleur les octets qui changent. can0 est l'interface sur laquelle nous souhaitons écouter le traffic. En quelques secondes, les paquets statiques disparaissent.

Vous devriez maintenant avoir quelque chôse de similaire à l'image ci-dessous, avec bien sûr des nombres complètement différents.

Ecoute de trames CAN moteur arrêté

Ecoute de trames CAN moteur arrêté

1-La première colonne (delta) donne le débit avec lequel les trames pour cet Arbitration ID particulier sont reçues. 2-La seconde colonne contient l'Arbitration ID, 3-Les autres colonnes alpha-numériques contiennent les octets de données; si ces données ont une représentation ASCII, nous pouvons la voir ici, sinon un point s'affiche.

Quand vous démarrez le moteur et appuyez sur l'accélérateur pour faire augmenter le compte-tours (RPM), il devrait y avoir des changements sur les trames affichées ou vous devriez voir apparaître de nouvelles trames.

Il nous faut maintenant trouver les octets qui changent et faire le rapprochement avec le nombre de tours par minute (RPM). Nous nous attendons à voir une valeur augmenter/baisser en fonction du nombre de tours par minute du moteur (RPM).

La première trame que nous voyons changer avec notre sniffer est la trame avec l'Arbitration ID C9. Il y a potentiellement de nombreuses trames qui changent avec le compte-tours, celle-ci est la première.

Trames corrélées avec le nombre de tours par minute (RPM)

Trames corrélées avec le nombre de tours par minute (RPM)

On voit apparaître 4 octets qui varient (colorés en rouge) dans cette trame mais tous n'indiquent pas forcément l'information du nombre de tours par minute (RPM). Des variations dans le troisième octet 07 en particulier semblent n'avoir rien à voir avec le paramètre recherché.

Le dernier octet 1B semble bien être le bon !

Cependant, dès que nous retirons le pied de l'accélérateur, cet octet revient à 00.

Ceci semble indiquer la position de la pédale d'accélérateur et pas du nomre de tours par minute (RPM).

Finalement, nous remarquons 2 octets 21 C0 qui semblent corredpondre au changement du nombre de tours par minute. Et même nous remarquons qu'ils varient comme un entier de 16 bits i.e. quand le second octet C0 déborde, le premier octet 21 est incrémenté. Il semble également que 21 corresponde environ à 2000 tours par minute (RPM). This is good to note when you will replay the message.

Rejeu

Maintenant que nous avons une idée plus précise, nous allons tester l'envoi d'informations directement sur le bus CAN avec la commande suivante :

cansend can0 0C9#8021C0071B101000

La trame a le format <arb_id>#{data} et doit être remplacée par votre propre message.

Votre voiture peut être allumée ou en mode accessoire. Soyez surs d'utiliser une trame que vous avez enregistré quand le moteur était en état "non-idle" ou sinon vos commandes ne seront pas prises en compte tant que votre moteur est en état idle.

Si vous envoyer votre trame 1 seule fois, vous ne verrez sans doute rien changer sur le tableau de bord. C'est parce que le message original est envoyé continuellement à des intervalles de 0,2 secondes par l'ECU - votre message sera ignoré.

Rappelez-vous que la fréquence apparait sur la première colonne de votre cansniffer. Il y a 2 façons de gérer ce point, l'option 0 étant de déconnecter l'ECU qui génère ce message...

La première solution est de transmettre le même message à une fréquence plus importante que celle de l'ECU.

Vous pouvez le faire en lançant la commande suivante dans votre Linux :

while true; do cansend can0 0C9#8021C0071B101000; sleep 0.002; done

Substituez le message CAN avec celui que vous avez identifié lors de votre enregistrement. Pressez pour stopper.

Une autre option consiste à monitorer le bus et, à chaque fois que vous détectez une trame que vous souhaitez usurper ("spoofer"), envoyer immédiatement votre trame.

Pour le faire lancez la commande suivante sous Linux :

candump can0 | grep " 0C9 " | while read line; do cansend can0 0C9#8021C0071B101000; done

Changez la trame CAN par la votre et 0C9 avec la trame CAN que vous avez identifié et son Arbitration ID respectivement. Expérimentez les deux approches pour voir laquelle fonctionne le mieux dans votre cas.

Si votre tachymètre change, félicitations, vous y êtes arrivés ! Sinon identifiez le prochain message avec une coorélation sur le nombre de tours par minute (RPM) et rejouez ce message.

Fuzzing

Maintenant que vous avez la trame CAN qui permet de communiquer avec le tachymètre sur le tableau de bord, vous pouvez jouer avec les données que vous envoyez pour ... voir ce qui arrive ...

Nous avons noté que les 2 octets qui correspondent au nombre de tours par minute (RPM) se comportent comme un entier de 16 bits. Donc pour amener la jauge à 8000 tours/minute, nous lançons la commande suivante sous Linux :

while true; do cansend can0 0C9#0080000000101000; sleep 0.002; done

Et le résultat est ...

Image tachymètre

Tachymètre usurpé avec moteur éteint

Ca y est ! Vous pouvez maintenant essayer de contrôler le contrôleur de vitesse, la radio, les lumières, la fermeture des portes, etc... en utilisant la même approche.

Difficultés potentielles

Alors que le bus CAN est un réseau populaire, ce n'est pas le seul dans une automobile. Si vous ne pouvez pas trouver la trame que vous rechercher sur le bus CAN essayez un réseau différent. En particulier les messages non critiques comme la radio, les lumières, les fermetures de porte auront sans doute un bus spécifique.

Comme mentionné, les données exactes transmises sur le bus CAN dépendent du constructeur, de son modèle, de son année de construction. Certaines voitures utilisent un compteur dans la trame CAN pour assurer que le message n'est pas transmis plusieurs fois. C'est un peu plus difficile mais vous devriez arriver à rejouer des trames avec les informations de ce tutoriel.

Certaines trames utilisent aussi une "checksum" pour assurer l'intégrité des données. Calculer cette checksum peut être relativement compliqué.

Si vous avez une Toyota, regardez "Adventures in Automotive Networks and Control Units", p. 10, Checksum-Toyota. Tout le monde devrait lire l'intégralité de ce document.

Quand on rejoue les trames identifiées sur le bus CAN, votre dispositif CAN vers USB peut passer en mode "bus off". C'est une fonctionnalité du standard CAN qui arrive lorsque le dispositif a rencontré trop d'erreurs.

Ca arrive généralement lorsqu'il y a beaucoup de traffic sur le bus. Afin de ne pas avoir ce problème, vous pouvez faire des rejeux avec des délais et gérer le timing, peut-être essayer de relayer les trames immédiatement après avoir place la voiture en mode accessoire, attendez un peu, essayez avec le moteur allumé. Si vous avez identifié quels ECU sont connectés au bus CAN, vous pouvez également retirer leurs fusibles pour les "déconnecter" du bus et alléger le traffic.

A lire absolument

Soyez surs de jeter un oeil à Open Garages et leurs vidéos

Test simplifié pour systèmes CAN


  1. OBD-II: NDLR: le port de diagnostic de votre véhicule 

  2. ECU: Electronic Control Units, le nom d'un calculateur automobile  


Pour aller plus loin

Ressources