Nashorn in der Katze - Führen Sie die Firmware im Kopycat-Emulator aus


Im Rahmen des Treffens 0x0A DC7831 DEF CON Nizhny Novgorod am 16. Februar präsentierten wir einen Bericht über die Grundprinzipien der Binärcode-Emulation und unsere eigene Entwicklung - einen Emulator der Hardwareplattformen Kopycat .


In diesem Artikel beschreiben wir den Start der Geräte-Firmware im Emulator, demonstrieren die Interaktion mit dem Debugger und führen eine kleine dynamische Analyse der Firmware durch.


Hintergrund


Vor langer Zeit in einer weit entfernten Galaxie


Vor ein paar Jahren musste in unserem Labor die Firmware des Geräts untersucht werden. Die Firmware wurde komprimiert und vom Bootloader entpackt. Er tat dies auf sehr verwirrte Weise und verschob mehrmals Daten im Speicher. Ja, und die Firmware selbst interagierte dann aktiv mit den Peripheriegeräten. Und das alles auf dem MIPS-Kern.


Aus objektiven Gründen passten die vorhandenen Emulatoren nicht zu uns, aber ich wollte den Code trotzdem ausführen. Dann haben wir uns entschlossen, einen eigenen Emulator zu erstellen, der ein Minimum darstellt und das Entpacken der Hauptfirmware ermöglicht. Wir haben es versucht - es stellte sich heraus. Wir dachten, was ist, wenn wir Peripheriegeräte hinzufügen, um auch die Hauptfirmware auszuführen. Es war nicht sehr schmerzhaft - und es hat auch geklappt. Wir überlegten noch einmal und beschlossen, einen vollwertigen Emulator zu entwickeln.


Das Ergebnis war ein Emulator der Computersysteme Kopycat .



Warum Kopycat?

Es gibt ein Wortspiel.


  1. Nachahmer (Englisch, n. [ˈkɒpɪkæt]) - Nachahmer, Nachahmer
  2. Katze (Englisch, n. [ˈkæt]) - eine Katze, eine Katze - ein Lieblingstier eines der Schöpfer des Projekts
  3. Buchstabe "K" - aus der Programmiersprache Kotlin

Kopycat


Bei der Erstellung des Emulators wurden absolut spezifische Ziele festgelegt:


  • die Fähigkeit, schnell eine neue Peripherie, ein neues Modul und einen neuen Prozessorkern zu erstellen;
  • die Fähigkeit, ein virtuelles Gerät aus verschiedenen Modulen zusammenzusetzen;
  • die Fähigkeit, beliebige Binärdaten (Firmware) in den Speicher des virtuellen Geräts zu laden;
  • die Fähigkeit, mit Schnappschüssen zu arbeiten (Schnappschüsse des Systemzustands);
  • die Fähigkeit, über den eingebauten Debugger mit dem Emulator zu interagieren;
  • schöne moderne Sprache zu entwickeln.

Aus diesem Grund wurde Kotlin für die Implementierung, die Busarchitektur (wenn die Module über virtuelle Datenbusse miteinander kommunizieren), JSON als Gerätebeschreibungsformat und GDB RSP als Protokoll für die Interaktion mit dem Debugger ausgewählt.


Die Entwicklung dauert etwas mehr als zwei Jahre und wird aktiv fortgesetzt. Während dieser Zeit wurden MIPS-, x86-, V850ES-, ARM- und PowerPC-Prozessorkerne implementiert.


Das Projekt wächst und es ist Zeit, es der Öffentlichkeit vorzustellen. Wir werden das Projekt später detailliert beschreiben, aber jetzt konzentrieren wir uns auf die Verwendung von Kopycat.


Für die Ungeduldigsten - die Promo-Version des Emulators kann hier heruntergeladen werden .


Nashorn im Emulator


Erinnern Sie sich daran, dass früher für die SMARTRHINO-2018-Konferenz ein Testgerät "Rhinoceros" für die Ausbildung in Reverse Engineering-Fähigkeiten entwickelt wurde. Der Prozess der statischen Firmware-Analyse wurde in diesem Artikel beschrieben .


