
Ich habe einen Freund, der sich mit der Reparatur von Autoeisen beschäftigt. Er brachte mir irgendwie einen Mikrocontroller, der von einer autonomen Heizungssteuereinheit gelötet wurde. Er sagte, dass sein Programmierer es nicht nimmt, und er möchte in der Lage sein, Firmware hin und her zu übertragen, weil Es gibt viele Blöcke, in Eisen sind sie oft gleich, aber die Einheiten, die sie steuern, sind unterschiedlich. Und es scheint, dass es einen Block anstelle eines fehlerhaften gibt, aber die Software ist anders und Sie können ihn einfach nicht ersetzen. Da die Aufgabe interessant war, beschloss ich, herumzustöbern. Wenn das Thema für Sie interessant ist, bitte unter der Katze ...
Betreff war M306N5FCTFP. Dies ist ein Mikrocontroller der M16C / 6N5-Gruppe. Der M16C / 60-Kern wurde von Mitsubishi und as entwickelt Seit 2003 ist Renesas der Nachfolger dieses Unternehmens in Bezug auf MK. Jetzt sind diese Mikrocontroller unter dieser Marke bekannt.
Ein bisschen über den Mikrocontroller selbst
Der Kiesel ist ein 16-Bit-Mikrocontroller in einem 100-Pin-QFP-Gehäuse. Der Kernel verfügt über 1 MB Adressraum, eine Taktfrequenz von 20 MHz für die Fahrzeugleistung. Der Satz an Peripheriegeräten ist ebenfalls sehr umfangreich: Zwei 16-Bit-Timer und die Möglichkeit, eine 3-Phasen-PWM zur Steuerung von Motoren, alle Arten von UART, SPI, I2C natürlich, 2 DMA-Kanäle, einen eingebauten CAN2.0B-Controller sowie eine PLL zu erzeugen. Meiner Meinung nach ist es sehr gut für den alten Mann. Hier ist eine Übersichtstabelle aus der Dokumentation:

Da es meine Aufgabe ist, die Software herauszureißen, interessiert sie sich auch sehr für das Gedächtnis. Dieser MK wurde in zwei Versionen hergestellt: maskiert und Flash. Ich habe, wie oben erwähnt, den M306N5FCTFP bekommen. Über ihn sagt die Beschreibung Folgendes:
- Flash-Speicherversion
- 128 KByte + 4K (zusätzliche 4K - der sogenannte Block A als Geschenk an den Benutzer zum Speichern von Daten, kann aber auch das Programm speichern)
- V-ver. (Automobilversion mit einem Bereich von + 125 ° C)
Wie man vom Gerät zieht, was Entwickler gezogen haben
Es ist nur natürlich, dass Sie versuchen sollten, etwas aus dem Mikrocontroller herauszuholen, indem Sie die Mechanismen untersuchen, die der Chipentwickler für Speicherprogrammierungsaufgaben integriert. Das Handbuch besagt, dass der Hersteller freundlicherweise einen Bootloader für die Anforderungen der In-Circuit-Programmierung des Geräts in den Speicher gestellt hat.

Wie Sie auf dem Bild oben sehen können, ist der Speicher in zwei Teile unterteilt: den Benutzerbereich und den Bootloader-Bereich. Im zweiten Schritt wird ab Werk ein Standard-Bootloader geladen, der den Benutzerspeicher schreiben, lesen, löschen und über eine asynchrone, synchrone oder CAN-Schnittstelle kommunizieren kann. Es wird angezeigt, dass es nach Ihren Wünschen umgeschrieben werden kann oder nicht. Am Ende lässt sich dies leicht überprüfen, indem versucht wird, den Standard-Bootloader zumindest über UART anzuklopfen ... Mit Blick auf die Zukunft: Der Hersteller der Heizung hat sich nicht um seinen Bootloader gekümmert, sodass Sie weiter in diese Richtung graben können. Machen Sie sofort einen Vorbehalt, dass es noch eine parallele Programmiermethode gibt, aber seitdem Ich hatte keinen Programmierer dafür, ich habe diese Option nicht in Betracht gezogen.
Das Aufrufen des Bootloader-Betriebsmodus erfolgt durch eine bestimmte Kombination an den Eingängen CNVSS, P5_0, P5_5 während eines Hardware-Resets. Schreiben Sie als Nächstes entweder Ihr eigenes Dienstprogramm, um den Inhalt des Speichers zu kopieren, oder verwenden Sie das fertige. Renesas bietet ein eigenes Dienstprogramm namens "M16C Flash Starter", das jedoch über eine reduzierte Lesefunktion verfügt. Es speichert nicht das, was es liest, auf der Festplatte, sondern vergleicht es mit einer Datei von der Festplatte. Das heißt, Dies ist in der Tat kein Lesen, sondern eine Überprüfung. Es gibt jedoch ein deutsches kostenloses Dienstprogramm namens M16C-Flasher, das Firmware lesen kann. Im Allgemeinen wurde das erste Toolkit abgeholt.
Informationen zum Leseschutz

