def write_car_event_to_can_packet(car: Vehicle, event_list: CarEvent): pkt_list = [] for event in event_list: if event.ID == CarEvent.CAR_EVENT_FREE: continue data = car.dbc_data.simple_msg_encode(event.ID, event.value) # extend to 8 bytes by padding zero data = data + '00' * (8 - car.dbc_data.get_msg_length_in_byte(event.ID)) byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7 = \ int(data[0:2], 16), \ int(data[2:4], 16), \ int(data[4:6], 16), \ int(data[6:8], 16), \ int(data[8:10], 16), \ int(data[10:12], 16), \ int(data[12:14], 16), \ int(data[14:], 16) can_payload = \ struct.pack('<8B', byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7) pkt = CAN(identifier=event.ID, length=len(data), data=can_payload) pkt.time = event.timestamp pkt_list.append(pkt) wrpcap("can_packet.pcap", pkt_list) return
def can_send(self, load): # type: (bytes) -> None if self.padding: load += b"\xCC" * (CAN_MAX_DLEN - len(load)) if self.tx_id is None or self.tx_id <= 0x7ff: self.can_socket.send(CAN(identifier=self.tx_id, data=load)) else: self.can_socket.send( CAN(identifier=self.tx_id, flags="extended", data=load))
def recv(self): msg = self.iface.recv(timeout=1) if msg is None: raise CANSocketTimeoutElapsed frame = CAN(identifier=msg.arbitration_id, length=msg.dlc, data=bytes(msg.data)) if msg.is_error_frame: frame.flags |= 0x1 if msg.is_remote_frame: frame.flags |= 0x2 if msg.is_extended_id: frame.flags |= 0x4 frame.time = msg.timestamp return frame
def fragment(self): data_bytes_in_frame = 7 if self.exdst is not None: data_bytes_in_frame = 6 if len(self.data) > ISOTP_MAX_DLEN_2015: raise Scapy_Exception("Too much data in ISOTP message") if len(self.data) <= data_bytes_in_frame: # We can do this in a single frame frame_data = struct.pack('B', len(self.data)) + self.data if self.exdst: frame_data = struct.pack('B', self.exdst) + frame_data pkt = CAN(identifier=self.dst, data=frame_data) return [pkt] # Construct the first frame if len(self.data) <= ISOTP_MAX_DLEN: frame_header = struct.pack(">H", len(self.data) + 0x1000) else: frame_header = struct.pack(">HI", 0x1000, len(self.data)) if self.exdst: frame_header = struct.pack('B', self.exdst) + frame_header idx = 8 - len(frame_header) frame_data = self.data[0:idx] frame = CAN(identifier=self.dst, data=frame_header + frame_data) # Construct consecutive frames n = 1 pkts = [frame] while idx < len(self.data): frame_data = self.data[idx:idx + data_bytes_in_frame] frame_header = struct.pack("b", (n % 16) + N_PCI_CF) n += 1 idx += len(frame_data) if self.exdst: frame_header = struct.pack('B', self.exdst) + frame_header pkt = CAN(identifier=self.dst, data=frame_header + frame_data) pkts.append(pkt) return pkts
def recv(self, x=CAN_FRAME_SIZE): try: pkt, sa_ll = self.ins.recvfrom(x) except BlockingIOError: # noqa: F821 warning("Captured no data, socket in non-blocking mode.") return None except socket.timeout: warning("Captured no data, socket read timed out.") return None except OSError: # something bad happened (e.g. the interface went down) warning("Captured no data.") return None # need to change the byteoder of the first four bytes, # required by the underlying Linux SocketCAN frame format pkt = struct.pack("<I12s", *struct.unpack(">I12s", pkt)) len = pkt[4] canpkt = CAN(pkt[:len + 8]) canpkt.time = get_last_packet_timestamp(self.ins) if self.remove_padding: return canpkt else: return canpkt / Padding(pkt[len + 8:])
def recv(self, x=CAN_FRAME_SIZE): try: pkt, sa_ll = self.ins.recvfrom(x) except BlockingIOError: # noqa: F821 warning("Captured no data, socket in non-blocking mode.") return None except socket.timeout: warning("Captured no data, socket read timed out.") return None except OSError: # something bad happened (e.g. the interface went down) warning("Captured no data.") return None # need to change the byteoder of the first four bytes, # required by the underlaying Linux SocketCAN frame format pkt = struct.pack("<I12s", *struct.unpack(">I12s", pkt)) len = pkt[4] canpkt = CAN(pkt[:len + 8]) canpkt.time = get_last_packet_timestamp(self.ins) if self.remove_padding: return canpkt else: return canpkt / Padding(pkt[len + 8:])
if args.extended_only: extended_only = True if args.k: keep_awake = True awake_interface = args.k # Dictionary with Send-to-ID as key and a tuple (received packet, Recv_ID) found_packets = {} # List with paket-IDs of background noise packets noise_IDs = [] # Seconds to listen to noise noise_listen_time = 10 # Number of pakets send in a single blow extended_load = 100 dummy_pkt = CAN(identifier=0x123, data=b'\xaa\xbb\xcc\xdd\xee\xff\xaa\xbb') # Interface for communication CanSocket_communication = CANSocket(scan_interface) # Keep ECU awake if keep_awake: CanSocket_keep_awake = CANSocket(awake_interface) awake_thread = isotpscan.KeepAwakeThread(CanSocket_keep_awake, dummy_pkt) awake_thread.start() # Listen for default messages on CAN-bus print("Filtering background noise...") CanSocket_communication.sniff( prn=get_background_noise_callback, timeout=noise_listen_time,
def isotp_scan( sock, # type: SuperSocket scan_range=range(0x7ff + 1), # type: Iterable[int] extended_addressing=False, # type: bool extended_scan_range=range(0x100), # type: Iterable[int] noise_listen_time=2, # type: int sniff_time=0.1, # type: float output_format=None, # type: Optional[str] can_interface=None, # type: Optional[str] extended_can_id=False, # type: bool verbose=False # type: bool ): # type: (...) -> Union[str, List[SuperSocket]] """Scan for ISOTP Sockets on a bus and return findings Scan for ISOTP Sockets in the defined range and returns found sockets in a specified format. The format can be: - text: human readable output - code: python code for copy&paste - sockets: if output format is not specified, ISOTPSockets will be created and returned in a list :param sock: CANSocket object to communicate with the bus under scan :param scan_range: range of CAN-Identifiers to scan. Default is 0x0 - 0x7ff :param extended_addressing: scan with ISOTP extended addressing :param extended_scan_range: range for ISOTP extended addressing values :param noise_listen_time: seconds to listen for default communication on the bus :param sniff_time: time the scan waits for isotp flow control responses after sending a first frame :param output_format: defines the format of the returned results (text, code or sockets). Provide a string e.g. "text". Default is "socket". :param can_interface: interface used to create the returned code/sockets :param extended_can_id: Use Extended CAN-Frames :param verbose: displays information during scan :return: """ if verbose: print("Filtering background noise...") # Send dummy packet. In most cases, this triggers activity on the bus. dummy_pkt = CAN(identifier=0x123, data=b'\xaa\xbb\xcc\xdd\xee\xff\xaa\xbb') background_pkts = sock.sniff(timeout=noise_listen_time, started_callback=lambda: sock.send(dummy_pkt)) noise_ids = list(set(pkt.identifier for pkt in background_pkts)) if extended_addressing: found_packets = scan_extended(sock, scan_range, extended_scan_range=extended_scan_range, noise_ids=noise_ids, sniff_time=sniff_time, extended_can_id=extended_can_id, verbose=verbose) else: found_packets = scan(sock, scan_range, noise_ids=noise_ids, sniff_time=sniff_time, extended_can_id=extended_can_id, verbose=verbose) filter_periodic_packets(found_packets, verbose) if output_format == "text": return generate_text_output(found_packets, extended_addressing) if output_format == "code": return generate_code_output(found_packets, can_interface, extended_addressing) return generate_isotp_list(found_packets, can_interface or sock, extended_addressing)
def can_send(load): can_socket.send(CAN(identifier=sid, data=load))
def fragment(self, *args, **kargs): # type: (*Any, **Any) -> List[Packet] """Helper function to fragment an ISOTP message into multiple CAN frames. :return: A list of CAN frames """ data_bytes_in_frame = 7 if self.rx_ext_address is not None: data_bytes_in_frame = 6 if len(self.data) > ISOTP_MAX_DLEN_2015: raise Scapy_Exception("Too much data in ISOTP message") if len(self.data) <= data_bytes_in_frame: # We can do this in a single frame frame_data = struct.pack('B', len(self.data)) + self.data if self.rx_ext_address: frame_data = struct.pack('B', self.rx_ext_address) + frame_data if self.rx_id is None or self.rx_id <= 0x7ff: pkt = CAN(identifier=self.rx_id, data=frame_data) else: pkt = CAN(identifier=self.rx_id, flags="extended", data=frame_data) return [pkt] # Construct the first frame if len(self.data) <= ISOTP_MAX_DLEN: frame_header = struct.pack(">H", len(self.data) + 0x1000) else: frame_header = struct.pack(">HI", 0x1000, len(self.data)) if self.rx_ext_address: frame_header = struct.pack('B', self.rx_ext_address) + frame_header idx = 8 - len(frame_header) frame_data = self.data[0:idx] if self.rx_id is None or self.rx_id <= 0x7ff: frame = CAN(identifier=self.rx_id, data=frame_header + frame_data) else: frame = CAN(identifier=self.rx_id, flags="extended", data=frame_header + frame_data) # Construct consecutive frames n = 1 pkts = [frame] while idx < len(self.data): frame_data = self.data[idx:idx + data_bytes_in_frame] frame_header = struct.pack("b", (n % 16) + N_PCI_CF) n += 1 idx += len(frame_data) if self.rx_ext_address: frame_header = struct.pack('B', self.rx_ext_address) + frame_header # noqa: E501 if self.rx_id is None or self.rx_id <= 0x7ff: pkt = CAN(identifier=self.rx_id, data=frame_header + frame_data) # noqa: E501 else: pkt = CAN(identifier=self.rx_id, flags="extended", data=frame_header + frame_data) pkts.append(pkt) return pkts
# CAN-ID Range min_ID = int(sys.argv[1], 16) max_ID = int(sys.argv[2], 16) # Get arguments args = [] for i in range(0, len(sys.argv)): args.append(sys.argv[i]) if "-e" in args: extended = True if "-k" in args: awake_interface = True if "-eo" in args: extended_only = True dummy_pkt = CAN(identifier=0x123, data=b'\xaa\xff\xff\xff\xff\xff\xff\xee') # Interface CanSocket_communication = CANSocket("can1") # Keep ECU awake if awake_interface: CanSocket_keep_awake = CANSocket("can0") awake_thread = keep_awake_thread(dummy_pkt) awake_thread.start() # Listen for default messages on CAN-bus print("Filtering background noise...") CanSocket_communication.sniff(prn=get_background_noise, timeout=noise_listen_time, started_callback=lambda: