
Im Rahmen des Treffens 0x0A DC7831 Am 16. Februar prĂ€sentierten wir einen Vortrag ĂŒber die grundlegenden Prinzipien der Emulation von BinĂ€rcode und unsere eigene Entwicklung â einen Emulator fĂŒr Hardwareplattformen. .
In dem 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.
Vorgeschichte
Vor langer Zeit in einer weit, weit entfernten Galaxie
Vor ein paar Jahren hatte unser Labor die Notwendigkeit, die Firmware eines GerÀts zu untersuchen. Die Firmware war komprimiert und wurde vom Bootloader entpackt. Dieser tat dies auf eine sehr komplexe Weise, indem er die Daten mehrfach im Speicher umlegte. Auch die Firmware selbst interagierte aktiv mit der Peripherie. Und das alles auf einem MIPS-Kernel.
Die vorhandenen Emulatoren waren aus objektiven GrĂŒnden nicht zufriedenstellend, und wir wollten den Code schlieĂlich ausfĂŒhren. Daher beschlossen wir, unseren eigenen Emulator zu entwickeln, der das Minimum erledigt und es ermöglicht, die Hauptfirmware zu entpacken. Wir probierten es aus â es funktionierte. Wir dachten, was wĂ€re, wenn wir auch die Peripherie hinzufĂŒgen, um auch die Hauptfirmware auszufĂŒhren. Es war nicht allzu schmerzhaft â und es funktionierte auch. Wir dachten erneut nach und entschieden uns, einen vollstĂ€ndigen Emulator zu entwickeln.
Am Ende entstand ein Emulator fĂŒr Rechensysteme. .

Warum Kopycat?
Es handelt sich um ein Wortspiel.
- copycat (engl., Substantiv [ËkÉpÉȘkĂŠt]) â Nachahmer, Imitator
- cat (engl., Substantiv [ËkĂŠt]) â Katze, Kater â das Lieblingstier eines der Projektverfasser
- Der Buchstabe âKâ stammt von der Programmiersprache Kotlin.
Kopycat
Bei der Erstellung des Emulators wurden ganz bestimmte Ziele gesetzt:
- die Möglichkeit, relativ schnell eine neue Peripherie, ein Modul, einen Prozessorkern 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 (SystemzustÀnde) zu arbeiten;
- die Möglichkeit, ĂŒber einen integrierten Debugger mit dem Emulator zu interagieren;
- eine angenehme moderne Sprache fĂŒr die Entwicklung.
Am Ende wurde Kotlin fĂŒr die Implementierung gewĂ€hlt, eine Busarchitektur (das ist, wenn Module ĂŒber virtuelle Datenschnitte miteinander verbunden werden), 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-Prozessor-Kerne realisiert.
Das Projekt wĂ€chst, und es ist an der Zeit, es der breiten Ăffentlichkeit vorzustellen. Eine ausfĂŒhrliche Projektbeschreibung werden wir spĂ€ter geben, und jetzt konzentrieren wir uns auf die Nutzung von Kopycat.
FĂŒr die Ungeduldigen â die Promo-Version des Emulators kann man herunterladen unter .
Nashorn im Emulator
Wir erinnern daran, dass fĂŒr die Konferenz SMARTRHINO-2018 ein TestgerĂ€t "Nashorn" erstellt wurde, um FĂ€higkeiten im Reverse Engineering zu trainieren. Der Prozess der statischen Analyse der Firmware wurde in .
Jetzt werden wir versuchen, "Dynamik" hinzuzufĂŒgen und die Firmware im Emulator zu starten.
Wir benötigen:
1) Java 1.8
2) Python und das Modul zum Einsatz von Python innerhalb des Emulators. Die WHL-Version des Jep-Moduls fĂŒr Windows kann man .
FĂŒr Windows:
1)
2)
FĂŒr Linux:
1) socat
Als GDB-Client kann Eclipse, IDA Pro oder radare2 verwendet werden.
Wie funktioniert das?
Um die Firmware im Emulator auszufĂŒhren, ist es notwendig, ein virtuelles GerĂ€t zusammenzustellen, das ein Analogon des realen GerĂ€ts darstellt.
Das reale GerÀt ("Nashorn") kann in einem strukturellen Diagramm 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 Name des Plugins sollte mit dem Dateinamen (oder dem vollstĂ€ndigen Pfad vom Beginn der Bibliothek) ĂŒbereinstimmen
"plugin": "rhino",
// Verzeichnis, in dem das Plugin platziert wird
"library": "user",
// Plugin-Parameter (Konstruktorparameter, wenn es sich um die JAR-Plugin-Version handelt)
"params": [
{ "name": "tty_dbg", "type": "String"},
{ "name": "tty_bt", "type": "String"},
{ "name": "firmware", "type": "String", "default": "NUL"}
],
// Externe AnschlĂŒsse des Plugins
"ports": [ ],
// Interne Bussen 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" }
],
// Verbindung des Plugins 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"]
]
}Bitte beachten Sie den Parameter Firmware im Abschnitt Parameter â dies ist der Name der Datei, die als Firmware in das virtuelle GerĂ€t hochgeladen werden kann.
Das virtuelle GerÀt und seine Interaktion mit dem Hauptbetriebssystem können durch folgendes Schema dargestellt werden:

