ABOUT ME

-

  • UDS DID(data identifier) 스캐닝
    application 2025. 1. 27. 16:03

    시작하기 전에 

    진단 응답 해석하기 :: hsl's tsmaster 사용기 에서 Read ECU ID, Read DTC, Read Software Version, Tester Present 요청으로 진단 통신의 m_id (0x700 ~ 0x7FF)를 스캐닝해보았다. Read ECU ID 요청의 응답은 유용했다. Read DTC나 Read Software Version 요청들의 응답은 유용하지 못했다. 서비스 요청의 파라미터가 제어기들이 지원하지 않는 것이기 때문일 수 있다고 생각한다. 그렇다면 "제어기들이 지원하는 파라미터는 어떤 것들일까?" 하는 의문이 생겼다. m_id를 스캐닝한 것처럼 파라미터를 스캐닝해볼 수 있다. 

     

    UDS에 정의되어 있는 모든 서비스들을 대상으로 파라미터를 찾는 것은 데모로는 과하다. Read ECU ID 요청과 Read Software Version 요청은 Read Data By Identifier 요청(0x22)에 속한다. Data Identifier (DID)만 다르다. Read Data By Identifier 서비스의 DID를 대상으로 스캐닝을 해본다. (이 글의 제목이다.)

     

    DID는 2 바이트다. 두 바이트는 십진수로 65,536에 해당한다. DID를 바꿔가며 1초에 1회 진단 요청을 한다면, 스캐닝은 18.2 시간 걸린다. (너무 길다.) 100msec 마다 1회로 주기를 10배 단축하면 1.8시간 걸린다. (아직 길다. 차를 1.8시간이나 아이들링하며 차 안에 있고 싶지 않다.) 10msec로 단축하면 0.18시간, 즉, 11분 걸린다. (ok) 제어기들이 이렇게 빨리 응답할 수 있을까? 못한다면 주기를 늘려가며 최적의 주기를 찾기로 한다. 그리고 이를 진단 요청과 응답 m_id 짝 찾기 :: hsl's tsmaster 사용기에서 찾은 진단 m_id들을 대상으로 베뉴에서 DID를 스캐닝해보자.

     

    내가 갖고 있는 ESC 단품을 이용해서 적당한 DID 스캐닝 주기를 찾는다.

     

     

    개요

    • Read Data By Identifier의 DID를 스캐닝하기
    • 0x700 ~ 0x7FF 메시지들만 측정하기
    • 측정 데이터 분석

     

    Read Data By Identifier의 DID를 스캐닝하기

    • 일정한 주기로 Read Data By Identifer의 DID를 0x0000 부터 1씩 증가하면서 0xFFFF까지 변경하며 서비스를 요청하는 미니프로그램을 작성한다. (사이버 보안에서는 이를 brute force attack 이라고 한다. 단순 무식 공격이다.)
    • 일정한 주기로 요청 메시지를 전송하기 위한 timer를 정의한다. Timers에서 마우스 우클릭하여 Add Timer 메뉴를 클릭하여 아래 그림과 같이 timer_scan_data_id를 정의한다.

    요청 메시지를 주기적으로 전송하기 위한 타이머 timer_scan_data_id를 추가한다.

     

    • timer_scan_data_id가 트리거할 때마다 실행할 함수를 정의한다. On Timer에서 마우스 우클릭하여 Add On Timer 메뉴를 선택한다. 아래 그림과 같이 Timer Name에서 timer_scan_data_id를 선택하고, Name에 scan_data_id를 입력한다.

    timer_scan_data_id가 트리거 할 때마다 실행할 함수를 정의한다.

     

    • on_timer_scan_data_id() 함수를 아래 코드와 같이 정의한다. DID를 증가해가며 Read Data By Identifier 요청을 전송한다.
    def on_timer_scan_data_id() -> None:
    
        global k_is_can_fd
        global k_m_id_esc_diag_req
        global k_req_readDataById
        global data_id_low
        global data_id_high
        global is_timer_scan_data_id_on
    
        # k_req_readDataById = [0x03, 0x22, 0x01, 0x02, 0xAA, 0xAA, 0xAA, 0xAA] 
        # 0x03: 서비스 요청의 길이, 3 바이트
        # 0x22: readDataByIdentifier 서비스의 Serive Id
        # 0x01: DID의 High Byte 위치
        # 0x02: DID의 Low Byte 위치
    
        # DID의 High Byte와 Low Byte를 변경한다.
        k_req_readDataById[3] = data_id_low
        k_req_readDataById[2] = data_id_high
    
        # diag_req 메시지를 만든다.
        # CAN-FD 메시지와 CAN 메시지는 설정이 다르다. 
        if k_is_can_fd:
            # CAN-FD 메시지
            msg_diag_req = RawCAN(k_m_id_esc_diag_req, 8, CH1, 0, k_req_readDataById, 0x306)
        else:
            # CAN 메시지
            msg_diag_req = RawCAN(k_m_id_esc_diag_req, 8, CH1, 0, k_req_readDataById)
    
        # diag_req 메시지를 전송한다.
        if com.transmit_can_async(msg_diag_req) == 0:
            # app.log_text(f'{msg_diag_req}', lvlOK)
            # 출력량이 너무 많아서 디버깅할 때만 사용한다.
            # 트레이스 윈도에서 전송 메시지를 확인할 수 있다.
            pass
        
        # 모든 DID를 처리한 후에 timer_scan_data_id를 멈춘다.
        if (data_id_low == 0xFF) and (data_id_high == 0xFF):
            timer_scan_data_id.Stop()
            is_timer_scan_data_id_on = False
            app.log_text('timer_scan_data_id stopped', lvlOK)
            
        # DID를 +1만큼 증가한다.
        data_id_low += 1
        if data_id_low > 0xFF:
            data_id_low = 0x00 
            data_id_high += 1

     

    • 미니프로그램을 시작하면 timer_scan_data_id는 정지된 상태이다. 타이머를 시작해줘야 한다. 키보드에서 Ctrl+5 키를 입력하면 타이머가 시작되도록 한다.
    • On Shortcut에서 마우스 우클리하여 Add On Shortcut 메뉴를 선택한다. 아래 그림과 같이 Shortcut과 Name을 입력한다. Shortcut을 선택하고 키보드에서 Ctrl 키를 누른 채로 5 키를 누르면 Ctrl+5가 입력된다.

    Ctrl+5 키 입력이 있으면 timer_scan_data_id를 시작하도록 한다.

    • on_shortcut_ctrl_5_scan_data_id() 함수를 아래 코드와 같이 정의한다. DID를 시작 값을 0x0000으로 초기화하고 timer_scan_data_id를 시작한다.
    def on_shortcut_ctrl_5_scan_data_id() -> None:
    
        global k_msg_extDiag
        global data_id_low
        global data_id_high
        global m_id_diag_req
        global k_m_id_esc_diag_req
        global is_timer_diag_req_on
        global is_timer_tester_present_on
        global is_timer_scan_data_id_on
    
        # ESC를 대상으로 한다. 
        # 다른 제어기를 대상으로 할 경우, 
        # 그 제어기의 진단 "요청" m_id를 사용한다. 
        m_id_diag_req = k_m_id_esc_diag_req
    
        # DID를 스캐닝을 시작할 값으로 초기화한다.
        data_id_high = 0x00
        data_id_low = 0x00
    
        # data_id 스캔 중에는 timer_diag_req를 정지한다.
        timer_diag_req.Stop()
        is_timer_diag_req_on = False
        app.log_text('timer_diag_req stopped', lvlOK)
    
        # data_id scan을 위한 readDataById 요청의 주기가 
        # tester_present의 주기보다 짧으면 tester_present 가 필요없다.
        # timer_tester_present를 정지한다.
        if timer_scan_data_id.IntervalUs <= timer_tester_present.IntervalUs:
            timer_tester_present.Stop()
            is_timer_tester_present_on = False
            app.log_text('timer_tester_present stopped', lvlOK)
        
        if com.transmit_can_async(k_msg_extDiag) == 0:
            app.log_text('extended diag session', lvlOK)
    
            timer_scan_data_id.Start()
            is_timer_scan_data_id_on = True
            app.log_text('timer_scan_data_id started', lvlOK)
    • 미니프로그램 코드

    mobis_esc_ecu_id_rev_eng.py
    0.03MB

     

     

    0x700 ~ 0x7FF 메시지들만 측정하기

    • 전송 주기에 따라 매우 장시간 데이터를 측정해야 한다. 전체 메시지를 측정한다면 파일 크기가 쓸 때 없이 매우 커질 것이다. 메시지 아이디가 0x700에서 0x7FF까지인 진단 통신 메시지만 측정한다. 방법은 아래와 같다.
    • 메인 메뉴/ Analysis/ Measurement Setup 버튼을 클릭하여 Measurement Setup 창을 연다.

    filter를 추가하기 위해 Measurement Setup 창을 연다.

    • Bus Logging을 선택한 후 마우스 우클릭을 한다. 팝-업 메뉴에서 Insert Filter를 선택한다.

    Bus Logging 을 선택한 후 마우스 우클릭으로 Insert Filter를 선택하여 Logger 앞에 Filter를 삽입한다.

    • 필터를 Pass 필터로 설정한다. 
    • Add 메뉴를 클릭한 후 Add Id Range를 선택한다.

    0x700에서 0x7FF 구간의 메시지들이 통과되도록 Add Id Range를 선택한다.

    • 범위를 0x700에서 0x7FF로 설정한다. Enabled를 Active로 체크한다.

    0x700에서 0x7FF 메시지들이 통과되도록 필터를 설정한다.

     

     

    측정 데이터 분석

    mobis_esc_readDID_scan_blf.ipynb
    0.03MB

     

     

    결론

    • 스캐닝을 통해서 (내가 갖고 있는) ESC에는 23개의 DID가 있다는 것을 알았다. 내게는 진단 통신 사양서 없어서 아주 분명한 몇 개를 제외하고 각 DID의 의미를 알 수 없었다. 
    • 23 종류나 되는 제어기 하드웨어와 소프트웨어에 관한 정보가 있다면 그리고 실차에서 이 정보를 수집한다면, 실차의 형상을 상세하게 파악할 수 있을 것으로 기대한다.
    • 실차 수집 형상 정보와 설계 기준 형상을 비교하여 오류와 오류의 원인을 찾는 프로그램을 작성할 수 있지 않겠는가?

     

     

     

    목차 :: hsl's tsmaster 사용기