Wednesday, July 4, 2012

Techniques avancées - par Shellcoding Darawk



Introduction

Ce document suppose une connaissance pratique des techniques de base shellcoding, et l'assemblage x86, je ne veux pas ressasser ces dans le présent document. J'espère que pour vous apprendre quelques-unes des techniques moins connues que shellcoding j'ai ramassé, qui vous permettra d'écrire des shellcodes plus petits et mieux. Je ne prétends pas avoir inventé l'une de ces techniques, sauf pour celui qui utilise l'instruction div.



La multiplicité des mul

Cette technique a été initialement développé par Sorbo de darkircop.net. L'instruction mul peut, à la surface, semblent banales, et c'est but évident. Toutefois, lorsqu'ils sont confrontés au défi difficile de la contraction de votre shellcode, il s'avère très utile. Tout d'abord quelques informations générales sur l'instruction MUL lui-même.

Mul effectue une multiplication de deux nombres entiers non signés. Il faut un seul opérande, l'autre est implicitement spécifié par le registre% eax. Ainsi, une instruction mul commune pourrait ressembler à ceci:

movl $ 0x0a,% eax
mul 0x0a $

Ce serait multiplier la valeur stockée dans% eax par l'opérande de mul, qui dans ce cas serait de 10 * 10. Le résultat est ensuite stocké dans EDX implicitement: EAX. Le résultat est stocké sur une période de deux registres, car il a le potentiel d'être considérablement plus grande que la valeur précédente, peut-être supérieure à la capacité d'un seul registre (c'est aussi la façon dont flottante points sont stockés dans certains cas, comme un sidenote intéressante) .

Alors, vient maintenant la question toujours importante. Comment pouvons-nous utiliser ces attributs à notre avantage lors de l'écriture shellcode? Eh bien, nous allons réfléchir pendant une seconde, l'instruction prend un seul opérande, donc, puisqu'il s'agit d'une instruction très commun, il va générer seulement deux octets dans notre shellcode final. Il multiplie tout ce qui est passé par la valeur stockée dans% eax, et stocke la valeur en% à la fois edx et% eax, complètement écraser le contenu de deux registres, indépendamment de savoir s'il est nécessaire de le faire, afin de stocker l' résultat de la multiplication. Mettons sur nos chapeaux mathématicien pour une seconde, et d'envisager cela, ce qui est le seul résultat possible d'une multiplication par 0? La réponse, comme vous l'aurez deviné, est de 0. Je pense qu'il est temps pour un exemple de code, si elle est ici:

% ecx xorl,% ecx
% ecx mul

Quel est ce shellcode faire? Eh bien, il ya le 0% ecx vous inscrire en utilisant l'instruction xor, si nous savons maintenant que ecx% est égal à 0. Puis il fait un ecx% mul, qui, comme nous venons d'apprendre, il est multiplie par la valeur d'opérande dans% eax, et procède ensuite à stocker le résultat de cette multiplication dans EDX: EAX. Donc, quel que soit le contenu précédent de% eax,% eax doit maintenant être égal à 0. Cependant ce n'est pas tout,% edx est 0'd maintenant trop, parce que, même si aucun débordement, il écrase encore le registre% edx avec le bit de signe (la plus à gauche bits) de% eax. En utilisant cette technique, nous pouvons mettre à zéro les trois registres en seulement trois octets, alors que par toute autre méthode (que je sache), il aurait fallu au moins six.


L'instruction div

