Pierre Graux (avec Marie-Laure Potet et dinh ta than) : Dévirtualisation de programme

De Ensiwiki
Aller à : navigation, rechercher
Cornues.png
Titre du projet Dévirtualisation de programme
Cadre IRL

Équipe PACSS
Encadrants Marie-Laure Potet et Dinh Ta Tanh


Introduction

Les programmes informatiques que nous utilisons tous les jours peuvent contenir des informations sensibles. En effet ils peuvent contenir par exemple un algorithme de validation de licence qui, s'il est découvert, pourrait permettre à des utilisateurs de ne pas payer le programme. De manière plus générale le contenu d'un programme peut être une propriété intellectuelle.

C'est pourquoi des techniques dites d'obscurcissement ont été développées, elles ont pour but de rendre plus compliqué la compréhension du fonctionnement d'un programme. Elles sont également utilisées à des fins illégales : pour éviter aux chercheurs en sécurité informatique de comprendre le fonctionnement d'un malware et pouvoir ainsi l'empêcher de fonctionner.

L'une de ces techniques s'appelle la virtualisation. C'est cette dernière que j'ai étudié lors du module d'Introduction à La Recherche en Laboratoire dans le but de proposer une méthode d'analyse de programme virtualisé.

Le rapport complet peut être trouvé ici : Fichier:Rapport.pdf.

Virtualisation

Afin de comprendre ce qu'est la virtualisation j'ai étudié Tigress, un logiciel de virtualisation de programme développé par Christian Collberg. Il permet de modifier un code source C pour virtualiser une ou plusieurs fonctions.

Pour étudier la structure des programmes, une méthode consiste à étudier les graphe de flot de contrôle (CFG). Un CFG est une représentation graphique de tous les chemins empruntables par le code d'un programme.

Par exemple la fonction suivante :

   int bin(char* str, int length){
       int res=0;
       int i;
       for(i=0;i<length;i++) {
               res *= 2;
               if( str[i] == '1' )
                       res ++;
               else if( str[i] != '0' )
                       return 0;
       }
       return res;
   }

Possède le CFG suivant : Bin.png

En effet le principe de la virtualisation est de déplacer le code dans le segment de données sous forme d'opcode. Le segment de code est alors remplacé par le code d'un interpréteur qui vient regarder le code dans le segment de donnée et l'exécuter. Pour cela à chaque opération du programme est associé un opcode (une valeur aléatoire). Le programme entier est alors représenté par un tableau d'opcode. Le code est alors remplacé par une boucle infinie qui vient regarder la valeur de chaque opcode pour savoir quelle portion de code exécuter.

Lorsque l'on regarde le CFG de la fonction bin une fois virtualisée, il est donc totalement modifié : Bin call init.png

Méthode d'Analyse Proposée

Une fois la technique de virtualisation connue j'ai pu m'atteler à la conception d'une méthode pour retrouver le CFG des codes des instructions. En d'autres termes nous voulons, à partir du programme virtualisé, reconstruire un CFG qui décrit tous les chemins qui peuvent être empruntés par l'interprétation.

La méthode que je propose est :

  • réaliser un ensemble de traces du programme
  • les combiner pour construire un CFG
  • repérer dans ce CFG les noeuds aux arités élevées (ce qui correspond aux noeuds de l'interpréteur)
  • réaliser de nouvelles traces en ne prenant en compte que le code qui est contenu entre l'entrée et la sortie de l'interpréteur (ce qui correspond aux codes des instructions du programme)
  • combiner ces nouvellles traces pour construire un nouveau CFG qui devrait être similaires au CFG inital

Après avoir implémenté cette méthode (grâce à cfgrecon et trace-pin) j'ai pu constaté sur des exemples que cette méthode marche.

Notamment sur la fonction suivante:

int func(int a,int b) {
    return a+b;
}

Cependant elle ne marche pas (au niveau du comptage des arités) pour la virtualisation implémentée avec un switch.

Conclusion

Au terme de ces trois mois de travail, j'ai eu l'occasion d'approcher l'univers de la recherche. Au travers de l'étude d'un problème ouvert, celui de la dévirtualisation de programme, j'ai pu découvrir comment me renseigner sur un sujet, proposer et valider une approche. Pour ce qui est de la méthode proposée elle est concluante sur une partie des techniques de virtualisation.

Même si le module d'Introduction à la Recherche en Laboratoire est terminé, mon travail sur la dévirtualisation n'est pas fini puisque je compte rester en contact avec l'équipe pour finir la méthode et soumettre un éventuelle article.