In this week’s update, we’ll be talking about writing code for CANtact using Python. Python is a very popular scripting language in information security and automotive security. Because of its popularity, a wide range of CAN tools written in Python, and many supporting libraries exist.
The most popular Python library for CAN is python-can. This library deals with many of the lower level details of interacting with CAN hardware and provides a simple, interface agnostic abstraction. Recently, CANtact support was merged into python-can!
Previously, users of CANtact could use python-can with SocketCAN, but this only worked on Linux. Now, users can write Python code for CANtact on Windows, macOS, and Linux. This means writing a script once and running it everywhere.
So how can we use this in practice? After installing the
cantact packages using
pip, the built-in scripts can be used to test the installation. To show messages received on CANtact channel 0:
pip install python-can==4.0.0.dev0 cantact can_logger.py -i cantact -c0
There’s also a complete example of sending frames using python-can and CANtact.
The udsoncan package provides a Unified Diagnostic Services (UDS, specified as ISO 14229) implementation in Python. This is the diagnostic protocol used in most passenger vehicles today.
Interacting with UDS usually requires purchasing the standards from ISO, writing implementations for the services, and writing an implementation of the underlying ISO-TP (ISO 15765-2) protocol. This is made much simpler with udsoncan.
Here’s an example of issuing an ECUReset command using udsoncan and CANtact.
The cross-platform CANtact driver is written in Rust (source). This driver uses the Rust PyO3 crate to generate a native Python module. The build process automatically builds native Python modules for Windows, macOS, and Linux which are published to PyPI. This allows end users to install a pre-built binary distribution.
cantact Python package is quite minimal by design. The excellent work of the
python-can developers means we can leverage years of developing without reinventing the wheel.
Cross-platform support is achieved by using libusb. The first attempt to implement this driver used the Rust rusb crate. Unfortunately, this only supported the libusb synchronous API, which was too slow to keep up with the device. The driver was rewritten using the libusb1-sys crate to provide access to the libusb asynchronous API, providing a major performance improvement.
The state of CANtact Python support gets us much closer to the goal of a cross-platform Python tool. "Write once, run anywhere" is now possible with CANtact! Many thanks to the python-can developers for their feedback and help with getting this support merged.