Zum Inhalt springen
AutoST by Zyberum GmbH
Menü
UDSNRC

UDS Negative Response Codes erklärt für Tester

Was eine negative UDS-Antwort (0x7F) am Prüfstand verrät: der Aufbau, die Codes, die bei Enumeration und SecurityAccess zählen, und wie du sie liest.

Tom Zaubermann · Veröffentlicht · 8 Min. Lesezeit

Eine negative UDS-Antwort ist das ECU, das dir sagt, dass es nicht tut, worum du gebeten hast, und warum. Die Antwort besteht immer aus drei Bytes: 7F, dem Service-Identifier (SID) des abgelehnten Requests und einem Negative Response Code (NRC). Richtig gelesen bilden diese Codes das ECU für dich ab, denn ein ECU, das präzise ablehnt, beschreibt zugleich seine eigene Struktur, eine Antwort nach der anderen.

Der Aufbau, Byte für Byte

Sende einen Request und du bekommst eines von drei Ergebnissen. Eine positive Antwort beginnt mit dem SID plus 0x40: ein Request 22 F1 90 (ReadDataByIdentifier, DID 0xF190), beantwortet mit 62 F1 90 ..., ist ein Erfolg. Eine negative Antwort sieht so aus:

7F 22 31
│  │  └─ NRC: requestOutOfRange
│  └──── abgelehnter SID: 0x22 ReadDataByIdentifier
└─────── Negative-Response-Service-Identifier

Das dritte Ergebnis ist Stille, die auf CAN meist bedeutet, dass der ISO-TP-Frame (ISO 15765-2) nie akzeptiert wurde, die Arbitration-ID falsch ist oder das ECU beschäftigt ist. Stille ist kein NRC, und du solltest sie anders behandeln als eine ausdrückliche Ablehnung.

Die Codes mit dem meisten Informationsgehalt

ISO 14229-1 Anhang A definiert die volle Tabelle. Während eines Scans erledigt eine Handvoll Codes die meiste Arbeit:

CodeISO-NameWas er dem Tester sagt
0x10generalRejectDas ECU lehnt ohne Grund ab. Manche Implementierungen antworten das auf alles Unverstandene, was Struktur verbirgt.
0x11serviceNotSupportedDer Service existiert auf diesem ECU gar nicht.
0x12subFunctionNotSupportedDer Service existiert, die Sub-Funktion nicht.
0x13incorrectMessageLengthOrInvalidFormatLänge oder Format falsch. Nützliches Signal beim Fuzzing.
0x22conditionsNotCorrectDer Service existiert, aber Vorbedingungen fehlen (falscher Zustand, Drehzahl, Spannung).
0x31requestOutOfRangeDer Parameter, meist ein DID oder RID, ist unbekannt oder out of range.
0x33securityAccessDeniedDer Service ist hinter SecurityAccess (0x27) gesperrt.
0x35invalidKeyFalscher Key an SecurityAccess gesendet.
0x36exceedNumberOfAttemptsZu viele falsche Keys; der Lockout hat ausgelöst.
0x37requiredTimeDelayNotExpiredDu musst warten, bevor du es erneut versuchst.
0x7EsubFunctionNotSupportedInActiveSessionSub-Funktion existiert, nicht in dieser Session.
0x7FserviceNotSupportedInActiveSessionService existiert, nicht in dieser Session.
0x78requestCorrectlyReceived-ResponsePendingKein Fehler: auf die echte Antwort warten.

“Nicht hier” von “nicht jetzt” unterscheiden

Die nützlichste Unterscheidung während der Enumeration ist die zwischen einem Service, der nicht existiert, und einem, der existiert, aber hinter einer Session oder SecurityAccess gesperrt ist. Die Codes machen das explizit.

  • 0x11 serviceNotSupported: der SID fehlt. Hör auf, ihn zu proben.
  • 0x7F serviceNotSupportedInActiveSession: der SID ist da, du bist in der falschen Session. Sende nach 10 03 (Extended) oder, vorsichtig, 10 02 (Programming) erneut.
  • 0x33 securityAccessDenied: der SID ist da und in dieser Session erreichbar, braucht aber zuerst eine entsperrte SecurityAccess-Stufe.

