
Nur-binärer Firmware-Historian, der lernt, Funktionen in rohen Binärdateien zu lokalisieren, indem er bekannte Funktionen aus ähnlichen Binärdateien extrahiert, was einen schnellen Funktionsabgleich ohne Disassemblierung für die Analyse eingebetteter Firmware ermöglicht.
Polypyus lernt, Funktionen in rohen Binärdateien zu lokalisieren, indem es bekannte Funktionen aus ähnlichen Binärdateien extrahiert. Somit ist es ein Firmware-Historian. Polypyus arbeitet ohne diese Binärdateien zu disassemblieren, was ein Vorteil für Binärdateien ist, deren Disassemblierung komplex ist und bei denen gängige Werkzeuge Funktionen übersehen. Darüber hinaus macht der rein binäre Ansatz es sehr schnell und lässt es innerhalb weniger Sekunden laufen. Allerdings erfordert dieser Ansatz, dass die Binärdateien für dieselbe Architektur bestimmt sind und ähnliche Compiler-Optionen aufweisen.
Polypyus integriert sich in den Workflow vorhandener Werkzeuge wie Ghidra, IDA, BinDiff und Diaphora. So kann es beispielsweise zuvor annotierte Funktionen importieren und daraus lernen, und auch gefundene Funktionen exportieren, um sie in IDA zu importieren. Da Polypyus eher strenge Schwellenwerte verwendet, hat es in unseren Experimenten nur korrekte Übereinstimmungen gefunden. Dies führt zwar zu weniger Ergebnissen als in vorhandenen Werkzeugen, ist aber ein guter Ausgangspunkt, um diese Übereinstimmungen in IDA zu laden, um dessen Auto-Analyse-Ergebnisse zu verbessern und dann BinDiff darauf anzuwenden.
Bei der Arbeit mit rohen Firmware-Binärdateien, nämlich verschiedenen Broadcom- und Cypress-Bluetooth-Firmware-Versionen, stellten wir fest, dass die IDA-Autoanalyse Funktionsanfänge oft falsch identifizierte. In IDA Pro 6.8 ist die Autoanalyse etwas aggressiver, was zu mehr Ergebnissen, aber auch mehr falsch Positiven führt. Insgesamt war IDA Pro 7.2 pessimistischer, übersah aber viele Funktionen. Dies führte zu nur wenigen BinDiff-Übereinstimmungen zwischen unseren Firmwares in IDA Pro 6.8 und zu gar keinen brauchbaren Übereinstimmungen in IDA Pro 7.2.
Interessanterweise scheiterte BinDiff oft daran, Funktionen zu identifizieren, die – abgesehen von Verzweigungen – byteweise identisch waren. Beachten Sie, dass Polypyus genau nach diesen byteweise identischen Funktionen sucht. Wir vermuten, dass BinDiff bei diesen Funktionen aufgrund eines anderen Call-Graphen scheitert, der durch fehlende Funktionen und falsch Positive entsteht. Manchmal wurden diese Funktionen bereits von IDA erkannt, aber oft erkannte IDA sie entweder nicht als Code oder markierte sie nicht als Funktion. Beachten Sie, dass Diaphora ähnliche Probleme hat, da es von IDA identifizierte Funktionen exportiert, bevor es sie weiterverarbeitet. Im Folgenden wird ein Benchmark auf dem CYW20735B1-Bluetooth-Firmware-Binärlauf gezeigt, der verschiedene Disassembler und die daraus resultierenden Folgeprobleme beim Diffing vergleicht.
Darüber hinaus fanden wir zwar, dass Amnesia viele Funktionen findet, aber auch viele falsch Positive. Allerdings haben viele Funktionen einen ähnlichen Stack-Frame-Aufbau am Anfang. Daher bietet Polypyus eine Option, um gängige Funktionsanfänge aus den annotierten Eingabe-Binärdateien zu lernen und auf andere Binärdateien anzuwenden, um Funktionen ohne Namenszuordnung zu identifizieren. Dieser optionale Schritt wird nur auf die Bereiche angewendet, in denen zuvor keine Funktionen lokalisiert wurden, sodass die Methode der gemeinsamen Funktionsanfänge und die Hauptfunktionssuche nicht in Konflikt geraten.
Da diese Matcher auf der rohen Binärdatei arbeiten, sind sie nicht von einem Disassembler abhängig. Dies hat jedoch einen wichtigen Nachteil: Wenn unterschiedliche Compiler-Optionen oder eine andere Zielarchitektur vorlagen, wird Polypyus keine ähnlichen Funktionen erkennen. Darüber hinaus sind die identifizierten Übereinstimmungen zwar sehr zuverlässig, die Identifizierung von Funktionsanfängen ist jedoch etwas weniger zuverlässig, daher ist letztere mit Vorsicht zu verwenden. Im Folgenden sehen Sie, dass die Cypress-Evaluierungs-Kits einander sehr ähnlich sind, die MacBook-Firmware jedoch sehr unterschiedlich ist.
Polypyus erstellt unscharfe binäre Matcher durch den Vergleich gemeinsamer Funktionen in einer Sammlung annotierter Firmware-Binärdateien.
Derzeit werden die folgenden Annotationen unterstützt:
patch.elf-Datei, eine spezielle ELF-Datei, die nur Symboldefinitionen enthält..symdefs-Datei, wie sie von den meisten ARM-Compilern erzeugt wird..csv-Datei mit einem im Ordner firmware dokumentierten Format.Diese Annotationen enthalten die Adresse, Größe und den Namen bekannter Funktionen. Je mehr Gemeinsamkeiten die Eingabe-Binärdateien in der Historiensammlung haben, desto besser für die Leistung und die Ergebnisse von Polypyus. Bei mehreren leicht unterschiedlichen Funktionen erstellt Polypyus sehr gute Matcher.
Polypyus erfordert Python 3 >= 3.6. Wir empfehlen die Verwendung einer virtuellen Umgebung für die folgende Installation. Klonen Sie dieses Repository und führen Sie in diesem Ordner Folgendes aus:
pip install .
Nach der Installation stehen die folgenden Befehle zur Verfügung:
polypyus-guipolypyus-cliPolypyus ist über eine grafische und eine Befehlszeilen-Schnittstelle verfügbar.
Sowohl die GUI polypyus-gui als auch die CLI polypyus-cli akzeptieren beim Aufruf diese Argumente:
--verbose Legt den Ausführlichkeitsgrad fest. Standardmäßig werden Warnungen angezeigt, -v zeigt Informationen, -vv Debug-Informationen.
--project Legt den Speicherort der Projektdatei fest. Dies ist entweder ein Dateipfad oder ":memory:".
--help Zeigt die Hilfemeldung an.
Die Projektoption ermöglicht es Ihnen, Ihre Arbeit für verschiedene Kontexte in verschiedenen Dateien zu speichern und auch wieder zu öffnen.
Der allgemeine GUI-Workflow geht von der linken Seite des Fensters zur rechten Seite.
Zuerst werden Binärdateien zum Verlauf hinzugefügt. Dann folgen Symbolannotationen zu den Einträgen im Verlauf.
Danach können Ziel-Binärdateien hinzugefügt werden.
Für das Matching klicken Sie auf Create matchers from history. Sobald die Matcher erstellt sind, können einzelne Ziele ausgewählt oder alle Ziele durch Auswahl von batch match gematcht werden.
Schließlich können die Ergebnisse in eine .csv-Datei exportiert werden.
Im Folgenden sehen Sie ein Demo-Video, in dem Polypyus nur wenige Sekunden benötigt, um aus zwei Eingabe-Binärdateien zu lernen, diese zu annotieren, Matcher zu erstellen und Übereinstimmungen auf eine neue Binärdatei anzuwenden.
Der Vorteil der CLI ist ihre Automatisierbarkeit. Derzeit kann sich das Ausgabeformat der CLI noch ändern. Hier ist jedoch ein Beispiel für den Aufruf:
polypyus-cli --history firmware/history/20819-A1.bin --annotation firmware/history/20819-A1_patch.elf --history firmware/history/20735B1.bin --annotation firmware/history/20735B1_patch.elf --project test.sqlite
polypyus-cli --target firmware/history/20739B1.bin --project test.sqlite
Der erste Befehl erstellt test.sqlite als neue Projektdatei und importiert 20819-A1.bin und 20735B1.bin mit ihren jeweiligen patch.elf-Dateien.
Der zweite Aufruf verwendet dieselbe Projektdatei erneut und matcht gegen die Binärdatei 20739B1.bin.
Bei jedem Befehl muss die Anzahl der --history- und --annotation-Argumente übereinstimmen.
Diese beiden Befehle könnten auch zu einem kombiniert werden, indem das --target-Argument zum ersten Befehl hinzugefügt wird.
Ein Paper, das die Interna erklärt, wurde auf dem Workshop on Binary Analysis Research (BAR) 2021 mit dem Titel Polypyus - The Firmware Historian veröffentlicht. Einige weitere Details sind auch in der Abschlusspräsentation von Jans Masterarbeit enthalten, die die Probleme behandelt, die bei der Arbeit mit herkömmlichen binären Diffing-Ansätzen im ARM Thumb2-Modus auftreten, und wie der alternative, rein binäre Ansatz funktioniert.
Die geleakten Symbole im patch.elf- oder .symdefs-Format enthalten nur Funktions- und globale Variablennamen. Es gibt jedoch auch einige .pdom-Eclipse-Projektdateien in WICED Studio 6.2 und 6.4. Diese enthalten zusätzliche Typinformationen. Eclipse verwendet sie intern für Auto-Vervollständigung, Funktionssuche usw., und wir können sie beim Reversing nutzen, um Typinformationen hinzuzufügen. Da .pdom-Dateien nur teilweise, zwischengespeicherte Informationen enthalten, kann es hilfreich sein, mehrere von ihnen zu kombinieren.
In einem ersten Schritt exportieren wir .pdom-Typinformationen in eine SQLite-Datenbank. Der Export dauert eine Weile, kann aber sogar abgebrochen und später fortgesetzt werden. Der Export funktioniert wie folgt:
java -jar pdom/export/export.jar -P BCM20739-B0.1462220149391.pdom
Der PDOM-Import sucht nach Funktionsnamen in einer IDA-Datenbank, schlägt sie im PDOM nach, um Typinformationen zu finden, und wendet diese Typinformationen dann auf die IDA-Datenbank an. Daher muss die IDA-Datenbank vorab korrekte Funktionsnamen enthalten. Im Prinzip können diese mit den import_export-Skripten von Polypyus erstellt werden. Die etwas fortschrittlicheren Skripte, die den PDOM-Import unterstützen, können jedoch auch patch.elf-Abschnitte verarbeiten. Führen Sie den Import wie folgt durch:
T=0x1 (Alt-g).patch.elf-Datei aus (Select file).20739mapb0.h importieren, um Hardware-Register zu benennen (Import map.h).Dieses Skript wurde auf IDA Pro 7.4 und 7.5 getestet.
Nach einigen internen Tests können wir den folgenden Workflow bei der Arbeit mit IDA Pro und Polypyus empfehlen:
Alt-g, T=0x1).0x0 mit rx, RAM bei 0x200000 mit rwx (zumindest für die Bluetooth-Firmware).0x4 ist (o). Auf der CYW20735-Firmware zeigt er auf 0x3bc+1. Gehen Sie ein Byte zurück und erstellen Sie eine Funktion (p)....jetzt könnte Ihre IDA-Datenbank einigermaßen nützlich sein :) Im ARM Thumb2-Modus scheitert der Disassembler zwar immer noch an vielen Dingen, aber es ist weitaus besser als alles, was IDA alleine macht.
Der Ordner firmware enthält verschiedene Firmwares mit und ohne Symbole.
Alles im Verzeichnis history enthält Symbole, alles im Verzeichnis targets ist ohne Symbole.
Für die Samsung-Serie umfasst S8 auch das Note 8 und S8+ usw., und die S10/S20 umfasst alles vom S10e bis zum Note 20 5G.
Die Dump-Qualität kann variieren, einige sind mit RAM und einige sind nur das ROM. Wir haben Zugang zu den meisten Geräten in dieser Liste. Wenn Sie einen Dump mit den aktuellsten Patch-Leveln und einschließlich RAM benötigen, kontaktieren Sie uns gerne.
Einige im Paper erwähnte Geräte sind hier nicht enthalten, da es sich möglicherweise nicht um reine Forschungsgeräte handelt usw. Einige iPhones und MacBooks fehlen ebenfalls, da wir sie als reine Forschungsgeräte haben, der ursprüngliche Dump jedoch nicht. Diese Geräte werden bald hinzugefügt :)
In diesem Repository befindet sich eine .editorconfig-Datei. Sie konfiguriert den Einrückungsstil, die Zeichenkodierung und die Zeilentrenner. Befolgen Sie diese Konfiguration beim Mitwirken, was durch die Verwendung eines IDE-Plugins für .editorconfig erleichtert werden kann.
Um die Testabhängigkeiten zu installieren, führen Sie
pip install '.[test]'
aus. Dies installiert Pakete, die nur für die Ausführung von Testfällen benötigt werden.
Entwicklungsabhängigkeiten bieten z. B. Stubs für Pakettypen. Um sie zu installieren, führen Sie
pip install '.[development]'
aus.
pytest führt alle Tests aus.
Das Projekt verwendet tox, um die Tests lokal gegen verschiedene Python-Versionen auszuführen. Tox ist so eingerichtet, dass es gegen die Versionen 3.6, 3.7, 3.8 und 3.9 testet. Um tox auszuführen, installieren Sie die Testabhängigkeiten und diese 4 genannten Python-Versionen. Unsere empfohlene Methode zur Installation und Verwaltung mehrerer Python-Versionen ist pyenv.
Schritte:
pyenv install 3.9.1
pyenv install 3.8.6
pyenv install 3.7.9
pyenv install 3.6.12
pyenv virtualenv 3.9.1 polypyus
pyenv local polypyus 3.8.6 3.7.9 3.6.12
pip install '.[test]'
pip install '.[development]'
tox aus.Polypyus verwendet GitHub Actions für automatisierte Testläufe und einige Linting-Schritte. Wenn Sie möchten, können Sie die Linting-Schritte lokal mit Pre-Commit-Git-Hooks ausführen.
Jedes Mal, bevor ein neuer Commit erstellt wird, wird dadurch das Linting ausgelöst und die Probleme angezeigt, die verhindern würden, dass dieser Code den GitHub Actions-Linting-Schritt besteht. Es wird auch geänderte Dateien mit Black formatieren.
pip install '.[development]'
pre-commit install
Wir danken Anna Stichling für die Erstellung des Polypyus-Logos. Wir danken auch Christian Blichmann und Joxean Koret für ihr Feedback.
Polypyus ist Open-Source und unter der GPLv3 lizenziert.
| Chip | Gerät | Bau-Datum | Symbole |
|---|
| BCM20703A2 | MacBook/iMac 2016-2017 | 22. Okt. 2015 | ✔ |
| CYW20719B1 | Evaluierungsboard | 17. Jan. 2017 | ✔ |
| CYW20735B1 | Evaluierungsboard | 18. Jan. 2018 | ✔ |
| CYW20819A1 | Evaluierungsboard | 22. Mai 2018 | ✔ |
| Chip | Gerät | Bau-Datum | Symbole |
|---|
| BCM2046A2 | iMac Late 2009 | 2007? | - |
| BCM2070B0 | MacBook 2011, Thinkpad T420 | 9. Juli 2008 | - |
| BCM20702A1 | Asus USB-Dongle | Feb. (?) 2010 | - |
| BCM4345B0 | iPhone 6 | 15. Juli 2013 | - |
| BCM4335C0 | Google Nexus 5 | 11. Dez. 2012 | - |
| BCM4345B0 | Google Nexus 6P / Galaxy S6 | 23. Okt. 2014 | - |
| BCM43430A1 | Raspberry Pi 3 und Zero W | 2. Juni 2014 | - |
| BCM4345C0 | Raspberry Pi 3+ und 4 | 19. Aug. 2014 | - |
| BCM4347B0 | Samsung Galaxy S8-Serie | 3. Juni 2016 | - |
| BCM4375B1 | Samsung Galaxy S10/20-Serie | 13. Apr. 2018 | - |
| BCM4378B1 | iPhone 11/SE2 | 25. Okt. 2018 | Strings |