Skip to content

실습 목표#

  • 진단 계층에서 발생하는 오류를 직접 재현한다.
  • Wireshark 패킷과 클라이언트 로그를 비교해 오류 유형을 구분한다.
  • 오류별 신호를 기록하고 필요한 대응 방법을 판단한다.


실습 1. 정상 동작 기준 잡기#


오류를 걸기 전에 정상 흐름을 먼저 캡처해 비교 기준으로 삼는다. 오류 상황마다 서버 코드를 매번 수정하면 번거롭기 때문에 오류 모드를 인자로 받는다. 이때 기본값은 normal이다.
정상 흐름은 다음과 같다.

라우팅 요청(0x0005) → 응답(0x0006) → 진단 요청(UDS 0x22) → 진단 응답(UDS 0x62)

라즈베리파이·터미널
make
./ecu_faulty normal
노트북·WSL
make
./tester_client
테스터 출력
-> positive (VIN): TESTVIN0123456789


Wireshark 분석#

다음 단계를 따라가며 Wireshark 분석을 진행한다. alt text ① 테스터가 ECU에 Routing Activation을 요청한다.

② ECU가 응답하면서 진단 통신 경로가 활성화된다.

③ 라우팅 활성화 후 테스터가 DID 0xF190의 VIN 읽기를 요청하고 ECU가 정상 응답을 반환한다.

④ UDS 응답 상세에서 ECU 주소 0x0001, 테스터 주소 0x0E00, VIN DID 0xF190을 확인할 수 있다.

⑤ 원시 데이터의 62 F1 90은 VIN 읽기 긍정 응답이며, 이후 바이트는 TESTVIN0123456789를 나타낸다.


실습 2. 응답 지연 0x78#


pending이란 응답 지연이 발생하는 것을 의미한다. 응답이 지연되는 것이므로 오류는 아니다.

라즈베리파이·터미널
./ecu_faulty pending
노트북·WSL
./tester_client
테스터 출력
-> responsePending (0x78): ECU busy, waiting...
-> positive (VIN): TESTVIN0123456789


Wireshark 분석#

다음 단계를 따라가며 Wireshark 분석을 진행한다. alt text

① 테스터가 ECU에 0x22 F190으로 VIN 읽기를 요청한다.

② ECUbird는 요청을 정상적으로 받았지만 처리가 끝나지 않아 7F 22 78을 보낸다. 여기서 0x78은 실패가 아니라 계속 기다리라는 responsePending 응답이다.

③ 약 1.5초 뒤 ECU가 0x62 F190과 VIN 데이터를 최종 응답으로 전송한다.

④ 패킷 상세 정보에서 요청 SID 0x22와 NRC 0x78을 확인할 수 있으며, ⑤ 원시 데이터에서도 7F 22 78이 나타난다.

0x78을 받은 뒤 요청을 다시 보내지 않고 같은 연결에서 최종 응답을 기다린다는 점이 중요하다.


결과: 0x78 프레임 분석#

02 FD 80 01 00 00 00 07 00 01 0E 00 7F 22 78
오프셋 바이트 필드 의미
0 ~ 1 02 FD Version / Inverse 정상적인 DoIP 헤더
2 ~ 3 80 01 Payload Type 진단 메시지이며 NACK가 아님
4 ~ 7 00 00 00 07 Payload Length 페이로드 길이 7바이트
8 ~ 9 00 01 Source Address ECU 주소
10 ~ 11 0E 00 Target Address 테스터 주소
12 7F 부정 응답 표시 부정 응답 형식
13 22 요청 SID VIN 읽기 요청에 대한 응답
14 78 NRC responsePending: 처리 중이므로 계속 대기


실습 3. 응답 타임아웃#


timeout은 ECU가 요청을 받고 응답도, 응답 지연 신호(0x78)도 보내지 않는 경우를 의미한다. 데이터가 사라진 것이 아니므로 TCP 재전송도 일어나지 않는다.

라즈베리파이·터미널
./ecu_faulty timeout
노트북·WSL
./tester_client
테스터 출력
-> TIMEOUT: no response within 2 s (P2 timeout)


Wireshark 분석#

다음 단계를 따라가며 Wireshark 분석을 진행한다. alt text

① 테스터가 ECU에 0x22 F190으로 VIN 읽기를 요청한다.

② ECU가 TCP ACK를 보내 요청 데이터가 정상적으로 도착했음을 알린다. 이 패킷은 TCP 수신 확인일 뿐, UDS 진단 응답은 아니다.

③ 이후 약 2초 동안 ECU가 정상 응답이나 0x78 responsePending을 보내지 않는다. 요청은 정상적으로 전달되었으므로 TCP 재전송도 발생하지 않는다.

④ 설정된 P2 대기 시간이 지나면 테스터는 응답 타임아웃으로 판단하고 FIN, ACK를 보내 연결을 종료한다.

확인 포인트

TCP ACK가 있는데 UDS 응답이 없으면 패킷 손실이 아니라 ECU 응답 타임아웃으로 판단할 수 있다.


실습 4. 세션 끊김#


drop은 ECU가 진단 도중 연결을 끊어 버리는 경우로, 리셋이나 내부 오류에 의해 발생한다. 이때 테스터는 응답 대신 연결이 끊어졌다는 신호를 받는다.

라즈베리파이·터미널
./ecu_faulty drop
노트북·WSL
./tester_client
테스터 출력
-> connection closed by ECU (session drop)


Wireshark 분석#