Die aktuelle Testversion des Emulators beinhaltet die Interaktion mit den COM-Ports des Hauptbetriebssystems (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 braucht man genau com0com / socat).
Um von auĂen mit dem Emulator zu interagieren, gibt es derzeit zwei Hauptwege:
- das GDB RSP-Protokoll (die entsprechenden unterstĂŒtzenden Werkzeuge sind - Eclipse / IDA / radare2);
- die interne Eingabeaufforderung des Emulators (Argparse oder Python).
Virtuelle COM-Ports
Um mit dem UART des virtuellen GerĂ€ts auf dem lokalen Rechner ĂŒber ein Terminal zu interagieren, mĂŒssen Sie ein Paar verbundener virtueller COM-Ports erstellen. In unserem Fall nutzt ein Port den Emulator und der andere das Terminal-Programm (PuTTY oder screen):

Verwendung von com0com
Die virtuellen COM-Ports werden mit dem Setup-Tool aus dem Paket com0com konfiguriert (Konsolen-Version - C:Program Files (x86)com0comsetupc.exe, oder GUI-Version - C:Program Files (x86)com0comsetupg.exe):

Es sollten HĂ€kchen gesetzt werden fĂŒr enable buffer overrun fĂŒr alle erstellten virtuellen Ports, ansonsten wird der Emulator auf eine RĂŒckmeldung vom COM-Port warten.
Verwendung von socat
Unter UNIX-Systemen werden die virtuellen COM-Ports automatisch durch den Emulator mit dem Tool socat erstellt, dazu genĂŒgt es, beim Start des Emulators im Portnamen das PrĂ€fix socat:.
Internes Kommandozeileninterface (Argparse oder Python)
Da Kopycat eine Konsolenanwendung ist, bietet der Emulator zur Interaktion mit seinen Objekten und Variablen zwei Varianten eines Kommandozeileninterfaces: Argparse und Python.
Argparse ist das CLI, das in Kopycat integriert ist, es ist immer und fĂŒr jeden zugĂ€nglich.
Das alternative CLI ist der Python-Interpreter. Um ihn zu nutzen, muss das Python-Modul Jep installiert und der Emulator fĂŒr die Arbeit mit Python konfiguriert werden (der im Hauptsystem 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, muss zunĂ€chst das Windows SDK und die entsprechende Microsoft Visual Studio installiert werden. Wir haben Ihnen die Aufgabe ein wenig erleichtert und JEP fĂŒr die aktuellen Versionen von Python fĂŒr Windows, daher kann das Modul aus der Datei installiert werden:
pip install jep-3.8.2-cp27-cp27m-win_amd64.whlUm die Installation von Jep zu ĂŒberprĂŒfen, muss in der Eingabeaufforderung Folgendes ausgefĂŒhrt werden:
python -c "import jep"Als Antwort sollte die folgende Nachricht erhalten werden:
ImportError: Jep wird in eigenstĂ€ndigem Python nicht unterstĂŒtzt, es muss in Java eingebettet werden.In der Batchdatei 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 â es muss den Pfad zum installierten Jep-Modul enthalten.
FĂŒr Windows sollte die resultierende Zeile wie folgt aussehen:
set DEFAULT_JVM_OPTS="-XX:MaxMetaspaceSize=256m" "-XX:+UseParallelGC" "-XX:SurvivorRatio=6" "-XX:-UseGCOverheadLimit" "-Djava.library.path=C:\/Python27\/Lib\/site-packages\/jep"Kopycat starten
Der Emulator ist eine konsolenbasierte JVM-Anwendung. Der Start erfolgt ĂŒber ein Skript der Betriebssystem-Eingabeaufforderung (sh\/cmd).
Der Befehl zum Starten unter Windows:
binkopycat -g 23946 -n rhino -l user -y library -p firmware=firmwarerhino_pass.bin,tty_dbg=COM26,tty_bt=COM28Der Befehl zum Starten unter Linux mit dem Tool 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 in Zusammenstellung);-l userâ Name der Bibliothek zur Suche nach dem Hauptmodul;-y libraryâ Pfad zur Suche nach Modulen, die zum GerĂ€t gehören;firmwarerhino_pass.binâ Pfad zur Firmware-Datei;- COM26 und COM28 â virtuelle COM-Ports.
Infolgedessen wird die Eingabeaufforderung angezeigt Python > (oder Argparse >):
18:07:59 INFO [eFactoryBuilder.create ]: Modul top erfolgreich als top erstellt
18:07:59 INFO [ Module.initializeAndRes]: Setup core zu top.u1_stm32.cortexm0.arm fĂŒr top
18:07:59 INFO [ Module.initializeAndRes]: Setup Debugger zu top.u1_stm32.dbg fĂŒr top
18:07:59 WARN [ Module.initializeAndRes]: Tracer wurde in top nicht gefunden...
18:07:59 INFO [ Module.initializeAndRes]: Initialisiere Ports und Bussen...
18:07:59 WARN [ Module.initializePortsA]: ACHTUNG: Einige Ports haben Warnungen, verwenden Sie printModulesPortsWarnings, um es zu sehen...
18:07:59 FINE [ ARMv6CPU.reset ]: Setze Einstiegspunktadresse auf 08006A75
18:07:59 INFO [ Module.initializeAndRes]: Modul top wurde erfolgreich initialisiert und als Hauptzelle zurĂŒckgesetzt!
18:07:59 INFO [ Kopycat.open ]: Virtualisierung der Platine top[rhino] mit arm[ARMv6Core] gestartet
18:07:59 INFO [ GDBServer.debuggerModule ]: Neuen Debugger-Modul top.u1_stm32.dbg fĂŒr GDB_SERVER(port=23946,alive=true) gesetzt
Python >Interaktion mit IDA Pro
Als Eingangsdatei fĂŒr die Analyse in IDA verwenden wir zur Vereinfachung der Tests die Firmware âRhinoâ in Form von (dort ist die Metainformation gespeichert).
Sie können auch die Hauptfirmware ohne Metainformation verwenden.
Nach dem Start von Kopycat in IDA Pro gehen Sie im MenĂŒ Debugger zu âDebugger wechselnâŠâ und wĂ€hlen âRemote GDB-Debugger«. Weiter geht's mit der Verbindungseinrichtung: MenĂŒ Debugger â ProzessoptionenâŠ
Werte festlegen:
- Anwendung â beliebiger Wert
- Hostname: 127.0.0.1 (oder die IP-Adresse der entfernten Maschine, auf der Kopycat lÀuft)
- Port: 23946

