Techniques avancées de Shellcoding - par Darawk

Techniques avancées de Shellcoding - par Darawk

 

Introduction

Ce document assume une connaissance fonctionnante des techniques shellcoding de base, et l'ensemble x86, je pas réchauffé ceux-ci en ce document. J'espère t'enseigner certaines des techniques shellcoding moins connues que j'ai repris, qui te permettra d'écrire de plus petits et meilleurs shellcodes. Je ne prétends pas avoir inventé quelconque d'entre ces techniques, excepté celle qui emploient l'instruction de division.

La multiplicité de mul

Cette technique a été à l'origine développée par Sorbo de darkircop.net. L'instruction de mul peut, sur la surface, sembler mondaine, et c'est but évident. Cependant, une fois confronté au défi difficile de rétrécir votre shellcode, il s'avère tout à fait utile. D'abord de l'information de fond sur l'instruction de mul elle-même.

le mul exécute un non signé se multiplient de deux nombres entiers. Il prend seulement un opérande, l'autre est implicitement spécifié par le registre de _eax. Ainsi, une instruction commune de mul pourrait regarder n'importe quoi de pareil :

movl $0x0a,%eax
mul $0x0a


Ceci multiplierait la valeur stockée dans le _eax par l'opérande du mul, qui dans ce cas-ci serait 10*10. Le résultat alors est implicitement stocké dans EDX : EAX. Le résultat est stocké au-dessus d'une envergure de deux registres parce qu'il a le potentiel d'être considérablement plus grand que la valeur précédente, dépassant probablement la capacité d'un registre simple (c'est également comment des virgules flottantes sont stockées dans certains cas, comme sidenote intéressant).

Ainsi, vient maintenant la question jamais-importante. Comment pouvons-nous employer ces attributs à notre avantage en écrivant le shellcode ? Bien, laissez-nous pensent pendant une seconde, l'instruction prend seulement un opérande, donc, puisque c'est une instruction très commune, elle produira de seulement deux bytes dans notre shellcode final. Il multiplie celui qui lui soit passé par la valeur stockée dans le _eax, et stocke la valeur dans le _edx et le _eax, recouvrant complètement le contenu des deux registres, indépendamment de s'il est nécessaire de faire ainsi, afin de stocker le résultat de la multiplication. Mettons dessus nos chapeaux de mathématicien pendant une seconde, et considérez ceci, ce qui est le seul résultat possible d'une multiplication par 0 ? La réponse, comme vous avez pu avoir deviné, est 0. Je pense qu'il a lieu au sujet d'heure pour un certain code d'exemple, tellement ici il est :

xorl %ecx,%ecx
mul %ecx


Que ce shellcode fait-il ? Bien, lui le registre du _ecx de 0 dehors utilisant l'instruction de xor, ainsi nous savent maintenant que le _ecx est 0. Alors il fait un _ecx de mul, qui en tant que nous vient d'apprendre, le multiplie est opérande par la valeur dans le _eax, et puis procède stocker le résultat de cette multiplication dans EDX : EAX. Ainsi, indépendamment du contenu précédent des _eax, le _eax doit maintenant être 0. Cependant qui n'est pas tout, le _edx est 0 ' d maintenant aussi, parce que, quoiqu'aucun débordement ne se produise, il recouvre toujours l'inscription de _edx au peu de signe (le peu extrême gauche) du _eax. Utilisant cette technique nous pouvons mettre dehors trois registres en seulement trois bytes, tandis que par n'importe quelle autre méthode (cette je sais de) elle aurait pris au moins six.

L'instruction de division

La division est très semblable au mul, parce qu'elle prend seulement un opérande et divise implicitement l'opérande par la valeur dans le _eax. Également comme, mul il stocke le résultat du clivage dans le _eax. Encore, nous exigerons du côté mathématique de nos cerveaux de figurer dehors comment nous pouvons tirer profit de cette instruction. Mais d'abord, laissez-nous pensent à ce qui est normalement stocké dans le registre de _eax. Le registre de _eax tient la valeur de retour des fonctions et/ou des syscalls. La plupart des syscalls qui sont employés dans shellcoding renverront -1 (sur l'échec) ou une valeur positive d'un certain aimable, seulement rarement ils renvoient 0 (cependant il se produit). Ainsi, si nous savons qu'après qu'un syscall soit exécuté, le _eax aura une valeur différente de zéro, et que le _eax de divl d'instruction divisera le _eax par lui-même, et stockez alors le résultat dans le _eax, nous pouvons dire cela exécutant l'instruction de _eax de divl après qu'un syscall mette la valeur 1 dans le _eax. Ainsi… comment est c'applicable à shellcoding ? Bien, leur est une autre chose importante que le _eax est employé pour, et c'est de passer le syscall spécifique que vous voudriez appeler à international $0x80. Il se produit juste ainsi que le syscall qui correspond à la valeur 1 est sortie (). Maintenant pour un exemple :

