SecurityInsider
Le blog des experts sécurité Wavestone

Tour d’horizon des techniques anti-reverse engineering



L’analyse de code malveillant (malwares) est une discipline complexe et soumise à de nombreuses contraintes. En particulier, le développement de code malveillant implémentant des techniques anti-analyses devient de plus en plus fréquent, que ce soit pour contourner les « boîtiers de sécurité » ou pour ralentir le travail des analystes.
Cet article propose de discuter de quelques-unes de ces techniques « anti-reverse ».

Polymorphisme et métamorphisme

Depuis de nombreuses années, les développeurs de malwares ont bien compris les défauts des antivirus « statiques » basés sur des signatures. Afin de contrer ces outils de sécurité statiques, les codes malveillants se réécrivent automatiquement à chaque réplication pour que la signature du malware soit modifiée, on parle de polymorphisme.
Les antivirus ne se basent pas forcément sur une signature globale, mais plutôt sur des signatures de morceaux du programme. Il est ainsi nécessaire pour le programme d’effectuer des modifications du code en différents endroits. Le chiffrement utilisant une clef différente à chaque génération est un exemple de polymorphisme.
Le métamorphisme est une technique qui automatise un polymorphisme afin que chaque propagation d’un malware entraine une réécriture automatique du malware sans s’appuyer sur des données constantes ou sans requérir une fonction de déchiffrement « statique ». Elle peut par exemple prendre la forme d’une addition de NOP, de la permutation de registres, de l’addition d’instructions ou boucles inutiles, du réordonnancement des fonctions, de la modification du flux du programme…
Des programmes visent à contrer de tels comportements, comme c’est le cas de TAPS (Trait Analytic Program Search) introduit par l’institut national de justice des États-Unis (NIJ).

Packers

Les packers sont des programmes devenus très populaires parmi les créateurs de malwares étant donné qu’ils permettent de cacher le malwares aux antivirus, de compliquer l’analyse et de réduire la taille des exécutables. Les packers permettent notamment de rendre l’analyse statique inutile, à moins de réussir à les contourner.
Le principe de fonctionnement des packers est de transformer un exécutable en un autre plus petit, qui va contenir l’ancien exécutable sous forme de données, ainsi qu’un système d’unpacking appelé par le système d’exploitation.
Pour contrer un packer il est nécessaire de réaliser l’opération inverse à celle qui a été réalisée. Le problème est que les packers peuvent intervenir de différentes manières, et il est donc impératif de comprendre les actions qui ont été réalisées afin de les inverser.
Il existe plusieurs indicateurs d’un programme packé, parmi lesquels :
  • Le fait que le programme contienne peu de fonctions importées, et que LoadLibrary et GetProcAddress en fasse partie.
  • Lorsque le programme est chargé par IDA Pro, seule une petite partie du code est reconnue automatiquement.
  • Lorsque le programme est lancé dans OllyDbg, une pop-up signale que le programme est peut-être packé.
  • Le programme indique des noms de sections spécifiques à un packer particulier, par exemple UPX0.
  • Les tailles virtuelles de certaines sections (notamment la section .text) sont beaucoup plus grandes que les tailles sur le disque.
  • PEiD réussi à déterminer que le programme est packé, et donne le nom du packer.
  • L’entropie du programme est particulièrement haute (cela peut également être vrai si le programme est chiffré).
Dès lors que le packing est reconnu, l’analyste peut essayer d’inverser l’opération. Cela peut parfois être assez simple, par exemple si le packer identifié est UPX, il suffit de réitérer la commande avec l’option –d. Cependant lorsque l’analyste doit effectuer cette action manuellement, elle peut s’avérer très complexe et longue. Elle suit généralement les étapes suivantes :
  • Dépacker le programme original en mémoire.
  • Reconstruire la table des fonctions importées.
  • Trouver le point d’entrée original et le replacer.

Anti-virtualisation et anti-émulation

L’analyse de codes malveillants nécessite un environnement contrôlé. Beaucoup d’analystes vont donc choisir d’utiliser des machines virtuelles, présentant de plus l’avantage de pouvoir revenir facilement à un état enregistré. C’est pourquoi les créateurs de malwares ont commencé à y implémenter des éléments anti-machines virtuelles (anti-VM).
Ces techniques sont le plus souvent employées pour des malwares ayant pour but de se propager à grande échelle. Cependant, le gain obtenu par l’attaquant est aujourd’hui à mettre au regard de la prolifération des « virtual desktops » : les machines virtuelles sont en effet de plus en plus utilisées par des utilisateurs standards non analystes... autrement dits, les cibles des malwares.
Il existe énormément de techniques anti-VM, notamment car certaines techniques sont spécifiques à un hyperviseur, et peuvent souvent être déclinées pour tous. Dans la suite de cet article, seules certaines des techniques les plus connues seront présentées.

Recherche d'artefacts

Cette technique consiste à rechercher des éléments présents uniquement dans une machine virtuelle, comme certains processus. Elle est évidemment à adapter selon l’hyperviseur. Par exemple sur une machine virtuelle Windows lancée avec l’hyperviseur VMware, le gestionnaire de tâche présente trois processus liés à VMware.
Gestionnaire de tâche sur une machine virtuelle lancée par VMware

