UDS in Scapy#

Overview#

../../_images/ScanpySWArchitecture1.png

Fig. 55 Overview of UDS packets and socket types on Linux.#

Preparations#

from scapy.all import *   # If you launch `scapy` directly, this import isn't necessary

conf.contribs['CANSocket'] = {'use-python-can': False}
conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': True}
load_contrib("isotp")
load_contrib("automotive.uds")

Examples#

  • Create a socket. basecls has to be set as UDS.

sock = ISOTPNativeSocket("vcan0", tx_id=0x6f1, rx_id=0x610, ext_address=0x10, rx_ext_address=0xf1, basecls=UDS)
  • Create a packet and sent it

rdbi_pkt = UDS()/UDS_RDBI(identifiers=[0x172a])
rx = sock.sr1(rdbi_pkt, timeout=1)
rx.show()
Begin emission:
Finished sending 1 packets.
*
Received 1 packets, got 1 answers, remaining 0 packets
###[ UDS ]### 
  service   = ReadDataByIdentifierPositiveResponse
###[ ReadDataByIdentifierPositiveResponse ]### 
     dataIdentifier= 0x172a
###[ Raw ]### 
        load      = '\x00\\xc0\\xa8\x11\\x97\\xff\\xff\\xff\x00\\xc0\\xa8\x11\x01'
  • Alternative way to send and receive a packet

rdbi_pkt = UDS()/UDS_RDBI(identifiers=[0x172a])
rx = sock.sniff(timeout=1, count=1, started_callback=lambda: sock.send(rdbi_pkt))
rx[0].show()
###[ UDS ]### 
  service   = ReadDataByIdentifierPositiveResponse
###[ ReadDataByIdentifierPositiveResponse ]### 
     dataIdentifier= 0x172a
###[ Raw ]### 
        load      = '\x00\\xc0\\xa8\x11\\x97\\xff\\xff\\xff\x00\\xc0\\xa8\x11\x01'
  • Basecls is UDS(Packet)

  • UDS implements fake layers to auto-fill fields

  • Identifiers can be customized

  • OEM specific packets can be added to the parser, easily

Customization of Packets#

  • Define identifier 0x172a as GatewayIP

rdbi_pkt = UDS()/UDS_RDBI(identifiers=[0x172a])
print(repr(rdbi_pkt))
UDS_RDBI.dataIdentifiers[0x172a] = 'GatewayIP'
print(repr(rdbi_pkt))
<UDS  service=ReadDataByIdentifier |<UDS_RDBI  identifiers=[0x172a] |>>
<UDS  service=ReadDataByIdentifier |<UDS_RDBI  identifiers=[GatewayIP] |>>
  • Also the received packet is affected

print(repr(rx))
<Sniffed: TCP:0 UDP:0 ICMP:0 Other:1>
  • Define a payload class

class DBI_IP(Packet):
    name = 'DataByIdentifier_IP_Packet'
    fields_desc = [
        ByteField('ADDRESS_FORMAT_ID', 0),
        IPField('IP', 0),
        IPField('SUBNETMASK', 0),
        IPField('DEFAULT_GATEWAY', 0)]
  • Connect RDBIPR with new payload class

bind_layers(UDS_RDBIPR, DBI_IP, dataIdentifier=0x172a)
  • Enjoy your new packet parser (show2() is called to rebuild the packet)

rx[0].show2()
###[ UDS ]### 
  service   = ReadDataByIdentifierPositiveResponse
###[ ReadDataByIdentifierPositiveResponse ]### 
     dataIdentifier= GatewayIP
###[ DataByIdentifier_IP_Packet ]### 
        ADDRESS_FORMAT_ID= 0
        IP        = 192.168.17.151
        SUBNETMASK= 255.255.255.0
        DEFAULT_GATEWAY= 192.168.17.1
  • Get all possible packets of a layer in Scapy

