Dieses Vortrag dokumentiert das anspruchsvolle Reverse Engineering und die erfolgreiche Portierung des Spiels DOOM auf ein unbekanntes eingebettetes System – ein Playset mit Display, Audio-/Videoausgabe und Lichteffekten – für das keine offiziellen SDK-Informationen verfügbar waren. Der Vortragende, bekannt als Red F vom Hackspace Heilbronn, beschreibt den gesamten Prozess von der initialen Hardware-Analyse über das Dumpen von Firmware-Komponenten (SPI-Flash, SD-kompatibler NAND-Chip), die Überwindung von Watchdog-Mechanismen bis hin zur systematischen Kartierung der Peripherie und der Anpassung des Doom-Ports. Herausforderungen umfassten unvollständige Datenblätter, Probleme mit Debugging-Tools (Semi-Hosting) und Performance-Optimierungen für die WAD-Datei, die schlussendlich durch die Nutzung eines GBA-basierten Doom-Ports und externen Speichers gelöst wurden.
## Wichtigste Punkte & Zeitstempel
0:13 Projektübersicht: Red F stellt ein Projekt vor, bei dem DOOM auf ein unbekanntes Zielsystem portiert wurde, ohne SDK-Informationen für den verwendeten Chip zu besitzen.
0:25 Vortragender: Der Sprecher ist Red F, ein Hobbyist für Reverse Engineering und Hardware Hacking vom Hackspace Heilbronn (CC86 EV).
0:37 Zielhardware: Die Zielhardware ist ein Playset mit Display, Audio- und Videoausgabe sowie Lichteffekten, das vorinstallierte Videos abspielen kann.
1:39 Hardware-Analyse: Das System beinhaltet einen unbekannten Sonics IC, einen 8-Pin SPI Flash und einen SD-kompatiblen Nand Chip, der wie eine eingelötete SD-Karte fungiert.
2:03 SDK-Beschaffung: Das offizielle SDK war hinter einer Login- und Approval-Wall verborgen, aber ein SDK für einen ähnlichen, kleineren Chip konnte heruntergeladen werden und enthielt nützliche Informationen.
2:27 Flash-Dumping: Das SPI Flash konnte direkt ausgelesen werden. Das Dumpen des SD Nand war aufwendiger und erforderte das Anlöten von Widerständen; ein Pico wurde als SDPI verwendet, um das 0,5 GB große Flash in ca. 3 Stunden auszulesen.
3:08 Firmware-Analyse-Herausforderungen: Die Firmware enthielt Verweise auf Boot-ROM-Adressen, die nicht im Flash enthalten waren, und der SWD-Port reagierte zunächst nicht. Das Datenblatt war unvollständig und wies viele als „reserviert“ gekennzeichnete Bereiche auf, die sich später als Peripherie herausstellten.
3:51 Debugging-Ansatz:printf-Strings in den Firmware-Bibliotheksfunktionen gaben erste Anhaltspunkte. Spätere Analyse zeigte, dass die „reservierten“ Adressen tatsächlich beschrieben wurden.
4:33 Watchdog-Umgehung: Ein externer Watchdog-Chip wurde identifiziert, der nach 3 Sekunden einen Reset auslöste, wenn ein bestimmter Pin nicht regelmäßig getoggelt wurde. Dieser Pin musste direkt am Chip angelötet werden.
5:35 SD-Sperre & Watchdog-Kontrolle: Eine SD-Sperre in der Firmware wurde durch NOPs umgangen. Der externe Watchdog konnte durch externe Manipulation (Pull-Up/Pull-Down statt Hard-Set) kontrolliert werden, um längere Debugging-Sitzungen zu ermöglichen.
6:06 Semi-Hosting-Probleme: Das Semi-Hosting-Feature des Keil MDK Compilers verursachte Probleme, da es Ausnahmen auslöste, die das System zum Absturz brachten und daher entfernt werden mussten.
6:35 Peripherie-Kartierung: Nach dem Debugging-Setup wurde die entscheidende Peripherie schrittweise kartiert, beginnend mit der Display-Initialisierung.
6:57 Display-Initialisierung: Die Display-Initialisierung im SDK des „kleinen Bruders“ war nicht deckungsgleich. Ein fehlendes Bit in der extrahierten Original-Firmware-Initialisierung führte zu einem auf dem Kopf stehenden und gespiegelten Bild.
7:30 SD-Karten-Initialisierung: Die SD-Karte, auf der die DOOM-WAD-Datei gespeichert werden sollte, benötigte eine präzise Initialisierung. Ein einziger Byte-Fehler in einem Initialisierungsbefehl verhinderte die Funktion.
7:47 SD-Karten-Performance: Es wurde festgestellt, dass SD-Karten über 2 GB bei SPI/512-Byte-Zugriffen langsamer waren als solche bis 2 GB, was zu anfänglicher Verwirrung führte.
8:20 Doom-Portierung: Ein generischer DOOM-Port hatte zu hohe I/O-Anforderungen und laggte. Der Chip verfügte über 8 MB externen RAM, der für das Laden der WAD-Datei genutzt wurde.
8:54 GBA Doom Port: Ein Game Boy Advance (GBA) Doom Port wurde als Basis gewählt, da dieser darauf ausgelegt ist, vorkonvertierte WAD-Dateien direkt aus dem ROM zu lesen, was bei begrenztem RAM des Zielsystems ideal war.
9:10 Compiler- und Logikfehler: Compiler-Probleme und ein Logikfehler (irrtümlicher dreidimensionaler Array-Zugriff statt zweidimensional) führten zu massiven Performance-Einbrüchen („Seconds per frame“ anstelle von „Frames per second“).
12:10 Compiler-Tooling: Für das unbekannte ARM-Chip-System wurden vorhandene ARM-Compiler, das gefundene SDK eines ähnlichen Chips, extensive Datenblatt-Lektüre und Ghidra für die Disassemblierung genutzt.
13:07 Gerätebeschaffung: Das Gerät wurde regulär gekauft, wobei die Absicht zum Reverse Engineering und Hardware Hacking eine Gewohnheit des Vortragenden war.
14:02 GBA Port-Wahlgrund: Die Wahl des GBA Doom Ports basierte auf der Eigenschaft, dass dieser WAD-Dateien vorkonvertiert direkt aus dem ROM lädt und so auf weniger schnellen RAM optimiert ist, was für das Zielsystem vorteilhaft war.
## Glossar
SDK (Software Development Kit): Eine Sammlung von Tools, Bibliotheken, Dokumentationen und Codebeispielen, die Softwareentwicklern zur Verfügung gestellt werden, um Anwendungen für eine bestimmte Plattform oder Hardware zu erstellen.
Reverse Engineering: Der Prozess, die Funktionsweise, Struktur oder Zusammensetzung eines Hardware- oder Softwareprodukts durch Analyse seiner physischen oder digitalen Komponenten zu verstehen, oft ohne Originaldokumentation.
Hardware Hacking: Das Modifizieren oder Wiederverwenden von elektronischer Hardware für Zwecke, für die sie ursprünglich nicht vorgesehen war.
SPI Flash: Ein Typ von nichtflüchtigem Speicher (Flash-Speicher), der über die serielle Peripherieschnittstelle (SPI) kommuniziert und zum Speichern von Firmware oder Daten verwendet wird.
Nand Chip (NAND-Flash-Speicher): Eine Art von nichtflüchtigem Flash-Speicher, der häufig in USB-Sticks, SD-Karten und Solid-State-Laufwerken (SSDs) verwendet wird, um große Datenmengen zu speichern.
SD-kompatibler Nand Chip: Ein NAND-Flash-Speicherchip, der so konfiguriert ist, dass er über eine Schnittstelle angesprochen werden kann, die der einer SD-Karte ähnelt oder direkt SD-Karten-Protokolle unterstützt.
Pico (Raspberry Pi Pico): Ein kostengünstiger Mikrocontroller-Board, basierend auf dem RP2040-Chip von Raspberry Pi, oft im Hardware-Hacking für seine flexiblen I/O-Funktionen verwendet.
SDPI: Eine Abkürzung für "Serial Data Peripheral Interface", hier spezifisch im Kontext des Pico als Werkzeug zum Auslesen von SD-basiertem Speicher über eine serielle Schnittstelle.
Boot-ROM: Ein kleiner, schreibgeschützter Speicherbereich (ROM) auf einem Mikrocontroller oder Prozessor, der den initialen Code (Bootloader) enthält, der beim Start des Systems ausgeführt wird, um die Firmware zu laden.
SWD (Serial Wire Debug): Eine 2-Pin-Debug-Schnittstelle, die von ARM-Prozessoren verwendet wird, um Debugger mit dem Chip zu verbinden und Code auszuführen, anzuhalten oder Speicher auszulesen.
Watchdog-Chip (Watchdog-Timer): Ein Hardware-Timer, der dazu dient, ein eingebettetes System automatisch zurückzusetzen, wenn die Software aufgrund eines Fehlers (z.B. Endlosschleife) nicht mehr wie erwartet funktioniert. Er erwartet regelmäßige "Heartbeat"-Signale von der Software.
NOP (No Operation): Ein Maschinenbefehl oder eine Anweisung in der Programmierung, die keine Aktion ausführt, außer die Programmausführung zur nächsten Anweisung fortzusetzen. Wird oft im Reverse Engineering verwendet, um Code-Teile zu deaktivieren.
Pull-Up/Pull-Down: Widerstandsschaltungen in der Elektronik, die sicherstellen, dass ein Signaleingang einen definierten Zustand (HIGH oder LOW) hat, wenn kein aktives Signal anliegt. Wird hier verwendet, um den Zustand eines Watchdog-Pins extern zu steuern.
Keil MDK (Microcontroller Development Kit): Eine integrierte Entwicklungsumgebung (IDE) und Toolchain für ARM-basierte Mikrocontroller.
Semi-Hosting: Ein Mechanismus in Debuggern und Entwicklungsumgebungen für eingebettete Systeme, der es der Zielsoftware ermöglicht, I/O-Operationen (z.B. printf zum Konsolen-Output) auf dem Host-Computer des Debuggers auszuführen.
Peripherie: Komponenten eines Mikrocontrollers, die spezifische Funktionen ausführen, wie Timer, UARTs, SPI-Controller, GPIOs, ADC/DAC und Display-Controller.
Display-Initialisierung: Der Prozess des Sendens einer Sequenz von Befehlen an einen Display-Controller, um ihn in einen funktionsfähigen Zustand zu versetzen (z.B. Auflösung, Farbmodus, Kontrast).
WAD-Datei: Ein proprietäres Dateiformat, das in den DOOM-Spielen von id Software verwendet wird, um Spielressourcen wie Karten, Grafiken, Sounds und Texturen zu speichern.
Ghidra: Ein Software-Reverse-Engineering-Framework der NSA, das Funktionen für Disassemblierung, Dekompilierung und Analyse von Binärdateien bietet.
ARM-Chip: Ein Mikroprozessor, der auf der ARM-Architektur basiert (einer weit verbreiteten Familie von Befehlssatzarchitekturen für Computerprozessoren, besonders in eingebetteten Systemen und Mobilgeräten).
Frames per Second (FPS): Die Anzahl der Einzelbilder, die ein Display oder eine Grafikkarte pro Sekunde anzeigen kann. Ein Maß für die Flüssigkeit der Animation.
Seconds per Frame (SPF): Der Kehrwert von FPS, also die Zeit, die benötigt wird, um ein einzelnes Bild zu rendern. Ein hoher SPF-Wert deutet auf eine sehr schlechte Leistung hin.