Alles wäre ganz einfach, wenn der Bootloader keinen Schutz vor unbefugtem Zugriff bieten würde. Ich werde nur eine sehr kostenlose Übersetzung aus dem Handbuch geben.
ID-Überprüfungsfunktion
Wird im seriellen und CAN-Austauschmodus verwendet. Die vom Programmierer übertragene Kennung wird mit der im Flash-Speicher aufgezeichneten Kennung verglichen. Wenn die Bezeichner nicht übereinstimmen, werden vom Programmierer gesendete Befehle nicht akzeptiert. Wenn jedoch 4 Bytes des Rücksetzvektors FFFFFFFFh sind, werden die Bezeichner nicht verglichen, sodass alle Befehle ausgeführt werden können. Der Bezeichner besteht aus 7 Bytes, die beginnend mit dem ersten Byte nacheinander an den Adressen 0FFFDFh, 0FFFE3h, 0FFFEBh, 0FFFEFh, 0FFFF3h, 0FFFF7h und 0FFFFBh gespeichert werden.Um auf das Programm zugreifen zu können, müssen Sie die geschätzten 7 Bytes kennen. Mit Blick auf die Zukunft stellte ich erneut eine Verbindung zu MK mit demselben „M16C Flash Starter“ her und stellte sicher, dass Kombinationen aus Nullen und FF nicht funktionierten und dieses Problem irgendwie gelöst werden musste. Hier tauchte sofort eine Idee mit einem Angriff über Kanäle von Drittanbietern auf. Ich gab bereits vor, ein Kopftuch in meinem Kopf zu sein, mit dem ich den Strom im Stromkreis messen kann, entschied jedoch, dass das Internet groß ist und die meisten Fahrräder bereits erfunden wurden. Nachdem ich einige Suchanfragen durchgeführt hatte, fand ich auf hackaday.io schnell das Projekt Serge 'q3k' Bazanski mit dem Titel „Reverse Engineering Toshiba R100 BIOS“. Und im Rahmen dieses Projekts löste der Autor im Wesentlichen genau das gleiche Problem: das Extrahieren der Firmware aus MK M306K9FCLR. Außerdem - zu diesem Zeitpunkt wurde die Aufgabe bereits erfolgreich von ihm gelöst. Einerseits war ich ein wenig verärgert - ein interessantes Rätsel wurde von mir nicht gelöst. Auf der anderen Seite verwandelte sich die Aufgabe von einer Suche nach Schwachstellen in eine Ausnutzung, die eine viel schnellere Lösung versprach.
Kurz gesagt, q3k begann die Studie nach genau der gleichen Logik mit einer Analyse des aktuellen Verbrauchs, in dieser Hinsicht unter viel günstigeren Bedingungen, weil Er hatte ChipWhisperer, ich habe dieses Ding immer noch nicht. Aber seitdem Seine erste Sonde, die den Verbrauchsstrom entfernte, erwies sich als unangemessen und er konnte nichts Nützliches vom Rauschen isolieren. Er beschloss, einen einfachen Angriff auf die Reaktionszeit zu versuchen. Tatsache ist, dass der Bootloader während der Ausführung des Befehls die BUSY-Ausgabe abruft, um den Host darüber zu informieren, dass er beschäftigt ist oder bereit ist, den nächsten Befehl auszuführen. Gemäß der Annahme von q3k könnte das Messen der Zeit von der Übertragung des letzten Bits des Bezeichners bis zum Entfernen des Besetztzeichens als Informationsquelle während der Aufzählung dienen. Bei der Überprüfung dieser Annahme durch Aufzählung des ersten Bytes des Schlüssels wurde tatsächlich nur in einem Fall eine Zeitabweichung festgestellt - wenn das erste Byte gleich FFh war. Zur Vereinfachung der Zeitmessung verlangsamte der Autor den MK sogar, indem er den Quarzresonator ausschaltete und eine 666-kHz-Rechteckwelle an den Takteingang anlegte, um den Messvorgang zu vereinfachen. Danach wurde die Kennung erfolgreich ausgewählt und die Software abgerufen.
Der erste Pfannkuchen - ein Rechen
Ha! Ich dachte ... Jetzt niete ich das Programm schnell an meinen STM32VLDiscovery c STM32F100 an Bord, der den Code sendet, die Reaktionszeit misst und die Messergebnisse im Terminal ausspuckt. Weil Das Steckbrett mit dem Zielcontroller war zuvor über den USB-UART-Adapter mit dem PC verbunden. Um nichts am Steckbrett zu ändern, arbeiten wir im asynchronen Modus.