De nombreux artefacts différents peuvent être cherchés, mais ne seront pas détaillés ici. Cependant la manière de passer outre ces techniques est souvent la même : trouver la recherche d’artefacts dans le code assembleur et le modifier, soit en effectuant ou supprimant un saut pour qu’il ne soit plus appelé, soit en modifiant le code de la recherche lui-même.

Red Pill

Certaines instructions x86 permettent d’accéder à des informations matérielles sans pour autant générer d’interruptions. Cependant ces fonctions renvoient des résultats différents lorsqu’elles sont utilisées sur une machine virtuelle plutôt que sur un ordinateur physique.
Pour bien comprendre les techniques qui vont suivre, il est nécessaire de connaître certaines structures et tables utilisées par le processeur :
  • IDTInterrupt Descriptor Table : une structure de données interne au processeur et utilisée par le système d’exploitation pour déterminer la réponse à donner aux interruptions et exceptions.
  • GDTGlobal Descriptor Table – et LDTLocal Descriptor Table : tous les accès mémoire doivent passer par l’une de ces deux tables. Elles contiennent les détails d’accès aux segments, comme l’adresse de base, la taille ou les droits d’accès.
Les instructions sidt, sdgt et sldt permettent d’accéder à la valeur de ces tables.
La technique dénommée Red Pill en référence au film Matrix, utilise la fonction sidt pour accéder au registre IDT. Comme cette fonction ne lève pas d’interruption, la machine virtuelle n’est pas prévenue de cet appel et ne peux changer la valeur pour donner celle de l’hôte. La fonction renvoie donc la valeur de la machine virtuelle. Par exemple pour VMware, la valeur du registre IDT vaut 0xFF. Un bout de code permettant de détecter une machine virtuelle tournant sur VMware pourrait alors être le suivant :
Programme utilisant la technique de Red Pill introduite par Joanna Rutkowska

Remarque : Cette technique n’est valable que sur une machine ayant un simple processeur. En effet dans une machine à processeurs multiples, chaque processeur a une valeur d’IDT assignée, et la fonction sidt peut alors renvoyer différents résultats.
RedPill.exe utilisé dans une machine virtuelle.

No Pill

Cette technique va utiliser les fonctions sgdt et sldt. Elle se base sur le fait que la structure LDT est assignée à un processeur et non un système d’exploitation. Ce qui est intéressant est que Windows n’utilise en général pas cette structure alors que VMware la supporte. Les résultats seront donc différents.
Pour parer à cette technique, il suffit généralement de changer légèrement la configuration de la machine virtuelle en désactivant l’accélération par exemple.
Remarque : D’autres fonctions peuvent être utilisées dans la détection de machines virtuelles, parmi lesquelles smsw, str in et cpuid. Il peut être intéressant de faire une recherche sur ces instructions à l’aide d’un outil d’analyse tel qu’IDA Pro.

Scoopy

L’outil Scoopy, développé par Tobias Klein, permet d’identifier si un système est natif ou virtualisé par VMware. Les actions réalisées par cet outil sont les suivantes :
  • Les trois premiers tests utilisent les fonctions sidt, sgdt et sldt en reprenant les techniques Red Pill et No Pill.
  • Ensuite un quatrième test utilise str.
  • Les cinquièmes et sixièmes tests utilisent des backdoors présentes sur le port 0xa et sur les options 0x14 des entrées/sorties (I/O).
  • Un dernier test se basant sur un bogue plus ancien des anciennes versions de VMware tournant en mode émulation.
Le code de cette technique est le suivant :

Code désassemblé de Scoopy

Scoopy lancé sur un Windows 2000 dans VMware
Remarque : La dernière version en date est nommée ScoopyNG (reprises des fonctionnalités de Scoopy Doo et Jerry) : http://www.trapkit.de/research/vmm/scoopyng/index.html.

Techniques anti-émulation

Pendant longtemps l’émulation semblait être un meilleur choix pour l’analyse de malware étant donné qu’aucune technique d’évasion n’avait été trouvée. Puis Peter Ferrie a publié plusieurs de ses attaques, ce qui explique l’utilisation des machines virtuelles de nos jours, permettant une analyse plus rapide : http://pferrie.tripod.com/papers/attacks.pdf.

Jusqu'à la destruction du poste de l'analyse

De nombreuses autres techniques sont utilisées par les créateurs de malwares pour échapper à la détection d’un outil de sécurité… et pour complexifier le travail des analystes : des techniques anti-désassemblage (saut forcé, saut avec condition constante, rogue byte, etc.) aux techniques anti-débogage (IsDebuggerPresent, INT scanning, etc.).
Certains malwares particulièrement agressifs vont jusqu’à essayer de compromettre les outils de l’analyste, ou les données collectées. Dans certains cas extrêmes, des attaquants ont même créé des preuves de l’implication de l’analyste.
Un des exemples que l’on peut retrouver d’une telle technique est l’exploitation de la librairie libbfd utilisée dans le programme Strings qui fait souvent partie de l’analyse.
Nicolas DAUBRESSE & Vincent NGUYEN

Aucun commentaire:

Enregistrer un commentaire