• Aucun résultat trouvé

4.2 D´ etection symbolique de pr´ edicats opaques

4.2.2 M´ ethodologie

La m´ethode mise en œuvre pour d´etecter des pr´edicats opaques dans les condi- tions de branchement est la suivante :

? ´Etape 0, r´ecup´eration des blocs de base : D´esassemblage statique de code binaire puis construction d’un CFG pour obtenir la liste des blocs de base du programme. Cette ´etape peut ˆetre effectu´ee par des outils tels que IDA, Radare, Ghidra, . . .

? ´Etape 1, construction des contraintes : Pour chaque bloc de base ter-

minant par un saut conditionnel, lancer une instance de Triton en rendant symbolique l’ensemble des registres ainsi que chaque lecture m´emoire† – les ´ecritures m´emoire sont de fait inutiles. Cela correspond `a suivre pr´ecis´ement les registres tout en abstrayant compl`etement la m´emoire. Puis ex´ecuter avec Triton chacune des instructions du bloc de base. Ce dernier se charge de construire les expressions symboliques de chaque affectation (cellules m´emoire, registres et drapeaux) y compris celles du pointeur d’instructions. Si le bloc de base contient des appels externes, ignorer les appels et symboliser leur valeur de retour ce qui r´esulte en une sur-approximation de ces derni`eres. ? ´Etape 2, d´etection des pr´edicats opaques : Pour chaque bloc de base,

r´ecup´erer le pr´edicat de chemin φ construit par Triton et v´erifier qu’il est SAT, puis faire de mˆeme avec sa n´egation ¬φ. Si, l’un des deux pr´edicats φ ou¬φ est UNSAT, cela signifie que l’une des deux branches est inatteignable et qu’il existe un pr´edicat opaque dans la condition de branchement. Atten- tion, `a l’inverse si les deux pr´edicats de chemin sont SAT cela ne garantit pas l’absence d’un pr´edicat opaque dans la condition de branchement car nous effectuons une sur-approximation du raisonnement symbolique (voir Section 4.2.3), tout ´etant symbolis´e en d´ebut de bloc.

Note importante : Par d´efaut Triton concr´etise les acc`es m´emoire et renvoie

l’expression symbolique ϕ assign´ee `a la cellule m´emoire index´ee (voir r`egle @ en Figure 3.9). Lors de l’´etape 1, pour pouvoir renvoyer une nouvelle variable symbolique lorsqu’une lecture m´emoire a lieu, il faut interagir sur le compor- tement initial du moteur symbolique de Triton. Pour cela, nous utilisons une fonctionnalit´e de Triton nous permettant de placer des hooks sur diff´erentes ´etapes (lecture, ´ecriture, . . .) de ses composants internes (concret, symbolique, . . .). Les hooks ne permettent pas de modifier le comportement des r`egles d’ana- lyses mais uniquement de modifier le contexte avant et apr`es l’application de ces

derni`eres. Nous utilisons donc le m´ecanisme de hooks pour initialiser les cellules m´emoire avant chaque lecture de ces derni`eres (r`egle @) en y pla¸cant des nou- velles variables symboliques. Cela r´esulte en une sur-approximation des lectures m´emoire. Un exemple d’utilisation des hooks est pr´esent´ee ci-apr`es.

Sur-approximation des lectures m´emoire : Dans ce cas d’´etude, l’usage

de hook permettant de cr´eer une nouvelle variable symbolique d`es qu’une lecture m´emoire `a lieu, nous permet de prendre en compte l’ensemble des possibilit´es venant de la m´emoire (peu importe l’indexation de la lecture). Pour illustrer ce concept, prenons comme exemples les pseudo-codes des listings suivants.

x := @a y := @b if ( x > y ) { ... } ... Listing 4.2 – Exemple 1 x := @a y := @a if ( x == y ) { ... } ... Listing 4.3 – Exemple 2 @a := x y := @a if ( x == y ) { ... } ... Listing 4.4 – Exemple 3

Toutes les cellules m´emoire lues se verront assigner une nouvelle variable sym-

bolique. Dans l’exemple du Listing 4.2, au moment de la lecture m´emoire @a,

Triton concr´etise l’adresse point´ee par a (disons 0x1000) et assigne son contenu `a la variable x. Ici, avec l’usage des hooks, on va donc construire une variable sym- bolique (disons v1) et l’assigner `a la variable x (x := v1). On fait de mˆeme avec

la lecture @b (y := v2). Au moment de la condition de branchement, nous avons

donc un pr´edicat avec deux variables symboliques (v1 > v2) et cela peu importe la

valeur des adresses initiales.

Dans l’exemple du Listing 4.3 les variables x et y sont initialis´es avec le contenu m´emoire point´e par a. Dans cet exemple, x et y se verront assigner deux variables symboliques distinctes alors qu’elles pointaient sur la mˆeme adresse m´emoire. Lors de la condition de branchement le pr´edicat sera alors vrai ou f aux alors qu’il devrait toujours ˆetre vrai. Ce qui r´esulte en une sur-approximation des valeurs.

Dans l’exemple du Listing 4.4 la variable x est issue d’une assignation pr´ec´edente (ex. bloc de base parent), on dit alors qu’elle est externe au p´erim`etre local du bloc de base courant et donc symbolique (x := v1). Lors de l’instruction @a := x, la

variable v1 est plac´ee `a l’adresse de a mais lors de deuxi`eme instruction, nous char-

geons tout de mˆeme une nouvelle variable symbolique dans y (y := v2) car une

lecture m´emoire a lieu et tout contenu lu se voit symbolis´e. Lors de la condition de branchement le pr´edicat sera alors vrai ou f aux alors qu’il devrait toujours ˆetre vrai. Ce qui r´esulte en une sur-approximation des valeurs.

Travaux similaires pour la d´etection de POs : David et al. [16] on travaill´e sur des travaux similaires en effectuant une analyse symbolique dite en arri`ere born´ee (Backward-Bounded DSE ). Cela signifie qu’ils partent de chaque condition de branchement dans le programme `a une position X et effectue une ex´ecution

symbolique de X − N `a X o`u N est le nombre fixe d’instructions `a remonter

dans le CFG (dans leur ´etude la d´elimitation est fix´ee `a 16 instructions). Notre m´ethode est d’ailleurs proche de BB-SE [16] mais avec une borne dynamique (fin d’un bloc de base) au lieu d’une taille fixe d’instructions et nous calculons en avant (`a partir de la limite jusqu’`a la condition de branchement) plutˆot que en arri`ere (de la condition de branchement vers la limite). Cependant, tout comme David et al. nous calculons le mˆeme objet prek (pr´ed´ecesseurs en moins de k ´etapes). Pour

r´esumer, les diff´erences sont essentiellement :

1. Borne dynamique mais au sein d’un mˆeme bloc de base ; 2. Sur-approximation agressive de la m´emoire ;

Par ailleurs, notre m´ethode est proche de celle de DoSE [93]. Tout comme

DosE, nous effectuons une analyse symbolique bloc par bloc en avant born´ee.

Leur m´ethode est principalement utilis´ee pour d´eterminer l’´equivalence de deux blocs de base (d´etection de pr´edicat opaque de type Two-Way). Cependant ils peuvent ´egalement d´etecter la pr´esence de pr´edicats opaques dans les conditions de branchement (classe de pr´edicats opaques qu’ils ne consid`erent pas).

Documents relatifs