Question

Ceci est un shellcode pour exploiter la vulnérabilité BufferOverflow. Il définit la setuid(0) et génère un shell en utilisant execve(). Voici la façon dont je l'ai interprété:

xor    %ebx,%ebx       ; Xoring to make ebx value 0
lea    0x17(%ebx),%eax ; adds 23 to 0 and loads effective addr to eax. for setuid()
int    $0x80           ; interrupt
push   %ebx            ; push ebx
push   $0x68732f6e     ; push address // why this address only????
push   $0x69622f2f     ; push address // same question
mov    %esp,%ebx
push   %eax
push   %ebx
mov    %esp,%ecx
cltd                   ; mov execve sys call into al
mov    $0xb,%al
int    $0x80           ; interrupt

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

Était-ce utile?

La solution

int est le opcode pour déclencher une interruption logicielle. les interruptions de logiciel sont numérotés (de 0 à 255) et manipulés par le noyau. Sur les systèmes Linux, interruption 128 (0x80) est le point d'entrée classique pour les appels système. Le noyau attend les arguments d'appel du système dans les registres; en particulier, le registre% eax identifie quel appel système que 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 un ajout).
  3. L'appel système. % Eax contient 23, ce qui signifie que l'appel système est setuid. Qui utilise des appels système d'un argument (UID cible), que l'on trouve en% ebx, qui contient avantageusement 0 à ce moment (il a été défini dans la première instruction). Remarque: lors du retour, les registres ne sont pas modifiés, sauf% eax qui contient la valeur renvoyée de l'appel système, normalement 0 (si l'appel a été un succès)
  4. .
  5. Push% ebx sur la pile (qui est toujours 0).
  6. Appuyez 0x68732f6e $ sur la pile.
  7. Appuyez 0x69622f2f $ sur la pile. Étant donné que la pile grossit « vers le bas » et que les processeurs x86 utilisent peu d'encodage endian, l'effet des instructions 4 à 6 est que% esp (le pointeur de la pile) maintenant des points à une séquence de douze octets, des valeurs 2f 2f 62 69 6E 2f 73 68 00 00 00 00 (en hexadécimal). C'est le codage de la chaîne « // bin / sh » (avec un zéro et trois zéros supplémentaires après terminaison).
  8. Déplacer% esp% à EBX. Maintenant% ebx contient un pointeur sur la chaîne "// bin / sh" qui a été construit au-dessus.
  9. Push% eax sur la pile (% eax est égal à 0 à ce moment, il est l'état retourné de setuid).
  10. Push% EBX sur la pile (pointeur vers "// bin / sh"). Instructions 8 et 9 accumulation sur la pile une série de deux points, le premier étant le pointeur sur « // bin / sh » et le second un pointeur NULL. Ce tableau est ce que l'appel système de execve utilisera comme second argument.
  11. Déplacer% esp% à ECX. Maintenant% ecx points au tableau construit avec des instructions 8 et 9.
  12. Inscrivez-Extend% eax en% edx:% eax. cltd est la syntaxe AT & T pour ce que les Intel appellent cdq documentation. Depuis% eax est égal à zéro à ce moment-là, ce jeux% EDX à zéro aussi.
  13. Set% al (le moins d'octet significatif de% eax) à 11. Depuis% eax est égal à zéro, la valeur totale de% eax est maintenant 11.
  14. L'appel système. La valeur de% eax (11) identifie l'appel système comme execve. execve attend trois arguments, en% EBX (pointeur sur 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, la première étant une copie du nom du programme, être utilisé par le programme lui-même invoqué) et% EDX (pointeur vers un tableau de pointeurs vers des chaînes, qui sont les variables d'environnement;. Linux supporte cette valeur NULL, pour un environnement vide), respectivement

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

Ce code est assez alambiquée car il veut éviter des zéros: lorsqu'ils sont assemblés en opcodes binaires, la séquence d'utilisations d'instruction seulement octets non nuls. Par exemple, si l'instruction 12 avait été movl $0xb,%eax (réglage de l'ensemble de% eax à 11), la représentation binaire de cette opcode aurait contenu trois octets de valeur 0. L'absence de zéro marques cette séquence utilisable comme le contenu d'un zéro à terminaison chaîne C. Ceci est destiné à attaquer des programmes buggy débordements de tampon, bien sûr.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top