
Outil d'historique de firmware binaire uniquement qui apprend à localiser des fonctions dans des binaires bruts en extrayant des fonctions connues de binaires similaires, permettant une correspondance rapide des fonctions sans désassemblage pour l'analyse de firmware embarqué.
Polypyus apprend à localiser des fonctions dans des binaires bruts en extrayant des fonctions connues de binaires similaires. C'est donc un historien de firmware. Polypyus fonctionne sans désassembler ces binaires, ce qui est un avantage pour les binaires complexes à désassembler et pour lesquels les outils courants manquent des fonctions. De plus, l'approche binaire uniquement le rend très rapide et s'exécute en quelques secondes. Cependant, cette approche exige que les binaires soient de la même architecture et aient des options de compilateur similaires.
Polypyus s'intègre dans le flux de travail d'outils existants comme Ghidra, IDA, BinDiff et Diaphora. Par exemple, il peut importer des fonctions précédemment annotées et apprendre à partir de celles-ci, et également exporter les fonctions trouvées pour être importées dans IDA. Comme Polypyus utilise des seuils plutôt stricts, il n'a trouvé que des correspondances correctes dans nos expériences. Bien que cela conduise à moins de résultats que dans les outils existants, c'est un bon point de départ pour charger ces correspondances dans IDA afin d'améliorer ses résultats d'analyse automatique, puis d'exécuter BinDiff par-dessus.
Lors du travail sur des binaires de firmware bruts, notamment diverses versions de firmware Bluetooth Broadcom et Cypress, nous avons constaté que l'analyse automatique d'IDA identifiait souvent incorrectement les débuts de fonctions. Dans IDA Pro 6.8, l'analyse automatique est un peu plus agressive, ce qui donne plus de résultats mais aussi plus de faux positifs. Dans l'ensemble, IDA Pro 7.2 était plus pessimiste, mais manquait beaucoup de fonctions. Cela a conduit à seulement quelques correspondances BinDiff entre nos firmware dans IDA Pro 6.8 et à aucune correspondance utile dans IDA Pro 7.2.
Fait intéressant, BinDiff échouait souvent à identifier des fonctions qui, à l'exception des branches, étaient identiques octet par octet. Notez que Polypyus recherche exactement ces fonctions identiques octet par octet. Nous supposons que BinDiff échoue sur ces fonctions en raison d'un graphe d'appel différent produit par des fonctions manquantes et des faux positifs. Parfois, ces fonctions étaient déjà reconnues par IDA, mais souvent, IDA ne les reconnaissait pas comme du code ou ne les marquait pas comme fonction. Notez que Diaphora a des problèmes similaires, car il exporte les fonctions identifiées par IDA avant de les traiter plus avant. Ce qui suit montre un benchmark sur le binaire du firmware Bluetooth CYW20735B1 qui compare divers désassembleurs et comment les échecs du désassembleur entraînent des problèmes de différences en aval.
De plus, bien que nous ayons constaté qu'Amnesia trouve de nombreuses fonctions, il trouve aussi de nombreux faux positifs. Cependant, de nombreuses fonctions ont une configuration de cadre de pile similaire au début. Ainsi, Polypyus a une option pour apprendre les débuts de fonctions courants à partir des binaires d'entrée annotés et l'appliquer à d'autres binaires pour identifier des fonctions sans faire correspondre leur nom. Cette étape optionnelle n'est appliquée qu'aux régions dans lesquelles aucune fonction n'a été précédemment localisée, de cette façon la méthode des débuts de fonctions courants et la recherche principale de fonctions n'entrent pas en conflit.
Comme ces matchers travaillent sur le binaire brut, ils ne dépendent pas d'un désassembleur. Cela a aussi un inconvénient important : s'il y avait des options de compilateur différentes ou une architecture cible différente, Polypyus ne détectera pas de fonctions similaires. De plus, bien que les correspondances identifiées soient très fiables, l'identification du début de fonction est un peu moins fiable, donc utilisez cette dernière avec précaution. Dans ce qui suit, vous pouvez voir que les kits d'évaluation Cypress sont très similaires entre eux, mais que le firmware du MacBook est très différent.
Polypyus crée des matchers binaires flous en comparant des fonctions communes dans une collection de firmware binaires annotés.
Actuellement, les annotations suivantes sont prises en charge :
patch.elf WICED Studio, qui est un fichier ELF spécial contenant uniquement des définitions de symboles..symdefs tel que produit par la plupart des compilateurs ARM..csv avec un format documenté dans le dossier firmware.Ces annotations contiennent l'adresse, la taille et le nom des fonctions connues. Plus il y a de points communs entre les binaires d'entrée dans la collection d'historique, meilleures sont les performances et les résultats de Polypyus. Étant donné plusieurs fonctions légèrement différentes, Polypyus crée de très bons matchers.
Polypyus nécessite Python 3 >= 3.6. Nous conseillons d'utiliser un virtualenv pour l'installation suivante. Clonez ce dépôt et dans ce dossier exécutez :
pip install .
Après l'installation, les commandes suivantes sont disponibles :
polypyus-guipolypyus-cliPolypyus est disponible via une interface graphique et une interface en ligne de commande.
L'interface graphique polypyus-gui et la CLI polypyus-cli prennent toutes deux ces arguments lors de l'appel :
--verbose est le niveau de verbosité. Par défaut, il affiche les avertissements -v affiche les infos -vv affiche les informations de débogage.
--project définit l'emplacement du fichier de projet. Il s'agit soit d'un chemin de fichier, soit de ":memory:".
--help Affiche le message d'aide.
L'option de projet vous permet de stocker votre travail pour différents contextes dans différents fichiers et également de les rouvrir.
Le flux de travail général de l'interface graphique va du côté gauche de la fenêtre vers la droite.
D'abord, des binaires sont ajoutés à l'historique. Ensuite, des annotations de symboles pour les entrées
de l'historique sont ajoutées.
Après cela, des binaires cibles peuvent être ajoutés.
Pour la correspondance, cliquez sur Créer des matchers à partir de l'historique. Une fois les matchers créés, des cibles
individuelles peuvent être sélectionnées, ou toutes les cibles peuvent être mises en correspondance en sélectionnant batch match.
Enfin, les résultats peuvent être exportés dans un fichier .csv.
Dans la vidéo de démonstration ci-dessous, Polypyus ne prend que quelques secondes pour apprendre à partir de deux binaires d'entrée, les annoter, créer des matchers et appliquer les correspondances à un nouveau binaire.
L'avantage d'utiliser la CLI est sa capacité à être automatisée. Pour l'instant, le format de sortie de la CLI est susceptible de changer. Voici néanmoins un exemple d'appel :
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
La première commande crée test.sqlite comme nouveau fichier de projet et importe 20819-A1.bin et 20735B1.bin
avec leurs fichiers patch.elf respectifs.
La deuxième invocation réutilise le même fichier de projet et effectue la correspondance avec le binaire 20739B1.bin.
Pour chaque commande, le nombre de --history et --annotation doit correspondre.
Ces deux commandes peuvent également être combinées en une seule en ajoutant l'argument --target à la première commande.
Un article expliquant les mécanismes internes a été publié au Workshop on Binary Analysis Research (BAR) 2021 sous le titre Polypyus - The Firmware Historian. Quelques détails supplémentaires sont également contenus dans la présentation finale du Master de Jan, qui couvre les problèmes rencontrés lors du travail avec les approches de différenciation binaire classiques en mode ARM Thumb2, et comment l'approche alternative uniquement binaire fonctionne.
Les symboles divulgués dans les fichiers patch.elf ou au format .symdefs ne contiennent que des noms de fonctions et
de variables globales. Cependant, il existe également quelques fichiers de projet Eclipse .pdom
dans WICED Studio 6.2 et 6.4. Ceux-ci contiennent des informations de type supplémentaires. Eclipse les utilise
en interne pour l'auto-complétion, la recherche de fonctions, etc., et nous pouvons les utiliser en rétro-ingénierie
pour ajouter des informations de type. Comme les fichiers .pdom ne contiennent que des informations partielles et mises en cache, il peut
être utile d'en combiner plusieurs.
Dans une première étape, nous exportons les informations de type .pdom dans une base de données SQLite. L'exportation
prend du temps, mais peut même être interrompue et reprise plus tard. L'exportation fonctionne comme suit :
java -jar pdom/export/export.jar -P BCM20739-B0.1462220149391.pdom
L'importation PDOM recherche les noms de fonctions dans une base de données IDA, les recherche dans le PDOM pour trouver
des informations de type, puis applique ces informations de type dans la base de données IDA. Ainsi, la base de données IDA
doit contenir des noms de fonctions corrects au préalable. En principe, ceux-ci peuvent être créés avec les
scripts import_export de Polypyus. Cependant, les scripts un peu plus avancés
qui prennent en charge l'importation PDOM peuvent également gérer les sections patch.elf. Exécutez l'importateur comme suit :
T=0x1 (Alt-g).patch.elf (Select file).20739mapb0.h pour nommer les registres matériels (Import map.h).Ce script a été testé sur IDA Pro 7.4 et 7.5.
Après quelques tests internes, nous pouvons recommander le flux de travail suivant lorsque vous travaillez avec IDA Pro et Polypyus :
Alt-g, T=0x1).0x0 avec rx, RAM à 0x200000 avec rwx (au moins pour le firmware Bluetooth).0x4 (o).
Sur le firmware CYW20735, il pointe vers 0x3bc+1. Revenez d'un octet en arrière et créez une fonction (p)....maintenant votre base de données IDA pourrait être quelque peu utile :) Encore beaucoup de choses sur lesquelles le désassembleur échoue dans ARM Thumb2, mais bien mieux que tout ce qu'IDA fait tout seul.
Le dossier firmware contient divers firmware avec et sans symboles.
Tout ce qui se trouve dans history contient des symboles, tout ce qui se trouve dans targets est sans symboles.
Pour la série Samsung, le S8 inclut également le Note 8 et le S8+, etc., et le S10/S20 inclut également tout, du S10e au Note 20 5G.
La qualité des dumps peut varier, certains sont avec RAM et d'autres uniquement la ROM. Nous avons accès à la plupart des appareils de cette liste. Si vous avez besoin d'un dump avec les niveaux de correctifs les plus récents et incluant la RAM, n'hésitez pas à nous contacter.
Quelques appareils mentionnés dans l'article ne sont pas inclus ici, car ils pourraient ne pas être des appareils de recherche uniquement, etc. Quelques iPhones et MacBooks manquent également, car nous les avons comme appareils de recherche uniquement mais le dump original ne l'était pas. Ces appareils seront ajoutés bientôt :)
Il y a un fichier .editorconfig dans ce dépôt. Il configure le style d'indentation, le jeu de caractères et les séparateurs de ligne. Suivez cette configuration lorsque vous contribuez, ce qui peut être facilité si vous utilisez un plugin IDE pour .editorconfig.
Pour installer les dépendances de test, exécutez
pip install '.[test]'
cela installera les paquets qui ne sont nécessaires que pour exécuter les cas de test.
Les dépendances de développement fournissent par exemple des stubs pour les types de paquets. Pour les installer, exécutez
pip install '.[development]'
pytest exécutera tous les tests.
Le projet utilise tox pour exécuter localement les tests avec différentes versions de python. Tox est configuré pour tester les versions 3.6, 3.7, 3.8 et 3.9. Pour exécuter tox, installez les dépendances de test et installez ces 4 versions mentionnées de python. Notre méthode recommandée pour installer et gérer plusieurs versions de python est pyenv.
Étapes :
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
penv local polypyus 3.8.6 3.7.9 3.6.12
pip install '.[test]'
pip install '.[development]'
toxPolypyus utilise GitHub Actions pour les exécutions de tests automatisés et quelques vérifications de style. Si vous le souhaitez, vous pouvez exécuter les étapes de vérification de style localement avec des hooks git pre-commit.
Chaque fois qu'un nouveau commit est créé, cela déclenchera la vérification de style et affichera les problèmes qui empêcheraient ce code de réussir l'étape de vérification de style GitHub Actions. Cela formatera également les fichiers modifiés avec black .
pip install '.[development]'
pre-commit install
Nous remercions Anna Stichling pour la création du logo Polypyus. Nous remercions également Christian Blichmann et Joxean Koret pour leurs retours.
Polypyus est open-source et sous licence GPLv3.
| Puce | Appareil | Date de construction | Symboles |
|---|
| BCM20703A2 | MacBook/iMac 2016-2017 | 22 oct. 2015 | ✔ |
| CYW20719B1 | Carte d'évaluation | 17 janv. 2017 | ✔ |
| CYW20735B1 | Carte d'évaluation | 18 janv. 2018 | ✔ |
| CYW20819A1 | Carte d'évaluation | 22 mai 2018 | ✔ |
| Puce | Appareil | Date de construction | Symboles |
|---|
| BCM2046A2 | iMac Fin 2009 | 2007 ? | - |
| BCM2070B0 | MacBook 2011, Thinkpad T420 | 9 juil. 2008 | - |
| BCM20702A1 | Dongle USB Asus | Fév. (?) 2010 | - |
| BCM4345B0 | iPhone 6 | 15 juil. 2013 | - |
| BCM4335C0 | Google Nexus 5 | 11 déc. 2012 | - |
| BCM4345B0 | Google Nexus 6P / Galaxy S6 | 23 oct. 2014 | - |
| BCM43430A1 | Raspberry Pi 3 et Zero W | 2 juin 2014 | - |
| BCM4345C0 | Raspberry Pi 3+ et 4 | 19 août 2014 | - |
| BCM4347B0 | Samsung Galaxy S8 série | 3 juin 2016 | - |
| BCM4375B1 | Samsung Galaxy S10/20 série | 13 avr. 2018 | - |
| BCM4378B1 | iPhone 11/SE2 | 25 oct. 2018 | Chaînes |