
Im Rahmen des Treffens 0x0A DC7831 Am 16. Februar haben wir einen Vortrag über die Grundlagen der Emulation von Binärcode und unsere eigene Entwicklung – den Emulator für Hardwareplattformen – gehalten. .
In diesem Artikel werden wir die Ausführung der Firmware des Geräts im Emulator beschreiben, die Interaktion mit dem Debugger demonstrieren und eine kleine dynamische Analyse der Firmware durchführen.
Hintergrund
Vor langer Zeit in einer weit, weit entfernten Galaxie
Vor ein paar Jahren entstand in unserem Labor die Notwendigkeit, die Firmware eines Geräts zu untersuchen. Die Firmware war komprimiert und wurde vom Bootloader entpackt. Dies geschah auf eine recht komplizierte Art, indem die Daten mehrmals im Speicher umgelegt wurden. Zudem interagierte die Firmware aktiv mit der Peripherie. Und das alles auf einem MIPS-Kern.
Die vorhandenen Emulatoren haben aus objektiven Gründen nicht überzeugt, und wir wollten dennoch den Code ausführen. Daher beschlossen wir, unseren eigenen Emulator zu erstellen, der das Minimum bietet und es erlaubt, die Hauptfirmware zu entpacken. Wir probierten es aus – und es gelang. Dann dachten wir, was wäre, wenn wir die Peripherie hinzufügen, um auch die Hauptfirmware ausführen zu können. Es war nicht allzu schmerzhaft – und es gelang erneut. Schließlich beschlossen wir, einen vollwertigen Emulator zu entwickeln.
So entstand ein Emulator für Rechensysteme. .

Warum Kopycat?
Es handelt sich um ein Wortspiel.
- copycat (engl., Subst. [ˈkɒpɪkæt]) – Nachahmer, Imitator
- cat (engl., Subst. [ˈkæt]) – Katze, Kater – das Lieblingstier eines der Projektmitglieder
- Der Buchstabe „K“ stammt aus der Programmiersprache Kotlin.
Kopycat
Bei der Erstellung des Emulators wurden ganz bestimmte Ziele gesetzt:
- die Möglichkeit, relativ schnell neue Peripherie, Module und Prozessorkerne zu erstellen;
- die Möglichkeit, ein virtuelles Gerät aus verschiedenen Modulen zusammenzustellen;
- die Möglichkeit, beliebige Binärdaten (Firmware) in den Speicher des virtuellen Geräts zu laden;
- die Möglichkeit, mit Snapshots (Systemzustandsaufnahmen) zu arbeiten;
- die Möglichkeit, über einen eingebauten Debugger mit dem Emulator zu interagieren.
- eine angenehme moderne Programmiersprache.
Letztendlich wurde Kotlin für die Implementierung gewählt, ein Busarchitektur-Modell (bei dem Module über virtuelle Datenbusse miteinander verbunden sind), JSON als Format zur Beschreibung des Geräts und GDB RSP als Protokoll für die Interaktion mit dem Debugger.
Die Entwicklung läuft seit etwas mehr als zwei Jahren und wird aktiv fortgesetzt. In dieser Zeit wurden MIPS-, x86-, V850ES-, ARM- und PowerPC-Prozessorkerne umgesetzt.
Das Projekt wächst, und es ist an der Zeit, es der breiten Öffentlichkeit vorzustellen. Eine detaillierte Beschreibung des Projekts wird später erfolgen, während wir uns jetzt auf die Verwendung von Kopycat konzentrieren.
Für die Ungeduldigen – die Promo-Version des Emulators kann heruntergeladen werden unter .
Rhino im Emulator
Erinnern wir uns daran, dass für die SMARTRHINO-2018-Konferenz ein Testgerät mit dem Namen „Rhino“ zur Schulung von Reverse-Engineering-Fähigkeiten erstellt wurde. Der Prozess der statischen Analyse der Firmware wurde hier beschrieben .
Jetzt versuchen wir, etwas „Dynamik“ hinzuzufügen und die Firmware im Emulator auszuführen.
Wir benötigen:
1) Java 1.8
2) Python und das Modul um Python innerhalb des Emulators zu verwenden. Das WHL-Paket des Jep-Moduls für Windows können Sie .
Für Windows:
1)
2)
Für Linux:
1) socat
Als GDB-Client können Sie Eclipse, IDA Pro oder radare2 verwenden.
Wie funktioniert das?
Um die Firmware im Emulator auszuführen, müssen Sie ein virtuelles Gerät "zusammenstellen", das ein analoges Gerät darstellt.
Das reale Gerät ("Nashorn") kann in einem Strukturdiagramm dargestellt werden:

