UDS in Scapy#

Overview#

../../_images/ScanpySWArchitecture1.png

Fig. 66 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 send 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      = b'\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      = b'\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                                           
---------------------|-----------------------------------------------
DTC                  |Diagnostic Trouble Code                        
DTCAndStatusRecord   |DTC and status record                          
DTCExtendedData      |Diagnostic Trouble Code Extended Data          
DTCExtendedDataRecord|                                               
DTCSnapshot          |                                               
DTCSnapshotRecord    |                                               
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