Wenn beim Start des Bootloaders der Eingang CLK1 zu Boden gezogen wird, erkennt er, dass sie eine asynchrone Kommunikation von ihm wünschen. Deshalb habe ich es benutzt - der Hosenträger war bereits gelötet und ich habe nur die beiden Platinen mit Drähten verbunden: Discovery und das Steckbrett mit dem Ziel M306.
Hinweis zur Harmonisierung der Ebenen:
Weil Da M16 über TTL-Pegel an den Terminals verfügt und STM32 über LVTTL (vereinfacht, Einzelheiten siehe Datenblatt), ist eine Pegelanpassung erforderlich. Weil Dies ist kein Gerät, das wie eine bekannte Batterie funktionieren, funktionieren und funktionieren sollte, aber tatsächlich wird es einmal auf dem Tisch angeschlossen, dann habe ich mich nicht um Pegelübersetzer gekümmert: die 5-Volt-MK-verdauten Ausgangspegel von STM32 im Sinne von 3 Volt, die es als "1" wahrnimmt. werden die Ausgänge von M16 den 5V-toleranten STM32-Eingängen zugeführt, damit es sich nicht schlecht anfühlt, und wir vergessen nicht, das Bein, das RESET M16 zieht, in den Open-Drain-Modus zu versetzen. Ich habe es vergessen, und das sind + 2 Stunden bis zum Sparschwein der verlorenen Zeit.
Dieses Minimum reicht aus, um die Drüsen des anderen zu verstehen.Die Logik der angreifenden Software lautet wie folgt:
- Wir stellen eine Verbindung mit dem Controller her. Dazu müssen Sie warten, bis der Reset abgeschlossen ist, und dann 16 Nullzeichen mit einem Intervall von mehr als 20 ms übertragen. Dies dient dazu, den Algorithmus zur automatischen Ermittlung des Wechselkurses zu erarbeiten, weil Die Schnittstelle ist asynchron und MK weiß nichts über ihre Frequenz. Die Startgeschwindigkeit des Senders sollte 9600 Baud betragen, bei dieser Geschwindigkeit berechnet der Lader. Danach können Sie auf Wunsch einen anderen von fünf verfügbaren Wechselkursen im Bereich 9600-115200 anfordern (obwohl sich der Lader in meinem Fall geweigert hat, an 115200 zu arbeiten). Ich muss die Geschwindigkeit nicht ändern, daher habe ich nur die Bootloader-Version angefordert, um die Synchronisation zu steuern. Wir passieren FBh, der Lader antwortet mit einer Zeile wie „VER.1.01“.
- Wir senden den Befehl "entsperren", der die aktuelle Iteration des Schlüssels enthält, und messen die Zeit, bis das Besetztzeichen gelöscht wird.

Der Befehl besteht aus F5h-Code, drei Bytes der Adresse, an der der Bezeichnerbereich beginnt (in meinem Fall 0FFFDFh für den M16C-Kernel), der Länge (07h) und dem Bezeichner selbst.
- Wir messen die Zeit zwischen der Übertragung des letzten Bits der Kennung und dem Entfernen des Besetztzeichens.
- Wir erhöhen das zu sortierende Schlüsselbyte (KEY1 in der Anfangsphase) und kehren zu Schritt 2 zurück, bis wir alle 255 Werte des aktuellen Bytes sortiert haben.
- Wir setzen die Statistiken auf das Terminal zurück (oder wir führen die Analyse „an Bord“ durch).
Um mit dem Ziel-MK zu kommunizieren, habe ich USART in STM32 zum Messen der Zeit verwendet - einen Timer im Input Capture-Modus. Der Einfachheit halber habe ich nicht die Zeit zwischen dem letzten Bit des Schlüssels und dem Entfernen des Flags gemessen, sondern zwischen dem Beginn der Übertragung und dem Flag. Der Grund war, dass sich das letzte Bit ändern konnte und im asynchronen Modus nichts an die Erfassungseingabe angehängt werden konnte. Gleichzeitig ist UART Hardware und die Übertragungszeit ist grundsätzlich identisch und es sollten keine greifbaren Fehler auftreten.
Infolgedessen waren die Ergebnisse für alle Werte identisch. Völlig identisch. Die Taktfrequenz des Timers betrug 24 MHz, die Zeitauflösung beträgt 41,6 ns. Okay, ich habe versucht, das Ziel MK zu verlangsamen. Nichts hat sich geändert. Hier stellte sich in meinem Kopf die Frage: Was mache ich falsch, wie es Q3K getan hat? Nach dem Vergleich wurde der Unterschied festgestellt: Es wird eine synchrone Austauschschnittstelle (SPI) verwendet, und ich bin asynchron (UART). Und irgendwo hier machte ich auf den Moment aufmerksam, den ich am Anfang verpasst hatte. Selbst in Schaltplänen für synchrone und asynchrone Bootloader-Modi wird die Bereitschaftsausgabe unterschiedlich benannt:

