• Aucun résultat trouvé

Dans cette section nous discutons des limitations de notre approche ainsi que des contre-mesures pouvant ˆetre misent en place afin de contrer notre analyse. Pour cela, nous commen¸cons par introduire les d´efinitions des termes r´esultat correct, r´esultat complet et r´esultat pertinent.

5.7.1

Propri´et´es attendues

Soit la fonction f0 obtenue `a partir d’une fonction f avec notre approche. On note φw la disjonction logique de l’ensemble des pr´edicats de chemin calcul´e en

reconstruisant f0. On d´efinit Sf0 comme l’ensemble des valeurs satisfaisant φw. Sf0

est le support de construction de f0.

R´esultat correct : Soit f0 la fonction reconstruite d’une fonction virtualis´ee f , et Sf0 son support de construction. On consid`ere que la fonction f0 est correcte

si pour toutes les entr´ees dans Sf0, la valeur retourn´ee par l’ex´ecution de f0 est

identique `a celle retourn´ee par l’ex´ecution de f . Soit : ∀x ∈ Sf0, f0(x) = f (x). Si

la fonction d´evirtualis´ee est correcte, on dit que le r´esultat de notre approche est correct.

R´esultat complet : Soit f0 la fonction reconstruite d’une fonction virtualis´ee f , et Sf0 son support de construction comprenant toutes les entr´ees (x ∈ X).

On consid`ere que la fonction f0 est compl`ete si pour toutes les entr´ees dans Sf0, la

valeur retourn´ee par l’ex´ecution de f0 est identique `a celle retourn´ee par l’ex´ecution de f . Soit : ∀x ∈ Sf0, f0(x) = f (x). Si la fonction d´evirtualis´ee est compl`ete, on

dit que le r´esultat de notre approche est complet.

R´esultat pertinent : Soit f0 la fonction reconstruite d’une fonction virtualis´ee f . On dit que le r´esultat de notre analyse est pertinent si la concision (crit`ere C1,

Section 5.4.1) de la fonction f0(x) est b´en´efique pour un analyste.

Le Tableau 5.8 est l’aper¸cu des cons´equences de chacune des limitations sur le r´esultat de notre approche, ces limitations ´etant ensuite discut´ees dans les sections qui suivent.

R´esultat de notre approche

Pr´esence d’index symbolique incorrect & incomplet

Couverture incompl`ete des chemins incomplet

Timeout du solveur de contraintes incomplet

sous-approximation de la teinte incorrect & incomplet

sur-approximation de la teinte non pertinent

Bytecode prot´eg´e non pertinent

Cas nominal correct, complet et pertinent

Table 5.8 – Aper¸cu des cons´equences de chacune des limitations sur le r´esultat de notre approche.

† : indexes concrets, peu de chemins, teinte et solveur ok

5.7.2

Acc`es m´emoire `a index symbolique

La politique de concr´etisation du moteur symbolique de Triton (voir Sec-

tion 3.5.3, Figure 3.10) ne nous permet pas d’avoir une repr´esentation des acc`es m´emoires sous la forme symbolique. Cela signifie que l’impl´ementation de notre approche (voir Section 5.2.7) ne nous permet de reconstruire des acc`es m´emoire d´ependants des entr´ees de la fonction (arguments teint´es).

0 1 . char b y t e s [ ] = { 0 2 . 0 x11 , 0 x22 , 0 x33 , 0 x44 , 0 x55 , 0 x66 , 0 3 . 0 x77 , 0 x88 , 0 x99 , 0 xaa , 0xbb , 0 xcc , 0 4 . 0xdd , 0 xee , 0 x f f 0 5 . } ; 0 6 .

0 7 . unsigned f (unsigned x ) { 0 8 . i n t hash = 1 ; 0 9 . while ( x ) { 1 0 . hash ∗= b y t e s [ ( x & 0 x f f ) % s i z e o f( b y t e s ) ] ; 1 1 . x >>= 1 ; 1 2 . } 1 3 . return hash ; 1 4 . }

Listing 5.10 – Exemple d’index symbolique

Le Listing 5.10 illustre un exemple de structure de code impliquant un index symbolique. Dans cet exemple, l’argument x de la fonction f est symbolique ainsi que teint´e. `A la ligne 10, x est utilis´e comme index dans le tableau bytes et le contenu de ce tableau est utilis´e dans le calcul du hash. Compte tenu de la poli- tique de concr´etisation de Triton, ce lien entre l’argument de la fonction (qui est symbolique) et l’indexation du tableau dans le calcul du hash est perdu (concr´etis´e pour une entr´ee donn´ee). Cela signifie que le r´esultat de notre approche sera cor- rect uniquement pour une seule entr´ee (celle courante) mais incorrect pour le reste des valeurs possibles de x et par cons´equent incomplet.

Conclusion : En pr´esence d’indexation symbolique, le r´esultat de notre ap- proche est incorrect et incomplet.

5.7.3

Couverture de chemins et timeout

Explosion combinatoire : La compl´etude de notre approche est bas´ee sur le