xorl %ebx,%ebx
mul %ebx
push %edx
pushl $0x3268732f
pushl $0x6e69622f
mov %esp, %ebx
push %edx
push %ebx
mov %esp,%ecx
movb $0xb, %al #execve() syscall, doesn't return at all unless it fails, in which case it returns -1
int $0x80

divl %eax # -1 / -1 = 1
int $0x80


Maintenant, nous avons une fonction de sortie de 3 bytes, où comme avant elle étaient 5 bytes. Cependant, il y a un crochet, ce qui si un syscall renvoie 0 ? Bien dans la situation particulière dans laquelle cela pourrait se produire, vous pourriez faire beaucoup de différentes choses, comme le _eax d'inc., _eax de décembre, pas le _eax quelque chose qui rendra le _eax différent de zéro. Certains disent que la sortie ne sont pas importante dans le shellcode, parce que votre code obtient exécuté indépendamment de s'il sort proprement. Ils sont exacts aussi, si vous devez vraiment sauver 3 bytes pour adapter votre shellcode dedans quelque part, la sortie () n'est pas intéressant la conservation. Cependant, quand votre code finit, il essayera de s'exécuter celui qui ait été après votre dernière instruction, qui produira très probablement une DÉFECTUOSITÉ de SIG (instruction illégale) qui est une erreur plutôt impaire, et sera noté par le système. Ainsi, une sortie () ajoute simplement une couche supplémentaire de discrétion à votre exploit, de sorte que même si elle échoue ou vous ne pouvez pas essuyer toutes les notations, au moins la présente partie de votre présence soit claire.

Ouvrir la puissance de leal

L'instruction leal est une instruction souvent négligée dans le shellcode, quoiqu'il soit tout à fait utile. Considérez ce morceau court de shellcode.

xorl %ecx,%ecx
leal 0x10(%ecx),%eax


Ceci chargera la valeur 17 dans l'eax, et clair tout les peu étranger d'eax. Ceci se produit parce que l'instruction leal charge une variable du type longtemps dans elle est opérande de desitination. Dans elle est l'utilisation normale, ceci chargerait l'adresse d'une variable dans un registre, de ce fait créant un indicateur des sortes. Cependant, puisque l'ecx est 0 ' d et 0+17=17, nous chargeons la valeur 17 dans l'eax au lieu de n'importe quel genre d'adresse réelle. Dans un shellcode normal nous ferions n'importe quoi de pareil, pour accomplir la même chose :

xorl %eax,%eax
movb $0x10,%eax


Je peux vous entendre dire, mais ce shellcode est un byte plus court que le leal, et vous avez tout à fait raison. Cependant, dans un vrai shellcode vous pouvez devez déjà 0 dehors un registre comme l'ecx (ou tout autre registre), ainsi l'instruction de xorl dans le shellcode leal n'est pas comptée. Voici un exemple :

xorl %eax,%eax
xorl %ebx,%ebx
movb $0x17,%al
int $0x80

xorl %ebx,%ebx
leal 0x17(%ebx),%al
int $0x80


Tous les deux shellcodes appellent le setuid (0), mais on le fait en 7 bytes tandis que l'autre le fait dans 8. Encore, je vous entends dire mais c'est seulement un byte qu'il ne fait pas ce beaucoup d'une différence, et vous avez raison, ici elle ne fait pas grand cas d'une différence (excepté dans la shellcode-taille pissant le =p) de concours, mais une fois appliquée à des shellcodes beaucoup plus grands, qui ont beaucoup d'appels et besoin de fonction de faire des choses comme ceci fréquemment, elle peut sauver tout à fait un peu de l'espace.

Conclusion

Je vous espère tout instruit quelque chose, et sortirai et appliquerai votre connaissance pour créer de plus petits et meilleurs shellcodes. Si vous savez qui a inventé la technique leal, dites-svp moi qu'et je créditerai lui/elle.


Pick a language
English  French