[PYTHON] Essayez de créer un visualiseur de différence de chemin d'exécution avec angr + bingraphvis

Au fait, c'était l'époque du calendrier de l'Avent, alors je vais donner un service commémoratif au scénario que j'ai écrit hier. Cet article est l'article du 13e jour de Security Tools Advent Calendar 2018.

Le visualiseur de différence de chemin d'exécution est un outil qui visualise la différence entre les chemins d'exécution lorsque deux entrées sont données au même programme. (Je pensais que le nom était approprié maintenant) Par exemple, s'il existe un programme qui accepte les lettres «AB» comme indiqué ci-dessous

test.c


#include <stdio.h>
#include <stdlib.h>

void one_match() {
        puts("One match");
}

void all_match() {
        puts("Accepted!");
}

int main(int argc, char *argv[]) {
        FILE *fp;
        char buf[32] = {0};
        if (argc < 2) { 
                fprintf(stderr, "usage: ./test <input>\n");
                exit(0);
        }
        fp = fopen(argv[1], "r");
        fread(buf, sizeof(char), 31, fp);
        if (buf[0] == 'A') {
                if (buf[1] == 'B') {
                        all_match();
                        return 0;
                } else {
                        one_match();
                }
        }
        puts("Not good");
        return 0;        
}

Étant donné la chaîne "AX", "Not good" après one_match (), Étant donné la chaîne "AB", all_match (), Je veux visualiser cela d'une bonne manière même si cela passe par différents chemins d'exécution.

python


$ cat test1.in test2.in
AX
AB
$ ./test test1.in 
One match
Not good
$ ./test test2.in 
Accepted!

angr+Bingraphvis Il y a deux choses principales que je veux faire cette fois.

Cette fois, j'ai utilisé angr et Bingraphvis. Bingraphvis est une bibliothèque de base qui prend en charge angr-utils pour visualiser CFG généré par angr. Il gère les opérations, les transformations et les tracés des nœuds CFG. En utilisant ceci et le QEMU Runner (traceur) de angr,

  1. Enregistrez une trace pour deux entrées avec QEMU Runner
  2. Générez CFG après la fonction principale avec CFGEmulated
  3. Colorez le nœud CFG qui correspond à la différence de trace avec Bingraphviz
  4. Enregistrez CFG au format png

Je l'ai fait. La raison pour laquelle je n'ai pas utilisé le wrapper angr-utils était que je voulais définir et utiliser une variante CFG avec mes propres différences de trace. Si vous l'exécutez contre le programme mentionné précédemment, il crachera l'image ci-dessous.

python


$ python3 input-tracer.py -b ./test -i test1.in,test2.in -v
[+] Opening binary ./test
[+] CFG Cache found 
CFG size = 46
[+] Tracing .... test1.in
Size: 46079
[+] Tracing .... test2.in
Size: 46033
[+] CFG processing ....
Graph len= 30
[+] Complete! Saved to outd/input_trace_test_entire.png

input_trace_test_entire.png

Le chemin quand le rouge donne test1.in et le bleu donne test2.in. Le commun est noir.

Tracer par fonction à l'aide de CFGFast

Si vous faites ce qui précède pour un programme comme un utilitaire UNIX, vous tracerez un énorme CFG (5 000 nœuds ou plus) et générerez une image de dizaines de milliers de pixels. Bien sûr, le spectateur ne peut pas être affiché et tombe, ce qui altère le sens de la visualisation. Il est possible d'afficher uniquement les nœuds avec des différences au lieu de l'ensemble du CFG (sans -v de la commande ci-dessus), mais les différences seules peuvent être très importantes. Par conséquent, nous avons également ajouté une fonction pour tracer CFG en divisant l'image pour chaque fonction du programme.

  1. Enregistrez une trace pour deux entrées avec QEMU Runner
  2. Obtenez une liste des fonctions définies dans le binaire avec CFGFast de angr.
  3. Effectuez le même processus que ci-dessus pour chaque fonction

Activé avec l'option -f.

$ python3 ./input-tracer.py -b mp3_player -i invalid.mp3,1.mp3 -f                              
[+] Opening binary mp3_player                                 
[+] Searching for all the functions (using CFGFast)                             
100% |#####################################| Elapsed Time: 0:00:02 Time: 0:00:02
   ==> 106 functions to process.                                                
[+] Tracing .... invalid.mp3                                                    
Size: 1305732                                                                   
[+] Tracing .... 1.mp3                                                          
Size: 6084333                                                                   
[+] CFG processing ....                                                         
[+](0/106) Computing Accurate CFG for function _init (0x8049cd8)               
[+] CFG Cache found                                                             
Graph len= 0                                                                    
[+] Complete! Saved to outd/input_trace_mpg321-0.3.0__init.png                  
[+](1/106) Computing Accurate CFG for function sub_8049d0c (0x8049d0c)         
[+] CFG Cache found  

Donnez au lecteur des données mp3 clairement invalides et des données mp3 valides, par exemple "ABCD". La différence CFG pour chaque fonction est représentée dans outd. input-tracer.png

En regardant la différence entre les fonctions du lecteur mp3 appelé calc_length, c'est comme suit.

input_trace_mpg321-0.3.0_calc_length.png

Code source

Le code est ci-dessous https://gist.github.com/RKX1209/3cb60b0fa0ba92da6575716680f32aa0

Recommended Posts

Essayez de créer un visualiseur de différence de chemin d'exécution avec angr + bingraphvis
Créer une visionneuse de traitement d'image avec PySimpleGUI
Essayez de générer une image avec aliénation
Essayez de créer un serveur HTTP en utilisant Node.js
Essayez de créer un Checkbutton dynamiquement avec Tkinter en Python
Un moyen simple de créer un module d'importation avec jupyter
Makefile minimal et buildout.cfg pour créer un environnement avec buildout
[Python] Récupère le répertoire d'exécution du script avec un chemin absolu
[Python Kivy] Comment créer un fichier exe avec pyinstaller
J'ai essayé de créer un article dans Wiki.js avec SQL Alchemy
Essayez de défier le sol par récursif
Créer un environnement avec virtualenv
Créer une API avec Django
Essayez Auto Encoder avec Pytorch
Créer une visionneuse d'images avec Tkinter
Créez un alias pour Route53 vers CloudFront avec l'API AWS
Essayez de créer un environnement python avec Visual Studio Code et WSL
Essayez d'extraire une chaîne de caractères d'une image avec Python3
Les utilisateurs de Rails essaient de créer un moteur de blog simple avec Django
Essayez de résoudre l'itinéraire le plus court avec les données sociales Python + NetworkX +
Essayez de créer un article de Qiita avec l'API REST [Préparation environnementale]
Essayez d'exploiter Facebook avec Python
Essayez de profiler avec ONNX Runtime
Créez une tranche d'âge avec les pandas
Essayez de produire de l'audio avec M5 STACK
J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming [Execution] (3/3)
Je souhaite créer un profil utilisateur Ubuntu Chrome avec Colab uniquement
(Remarque) Une application Web qui utilise TensorFlow pour déduire les noms de morceaux recommandés [Créer un environnement d'exécution avec docker-compose]