explore("scapy.contrib.automotive.uds")
Packets contained in scapy.contrib.automotive.uds:
Class      |Name                                           
-----------|-----------------------------------------------
UDS        |UDS                                            
UDS_ATP    |AccessTimingParameter                          
UDS_ATPPR  |AccessTimingParameterPositiveResponse          
UDS_AUTH   |Authentication                                 
UDS_AUTHPR |AuthenticationPositiveResponse                 
UDS_CC     |CommunicationControl                           
UDS_CCPR   |CommunicationControlPositiveResponse           
UDS_CDTCI  |ClearDiagnosticInformation                     
UDS_CDTCIPR|ClearDiagnosticInformationPositiveResponse     
UDS_CDTCS  |ControlDTCSetting                              
UDS_CDTCSPR|ControlDTCSettingPositiveResponse              
UDS_DDDI   |DynamicallyDefineDataIdentifier                
UDS_DDDIPR |DynamicallyDefineDataIdentifierPositiveResponse
UDS_DSC    |DiagnosticSessionControl                       
UDS_DSCPR  |DiagnosticSessionControlPositiveResponse       
UDS_ER     |ECUReset                                       
UDS_ERPR   |ECUResetPositiveResponse                       
UDS_IOCBI  |InputOutputControlByIdentifier                 
UDS_IOCBIPR|InputOutputControlByIdentifierPositiveResponse 
UDS_LC     |LinkControl                                    
UDS_LCPR   |LinkControlPositiveResponse                    
UDS_NR     |NegativeResponse                               
UDS_RC     |RoutineControl                                 
UDS_RCPR   |RoutineControlPositiveResponse                 
UDS_RD     |RequestDownload                                
UDS_RDBI   |ReadDataByIdentifier                           
UDS_RDBIPR |ReadDataByIdentifierPositiveResponse           
UDS_RDBPI  |ReadDataByPeriodicIdentifier                   
UDS_RDBPIPR|ReadDataByPeriodicIdentifierPositiveResponse   
UDS_RDPR   |RequestDownloadPositiveResponse                
UDS_RDTCI  |ReadDTCInformation                             
UDS_RDTCIPR|ReadDTCInformationPositiveResponse             
UDS_RFT    |RequestFileTransfer                            
UDS_RFTPR  |RequestFileTransferPositiveResponse            
UDS_RMBA   |ReadMemoryByAddress                            
UDS_RMBAPR |ReadMemoryByAddressPositiveResponse            
UDS_ROE    |ResponseOnEvent                                
UDS_ROEPR  |ResponseOnEventPositiveResponse                
UDS_RSDBI  |ReadScalingDataByIdentifier                    
UDS_RSDBIPR|ReadScalingDataByIdentifierPositiveResponse    
UDS_RTE    |RequestTransferExit                            
UDS_RTEPR  |RequestTransferExitPositiveResponse            
UDS_RU     |RequestUpload                                  
UDS_RUPR   |RequestUploadPositiveResponse                  
UDS_SA     |SecurityAccess                                 
UDS_SAPR   |SecurityAccessPositiveResponse                 
UDS_SDT    |SecuredDataTransmission                        
UDS_SDTPR  |SecuredDataTransmissionPositiveResponse        
UDS_TD     |TransferData                                   
UDS_TDPR   |TransferDataPositiveResponse                   
UDS_TP     |TesterPresent                                  
UDS_TPPR   |TesterPresentPositiveResponse                  
UDS_WDBI   |WriteDataByIdentifier                          
UDS_WDBIPR |WriteDataByIdentifierPositiveResponse          
UDS_WMBA   |WriteMemoryByAddress                           
UDS_WMBAPR |WriteMemoryByAddressPositiveResponse           
  • Get all fields of a packet

ls(UDS_RC)
routineControlType : ByteEnumField                       = ('0')
routineIdentifier : XShortEnumField                     = ('0')
  • Tester present sender

tps = UDS_TesterPresentSender(sock)
tps.start()
print("Do whatever you need to do")
tps.stop()
  • Security Access Seed

../../_images/scapy_sa_tx.svg
../../_images/scapy_sa_rx.svg
  • Security Access Key

../../_images/scapy_sa_tx2.svg
../../_images/scapy_sa_rx2.svg