Der Emulator hat eine modulare Struktur, und das endgültige virtuelle Gerät kann in einer JSON-Datei beschrieben werden.
JSON mit 105 Zeilen
{
"top": true,
// Der Plugin-Name sollte dem Dateinamen (oder dem vollständigen Pfad ab Bibliotheksstart) entsprechen
"plugin": "rhino",
// Verzeichnis, in dem das Plugin platziert wird
"library": "user",
// Plugin-Parameter (Konstruktorparameter wenn jar-plugin Version)
"params": [
{ "name": "tty_dbg", "type": "String"},
{ "name": "tty_bt", "type": "String"},
{ "name": "firmware", "type": "String", "default": "NUL"}
],
// Externe Ports des Plugins
"ports": [ ],
// Interne Busse des Plugins
"buses": [
{ "name": "mem", "size": "BUS30" },
{ "name": "nand", "size": "4" },
{ "name": "gpio", "size": "BUS32" }
],
// Interne Komponenten des Plugins
"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-Verbindungen zwischen Komponenten
"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 Parameter Firmware im Bereich Parameter — dies ist der Dateiname, der in das virtuelle Gerät als Firmware hochgeladen werden kann.
Das virtuelle Gerät und seine Interaktion mit dem Hauptbetriebssystem lassen sich mit folgendem Schema darstellen:

Die aktuelle Testinstanz des Emulators ermöglicht die Interaktion mit den COM-Ports des Hauptbetriebsystems (Debug-UART und UART für das Bluetooth-Modul). Dies können reale Ports sein, an die Geräte angeschlossen sind, oder virtuelle COM-Ports (dafür benötigen wir com0com / socat).
Für die Interaktion mit dem Emulator gibt es derzeit zwei Hauptmethoden:
- das GDB RSP-Protokoll (entsprechend unterstützen diese Protokolle-Tools — Eclipse / IDA / radare2);
- die interne Befehlszeile des Emulators (Argparse oder Python).
Virtuelle COM-Ports
Um mit dem UART des virtuellen Geräts auf der lokalen Maschine über ein Terminal zu interagieren, müssen Sie ein Paar verbundener virtueller COM-Ports erstellen. In unserem Fall verwendet ein Port den Emulator und der andere das Terminalprogramm (PuTTY oder screen):

Verwendung von com0com
Virtuelle COM-Ports werden mit dem Setup-Tool aus dem Paket com0com konfiguriert (Konsolenversion — C:Program Files (x86)com0comsetupс.exe, oder GUI-Version — C:Program Files (x86)com0comsetupg.exe.):

Es sollten Häkchen gesetzt werden enable buffer overrun für alle erstellten virtuellen Ports, sonst erwartet der Emulator eine Rückmeldung vom COM-Port.
Verwendung von socat
Unter UNIX-Systemen werden virtuelle COM-Ports automatisch vom Emulator mit dem Tool socat erstellt. Dazu muss beim Starten des Emulators im Portnamen einfach das Präfix socat:.
Interner Befehlszeilen-Interface (Argparse oder Python)
Da Kopycat eine Konsolenanwendung ist, bietet der Emulator zwei Alternativen für die Interaktion mit seinen Objekten und Variablen: Argparse und Python.
Argparse ist das in Kopycat integrierte CLI, das immer und jedem zur Verfügung steht.
Die alternative CLI ist der Python-Interpreter. Um diesen zu verwenden, muss das Python-Modul Jep installiert und der Emulator für die Arbeit mit Python konfiguriert werden (der in der Hauptsystemumgebung des Benutzers installierte Python-Interpreter wird verwendet).
Installation des Python-Moduls Jep
Unter Linux kann Jep über pip installiert werden:
pip install jepUm Jep unter Windows zu installieren, müssen Sie zunächst das Windows SDK und die entsprechende Microsoft Visual Studio installieren. Wir haben es Ihnen ein wenig einfacher gemacht und JEP für die aktuellen Python-Versionen für Windows erstellt, sodass das Modul aus der Datei installiert werden kann:
pip install jep-3.8.2-cp27-cp27m-win_amd64.whlZur Überprüfung der Installation von Jep müssen Sie in der Eingabeaufforderung folgendes ausführen:
python -c "import jep"Die Antwort sollte die folgende Meldung enthalten:
ImportError: Jep wird in eigenständigem Python nicht unterstützt, es muss in Java eingebettet werden.In der Batch-Datei des Emulators für Ihr System (kopycat.bat — für Windows, kopycat — für Linux) fügen Sie der Parameterliste DEFAULT_JVM_OPTS einen zusätzlichen Parameter hinzu Djava.library.path — er sollte den Pfad zum installierten Jep-Modul enthalten.
Das Ergebnis sollte für Windows folgendermaßen aussehen:
set DEFAULT_JVM_OPTS="-XX:MaxMetaspaceSize=256m" "-XX:+UseParallelGC" "-XX:SurvivorRatio=6" "-XX:-UseGCOverheadLimit" "-Djava.library.path=C:/Python27/Lib/site-packages/jep"Starten von Kopycat
Der Emulator ist eine Konsolen-JVM-Anwendung. Der Start erfolgt über ein Skript der Betriebssystem-Eingabeaufforderung (sh/cmd).
Befehl zum Starten unter Windows:
binkopycat -g 23946 -n rhino -l user -y library -p firmware=firmwarerhino_pass.bin,tty_dbg=COM26,tty_bt=COM28Befehl zum Starten 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 wird;-n rhino— Name des Hauptmoduls des Systems (Gerät im Zusammenbau);-l user— Name der Bibliothek zur Suche des Hauptmoduls;-y library— Pfad zur Suche nach Modulen, die im Gerät enthalten sind;firmwarerhino_pass.bin— Pfad zur Firmware-Datei;- COM26 und COM28 sind virtuelle COM-Ports.
In der Folge wird eine Eingabeaufforderung angezeigt Python > (oder Argparse >):
18:07:59 INFO [eFactoryBuilder.create]: Modul top erfolgreich als top erstellt
18:07:59 INFO [Module.initializeAndRes]: Core auf top.u1_stm32.cortexm0.arm für top eingerichtet
18:07:59 INFO [Module.initializeAndRes]: Debugger auf top.u1_stm32.dbg für top eingerichtet
18:07:59 WARN [Module.initializeAndRes]: Tracer wurde in top nicht gefunden...
18:07:59 INFO [Module.initializeAndRes]: Initialisierung von Ports und Bussen...
18:07:59 WARN [Module.initializePortsA]: ACHTUNG: Einige Ports haben Warnungen, verwenden Sie printModulesPortsWarnings, um diese zu sehen...
18:07:59 FINE [ARMv6CPU.reset]: Einstiegspunktadresse auf 08006A75 gesetzt
18:07:59 INFO [Module.initializeAndRes]: Modul top wurde erfolgreich initialisiert und als Top-Zelle zurückgesetzt!
18:07:59 INFO [Kopycat.open]: Virtualisierung des Boards top[rhino] mit arm[ARMv6Core] startet
18:07:59 INFO [GDBServer.debuggerModule]: Neues Debuggermodul top.u1_stm32.dbg für GDB_SERVER(port=23946,alive=true) gesetzt
Python >Interaktion mit IDA Pro
Als Eingabedatei für die Analyse in IDA zur Vereinfachung der Tests verwenden wir die Firmware "Rhino" in Form von (metainformation is stored there).
Sie können auch die Hauptfirmware ohne Metainformationen verwenden.
Nach dem Start von Kopycat in IDA Pro gehen wir im Menü Debugger zu „Debugger wechseln…“ und wählen „Remote GDB-Debugger“. Dann konfigurieren wir die Verbindung: Menü Debugger — Prozessoptionen…
Stellen Sie die Werte ein:
- Anwendung — beliebiger Wert
- Hostname: 127.0.0.1 (oder IP-Adresse des Remote-Systems, auf dem Kopycat läuft)
- Port: 23946

Jetzt wird die Schaltfläche zum Starten des Debuggens (Taste F9) verfügbar:
![]()
Wir drücken sie — die Verbindung zum Debugger-Modul im Emulator wird hergestellt. IDA wechselt in den Debugging-Modus, weitere Fenster werden angezeigt: Registerinformationen, Stapelinformationen.
Jetzt können wir alle Standardfunktionen des Debuggers nutzen:
- Einzelschritt-Ausführung (Rein и Übergehen — Tasten F7 und F8, entsprechend);
- Start und Anhält der Ausführung;
- Erstellung von Haltepunkten sowohl für Code als auch für Daten (Taste F2).
Die Verbindung zum Debugger bedeutet nicht, dass der Firmware-Code ausgeführt wird. Die aktuelle Ausführungsposition sollte die Adresse 0x08006A74 — der Beginn der Funktion Reset_Handler. Wenn Sie das Listing weiter nach unten scrollen, können Sie den Aufruf der Funktion sehen main. Sie können den Cursor auf dieser Zeile (Adresse 0x08006ABE) setzen und die Operation ausführen Bis zum Cursor ausführen (Taste F4).

Danach können Sie F7 drücken, um in die Funktion zu gelangen main.
Wenn Sie den Befehl ausführen Prozess fortsetzen (Taste F9), erscheint das Fenster „Bitte warten“ mit nur einem Button Anhalten:

Wenn Sie drücken Anhalten wird die Ausführung des Firmware-Codes angehalten und kann an der Adresse im Code fortgesetzt werden, an der sie unterbrochen wurde.
Wenn die Ausführung des Codes fortgesetzt wird, können in den an virtuellen COM-Ports angeschlossenen Terminals folgende Zeilen angezeigt werden:


Das Vorhandensein der Zeile „state bypass“ zeigt an, dass das virtuelle Bluetooth-Modul in den Datenempfangsmodus vom COM-Port des Benutzers gewechselt ist.
Jetzt können im Bluetooth-Terminal (in der Abbildung — COM29) Befehle gemäß dem Protokoll „Nashorn“ eingegeben werden. Zum Beispiel wird auf den Befehl „MEOW“ im Bluetooth-Terminal die Zeile „mur-mur“ zurückgegeben:

Emuliere mich nicht ganz
Bei der Erstellung des Emulators kann die Detailgenauigkeit der Emulation des jeweiligen Gerätes ausgewählt werden. So kann das Bluetooth-Modul beispielsweise unterschiedlich emuliert werden:
- Das Gerät wird vollständig mit dem gesamten Befehlssatz emuliert;
- AT-Kommandos werden emuliert, während der Datenstrom vom COM-Port des Hauptsystems empfangen wird;
- Das virtuelle Gerät ermöglicht eine vollständige Umleitung der Daten zu einem physischen Gerät;
- in Form eines einfachen Platzhalters, der immer "OK" zurückgibt.
In der aktuellen Version des Emulators wird der zweite Ansatz verwendet – das virtuelle Bluetooth-Modul konfiguriert, bevor es in den Modus des „Proxy“ wechselt, der die Daten vom COM-Port des Hauptsystems an den UART-Port des Emulators weiterleitet.

Betrachten wir die Möglichkeit einer einfachen Instrumentierung des Codes, falls ein Teil der Peripherie nicht implementiert ist. Zum Beispiel, wenn kein Timer erstellt wurde, der für die Kontrolle des Datentransfers im DMA verantwortlich ist (die Überprüfung erfolgt in der Funktion ws2812b_wait, die sich an der Adresse 0x08006840befindet), wird die Firmware immer auf das Zurücksetzen des Flags busy, das sich an der Adresse 0x200004C4, wartet, welches die Belegung der DMA-Datenleitung anzeigt:

Wir können diese Situation umgehen, indem wir das Flag busy sofort nach seiner Setzung „manuell“ zurücksetzen. In IDA Pro kann man eine Python-Funktion erstellen und sie im Breakpoint aufrufen, wobei der Breakpoint im Code nach dem Setzen des Wertes 1 im Flag gesetzt wird busy.
Breakpoint-Handler
Zuerst erstellen wir eine Python-Funktion in IDA. Menü Datei — Skriptbefehl…
Fügen Sie einen neuen Snippet in der linken Liste hinzu, geben Sie ihm einen Namen (zum Beispiel, BPT),
geben Sie im Textfeld rechts den Funktionscode ein:
def skip_dma():
print "Warte ws2812 wird übersprungen..."
value = Byte(0x200004C4)
if value == 1:
PatchDbgByte(0x200004C4, 0)
return False 
Danach klicken wir auf Ausführen und schließen das Skriptfenster.
Jetzt gehen wir zum Code unter der Adresse 0x0800688A, setzen einen Haltepunkt (Taste F2), bearbeiten ihn (Kontextmenü Haltepunkt bearbeiten…), und vergessen Sie nicht, den Skripttyp – Python einzustellen:


Wenn der aktuelle Wert des Flags busy gleich 1 ist, sollten wir die Funktion skip_dma in der Skriptzeile ausführen:

Wenn Sie die Firmware zur Ausführung starten, können Sie die Auslösung des Haltepunkt-Handlers im IDA-Fenster sehen Ausgabe in der Zeile Warte ws2812 wird übersprungen.... Jetzt wird die Firmware nicht auf das Zurücksetzen des Flags warten. busy.
Interaktion mit dem Emulator
Emulation um der Emulation willen wird wahrscheinlich nicht Begeisterung und Freude hervorrufen. Viel interessanter ist es, wenn der Emulator dem Forscher hilft, Daten im Speicher zu sehen oder die Interaktion von Threads zu etablieren.
Wir zeigen, wie man in der Dynamik die Interaktion von RTOS-Tasks einrichtet. Zuvor sollte die Ausführung des Codes angehalten werden, wenn sie läuft. Wenn Sie zur Funktion bluetooth_task_entry In den Command-Processing-Thread „LED“ (Adresse 0x080057B8), sieht man, dass zunächst erstellt wird, und dann in die Systemwarteschlange gesendet wird. ledControlQueueHandle eine bestimmte Nachricht.

Es sollte ein Haltepunkt beim Zugriff auf die Variable gesetzt werden ledControlQueueHandle, die sich an der Adresse 0x20000624 und die Ausführung des Codes fortgesetzt werden:

In der Folge wird zuerst an der Adresse 0x080057CA angehalten, vor dem Aufruf der FunktionosMailAlloc 0x08005806 angehalten, , dann — an der AdresseosMailPut , später nach einer gewissen Zeit — an der Adresse 0x08005BD4 (vor dem Aufruf der FunktionosMailGet ), die zur Funktion leds_task_entry

(LED-Task) gehört, was bedeutet, dass ein Taskwechsel stattgefunden hat und nun der LED-Task die Kontrolle übernommen hat.
So kann auf einfache Weise gezeigt werden, wie RTOS-Tasks miteinander interagieren.
Natürlich kann die Interaktion der Tasks in der Realität komplexer gestaltet sein, aber mit einem Emulator wird das Verfolgen dieser Interaktion weniger mühsam.
Man kann sich ein kurzes Video über den Start des Emulators und die Interaktion mit IDA Pro ansehen.
Start mit Radare2
Ein solches vielseitiges Tool wie Radare2 sollte nicht unerwähnt bleiben.
Um sich mit dem Emulator über r2 zu verbinden, sieht der Befehl folgendermaßen aus:radare2 -A -a arm -b 16 -d gdb://localhost:23946 rhino_fw42k6.elfdc) und Ausführung anhalten (Ctrl+C).
Leider gibt es momentan Probleme mit dem hardware GDB-Server und dem Speichermanagement in r2, wodurch Breakpoints und Stepping (Befehl ds) nicht funktionieren. Wir hoffen, dass dies bald behoben wird.
Starten mit Eclipse
Eine Möglichkeit, den Emulator zu nutzen, ist das Debuggen der Firmware des entwickelten Geräts. Zur Veranschaulichung werden wir auch die Firmware „Rhino“ verwenden. Die Quellcodes der Firmware können .
Wir verwenden Eclipse aus dem Paket .
Um die Firmware direkt aus Eclipse in den Emulator zu laden, muss der Parameter firmware=null zum Startbefehl des Emulators hinzugefügt werden:
binkopycat -g 23946 -n rhino -l user -y modules -p firmware=null,tty_dbg=COM26,tty_bt=COM28Einrichtung der Debug-Konfiguration
In Eclipse wählen wir das Menü Run — Debug Configurations… Im sich öffnenden Fenster müssen wir im Abschnitt GDB Hardware Debugging eine neue Konfiguration hinzufügen und anschließend auf dem Tab „Main“ das aktuelle Projekt und die zu debuggende Anwendung angeben:

Auf dem Tab „Debugger“ geben wir den GDB-Befehl an:
${openstm32_compiler_path}arm-none-eabi-gdb
Und geben Sie auch die Verbindungsparameter für den GDB-Server ein (Host und Port):

Im Reiter „Startup“ müssen Sie die folgenden Parameter angeben:
- das Kontrollkästchen aktivieren Bild laden (um das Laden des kompilierten Firmware-Abbilds im Emulator zu ermöglichen);
- das Kontrollkästchen aktivieren Symbole laden;
- Befehl hinzufügen:
set $pc = *0x08000004(setzen Sie den Wert aus dem Speicher an die Adresse in das PC-Register0x08000004— dort wird die Adresse des ResetHandlers gespeichert).
Bitte beachten Sie, wenn Sie die Firmware-Datei nicht aus Eclipse laden möchten, sind die Parameter Bild laden и Befehle ausführen nicht erforderlich.

Nach dem Klicken auf Debug können Sie im Debugger-Modus arbeiten:
- schrittweises Ausführen des Codes

- Interaktion mit Haltepunkten

Hinweis. In Eclipse gibt es, hmm… einige Besonderheiten… und damit muss man leben. Wenn beim Starten des Debuggers die Nachricht „No source available for „0x0““ erscheint, führen Sie den Befehl Step (F5) aus.

Abschließend
Die Emulation von nativen Code ist ein äußerst interessantes Unterfangen. Für Entwickler von Geräten besteht die Möglichkeit, die Firmware ohne das echte Gerät zu debuggen. Für Forscher bietet sich die Möglichkeit, eine dynamische Codeanalyse durchzuführen, was selbst bei Vorhandensein des Geräts nicht immer möglich ist.
Wir möchten Fachleuten ein Werkzeug bereitstellen, das benutzerfreundlich, einfach genug und nicht zeitintensiv bei der Einrichtung ist.
Teilen Sie uns in den Kommentaren Ihre Erfahrungen mit Hardware-Emulatoren mit. Wir laden Sie zur Diskussion ein und beantworten gerne Ihre Fragen.
Nur registrierte Benutzer können an der Umfrage teilnehmen. Sind Sie an Contour interessiert?
Wofür nutzen Sie den Emulator?
ich entwickle (debugge) Firmware
ich erforsche Firmware
ich starte Spiele (Dendi, Sega, PSP)
etwas anderes (schreiben Sie es in die Kommentare)
7 Nutzer haben abgestimmt. 2 Nutzer haben sich enthalten.
Welche Software nutzen Sie zur Emulation von nativen Code?
QEMU
Unicorn engine
Proteus
etwas anderes (schreiben Sie es in die Kommentare)
6 Nutzer haben abgestimmt. 2 Nutzer haben sich enthalten.
Was würden Sie an dem verwendeten Emulator verbessern?
ich wünsche mir Geschwindigkeit
ich wünsche mir eine benutzerfreundliche Einrichtung/Start
ich wünsche mir mehr Interaktionsmöglichkeiten mit dem Emulator (API, Hooks)
ich bin mit allem zufrieden
etwas anderes (schreiben Sie es in die Kommentare)
8 Nutzer haben abgestimmt. 1 Nutzer hat sich enthalten.
Quelle: habr.com