Ein RoutineControl-Probe, der 7F 31 33 zurückgibt, ist also keine Sackgasse. Es ist die Bestätigung, dass 0x31 hier existiert und dass etwas Schützenswertes hinter 0x27 sitzt. Dieses eine Byte lenkt den ganzen Test auf das Seed/Key-Tor.

Response Pending, und die ECUs, die es missbrauchen

0x78 ist das ECU, das um mehr Zeit bittet. Das korrekte Tester-Verhalten ist, den P2*-Timer zurückzusetzen und weiter auf eine positive Antwort oder einen anderen NRC zu warten. Byte für Byte:

tx 31 01 FF 00    RoutineControl startRoutine 0xFF00
rx 7F 31 78       Response Pending, weiter warten
rx 7F 31 78       arbeitet noch
rx 71 01 FF 00    finale positive Antwort

Zwei Muster sind selbst Findings. Ein ECU, das 0x78 sendet und nie nachliefert, hängt jeden Tester, der das Protokoll einhält. Ein ECU, das einen endlosen Strom von 0x78 sendet, lässt sich nutzen, um eine Session, sogar eine Programming-Session, viel länger offen zu halten als vorgesehen.

NRCs bei SecurityAccess nutzen

Die SecurityAccess-Codes bilden eine kleine Zustandsmaschine, die du beobachten kannst. Ein gesundes Tor läuft durch sie hindurch:

tx 27 01          requestSeed Level 1
rx 67 01 A1 B2    Seed zurückgegeben
tx 27 02 00 00    sendKey (falsch)
rx 7F 27 35       invalidKey
...wiederholen...
rx 7F 27 36       exceedNumberOfAttempts (Lockout ausgelöst)
tx 27 02 00 00    sendKey
rx 7F 27 37       requiredTimeDelayNotExpired

Ein ECU, das endlos 0x35 antwortet und nie zu 0x36 und 0x37 eskaliert, hat keinen Attempt-Counter und keine Verzögerung. Das ist ein schwaches Tor, und die NRC-Spur ist der Nachweis.

Wo die Codes in die Irre führen

Nicht jedes ECU nutzt die Tabelle sauber. Manche antworten 0x10 generalReject auf alles Unbekannte und löschen so den Unterschied zwischen “nicht unterstützt” und “nicht in dieser Session”. Manche geben 0x22 conditionsNotCorrect zurück, wo 0x31 korrekt wäre. Eine einzelne Antwort ist daher ein schwacher Nachweis. Die verlässliche Methode ist statistisch: jeden SID über alle entdeckten Sessions proben und die Response-Codes vergleichen, sodass auch ein falsch beschriftetes ECU seine echte Karte offenlegt. Genau das macht die Enumeration von AutoST, indem sie jeden Service aus seinem Antwortmuster klassifiziert statt einer einzigen Antwort zu trauen, und unser freier UDS-NRC-Decoder löst einen einzelnen Code auf, wenn du nur den Namen brauchst.

FAQ

Häufig gestellte Fragen

Wie ist eine negative UDS-Antwort aufgebaut?

Aus drei Bytes: 0x7F, dem Service-Identifier des abgelehnten Requests und dem Negative Response Code. Ein Tester, der 22 F1 90 sendet und 7F 22 31 erhält, lernt, dass der Service existiert, der Data Identifier aber out of range ist.

Ist Response Pending (0x78) ein Fehler?

Nein. requestCorrectlyReceived-ResponsePending sagt dem Tester, dass das ECU mehr Zeit braucht, also verlängert der Tester seinen P2*-Timeout und wartet. Ein ECU, das 0x78 sendet und dann nie antwortet, ist selbst ein Finding, weil es den Tester hängen lässt.

Warum antworten ECUs auf einen unbekannten DID mit 0x31 statt 0x7F?

requestOutOfRange (0x31) ist die korrekte Antwort auf einen Data Identifier, den das ECU nicht unterstützt. serviceNotSupportedInActiveSession (0x7F) heißt, der ganze Service ist in der aktuellen Session nicht verfügbar. Beides zu verwechseln ist häufig und erschwert die Enumeration.

Ruf uns anDemo buchen

Wähle einen Termin, der dir passt

In neuem Tab öffnen