BCM Firmware Reverse-Engineering (Bootloader)

  • Nach dem Hardware-Hacking mal etwas Software Reverse Engineering. Die Firmware gibt es ja komplett frei zum Download in Form von VBF-Update Files. Diesen "Service" von Ford finde ich großartig :)

    Der Bootloader

    Zunächst zum "Secondary Bootloader" (SBL) BG9T-14C097-AA

    Dieser enthält ein Stück Software welches in das RAM des BCM geladen wird und die Kontrolle übernimmt, quasi wie so eine Art Trojaner. Um das User-Flash neu zu programmieren darf die Software dort drin natürlich nicht ausgeführt werden (Henne/Ei Problem), auch kann nichts anderes da drin stehen. Daher diese Methode es ins RAM zu laden. Das wird bei praktischen allen Modul-Updates so gemacht.

    Mit dem VBF-Tool kann man sich den Inhalt des Paketes komfortabel ansehen und extrahieren:

    Dort findet man einen Kommentarblock mit ein paar interessanten Infos:

    Nun wissen wir was es ist (sw_part_type=SBL) und wie es zum BCM übermittelt wird (network=CAN_HS, frame_format=CAN_STANDARD) und welche UDS-Adresse dafür genutzt wird (ecu_address=0x726). Desweiteren sehen wir wo der "Entrypoint" nach einem Upload ins BCM liegt (call = 0x00000410). Der Entrypoint ist quasi die Start-Adresse der Software.

    Das VBT-Tool zeigt das das VBF zwei Datenblöcke enthält, Block 1:

    Die StartAddress gibt hierbei die Adresse im Flash des BCM an, an die dieser Block geladen wird. Die Länge beträgt 0x278D Bytes. Die Checksum dient nur dem Manipulations- und Übertragungsschutz. Dieser Teil enthält die ausführbare Software des SBL. Ein Blick ins Datenblatt des R32C verrät uns über die Memory Map das der Bereich für das RAM ab 0x0000 0400 beginnt:

    Er dehnt sich um 48KB aus, also geht er von 0x0000 0400 bis 0x0000 C400.

    Warum die nicht direkt nach 0x0000 0400 geladen wird ist mir grad nicht klar, ist aber auch egal.

    Der zweite Block im VBF wird an 0x0000 2BA0 geladen:

    Er enthält Daten, vermutlich Vorderfinierte Variablen und Konstanten die zur Ausführung der Software benötigt werden. Es ist üblich das Compiler hierfür aus dem Quellcode zwei getrennte Bereiche machen, selbst wenn beide im RAM liegen. Meist liegt aber die nicht veränderliche Software in einem Flash und nur die Daten im RAM. Hierbei geht das halt nicht anders.

    Somit steht die Software von 0x0000 0410 - 0x0000 2B9D im RAM, gleich gefolgt von den Daten ab 0x0000 2BA0 - 2FEB.

    Das ganze kann man nun mit einem Disassembler laden (z.B. mit IDA Pro >= 7.4 oder dem frei verfügbaren "High-performance Embedded Workshop" Tool von Renesas) und untersuchen was es genau macht.

    Die erste Hürde ist natürlich immer diese Software ins Steuergerät zu bekommen. Hierzu benötigt man einen Uploader. Dieser nimmt Kontakt mit dem Steuergerät per UDS auf und nutzt UDS-Funktionen um Daten in den gewünschten Speicherbereich hochladen zu können. Anschließend nutzt er eine weitere UDS-Funktion um diese dort zu Ausführung zu bringen, also den ProgramCounter (PC) an die Adresse 0x0000 0410 zu stellen. Danach übernimmt dann die hochgeladene Software das Steuergerät und kommuniziert direkt mit dem Uploader, ebenfalls weiter über UDS um das interne Flash zu löschen, die eigentliche Software zu laden und ins Flash zu programmieren.

    Damit der Uploader die UDS-Funktionen nutzen kann ist eine erweiterte UDS-Sitzung erforderlich. Diese ist in der Regel mit einem Kennwort geschützt. Das Verfahren (Challenge-Response) zur Übermittlung des Kennwortes ist bekannt, nicht aber der Code. Bei den alten Steuergeräten gibt es oft keine weiteren Schutzmechanismen sodass man auch Brute-Force Attacken dagegen fahren kann, also alle möglichen Kombinationen nacheinander ausprobieren lässt bis man das richtige hat. Oder man untersucht den Mechanismus wie die Dekodierung funktioniert um daraus die passenden Kennwörter zu bauen. Oft wird hier mit einer Tabelle gearbeitet, es ist also nicht ein einzelnes Passwort, sondern eine Liste. Das verhindert Replay-Attacken, also das einfache mitlesen der unverschlüsselten CAN-Botschaften und wiederverwenden der Zugangskennung.

    Eine dritte Option wäre die Routine zu lokalisieren wo die Kennwortprüfung stattfindet und diese im Flash des BCM zu patchen sodass die Antwort immer "Ok" lautet. Dazu wäre aber HW-Zugang erforderlich. Ich werde versuchen im laufe meines Rev-Engs diese Routine zu finden und die PW-Tabelle und Methode zu extrahieren um einen PW-Generator dafür zu bauen. Damit sollte es dann möglich sein rein per Software die Teile vom BCM runterzuladen die normalerweise verborgen bleiben, also den Data Flash und E2 Data Flash. Diese Blöcke könnte man dann ebenfalls per UDS auf ein anderes BCM speichern und somit den Clone-Vorgang ganz bequem per CAN, ohne öffnen des Steuergerätes durchführen.

    Ob man dafür dann einen eigenen SBL schreiben muss bleibt abzuwarten, möglicherweise kann man das alles von einem Uploader-Tool mittels UDS-Botschaften erledigen.

    "Lernen ist Erfahrung. Alles andere ist einfach nur Information."

    Albert Einstein

  • Zur Firmware selbst. Diese steckt im VBF "BG9T-14C094-AM".

    Das VBF verräts uns die Ladeadresse 0xFFF4 0000, was aber auch kein Geheimnis ist, denn genau da startet das User-Flash des R32C. Das VBF gibt aber keinen Entrypoint an, muss es auch nicht, denn das ist in der RESET-Prozedur der CPU geregelt. Diese lädt nach dem Start die Adresse aus dem Reset-Vektor, welcher sich an 0xFFFF FFFC (4 Byte) befindet und springt dann dort hin. Die Reset-Vektoren sind nie in den Firmware-Updates enthalten da sie sich in der Regel nicht ändern. Aber da ich ja ein komplettes Dump der MCU habe und nicht bloß die Firmware, kann ich ja da nachsehen:

    Also ist der Entrypoint 0xFFFF 8000 (Little-Endian).

    An dieser Adresse befindet sich der Bootloader, genauer gesagt der "Primary Bootloader (PBL)". Dieser hat die Aufgabe das System zu starten und die eigentliche Firmware zur Ausführung zu bringen. Im PBL sind oft auch Recovery-Funktionen enthalten um ein Gerät bei nicht erfolgreichem Update oder sonstigen Softwareproblemen wieder über den CAN-Bus "betanken" zu können. Klappt natürlich nur dann wenn der Bootloader selbst noch intakt ist. Vor allem aber wenn es Probleme mit der Hardware bzw. Firmware geben sollte, überhaupt noch eine Programmierung durchführen zu können. In manchen Tools, wie z.b. UCDS nennt sich sowas dann "Dead Module Programming".

    Soweit ich das bislang analysiert habe reagiert der Bootloader auf allen CAN-Bussen, also HS und MS, wogegen die UDS-Funktionen der Firmware auf HS-CAN beschränkt sind.

    Damit kann ich die Firmware schonmal in einen Disassembler laden und nachverfolgen was darin gemacht wird. Auch wenn die Größe von 768 kb überschaubar klingen sind es doch sehr viele Befehle die man erstmal verstehen muss.

    "Lernen ist Erfahrung. Alles andere ist einfach nur Information."

    Albert Einstein

  • Go4IT February 2, 2024 at 6:43 PM

    Changed the title of the thread from “BCM Firmware Reverse-Engineering” to “BCM Firmware Reverse-Engineering (Bootloader)”.

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!