In synchron ist es "BUSY", in asynchron ist es "Monitor". Wir sehen uns die Tabelle „Ausgabefunktionen im seriellen Standard-E / A-Modus“ an:
"Semyon Semenych ..."Die Kleinigkeit, die zuerst übersehen wurde, brachte den falschen Ort. Wenn dies im synchronen Modus genau das Bootloader-Besetzt-Flag ist, ist der asynchrone Modus (der im seriellen E / A-Modus 2) nur ein „Blinker“, um den Betrieb anzuzeigen. Vielleicht im Allgemeinen das Hardware-Signal der Bereitschaft des Transceivers und damit die erstaunliche Genauigkeit seiner Anhebung.
Im Allgemeinen löten wir den Widerstand am SCLK-Pin von Masse nach VCC, löten den Draht dort, haken alles an SPI und beginnen von vorne ...
Erfolg!

Im synchronen Modus ist fast alles gleich, es ist nur kein vorläufiges Verfahren zum Herstellen einer Verbindung erforderlich, die Synchronisation wird vereinfacht und die Zeiterfassung kann genauer durchgeführt werden. Wenn ich diesen Modus sofort wählen würde, würde ich Zeit sparen ... Ich habe die Zeit vom letzten Bit an nicht kompliziert und gemessen, sondern den Timer gestartet, bevor die Übertragung des letzten Bytes des Schlüssels gestartet wurde, d. H. Wir schalten den Timer ein und senden ihn an den KEY7-Sender (im obigen Screenshot sehen Sie vom Logikanalysator aus den Abstand zwischen den Cursorn. Dies ist das gemessene Zeitintervall).
Dies war mehr als genug für eine erfolgreiche Identifizierung. Hier ist die Aufzählung eines Bytes:

Auf der x-Achse haben wir die Anzahl der diskreten Zählungen, auf der y-Achse jeweils den übertragenen Schlüsselwert. Das Signal-Rausch-Verhältnis ist so, dass auch keine Filter erforderlich sind, wie in der Schule in einer Informatikstunde: Wir finden das Maximum im Array und gehen zur Auswahl des nächsten Bytes. Die ersten 6 Bytes werden einfach und schnell ausgewählt, etwas schwieriger mit den letzten: Da es nur dreistes Busting ist, das nicht funktioniert, müssen Sie das "Opfer" vor jedem Versuch zurücksetzen. Infolgedessen dauert jeder Versuch ungefähr 400 ms, und die Suche erfolgt im schlimmsten Fall im Bereich von eineinhalb Minuten. Aber das ist das Schlimmste. Nach jedem Versuch fordern wir einen Status an und hören auf, sobald wir vermuten. Zuerst ging ich im Allgemeinen nur schnell mit Stiften über die Kennung, fügte die Konsolenausgabe in Excel ein und zeichnete das Diagramm, umso mehr, als es eine einmalige Aufgabe war, aber für den Artikel entschied ich mich, eine automatische Iteration hinzuzufügen, um einer schönen Konsole willen ...

Wenn der Entwickler den Bootloader löschen würde (durch seinen eigenen ersetzt), wäre es natürlich nicht so einfach, herauszukommen, aber in der Automobilelektronik sind MKs oft überhaupt nicht geschlossen. Insbesondere in der Steuereinheit einer anderen Heizung, in der der V850 desselben Renesas installiert war, wurde alles durch Löten eines Kabelpaares und Kopieren der Firmware mit einem Standarddienstprogramm entschieden. Dies ist die gesamte Kryptowährungs-Engine in der ECU-Welt. Anscheinend mögen die Hersteller das Phänomen des Chip-Tunings und anderer Arten von Interferenzen nicht ... Obwohl dies wie ein Rennen aus Rüstungen und Granaten ist - die Drüsen sind steiler, teurer, aber es gibt keinen Gewinner ...
Referenzen:
- https://www.dataman.com/media/datasheet/Renesas/M16C6N5Group.pdf
- https://hackaday.io/project/723-reverse-engineering-toshiba-r100-bios/log/51302-ec-firmware-dumped
- https://q3k.org/slides-recon-2018.pdf