Rédacteur : Heurs
Date de création : 04/07/2006
Section : Sécurité > Shellcodes
Imprimer cet article : en noir et blanc ou en couleurs
Les shellcodes polymorphiques sont une sorte d'évolution des shellcodes, ils peuvent prendre un nombre illimité de formes tout en gardant les mêmes actions. Cela fait augmenter légèrement la taille de votre shellcode mais cette techniques permet de passer au travers de beaucoup de sécurités, notemment les IDS.
La première forme du polymorphisme est de réécrire une instruction en plusieurs différentes, par exemple :
peut devenir :
Ne rigolez pas pour le mov, certaines versions de gcc l'utilisent par défaut quand une fonction doit retourner 0... alors que le xor est bien plus rapide à exécuter pour un processeur !
Cette forme de polymorphisme à une infinité de possibilités, et est relativement efficace.
Mais souvent les IDS (des sortes de parfeu mais uniquement réseau) regardent si la chaine /bin/sh est présente. Là, une simple réécriture des instructions ne suffira pas.
C'est l'un des moyens les plus efficaces d'etre sur que votre shellcode sera illisible par un programme intermédiaire.
Le but va etre de crypter le shellcode et de créer un module de décryptage qui seras intégrer à notre shellcode (sinon celui-ci ne pourrait etre executé). Cela permetra donc a notre shellcode de prendre n'importe quel forme.
Pour le cryptage j'ai opté pour le xor (la base du cryptage), sa table de vérité est simple :
Nous voyons bien ici que si deux bits sont de valeurs différentes le résultat sera 1, et si ils ont la meme valeur ce sera 0. Cette table permet à partir d'une valeur et une clé de pouvoir en créer une nouvelle (valeur), mais aussi à partir de la nouvelle et de la clé retrouver l'ancienne. La preuve en image avec python :
Ici 16 est la clé, et nous pouvons constater que la clé permet de chiffrer/déchiffrer. (le ^ est l'opérateur de xor)
Codons maintennant un crypteur par xor en C :
Ici on reprend les octets a la suite en leur appliquant le xor, et on affiche le résultat de façon utilisable imméditement (\x90 par exemple). Bon je n'ai pas été trés inspiré désolé, nous utiliserons tout du long le fameux "Hello World !".
Nous avons donc vu comment l'algorithme de cryptage du shellcode, nous pouvons donc nous attarder sur le module de décryptage.
Il semble bien évident que ce module devra etre codé en assembleur. Je travaille sous knoppix 2.4.27 avec GCC 3.3.5 parce que sur ma bécane linux, GCC suporte mal l'assembleur inline, et comme j'ai la flème de recopier les shellcodes octets par octet (avec le risque d'erreurs que cela comporte). J'ai aussi codé un petit utilitaire ou j'entre mon code assembleur qui me recrache son code hexa (cf article Automatisation de la conception de shellcodes). Je concidère qu'il y a toujours un bit terminal, donc un .string est obligatoire à la fin de chaque code asm. Je vous présente donc le code assembleur du module puis vous le commente :
Etant initié aux shellcodes je ne vais vous expliquer que trés brièvement le fonctionnement de celui-ci. Le module va donc prendre l'adresse du shellcode crypté et va regarder si l'octet à décrypter est un 0. Si s'en est un (donc l'octet terminal) il sautera sur le shellcode, et donc l'executera. Pour le reste des valeurs possibles il appliqueras un xor sur l'octet avec la clé (ici 25). Nous lançons le prog pour afficher le shellcode :
Et voila notre module est codé !
Plus qu'a faire un petit prog en C pour automatiser les générations et le tour est joué !
Testons maintennent ceci sur un buffer overflow (donc en situation réelle) :
Je vous joint les deux programmes que j'ai codé :
gene_shellcode1.c
gene_shellcode1
poly-shell_all.c
poly-shell_all
Le tout disponible dans cette archive.
Je vous ai laissé les binaires comme ca si vous rencontrez les meme problèmes que moi au niveau de la compilation, vous pourrez quand meme utiliser ces outils).
Bien entendu, une partie du shellcode reste fixe ici (le décrypteur), mais il est possible, en faisant jouer votre imagination, de la rendre plus dynamique. Aprés avoir lu cet article vous devriez en etre capable tout du moins ;) .