Versuchen wir nun, "Lautsprecher" hinzuzufügen und die Firmware im Emulator auszuführen.


Wir werden brauchen:
1) Java 1.8
2) Python und das Jep- Modul zur Verwendung von Python im Emulator. Die WHL-Assembly des Jep-Moduls für Windows kann hier heruntergeladen werden .


Für Windows:
1) com0com
2) PuTTY


Für Linux:
1) socat


Sie können Eclipse, IDA Pro oder radare2 als GDB-Client verwenden.


Wie funktioniert es


Um Firmware im Emulator auszuführen, müssen Sie ein virtuelles Gerät "zusammenbauen", das ein Analogon eines realen Geräts ist.


Das reale Gerät ("Nashorn") kann in einem Blockdiagramm dargestellt werden:


Echte Geräteschaltung

Der Emulator ist modular aufgebaut und das endgültige virtuelle Gerät kann in einer JSON-Datei beschrieben werden.


JSON in 105 Zeilen
{ "top": true, // Plugin name should be the same as file name (or full path from library start) "plugin": "rhino", // Directory where plugin places "library": "user", // Plugin parameters (constructor parameters if jar-plugin version) "params": [ { "name": "tty_dbg", "type": "String"}, { "name": "tty_bt", "type": "String"}, { "name": "firmware", "type": "String", "default": "NUL"} ], // Plugin outer ports "ports": [ ], // Plugin internal buses "buses": [ { "name": "mem", "size": "BUS30" }, { "name": "nand", "size": "4" }, { "name": "gpio", "size": "BUS32" } ], // Plugin internal components "modules": [ { "name": "u1_stm32", "plugin": "STM32F042", "library": "mcu", "params": { "firmware:String": "params.firmware" } }, { "name": "usart_debug", "plugin": "UartSerialTerminal", "library": "terminals", "params": { "tty": "params.tty_dbg" } }, { "name": "term_bt", "plugin": "UartSerialTerminal", "library": "terminals", "params": { "tty": "params.tty_bt" } }, { "name": "bluetooth", "plugin": "BT", "library": "mcu" }, { "name": "led_0", "plugin": "LED", "library": "mcu" }, { "name": "led_1", "plugin": "LED", "library": "mcu" }, { "name": "led_2", "plugin": "LED", "library": "mcu" }, { "name": "led_3", "plugin": "LED", "library": "mcu" }, { "name": "led_4", "plugin": "LED", "library": "mcu" }, { "name": "led_5", "plugin": "LED", "library": "mcu" }, { "name": "led_6", "plugin": "LED", "library": "mcu" }, { "name": "led_7", "plugin": "LED", "library": "mcu" }, { "name": "led_8", "plugin": "LED", "library": "mcu" }, { "name": "led_9", "plugin": "LED", "library": "mcu" }, { "name": "led_10", "plugin": "LED", "library": "mcu" }, { "name": "led_11", "plugin": "LED", "library": "mcu" }, { "name": "led_12", "plugin": "LED", "library": "mcu" }, { "name": "led_13", "plugin": "LED", "library": "mcu" }, { "name": "led_14", "plugin": "LED", "library": "mcu" }, { "name": "led_15", "plugin": "LED", "library": "mcu" } ], // Plugin connection between components "connections": [ [ "u1_stm32.ports.usart1_m", "usart_debug.ports.term_s"], [ "u1_stm32.ports.usart1_s", "usart_debug.ports.term_m"], [ "u1_stm32.ports.usart2_m", "bluetooth.ports.usart_m"], [ "u1_stm32.ports.usart2_s", "bluetooth.ports.usart_s"], [ "bluetooth.ports.bt_s", "term_bt.ports.term_m"], [ "bluetooth.ports.bt_m", "term_bt.ports.term_s"], [ "led_0.ports.pin", "u1_stm32.buses.pin_output_a", "0x00"], [ "led_1.ports.pin", "u1_stm32.buses.pin_output_a", "0x01"], [ "led_2.ports.pin", "u1_stm32.buses.pin_output_a", "0x02"], [ "led_3.ports.pin", "u1_stm32.buses.pin_output_a", "0x03"], [ "led_4.ports.pin", "u1_stm32.buses.pin_output_a", "0x04"], [ "led_5.ports.pin", "u1_stm32.buses.pin_output_a", "0x05"], [ "led_6.ports.pin", "u1_stm32.buses.pin_output_a", "0x06"], [ "led_7.ports.pin", "u1_stm32.buses.pin_output_a", "0x07"], [ "led_8.ports.pin", "u1_stm32.buses.pin_output_a", "0x08"], [ "led_9.ports.pin", "u1_stm32.buses.pin_output_a", "0x09"], [ "led_10.ports.pin", "u1_stm32.buses.pin_output_a", "0x0A"], [ "led_11.ports.pin", "u1_stm32.buses.pin_output_a", "0x0B"], [ "led_12.ports.pin", "u1_stm32.buses.pin_output_a", "0x0C"], [ "led_13.ports.pin", "u1_stm32.buses.pin_output_a", "0x0D"], [ "led_14.ports.pin", "u1_stm32.buses.pin_output_a", "0x0E"], [ "led_15.ports.pin", "u1_stm32.buses.pin_output_a", "0x0F"] ] } 

Beachten Sie den Firmware- Parameter im Abschnitt params - dies ist der Name der Datei, die als Firmware auf das virtuelle Gerät heruntergeladen werden kann.


Ein virtuelles Gerät und seine Interaktion mit dem Hauptbetriebssystem können wie folgt dargestellt werden:


Schaltungsemuliertes Gerät

Die aktuelle Testinstanz des Emulators beinhaltet die Interaktion mit den COM-Ports des Hauptbetriebssystems (Debuggen von UART und UART für das Bluetooth-Modul). Dies können reale Ports sein, an die Geräte angeschlossen sind, oder virtuelle COM-Ports ( com0com / socat ist genau dafür ) .


Derzeit gibt es zwei Möglichkeiten, von außen mit dem Emulator zu interagieren:


  • GDB RSP-Protokoll (unterstützt dieses Protokoll, Tools - Eclipse / IDA / radare2);
  • interne Befehlszeile des Emulators (Argparse oder Python).

Virtuelle COM-Ports


Um über das Terminal mit dem UART des virtuellen Geräts auf dem lokalen Computer zu interagieren, müssen Sie mehrere verbundene virtuelle COM-Ports erstellen. In unserem Fall verwendet ein Port einen Emulator und der zweite ein Terminalprogramm (PuTTY oder Bildschirm):


Virtuelle COM-Ports

Mit com0com


Virtuelle COM-Ports werden mit dem Setup-Dienstprogramm aus dem com0com-Kit konfiguriert (die Konsolenversion lautet C: \ Programme (x86) \ com0com \ setup.exe oder die GUI-Version lautet C: \ Programme (x86) \ com0com \ setupg.exe ). ::


Konfigurieren Sie virtuelle COM-Ports

Aktivieren Sie die Kontrollkästchen zum Aktivieren des Pufferüberlaufs für alle erstellten virtuellen Ports. Andernfalls wartet der Emulator auf eine Antwort vom COM-Port.


Mit socat


Auf UNIX-Systemen werden virtuelle COM-Ports vom Emulator automatisch mit dem Dienstprogramm socat erstellt. Dazu reicht es aus, beim Starten des Emulators das Präfix socat: im socat: anzugeben.


Interne Befehlszeilenschnittstelle (Argparse oder Python)


Da Kopycat eine Konsolenanwendung ist, bietet der Emulator zwei Optionen für die Befehlszeilenschnittstelle, um mit ihren Objekten und Variablen zu interagieren: Argparse und Python.


Argparse ist die in Kopycat integrierte CLI, die immer für alle verfügbar ist.


Eine alternative CLI ist der Python-Interpreter. Um es zu verwenden, müssen Sie das Jep Python-Modul installieren und den Emulator für die Arbeit mit Python konfigurieren (der auf dem Hauptsystem des Benutzers installierte Python-Interpreter wird verwendet).


Installieren Sie das Python Jep-Modul


Unter Linux kann Jep über pip installiert werden:


 pip install jep 

Um Jep unter Windows zu installieren, müssen Sie zuerst das Windows SDK und das entsprechende Microsoft Visual Studio installieren. Wir haben Ihre Aufgabe ein wenig vereinfacht und WHL- JEP- Assemblys für die aktuellen Versionen von Python für Windows erstellt, damit das Modul aus einer Datei installiert werden kann:


 pip install jep-3.8.2-cp27-cp27m-win_amd64.whl 

Um die Installation von Jep zu überprüfen, müssen Sie die folgende Befehlszeile ausführen:


 python -c "import jep" 

Als Antwort sollte eine Nachricht empfangen werden:


 ImportError: Jep is not supported in standalone Python, it must be embedded in Java. 

Fügen Sie in der Emulator-Batchdatei für Ihr System ( kopycat.bat für Windows, kopycat für Linux) den zusätzlichen Parameter Djava.library.path zur Liste der Parameter DEFAULT_JVM_OPTS - er sollte den Pfad zum installierten Jep-Modul enthalten.


Daher sollten Sie für Windows eine Zeile wie die folgende erhalten:


 set DEFAULT_JVM_OPTS="-XX:MaxMetaspaceSize=256m" "-XX:+UseParallelGC" "-XX:SurvivorRatio=6" "-XX:-UseGCOverheadLimit" "-Djava.library.path=C:/Python27/Lib/site-packages/jep" 

Kopycat-Start


Der Emulator ist eine Konsolen-JVM-Anwendung. Der Start erfolgt über das Befehlszeilenskript des Betriebssystems (sh / cmd).


Befehl zum Ausführen unter Windows:


 bin\kopycat -g 23946 -n rhino -l user -y library -p firmware=firmware\rhino_pass.bin,tty_dbg=COM26,tty_bt=COM28 

Der Befehl zum Ausführen unter Linux mit dem Dienstprogramm socat:


 ./bin/kopycat -g 23946 -n rhino -l user -y library -p firmware=./firmware/rhino_pass.bin,tty_dbg=socat:./COM26,tty_bt=socat:./COM28 

  • -g 23646 - TCP-Port, der für den Zugriff auf den GDB-Server geöffnet ist;
  • -n rhino - der Name des Hauptmoduls des Systems (Gerätebaugruppe);
  • -l user - der Name der Bibliothek, die nach dem Hauptmodul gesucht werden soll;
  • -y library - der Pfad zum Suchen nach Modulen, die im Gerät enthalten sind;
  • firmware\rhino_pass.bin - Pfad zur Firmware-Datei;
  • COM26 und COM28 sind virtuelle COM-Ports.

Das Ergebnis ist die Argparse > Python > (oder Argparse > ):


 18:07:59 INFO [eFactoryBuilder.create ]: Module top successfully created as top 18:07:59 INFO [ Module.initializeAndRes]: Setup core to top.u1_stm32.cortexm0.arm for top 18:07:59 INFO [ Module.initializeAndRes]: Setup debugger to top.u1_stm32.dbg for top 18:07:59 WARN [ Module.initializeAndRes]: Tracer wasn't found in top... 18:07:59 INFO [ Module.initializeAndRes]: Initializing ports and buses... 18:07:59 WARN [ Module.initializePortsA]: ATTENTION: Some ports has warning use printModulesPortsWarnings to see it... 18:07:59 FINE [ ARMv6CPU.reset ]: Set entry point address to 08006A75 18:07:59 INFO [ Module.initializeAndRes]: Module top is successfully initialized and reset as a top cell! 18:07:59 INFO [ Kopycat.open ]: Starting virtualization of board top[rhino] with arm[ARMv6Core] 18:07:59 INFO [ GDBServer.debuggerModule ]: Set new debugger module top.u1_stm32.dbg for GDB_SERVER(port=23946,alive=true) Python > 

Interaktion mit IDA Pro


Um das Testen zu vereinfachen, verwenden wir die Rhino-Firmware als ELF-Datei (die Metainformationen werden dort gespeichert) als Quelldatei für die Analyse in IDA.


Sie können die Hauptfirmware auch ohne Metainformationen verwenden.


Gehen Sie nach dem Starten von Kopycat in IDA Pro im Menü Debugger zum Element " Debugger wechseln ... " und wählen Sie " Remote GDB-Debugger ". Konfigurieren Sie als Nächstes die Verbindung: Debugger- Menü - Prozessoptionen ...


Stellen Sie die Werte ein:


  • Anwendung - jeder Wert
  • Hostname: 127.0.0.1 (oder die IP-Adresse des Remotecomputers, auf dem Kopycat ausgeführt wird)
  • Hafen: 23946

Konfigurieren der Verbindung zum GDB-Server

Jetzt ist die Debug-Starttaste verfügbar (Taste F9):



Drücken Sie darauf - es wird eine Verbindung zum Debugger-Modul im Emulator hergestellt. IDA wechselt in den Debug-Modus, zusätzliche Fenster werden verfügbar: Informationen zu Registern, zum Stapel.


Jetzt können wir alle Standardfunktionen der Arbeit mit dem Debugger verwenden:


  • schrittweise Ausführung von Anweisungen ( Schritt in und Schritt über - Tasten F7 bzw. F8);
  • Ausführung starten und anhalten;
  • Erstellen von Haltepunkten für Code und Daten (Taste F2).

Das Herstellen einer Verbindung zum Debugger bedeutet nicht, dass der Firmware-Code gestartet wird. Die aktuelle Position für die Ausführung muss die Adresse 0x08006A74 - der Beginn der Funktion Reset_Handler . Wenn Sie in der folgenden Liste nach unten scrollen, können Sie den Aufruf der Hauptfunktion sehen. Sie können den Cursor auf diese Zeile setzen (Adresse 0x08006ABE ) und die Operation Bis Cursor ausführen (Taste F4) ausführen.


Bild


Als nächstes können Sie F7 drücken, um die Hauptfunktion aufzurufen.


Wenn Sie den Befehl Prozess fortsetzen (Taste F9) ausführen, wird das Fenster "Bitte warten" mit einer einzigen Schaltfläche " Anhalten " angezeigt :



Wenn Suspend gedrückt wird, wird die Ausführung des Firmware-Codes angehalten und kann an derselben Adresse im Code fortgesetzt werden, an der er unterbrochen wurde.


Wenn Sie den Code weiterhin ausführen, werden in den an die virtuellen COM-Ports angeschlossenen Terminals die folgenden Zeilen angezeigt:


Bild


Bild


Das Vorhandensein der Zeichenfolge "Statusumgehung" zeigt an, dass das virtuelle Bluetooth-Modul in den Modus zum Empfangen von Daten vom COM-Port des Benutzers gewechselt ist.


Jetzt können Sie im Bluetooth-Terminal (in der Abbildung - COM29) Befehle gemäß dem Rhino-Protokoll eingeben. Beispielsweise kehrt die Zeichenfolge "mur-mur" zum Befehl "MEOW" im Bluetooth-Terminal zurück:




Emuliere mich nicht ganz


Beim Erstellen eines Emulators können Sie den Detaillierungsgrad / die Emulation eines Geräts auswählen. So kann beispielsweise das Bluetooth-Modul auf verschiedene Arten emuliert werden:


  • vollständig emuliertes Gerät mit einem vollständigen Befehlssatz;
  • AT-Befehle werden emuliert und der Datenstrom wird vom COM-Port des Hauptsystems empfangen.
  • Das virtuelle Gerät bietet eine vollständige Datenumleitung zu einem realen Gerät.
  • als einfacher Stub, der immer "OK" zurückgibt.

In der aktuellen Version des Emulators wird der zweite Ansatz verwendet: Das virtuelle Bluetooth-Modul führt die Konfiguration durch und wechselt anschließend vom COM-Port des Hauptsystems zum UART-Port des Emulators in den Proxy-Modus für Daten.



Erwägen Sie die Möglichkeit einer einfachen Instrumentierung des Codes, wenn ein Teil der Peripherie nicht implementiert ist. Wenn beispielsweise kein Timer erstellt wird, der die Datenübertragung in DMA steuert (die Überprüfung erfolgt in der Funktion ws2812b_wait unter 0x08006840 ), wartet die Firmware immer auf das 0x200004C4 unter 0x200004C4 , um die DMA-Datenleitung zurückzusetzen:



Wir können diese Situation umgehen, indem wir das Besetztzeichen unmittelbar nach dem Setzen manuell zurücksetzen. In IDA Pro können Sie eine Python-Funktion erstellen und als Haltepunkt aufrufen. Der Haltepunkt muss im Code festgelegt werden, nachdem der Wert 1 in das Besetzt- Flag geschrieben wurde.


Haltepunkt-Handler


Erstellen Sie zunächst eine Python-Funktion in der IDA. Menü Datei - Skriptbefehl ...


Fügen Sie der Liste links ein neues Snippet hinzu, geben Sie ihm einen Namen (z. B. BPT ).
In das Textfeld rechts geben wir den Funktionscode ein:


 def skip_dma(): print "Skipping wait ws2812..." value = Byte(0x200004C4) if value == 1: PatchDbgByte(0x200004C4, 0) return False 


Klicken Sie danach auf Ausführen und schließen Sie das Skriptfenster.


Gehen wir nun zum Code unter 0x0800688A , setzen den Haltepunkt (F2-Taste), bearbeiten ihn ( Haltepunkt bearbeiten ... Kontextmenü), vergessen Sie nicht, den 0x0800688A - Python:




Wenn der aktuelle Wert des Besetzt- Flags 1 ist, sollte die Funktion skip_dma in der Skriptzeile ausgeführt werden:



Wenn Sie die Firmware zur Ausführung ausführen, wird der Code für den Haltepunkt-Handler in der IDA im Ausgabefenster in der Zeile Skipping wait ws2812... Jetzt wartet die Firmware nicht mehr darauf, das Besetztzeichen zurückzusetzen .


Emulator-Interaktion


Es ist unwahrscheinlich, dass eine Emulation zum Zwecke der Emulation Freude und Vergnügen hervorruft. Es ist viel interessanter, wenn der Emulator dem Forscher hilft, die Daten im Speicher zu sehen oder die Interaktion von Flüssen herzustellen.


Wir zeigen, wie Sie die Interaktion von RTOS-Aufgaben dynamisch herstellen können. Unterbrechen Sie zunächst die Codeausführung, wenn sie ausgeführt wird. Wenn Sie im Befehlsverarbeitungszweig "LED" (Adresse 0x080057B8 ) zur Funktion bluetooth_task_entry wechseln, können Sie sehen, was zuerst erstellt wird, und anschließend wird eine Nachricht an die Systemwarteschlange ledControlQueueHandle gesendet.


Bild


Sie sollten einen Haltepunkt festlegen, um auf die Variable 0x20000624 0x20000624 0x20000624 und den Code weiter auszuführen:



Infolgedessen stoppt es zuerst bei der Adresse 0x080057CA bevor die Funktion osMailAlloc aufgerufen wird, dann bei 0x08005806 bevor die Funktion osMailPut aufgerufen wird, und nach einer Weile bei der Adresse 0x08005BD4 (vor dem Aufrufen der Funktion osMailGet ), die zur Funktion leds_task_entry gehört (LED-Aufgabe), d. H. Es gab einen Taskwechsel, und jetzt hat die Steuerung eine LED-Task erhalten.


Bild


Auf so einfache Weise können Sie festlegen, wie RTOS-Aufgaben miteinander interagieren.


In der Realität kann die Interaktion von Aufgaben natürlich komplizierter sein, aber die Verwendung eines Emulators zur Verfolgung dieser Interaktion wird weniger schwierig.


Hier können Sie ein kurzes Video über den Start des Emulators und die Interaktion mit IDA Pro ansehen.


Starten Sie mit Radare2


Sie können ein universelles Tool wie Radare2 nicht ignorieren.


Um über r2 eine Verbindung zum Emulator herzustellen, sieht der Befehl folgendermaßen aus:


 radare2 -A -a arm -b 16 -d gdb://localhost:23946 rhino_fw42k6.elf 

Jetzt sind Start ( dc ) und Pausenausführung (Strg + C) verfügbar.


Leider gibt es derzeit in r2 Probleme beim Arbeiten mit einem Hardware-GDB-Server und Speicher-Markup. Aus diesem Grund funktionieren Haltepunkte und Schritte (der Befehl ds ) nicht. Wir hoffen, dass dies in naher Zukunft behoben wird.


Starten Sie mit Eclipse


Eine der Optionen für die Verwendung des Emulators ist das Debuggen der Firmware des in der Entwicklung befindlichen Geräts. Aus Gründen der Übersichtlichkeit verwenden wir auch die Rhino-Firmware. Sie können die Firmware-Quellen hier herunterladen.


Wir werden die Eclipse aus der System Workbench für STM32- Suite als IDE verwenden.


Damit die direkt in Eclipse kompilierte Firmware in den Emulator geladen werden kann, müssen Sie dem Emulator- firmware=null Parameter firmware=null hinzufügen:


 bin\kopycat -g 23946 -n rhino -l user -y library -p firmware=null,tty_dbg=COM26,tty_bt=COM28 

Debug-Konfiguration


Wählen Sie in Eclipse das Menü Ausführen - Debug-Konfigurationen ... aus. In dem sich öffnenden Fenster im Abschnitt GDB-Hardware-Debugging müssen Sie eine neue Konfiguration hinzufügen. Geben Sie anschließend auf der Registerkarte "Main" das aktuelle Projekt und die Anwendung zum Debuggen an:



Auf der Registerkarte Debugger müssen Sie den Befehl GDB angeben:
${openstm32_compiler_path}\arm-none-eabi-gdb


Geben Sie außerdem die Parameter für die Verbindung zum GDB-Server (Host und Port) ein:



Die folgenden Parameter müssen auf der Registerkarte "Start" angegeben werden:


  • Aktivieren Sie das Kontrollkästchen Image laden (damit das zusammengestellte Firmware-Image in den Emulator geladen wird).
  • Aktivieren Sie das Häkchen Symbole laden.
  • set $pc = *0x08000004 einen set $pc = *0x08000004 hinzu: set $pc = *0x08000004 (Setzen Sie den Wert aus dem Speicher auf die Adresse 0x08000004 im PC-Register - die Adresse des 0x08000004 wird dort gespeichert).

Beachten Sie, dass Sie, wenn Sie die Firmware-Datei nicht von Eclipse herunterladen möchten, die Parameter " Image laden" und " Befehle ausführen" nicht angeben müssen.



Nachdem Sie auf Debug geklickt haben, können Sie im Debug-Modus arbeiten:


  • Schritt-für-Schritt-Codeausführung
  • Interaktion mit Haltepunkten

Hinweis Eclipse hat, hmm ... einige Funktionen ... und man muss damit leben. Wenn beispielsweise beim Starten des Debuggers die Meldung "Keine Quelle für" 0x0 "verfügbar" angezeigt wird, führen Sie den Befehl "Schritt" (F5) aus.



Anstelle einer Schlussfolgerung


Die Emulation von nativem Code ist eine sehr interessante Sache. Für einen Geräteentwickler wird es möglich, Firmware ohne ein echtes Gerät zu debuggen. Für den Forscher - die Fähigkeit, eine dynamische Code-Analyse durchzuführen, die selbst mit einem Gerät nicht immer möglich ist.


Wir möchten Spezialisten ein Tool zur Verfügung stellen, das bequem und mäßig einfach ist und für dessen Konfiguration und Start nicht viel Aufwand und Zeit erforderlich ist.


Schreiben Sie in die Kommentare über Ihre Erfahrungen mit der Verwendung von Hardware-Emulatoren. Wir laden Sie zu einer Diskussion ein und beantworten gerne Ihre Fragen.

Source: https://habr.com/ru/post/de445798/


All Articles