다음 단계를 따라가며 Wireshark 분석을 진행한다. alt text

① 테스터가 ECU에 0x22 F190으로 VIN 읽기를 요청한다.

② ECU는 정상 응답이나 0x78 responsePending을 보내지 않고 곧바로 TCP FIN, ACK를 전송한다.

FIN, ACK 패킷의 출발지 포트가 13400이므로 ECU가 보낸 패킷임을 확인할 수 있다.

FIN 플래그는 ECU가 먼저 TCP 연결 종료를 요청했다는 것을 의미한다.

⑤ 연결 종료 신호를 받은 클라이언트의 recv()0을 반환하며, 클라이언트는 이를 세션 끊김으로 판단한다.

타임아웃과의 차이

타임아웃은 ECU의 종료 신호 없이 일정 시간 동안 응답이 없는 상태이다. 세션 끊김에서는 ECU가 보낸 FIN, ACK가 캡처에 남는다.


실습 5. 세션 불일치#


기본 세션에서 쓰기를 요청하면 세션 관문에서 거부된다. 확장 세션으로 바꾸면 세션 조건은 충족하지만 보안 관문에서 거부된다. ECU 서버가 실행 중인 상태에서 노트북 WSL의 시나리오만 변경하여 진행한다. 서버를 재시작해야 하는 경우 normal 모드로 실행한다.

라즈베리파이·터미널
./ecu_faulty normal
노트북·WSL
./tester_client write
노트북·WSL
./tester_client session-write

alt text


Wireshark 분석#

1. 기본 세션에서 쓰기 요청#

alt text

① 테스터가 기본 세션에서 0x2E F190으로 VIN 쓰기를 요청한다.

② ECU는 7F 2E 7F 부정 응답을 반환한다.

③ 응답의 마지막 바이트인 NRC 0x7FserviceNotSupportedInActiveSession을 의미한다. 현재 기본 세션에서는 쓰기 서비스를 사용할 수 없으므로 세션 관문에서 요청이 거부된다.

바이트 의미
7F 부정 응답 표시
2E 거부된 WriteDataByIdentifier 요청
7Folph 현재 세션에서 지원하지 않음


2. 확장 세션 전환 후 쓰기 요청#

alt text

① 테스터가 0x10 03으로 확장 세션 전환을 요청하고, ECU가 0x50 03으로 긍정 응답한다.

② 확장 세션으로 전환된 상태에서 0x2E F190 VIN 쓰기를 다시 요청한다.

③ ECU는 7F 2E 33 부정 응답을 반환한다.

④ NRC 0x33securityAccessDenied를 의미한다. 확장 세션으로 전환하여 세션 관문은 통과했지만, 보안 권한이 해제되지 않아 보안 관문에서 요청이 거부된다.

바이트 의미
7F 부정 응답 표시
2E 거부된 WriteDataByIdentifier 요청
33 보안 접근 권한 없음

두 결과 비교

기본 세션에서는 NRC 0x7F로 세션 관문에서 거부된다. 확장 세션으로 전환하면 세션 관문은 통과하지만 NRC 0x33으로 보안 관문에서 거부된다.


실습 6. 세션 만료와 유지#


확장 세션은 일정 세션 통신이 없으면 5초 후에 기본 세션으로 복귀한다. 세션을 유지하려면 TesterPresent를 주기적으로 전송해야 한다.

라즈베리파이·터미널
./ecu_faulty normal
노트북·WSL
./tester_client s3

노트북·WSL
./tester_client keepalive
alt text


Wireshark 분석#

1. 세션 만료 확인#

alt text

① 테스터가 0x10 03을 요청하고 ECU가 0x50 03으로 응답하면서 확장 세션으로 전환된다.

② 이후 TesterPresent를 보내지 않고 약 6초 동안 대기한다. ECU의 세션 유지 시간인 5초가 지나면서 확장 세션이 만료되고 기본 세션으로 돌아간다.

③ 테스터가 0x2E F190으로 쓰기를 요청하지만 ECU는 0x7F 2E 7F 부정 응답을 반환한다.

④ 마지막 NRC 0x7FserviceNotSupportedInActiveSession을 의미한다. 현재 세션에서 쓰기 서비스를 사용할 수 없으므로 확장 세션이 만료되었음을 확인할 수 있다.

확인 포인트

0x7F 2E 7F에서 첫 번째 0x7F는 부정 응답 표시이고, 마지막 0x7F가 세션 불일치를 나타내는 NRC이다.


2. TesterPresent를 이용한 세션 유지 확인#

alt text

① 테스터가 0x10 03을 요청하고 ECU가 0x50 03으로 응답하면서 확장 세션으로 전환된다.

② 테스터가 약 2초 간격으로 TesterPresent 요청 0x3E 00을 세 번 전송한다. ECU는 각 요청에 0x7E 00으로 응답하며 확장 세션의 유지 시간을 갱신한다.

③ TesterPresent 전송 후 테스터가 0x2E F190으로 쓰기를 요청하고, ECU는 0x7F 2E 33 부정 응답을 반환한다.

④ NRC 0x33securityAccessDenied를 의미한다. 세션 관문은 통과했지만 보안 인증이 수행되지 않아 보안 관문에서 거부된 것이다.

확인 포인트

결과가 NRC 0x7F가 아니라 0x33으로 바뀐 것은 확장 세션이 유지되고 있다는 증거이다. 실제 쓰기를 성공시키려면 별도의 SecurityAccess 절차가 필요하다.