fait de pouvoir lister l’ensemble des chemins d’une fonctions virtualis´ee. Cela pose probl`eme sur des grosses fonctions en raison de l’explosion combinatoire qu’im- plique l’exploration des chemins.

Conclusion : Si l’ensemble des chemins n’est pas ´enum´er´e, le r´esultat de notre approche est incomplet.

Expressions trop complexes : Comment mentionn´e pr´ec´edemment, nous de-

vons identifier toutes les branches possibles d’une fonction afin d’avoir un r´esultat complet. Pour cela, nous faisons appel au solveur de contraintes pour r´esoudre chaque condition de branchement et ainsi parcourir toutes les branches (voir Sec- tion 5.2.5.1) de la fonction virtualis´ee. Une contre-mesure possible pour cette ´etape

serait d’int´egrer des expressions complexes `a r´esoudre pour chaque condition de branchement (conditions d´ependantes des entr´ees teint´ees) afin d’engendrer un d´elai non n´egligeable (ex : timeout ) cˆot´e solveur de contraintes. Ci-dessous un exemple avec le Listing 5.11 o`u hash(x) serait une fonction de hachage cryptogra- phique non r´eversible.

i n t f (i n t x ) { i f ( hash ( x ) == 0 x 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 ) /∗ . . . ∗/ e l s e /∗ . . . ∗/ }

Listing 5.11 – Contre-mesure possible pour notre ´etape de couverture de chemin

Conclusion : En pr´esence de timeout lev´e par le solveur de contraintes, le r´esultat de notre approche est incomplet.

5.7.4

Sous ou sur-approximation de la teinte

´

Etant donn´e que nous nous reposons sur une analyse de teinte pour dissocier les instructions qui font partie de la machine virtuelle de celles qui sont ex´ecut´ees pour simuler le programme d’origine, il serait possible pour un d´efenseur d’entrelacer ces deux s´equences d’instructions pour (1) engendrer une sous-approximation de la teinte afin d’omettre certaines instructions utilis´ees dans le calcul du programme d’origine et donc d’impliquer une incorrection sur le r´esultat final, (2) engendrer une sur-approximation de la teinte afin d’int´egrer le plus d’instructions teint´ees possibles sur la trace d’ex´ecution. Par exemple, si nous imaginons que toutes les instructions ex´ecut´ees faisant partie de la machine virtuelle sont teint´ees, le r´esultat de notre approche serait la machine virtuelle dans son int´egralit´e (ce qui ne serait pas pertinent pour un analyste).

Conclusion : En cas d’une sous-approximation de la teinte, le r´esultat de notre approche est incorrect et incomplet. En cas d’une sur-approximation le r´esultat de notre approche est non pertinent.

5.7.5

Prot´eger le bytecode plutˆot que la VM

Une contre-mesure possible contre des attaques statiques et dynamiques se- rait de prot´eger le bytecode de la machine virtuelle plutˆot que ses composants (l’un n’empˆechant pas l’autre). Prenons comme exemple le code illustr´e dans le Listing 5.12. Cette fonction f effectue une simple multiplication de ses deux argu- ments.

i n t f (i n t x , i n t y ) {

return x ∗ y ; }

Listing 5.12 – ´Echantillon de fonction `a virtualiser

Supposons maintenant que nous voulions prot´eger ce calcul en appliquant une protection par virtualisation. Le Listing 5.13 illustre un exemple de bytecode pos- sible qui sera simul´e par une machine virtuelle. Dans notre exemple, le registre r9 est l’argument x et le registre r10 l’argument y. C’est deux registres sont mis respectivement dans r0 et r1, puis une multiplication est effectu´ee en pla¸cant le r´esultat dans r0. Le registre r0 ´etant le registre de retour (comme rax pour x86-64).

31 01 00 09 : MOV r0 , r 9 31 01 01 0 a : MOV r1 , r 1 0 44 00 00 01 : MUL r0 , r0 , r 1

60 : RET

Listing 5.13 – Bytecode de la fonction f

Nos exp´erimentations (voir Section 5.3) montrent clairement que ce genre

de code virtualis´e (simple fonction avec un calcul sans effet de bord) permet tr`es facilement de retrouver son code d’origine (x × y). En prot´egeant le by- tecode de la machine virtuelle par le biais de passes d’obfuscation, cela ren- drait le r´esultat de notre approche moins pertinent. Par exemple, l’utilisation de MBA rendrait la compr´ehension des expressions arithm´etiques et logiques apr`es d´evirtualisation plus compliqu´ees. Par exemple, Yongxin Zhou et al. [101] montrent qu’une op´eration x× y peut ˆetre transform´ee en une expression (x ∧ y) × (x ∨ y) + (x∧ (¬y)) × (¬x ∧ y). Si cette transformation est appliqu´ee sur le bytecode du Listing 5.13, notre approche ne pourrait pas retrouver le code d’origine x× y et aura pour r´esultat l’expression issue du MBA, ce qui nuirait `a la compr´ehension de la fonction f .

Conclusion : En cas de bytecode prot´eg´e, le r´esultat de notre approche est non pertinent.

Documents relatifs