Cet article a pour but d’expliquer comment mettre en en place un setup de différentiation de binaires (bindiffing en anglais) grâce à Bindiff et Binary Ninja. Dans un premier temps je vais présenter les deux outils, puis nous verrons comment les mettre en oeuvre.
Bindiff
Bindiff est un outil de comparaison permettant de trouver les différences et les similitudes entre des fichiers binaires. Il est principalement utilisé pour identifier et isoler les différents correctifs de sécurité entre deux mises à jour.
Bindiff a été créé par la société Zynamics. Zynamics a ensuite été rachetée par Google en 2011 qui a rendu l’outil gratuit en 2016.
Il est aussi possible d’exporter les noms des fonctions d’un binaire à un autre, ce qui permet d’automatiser la détection de certaines fonctions plus simplement après la mise à jour d’un binaire par exemple.
graphe Bindiff
Ci-dessus on peut voir les graphes d’une même fonction sur deux ROMs d’iPhones (A13 et A14).
Bindiff affiche en jaune les blocs modifiés et en rouge les instructions supprimées sur la fonction primaire. Les nouvelles instructions sont surlignées en bleu sur la fonction du second binaire.
Binary Ninja
Binary Ninja est un désassembleur que j’utilise depuis maintenant un an et demi. J’ai longtemps utilisé son concurrent, IDA Pro (merci à Jiang Ying pour ça), mais j’ai décidé d’utiliser Binja qui possède une API étendue, une interface graphique moderne ainsi que des mises à jour régulières. Les supports d’architecture sont tous compris pour le même prix.
screenshot de Binary Ninja avec un bootloader d’iPhone XR
Avec Binary Ninja on peut donc avoir une vue avec différents langages intermédiaires (LLIL, MLIL, HLIL) plus ou moins proche de l’assembleur. Le screenshot ci-dessus affiche certains des différents langages intermédiaires de Binary Ninja.
BinExport
Pour pouvoir exporter les données de Binary Ninja vers Bindiff on va utiliser BinExport, un plugin pour Ghidra, IDA et Binja permettant d’exporter le contenu d’une base de données au format requis par Bindiff.
Vous pouvez récupérer le plugin directement dans la section releases du projet Github. Il vous suffit de copier le binaire décompressé dans le bon répertoire pour votre système d’exploitation:
- Linux :
~/.binaryninja/plugins
- macOS :
~/Library/Application Support/Binary Ninja/plugins/
- Windows :
%AppData%\Binary Ninja\plugin
Après avoir redémarré Binary Ninja la ligne suivante devrait apparaître dans les logs :
1
BinExport 12 (@377499286, Jun 4 2021), (c)2004-2011 zynamics GmbH, (c)2011-2021 Google LLC.
Ce message confirme que le plugin a bien été chargé par Binary Ninja. Si vous vous rendez dans Tools -> Plugins
une nouvelle option apparait pour invoquer BinExport.
Binary Ninja avec option BinExport
Si vous lancez l’exportation vous devriez avoir les logs d’export de la base de données de Binary Ninja vers le nouveau fichier au format de BinExport.
1
2
3
4
5
6
7
8
9
10
11
12
13
/home/mathieu/Documents/diff_article/iBoots/iBoot.n841.RELEASE.15.2.1.bin: starting export
Added 0 entry points from calls
Added 6159 entry points from functions
flow analysis
Added 282412 entry points from flow analysis
sorting instructions
reconstructing flow graphs
reconstructing functions
Binary Ninja specific post processing
writing...
Writing to: "/home/mathieu/Documents/diff_article/iBoots/iBoot.n841.RELEASE.15.2.1.BinExport".
/home/mathieu/Documents/diff_article/iBoots/iBoot.n841.RELEASE.15.2.1.bin: 15.39s processing, 2.55s writing
/home/mathieu/Documents/diff_article/iBoots/iBoot.n841.RELEASE.15.2.1.bin: exported 6159 functions with 209018 instructions in 17.95s
Bindiffing
Les outils sont configurés, on peut passer à la pratique. Pour cela il faut deux binaires à analyser. Pour cet article je vais comparer les deux versions 15.2.1 et 15.3 beta 2 d’un bootloader pour iPhone XR.
Après avoir chargé ces images dans Binary Ninja avec le loader approprié, il faut les exporter avec BinExport dans Tools -> Plugins -> BinExport
ou bien avec la command palette (ctrl+p).
Comme vu ci-dessus, un nouveau fichier au format de BinExport est créé avec l’extension .BinExport
dans le même répertoire ou se trouve le fichier binaire.
On démarre Bindiff et on créer un nouveau Workspace (dans File -> New Workspace
). Puis on génère le fichier de Diff entre les deux fichiers au format BinExport
.
Creation de diff
Vous pouvez aussi lancer Bindiff depuis la ligne de commande en spécifiant les deux fichiers BinExport
.
1
2
3
4
5
6
7
8
9
10
11
λ ~ » /opt/bindiff/bin/bindiff --primary iBoot.n841.RELEASE.15.2.1.BinExport --secondary iBoot.n841.RELEASE.15.3b2.BinExport
BinDiff 7 (@377499286, Jun 4 2021), (c)2004-2011 zynamics GmbH, (c)2011-2021 Google LLC.
Setup: 12.92s
primary: iBoot.n841.RELEASE.15.2.1: 6159 functions, 641249 calls
secondary: iBoot.n841.RELEASE.15.3b2: 6147 functions, 639592 calls
Matching: 1h 17m 22.54s
matched: 6137 of 6159/6147 (primary/secondary, 6098/6087 non-library)
call graph MD index: primary 387.191
secondary 386.753
Similarity: 98.9679% (Confidence: 99.2021%)
Writing results: 3.86s
Le calcul entre les deux fichiers peut prendre un certain temps surtout si les fichiers sont très volumineux. Comme on peut le voir ci-dessus, l’analyse a mis 1 heure et 17 minutes.
Si vous êtes passé par la ligne de commande pour générer le fichier au format .diff
, vous pouvez charger ce même fichier depuis le menu suivant : Diffs -> Add Existing Diff
. On se retrouve ensuite sur la vue ci-dessous.
Bindiff overview
En cliquant sur “Matched Functions”, on peut avoir une liste de toutes les fonctions qui sont plus ou moins similaires avec un indicateur de confiance sur la similitude de deux fonctions.
Liste des fonctions
Et pour avoir un graphe comme la capture ci-dessous, il nous suffit de double-cliquer sur la ligne de la fonction que l’on veut différencier.
Graphe
Et voila ! Vous savez comment faire du bindiffing à l’aide de Bindiff et Binary Ninja !
Bindiff Viewer
Je vous disait plus haut qu’il était possible d’exporter les noms des fonctions d’un binaire à un autre.
Pour ce faire avec Binary Ninja, PistonMiner a développé un plugin, Bindiff Viewer, qui permet de visualiser dans une nouvelle fenêtre le resultat de Bindiif. Celui-ci disponible dans le plugin manager de Binary Ninja.
En lançant le plugin vous devrez sélectionner le fichier .diff
comme pour Bindiff et définir le type de votre BNDB actuellement ouverte dans Binja (primaire ou secondaire).
Une nouvelle fenêtre va s’ouvrir listant les fonctions similaires entre les deux fichiers.
Bindiff viewer
Vous pourrez ainsi visualiser la liste des fonctions similaires, comme dans Bindiff, mais cette fois-ci vous avez la possibilité d’exporter les symboles d’une BNDB à une autre, en les selectionnant puis en faisant un clic droit -> export symbols
.
IDA
Bindiff est aussi compatible avec IDA Home/Pro et on peut lister les correspondances de fonction directement IDA.
Bindiff permet d’avoir uniquement une vue par graphique. C’est parce que celui-ci n’exploite pas à 100% les APIs d’IDA. Il ne sera donc pas possible d’avoir une vue lineaire ou du pseudo-code, contrairement à Diaphora, un autre outil de bindiffing uniquement pour IDA.
Diaphora et IDA Home
N’hésitez pas à aller voir comment j’ai setup Diaphora pour appliquer des symboles sur une BootROM de Raspberry Pico
Donc voila, c’était une introduction à la mise en place d’un setup avec Bindiff et Binja.
J’espère que ce post vous a plu, n’hésitez pas à me contacter sur Twitter ou même par mail si vous avez des questions.
Liens et sources :