2010-11-08 9 views
4

Ceci est un shellcode pour exploiter la vulnérabilité bufferoverflow. Détermine le setuid (0) et génère un shell en utilisant exec()Quelqu'un peut-il expliquer ce code d'assemblage?

  1. XOR% ebx,% ebx */
  2. Ica 0x17 (% EBX),% eax */
  3. int 0x80 $ */
  4. % pousser EBX */
  5. bouton $ 0x68732f6e */
  6. bouton $ 0x69622f2f */
  7. mov% esp,% ebx */
  8. % pression eax */
  9. pression% EBX */
  10. mov% esp,% ecx */
  11. CTDJ */
  12. mov 0xb de $,% al */
  13. int 0x80 $

c'est la façon dont je l'ai interprété ...

  1. XOR pour faire valeur EBX 0
  2. ajoute 23 à 0 et charge addr efficace à eax. pour setuid()

3.interrupt

4.push EBX

adresse 5.push // y cette adresse uniquement ????

adresse // même question 6. Poussez

12 sys execve mov al remettent en

13 interruption

Quelqu'un peut-il expliquer les étapes entières clairement ??

Répondre

6

int est l'opcode permettant de déclencher une interruption logicielle. Les interruptions logicielles sont numérotées (de 0 à 255) et gérées par le noyau. Sur les systèmes Linux, l'interruption 128 (0x80) est le point d'entrée conventionnel pour les appels système. Le noyau attend les arguments d'appel système dans les registres; en particulier, le registre% eax identifie l'appel système dont nous parlons.

  1. Set% EBX à 0
  2. Compute% EBX + 23 et stocker le résultat dans% eax (l'opcode est lea comme « charge adresse effective », mais pas accès à la mémoire est impliqué, ce qui est juste une façon sournoise de faire une addition).
  3. Appel système. % eax contient 23, ce qui signifie que l'appel système est setuid. Cet appel système utilise un argument (l'UID cible), à ​​trouver dans% ebx, qui contient commodément 0 à ce point (il a été défini dans la première instruction). Remarque: lors du retour, les registres ne sont pas modifiés, à l'exception de% eax qui contient la valeur renvoyée de l'appel système, normalement 0 (si l'appel a réussi).
  4. Appuyez sur% ebx sur la pile (qui est toujours 0).
  5. Poussez $ 0x68732f6e sur la pile.
  6. Poussez $ 0x69622f2f sur la pile. Etant donné que la pile se décompose et que les processeurs x86 utilisent peu le codage endian, l'effet des instructions 4 à 6 est que% esp (le pointeur de pile) pointe maintenant sur une séquence de douze octets, de valeurs 2f 2f 62 69 6e 2f 73 68 00 00 00 00 (en hexadécimal). C'est l'encodage de la chaîne "// bin/sh" (avec un zéro final et trois zéros supplémentaires par la suite).
  7. Déplacez% esp vers% ebx. Maintenant% ebx contient un pointeur vers la chaîne "// bin/sh" qui a été construite ci-dessus.
  8. Appuyez sur% eax sur la pile (% eax est 0 à ce stade, il s'agit de l'état renvoyé de setuid).
  9. Poussez% ebx sur la pile (pointeur sur "// bin/sh"). Les instructions 8 et 9 construisent sur la pile un tableau de deux pointeurs, le premier étant le pointeur sur "// bin/sh" et le second un pointeur NULL. Ce tableau est ce que l'appel système execve utilisera comme deuxième argument.
  10. Déplacez% esp vers% ecx. Maintenant,% ecx pointe vers le tableau construit avec les instructions 8 et 9.
  11. Sign-extend% eax dans% edx:% eax. cltd est la syntaxe AT & T pour ce que les documentations Intel appellent cdq. Étant donné que% eax est égal à zéro à ce stade, cela met également% edx à zéro.
  12. Définissez% al (l'octet le moins significatif de% eax) sur 11. Comme% eax était égal à zéro, la valeur entière de% eax est maintenant égale à 11.
  13. Appel système. La valeur de% eax (11) identifie l'appel système comme execve. execve attend trois arguments, en% ebx (pointeur vers une chaîne nommant le fichier à exécuter),% ecx (pointeur vers un tableau de pointeurs vers des chaînes, qui sont les arguments du programme, le premier étant une copie du nom du programme, être utilisé par le programme invoqué lui-même) et% edx (pointeur sur un tableau de pointeurs vers des chaînes, qui sont les variables d'environnement, Linux accepte que cette valeur soit NULL, pour un environnement vide), respectivement.

Ainsi, le premier code appelle setuid(0), puis appelle execve("//bin/sh", x, 0)x des points à un réseau de deux pointeurs, le premier étant un pointeur vers « // bin/sh », tandis que l'autre est NULL.

Ce code est assez compliqué car il veut éviter les zéros: lorsqu'il est assemblé en opcodes binaires, la séquence d'instruction n'utilise que des octets non nuls. Par exemple, si la 12ème instruction avait été movl $0xb,%eax (en mettant la totalité de% eax à 11), alors la représentation binaire de cet opcode aurait contenu trois octets de valeur 0. L'absence de zéro rend cette séquence utilisable comme le contenu d'un Chaîne C terminée par zéro. Ceci est destiné à attaquer les programmes buggés à travers les débordements de tampon, bien sûr.

+0

U r Super !!!! ... Thnx beaucoup !!!!!!!! –

+1

Pomin: en fait, le code est compliqué car il essaie d'être aussi petit que possible. Celui-ci est une version modifiée d'un fameux shellcode de 24 octets utilisé par Gera de Core Security (j'espère avoir obtenu l'attribution correcte, je ne sais pas comment rechercher la première apparition de ce code sur le net). – ninjalj

Questions connexes