Scapy CAN-Layer#
The Scapy can-layer is a module within the Scapy packet manipulation tool that provides support for Controller Area Network (CAN) protocol. It allows users to craft, dissect, and manipulate CAN frames and packets. The can-layer is built on top of the Scapy’s core packet manipulation capabilities, providing a set of functions and classes for interacting with the CAN protocol. It allows the user to create and parse packets, set and get properties of the packets, and perform other common packet manipulation tasks. The can-layer also supports extended frame format and provides a way to define custom filters to select specific packets. The Scapy can-layer is a powerful tool for security researchers, developers, and penetration testers working with CAN-based systems as it allows them to easily automate and analyze CAN traffic.
Scapy CAN Frames#
Load the CAN layer in Scapy
from scapy.all import *
load_layer("can")
Create a CAN frame
frame = CAN(flags='extended', identifier=0x10010000, length=8, data=b'\x01\x02\x03\x04\x05\x06\x07\x08')
frame.show()
hexdump(frame)
###[ CAN ]###
flags = extended
identifier= 0x10010000
length = 8
reserved = 0
data = b'\x01\x02\x03\x04\x05\x06\x07\x08'
0000 90 01 00 00 08 00 00 00 01 02 03 04 05 06 07 08 ................
Scapy CANSockets#
Scapy provides two types of Sockets
NativeCANSocket:
Uses SocketCAN underneath. Requires Linux and Python3. Scapy NativeCANSocket objects are part of Scapy library that provide a way to interact directly with the CAN bus using the native socket interface of the operating system.PythonCANSocket:
Uses python-can underneath. Runs on Linux, Windows and OSX with Python2 and Python3. Scapy emulates the socket behavior similar to SocketCAN. Scapy PythonCANSocket objects are a part of the Scapy library that provide a way to interact with the CAN bus using the Python-CAN library.
Use NativeCANSocket
conf.contribs['CANSocket'] = {'use-python-can': False} # default
load_contrib('cansocket')
socket = CANSocket(channel='vcan0')
Use PythonCANSocket
conf.contribs['CANSocket'] = {'use-python-can': True}
load_contrib('cansocket')
socket = CANSocket(bustype='socketcan', channel='vcan0')
Send CAN frame
packet = CAN(identifier=0x123, data=b'01020304')
socket.send(packet)
16
Receive CAN frame
rx_packet = socket.recv()
rx_packet.show()
###[ CAN ]###
flags =
identifier= 0x123
length = 5
reserved = 0
data = b'"\x11\xaa\xbb\xcc'
Sniff 10 CAN frames
pkts = socket.sniff(timeout=5, count=10)
print(pkts)
pkts[0].show()
<Sniffed: TCP:0 UDP:0 ICMP:0 Other:10>
###[ CAN ]###
flags =
identifier= 0x57d
length = 8
reserved = 0
data = b'lU\xa79\xf8\xf4\xd1\x13'
Read and write pcap files#
Examplefile download: ECU_Trace.pcap.gz
x = CAN(identifier=0x7ff,length=8, data=b'\x01\x02\x03\x04\x05\x06\x07\x08')
wrpcap('/tmp/scapyPcapTest.pcap', x, append=False)
pkts = rdpcap('/tmp/scapyPcapTest.pcap', 1)
pkts[0].show()
###[ CAN ]###
flags =
identifier= 0x7ff
length = 8
reserved = 0
data = b'\x01\x02\x03\x04\x05\x06\x07\x08'
Read candump logfile#
Treat logfile as socket
with CandumpReader("candump.log") as sock:
can_msgs = sniff(count=50, opened_socket=sock)
print(len(can_msgs))
50
Read entire logfile
can_msgs = rdcandump("candump.log")
print(len(can_msgs))
100