Div est très similaire à mul, en ce qu'il prend seulement un opérande et divise implicitement l'opérande par la valeur dans% eax. En outre, comme, mul il stocke le résultat de la fracture dans% eax. Encore une fois, nous demandons à la partie mathématique de nos cerveaux pour comprendre comment nous pouvons profiter de cette instruction. Mais d'abord, nous devons penser à ce qui est normalement stocké dans le registre% eax. Le registre% eax contient la valeur de retour de fonctions et / ou syscalls. La plupart des appels système qui sont utilisés dans shellcoding retournera -1 (en cas d'échec) ou une valeur positive d'une certaine sorte, que rarement vont-ils retourner 0 (si elle ne se produisent). Donc, si nous savons que, après un appel système est effectué,% eax aura une valeur non nulle, et que l'instruction divl% eax va diviser% eax par lui-même, puis stocker le résultat dans% eax, nous pouvons dire que l'exécution l'% eax divl instruction après un syscall mettra la valeur 1 dans% eax. Alors ... comment est-ce applicable à shellcoding? Eh bien, leur est une autre chose importante que% eax est utilisé pour, et c'est pour passer le syscall spécifique que vous souhaitez appeler en int $ 0x80. Il se trouve que le syscall qui correspond à la valeur 1 est sortie (). Voici donc un exemple:

      
% ebx xorl,% ebx
% ebx mul
push% edx
pushl $ 0x3268732f
pushl $ 0x6e69622f
mov% esp,% ebx
push% edx
poussez% ebx
mov% esp,% ecx
movb 0xb $,% al # execve () syscall, ne retourne pas du tout à moins qu'il ne tombe en panne, auquel cas il renvoie -1
int $ 0x80

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

Maintenant, nous avons une fonction de 3 octets de sortie, alors qu'avant il était de 5 octets. Cependant, il ya un hic, si un syscall ne return 0? Eh bien dans la situation étrange dans laquelle ce qui pourrait arriver, vous pourriez faire beaucoup de choses différentes, comme inc% eax, eax dec%,% eax pas quelque chose qui fera% eax non-nulle. Certaines personnes disent que la sortie ne sont pas important dans le shellcode, parce que votre code est exécuté indépendamment de si oui ou non il sort proprement. Ils ont raison aussi, si vous avez vraiment besoin de sauver 3 octets pour s'adapter à votre shellcode en quelque part, la sortie () n'est pas la peine de garder. Toutefois, lorsque votre code ne finir, il va essayer d'exécuter tout ce qui était après votre dernière instruction, qui sera le plus susceptible de produire un SIG (instruction illégale) PEB qui est une erreur assez étrange, et sera consigné par le système. Ainsi, un exit () ajoute simplement une couche supplémentaire de la furtivité de votre exploit, de sorte que même si elle échoue ou si vous ne pouvez pas effacer tous les journaux, au moins cette partie de votre présence sera clair.



Libérer la puissance de leal

L'instruction est une instruction leal souvent négligé dans le shellcode, même si elle est très utile. Considérez cette courte pièce de shellcode.

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

Cela va charger la valeur 17 dans eax, et effacer tous les bits de eax étrangers. Cela se produit parce que l'instruction leal charge une variable de type long en opérande desitination son. Dans son utilisation normale, ce serait de charger l'adresse d'une variable dans un registre, créant ainsi un pointeur de toutes sortes. Cependant, depuis ecx est 0'd et 0 17 = 17, nous chargeons le 17 valeur dans eax au lieu de tout type d'adresse réelle. Dans un shellcode normale que nous ferions quelque chose comme ça, pour accomplir la même chose:

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

Je peux vous entendre dire, mais que le shellcode est un octet plus courte que la leal, et vous êtes tout à fait raison. Toutefois, dans un shellcode réel, vous pouvez déjà avoir à 0 sur un registre comme ecx (ou tout autre registre), de sorte que la formation xorl dans le shellcode Leal n'est pas compté. Voici un exemple:

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

Ces deux setuid appel shellcodes (0), mais on le fait en 7 octets tandis que l'autre c'est le cas dans 8. Encore une fois, je vous entends dire, mais c'est un seul octet il ne fait pas que beaucoup de différence, et vous avez raison, ici, il ne fait pas beaucoup de différence (sauf dans le shellcode de taille pisser concours = p) , mais lorsqu'il est appliqué à shellcodes beaucoup plus grandes, qui ont de nombreux appels de fonction et la nécessité de faire des choses comme cela fréquemment, il peut mettre un peu d'espace.



Conclusion

J'espère que vous tous appris quelque chose, et de sortir et d'appliquer vos connaissances pour créer shellcodes plus petits et mieux. Si vous savez qui a inventé la technique Leal, s'il vous plaît dites-moi et je lui créditer / elle.