Jetzt wird die SchaltflĂ€che zum Starten des Debuggings (Taste F9) verfĂŒgbar:
![]()
DrĂŒcken Sie sie â die Verbindung wird zum Debugger-Modul im Emulator hergestellt. IDA wechselt in den Debugging-Modus und zusĂ€tzliche Fenster werden verfĂŒgbar: Informationen zu Registern und zum Stack.
Jetzt können wir alle Standardfunktionen des Debuggers nutzen:
- Schrittweises AusfĂŒhren von Anweisungen (Einzelschritt und Ăbergehen â Tasten F7 und F8, jeweils);
- Start und Pause der AusfĂŒhrung;
- Setzen von Haltepunkten sowohl im Code als auch in Daten (Taste F2).
Die Verbindung zum Debugger bedeutet nicht, dass der Code der Firmware gestartet wird. Die aktuelle AusfĂŒhrungsposition muss die Adresse 0x08006A74 â Anfang der Funktion Reset_Handler. Wenn Sie den Listing nach unten scrollen, können Sie den Funktionsaufruf sehen. mainSie können den Cursor auf dieser Zeile (Adresse 0x08006ABE) positionieren und die Operation Fahre bis zum Cursor DurchfĂŒhren (Taste F4).

AnschlieĂend können Sie F7 drĂŒcken, um in die Funktion zu gelangen. main.
Wenn Sie den Befehl Prozess fortsetzen ausfĂŒhren (Taste F9), wird ein Fenster mit dem Text âBitte wartenâ und nur einer SchaltflĂ€che angezeigt. Suspendieren:

Wenn Sie drĂŒcken, Suspendieren wird die AusfĂŒhrung des Firmware-Codes angehalten und kann an derselben Adresse im Code fortgesetzt werden, wo sie unterbrochen wurde.
Wenn Sie die AusfĂŒhrung des Codes fortsetzen, können Sie in den Terminals, die mit virtuellen COM-Ports verbunden sind, die folgenden Zeilen sehen:


Das Vorhandensein der Zeile âstate bypassâ bedeutet, dass das virtuelle Bluetooth-Modul in den Datenempfangsmodus vom COM-Port des Benutzers gewechselt hat.
Jetzt können Sie im Bluetooth-Terminal (im Bild â COM29) Befehle gemÀà dem Protokoll âNashornâ eingeben. Zum Beispiel wird bei dem Befehl âMEOWâ im Bluetooth-Terminal die Zeile âmur-murâ zurĂŒckgesendet:

Emuliere mich nicht vollstÀndig
Bei der Erstellung des Emulators kann der Detaillierungsgrad / die Emulation des jeweiligen GerÀts gewÀhlt werden. So kann das Bluetooth-Modul beispielsweise unterschiedlich emuliert werden:
- das GerÀt wird vollstÀndig mit einem umfassenden Befehlssatz emuliert;
- AT-Befehle werden emuliert, wÀhrend der Datenstrom von dem COM-Port des Hauptsystems empfangen wird;
- das virtuelle GerĂ€t sorgt fĂŒr eine vollstĂ€ndige Umleitung der Daten an das reale GerĂ€t;
- in Form eines einfachen Platzhalters, der immer âOKâ zurĂŒckgibt.
In der aktuellen Version des Emulators wird der zweite Ansatz verwendet â ein virtueller Bluetooth-Modul konfiguriert und wechselt dann in den Modus "Proxy" von Daten vom COM-Port des Hauptsystems zum UART-Port des Emulators.

Betrachten wir die Möglichkeit einer einfachen Instrumentierung des Codes, falls ein Teil der Peripherie nicht implementiert ist. Beispielsweise, wenn kein Timer erstellt wurde, der fĂŒr die Kontrolle der DatenĂŒbertragung im DMA zustĂ€ndig ist (die ĂberprĂŒfung erfolgt in der Funktion ws2812b_wait, die sich an der Adresse 0x08006840), wird die Firmware immer auf das ZurĂŒcksetzen des Flags busy, das sich an der Adresse 0x200004C4, wartet, welches die Auslastung der DMA-Datenleitung anzeigt:

Wir können diese Situation umgehen, indem wir das Flag busy sofort nach seiner Einstellung "manuell" zurĂŒcksetzen. In IDA Pro kann man eine Python-Funktion erstellen und sie beim Breakpoint aufrufen, wobei der Breakpoint im Code nach dem Setzen des Wertes 1 in das Flag gesetzt wird. busy.
Breakpoint-Handler
Zuerst erstellen wir eine Python-Funktion in IDA. MenĂŒ Datei â Skript BefehlâŠ
FĂŒgen Sie einen neuen Snippet in der linken Liste hinzu, geben Sie ihm einen Namen (zum Beispiel, BPT),
geben Sie den Funktionscode im rechten Textfeld ein:
def skip_dma():
print "Skipping wait ws2812..."
value = Byte(0x200004C4)
if value == 1:
PatchDbgByte(0x200004C4, 0)
return False 
Nachdem wir dies gemacht haben, klicken wir auf AusfĂŒhren und schlieĂen das Skripte-Fenster.
Jetzt gehen wir zu dem Code an der Adresse 0x0800688A, setzen den Breakpoint (Taste F2), bearbeiten ihn (KontextmenĂŒ Breakpoint bearbeitenâŠ), und vergessen Sie nicht, den Skripttyp â Python einzustellen:


Wenn der aktuelle Wert des Flags busy gleich 1 ist, sollte die Funktion skip_dma in der Zeile des Skripts ausgefĂŒhrt werden:

Wenn Sie die Firmware ausfĂŒhren, sieht man das Auslösen des Breakpoint-Handhabers in IDA im Fenster Ausgabe mit der Zeile Skipping wait ws2812.... Jetzt wird die Firmware nicht auf das ZurĂŒcksetzen des Flags warten. busy.
Interaktion mit dem Emulator
Emulation um der Emulation willen wird wohl kaum Begeisterung und Freude hervorrufen. Viel interessanter ist es, wenn der Emulator dem Forscher hilft, Daten im Speicher zu sehen oder die Interaktion von Threads einzurichten.
Lassen Sie uns zeigen, wie man in der Dynamik die Interaktion von RTOS-Jobs einrichtet. Zuvor sollte die AusfĂŒhrung des Codes unterbrochen werden, wenn sie lĂ€uft. Wenn wir zur Funktion bluetooth_task_entry in den Zweig zur Verarbeitung des Befehls "LED " (Adresse 0x080057B8) gehen, sieht man, dass zunĂ€chst eine Nachricht erstellt und dann an die Systemwarteschlange ledControlQueueHandle gesendet wird.

Ein Breakpoint sollte beim Zugriff auf die Variable gesetzt werden ledControlQueueHandle, die sich an der Adresse 0x20000624 und die AusfĂŒhrung des Codes sollte fortgesetzt werden:

Daher erfolgt zunĂ€chst eine Anhaltung an der Adresse 0x080057CA vor dem Funktionsaufruf osMailAlloc, dann â an der Adresse 0x08005806 vor dem Funktionsaufruf osMailPut, dann nach einiger Zeit â an der Adresse 0x08005BD4 (vor dem Funktionsaufruf osMailGet), die der Funktion leds_task_entry zugeordnet ist (LED-Task), das heiĂt, es fand ein Wechsel der Tasks statt, und nun erhielt der LED-Task die Kontrolle.

Auf diese einfache Weise kann man feststellen, wie RTOS-Tasks miteinander interagieren.
NatĂŒrlich kann die Interaktion zwischen den Tasks in der RealitĂ€t komplexer sein, aber mit dem Emulator wird es weniger arbeitsintensiv, diese Interaktionen nachzuvollziehen.
Man kann sich ein kurzes Video ĂŒber den Start des Emulators und die Interaktion mit IDA Pro ansehen.
Start mit Radare2
Ein so vielseitiges Werkzeug wie Radare2 kann nicht ignoriert werden.
Um sich mit dem Emulator ĂŒber r2 zu verbinden, lautet der Befehl:
radare2 -A -a arm -b 16 -d gdb://localhost:23946 rhino_fw42k6.elfJetzt sind das Starten (dc) und das Anhalten der AusfĂŒhrung (Ctrl+C) verfĂŒgbar.
Leider gibt es im Moment Probleme mit r2 bei der Arbeit mit dem Hardware-GDB-Server und der Speicherkartierung, weshalb Haltepunkte und Stepping (Befehl ds) nicht funktionieren. Wir hoffen, dass dies in naher Zukunft behoben wird.
Start mit Eclipse
Eine Möglichkeit, den Emulator zu verwenden, ist das Debugging der Firmware des entwickelten GerĂ€ts. Zur Veranschaulichung verwenden wir auch die Firmware âNashornâ. Der Quellcode der Firmware kann heruntergeladen werden .
Als IDE verwenden wir Eclipse aus dem Paket .
Damit die Firmware, die direkt in Eclipse erstellt wurde, in den Emulator geladen wird, 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=COM28Konfiguration des Debugger-Setups
In Eclipse wĂ€hlen wir das MenĂŒ Run â Debug Configurations⊠Im sich öffnenden Fenster im Abschnitt GDB Hardware Debugging mĂŒssen wir eine neue Konfiguration hinzufĂŒgen, und auf der Registerkarte âMainâ das aktuelle Projekt und die zu debuggende Anwendung angeben:

Auf der Registerkarte âDebuggerâ muss der GDB-Befehl angegeben werden:
${openstm32_compiler_path}arm-none-eabi-gdb
und auch die Parameter fĂŒr die Verbindung zum GDB-Server (Host und Port) eingegeben werden:

Auf der Registerkarte âStartupâ mĂŒssen folgende Parameter angegeben werden:
- das HĂ€kchen setzen Load image (damit das Laden des erstellten Firmware-Images in den Emulator erfolgt);
- das HĂ€kchen setzen Load symbols;
- Startbefehl hinzufĂŒgen:
set $pc = *0x08000004(Wert aus dem Speicher an der Adresse im PC registrieren0x08000004â dort wird die Adresse gespeichert des ResetHandlers).
Bitte beachten Sie, wenn Sie die Firmware-Datei nicht aus Eclipse laden möchten, sind die Parameter Load image und Run-Befehle nicht erforderlich.

Nach dem DrĂŒcken von 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.

Zum Abschluss
Die Emulation von nativen Code ist ein sehr interessantes Thema. Entwicklern von GerĂ€ten wird die Möglichkeit gegeben, die Firmware ohne echtes GerĂ€t zu debuggen. FĂŒr Forscher bietet sich die Möglichkeit, die dynamische Analyse des Codes durchzufĂŒhren, was selbst bei Vorhandensein eines GerĂ€ts nicht immer möglich ist.
Wir möchten den Fachleuten ein Werkzeug zur VerfĂŒgung stellen, das bequem, einigermaĂen einfach und nicht zu viel Zeit und MĂŒhe fĂŒr seine Einrichtung und AusfĂŒhrung benötigt.
Teilen Sie uns in den Kommentaren Ihre Erfahrungen mit Hardware-Emulatoren mit. Wir laden zur Diskussion ein und freuen uns auf Ihre Fragen.
Nur registrierte Benutzer können an der Umfrage teilnehmen. .
Wozu verwenden Sie den Emulator?
ich entwickle (debugge) Firmware
ich forsche an Firmware
ich starte Spiele (Dendi, Sega, PSP)
etwas anderes (teilen Sie uns in den Kommentaren mit)
7 Benutzer haben abgestimmt. 2 Benutzer haben sich enthalten.
Welche Software verwenden Sie zur Emulation von nativem Code?
QEMU
Unicorn Engine
Proteus
etwas anderes (teilen Sie uns in den Kommentaren mit)
6 Benutzer haben abgestimmt. 2 Benutzer haben sich enthalten.
Was wĂŒrden Sie an dem verwendeten Emulator verbessern?
ich hÀtte gerne Geschwindigkeit
ich hĂ€tte gerne eine einfachere Einrichtung/AusfĂŒhrung
ich hÀtte gerne mehr Interaktionsmöglichkeiten mit dem Emulator (API, Hooks)
ich bin mit allem zufrieden
etwas anderes (teilen Sie uns in den Kommentaren mit)
8 Benutzer haben abgestimmt. 1 Benutzer hat sich enthalten.
Quelle: habr.com


