web-dev-qa-db-fra.com

Pourquoi JMP ESP au lieu de sauter directement dans la pile

Tout d'abord, je suis désolé si ce message ne correspond pas exactement ici, ou peut être mieux adapté dans RE. Nous pourrions le déplacer si nécessaire.

Donc, je lisais ceci writeup à propos d'un exploit dans vulnserver (pour ceux qui ne le connaissent pas, vulnserver est un programme conçu avec des défauts à l'esprit, c'est-à-dire pour pratiquer des techniques d'exploitation)

À un certain moment, il dit:

Dans cette étape, nous devons vérifier les registres et la pile. Nous devons trouver un moyen de passer à notre tampon pour exécuter notre code. ESP pointe vers le début de la partie C de notre tampon. Nous devons trouver un JMP ESP ou CALL ESP N'oubliez pas que l'adresse ne doit pas contenir de mauvais caractères!

Cela a du sens, mais; Ne serait-il pas possible et plus facile de sauter directement dans la pile puisque nous contrôlons EIP? (Nous supposons que l'ASLR et le DEP sont bien sûr désactivés). Principalement parce que:

  1. Comment sait-il ESP pointe vers son shellcode? Pourquoi ESP pointe exactement là? Ne devrait-il pas plutôt pointer vers la fin de son shellcode?

  2. Comment cela est-il censé fonctionner via des redémarrages ou sur différents ordinateurs?

Merci.

Votre charge utile d'exploit se retrouve sur la pile parce que vous débordez d'un tampon sur la pile, et c'est ainsi que vous contrôlez également l'adresse de retour.

ESP pointe directement vers le début de votre charge utile (après l'exécution de ret dans la fonction que vous attaquez) car vous placez la charge utile juste après les 4 octets qui écrasent l'adresse de retour sur la pile. ret insère 4 (ou 8) octets dans EIP, laissant ESP pointant vers la charge utile qui suit directement.

Mais vous ne savez pas quelle valeur ESP aura à ce moment-là , à cause de la pile ASLR et parce qu'un autre la profondeur de la pile d'appels menant à ce point pourrait changer l'adresse. Vous ne pouvez donc pas coder en dur une adresse de retour correcte .

Mais s'il y a des octets qui décodent comme jmp esp ou call esp n'importe où à une adresse fixe (non ASLRed) dans la mémoire du processus , vous pouvez coder en dur ça comme adresse de retour dans votre exploit. L'exécution ira là, puis à votre charge utile.

C'est en fait souvent le cas: certaines DLL n'ont pas ASLR activé pour leur code, et le code de l'exécutable principal peut ne pas être ASLR non plus.

Code ASLR pour tous le code bat un jmp esp attaque, sauf si l'attaquant peut provoquer la fuite d'adresses du processus cible.

Notez que pour le code 64 bits, il est peu probable que vous puissiez utiliser jmp rsp pour les débordements de tampon basés sur des chaînes, car les adresses de code contiendront quelques 0 octets .


Ainsi, jmp esp vous offre un exploit beaucoup plus fiable que de deviner à plusieurs reprises une adresse de retour (avec un très grand traîneau NOP).

Des suppositions répétées planteront le processus cible chaque fois que vous vous trompez, mais un jmp esp peut vous donner une grande chance de succès du premier coup. Cela évitera de laisser des journaux de plantage. Il pourrait également vaincre un système de détection d'intrusion qui recherche les processus serveur en panne et bloque les connexions de votre adresse IP, ou similaire.


Notez que l'instruction à 2 octets que vous recherchez peut apparaître dans le cadre d'une autre instruction lorsque le programme s'exécute normalement, ou sous forme de données statiques (en particulier, les données en lecture seule se trouvent souvent dans des pages exécutables). Il vous suffit donc de rechercher la séquence de 2 octets, pas de jmp esp lors du démontage du programme. Les compilateurs n'utiliseront jamais jmp esp, donc vous n'en trouverez pas de cette façon.


Plus généralement , toute fonction se terminant par un pointeur tampon dans n'importe quel registre (par exemple à partir d'un memcpy ou surtout strcpy ) peut permettre une attaque ret2reg , en recherchant une jmp eax instruction.

Cela peut fonctionner en mode 64 bits, où les adresses ont des octets zéro élevés; si le zéro final de strcpy écrit cet octet d'adresse élevé pour vous, la fin de votre chaîne d'exploitation pourrait être les octets d'adresse non nulle qui écrasent l'adresse de retour sur la pile.

Dans ce cas, la charge utile exécutable irait avant l'adresse de retour, à l'endroit du tampon où la fonction laisse un registre pointé. (Généralement, le début du tampon s'il y a des pointeurs utiles vers le tampon dans les registres).

10
Peter Cordes

Une fois qu'un tampon a dépassé, ESP a le shellcode. Vous pouvez le vérifier dans l'immunité, EIP doit pointer vers ESP. Ma compréhension est avant l'exploit, les DLL système, devraient utiliser ESP, selon lorsque les DLL sont appelées.

Mais après le dépassement de la mémoire tampon, EIP n'a aucune idée de l'endroit où pointer. Notez que les 4 octets que nous transmettons à EIP peuvent être l'une des adresses [jmp ESP].

Alors ça va comme ça -

  1. Débordez le tampon exactement jusqu'à EIP
  2. Passer l'adresse [jmp ESP] à EIP
  3. La valeur stockée dans ESP est exécutée (NOPs + Shellcode)

J'ai écrit un exploit et utilisé des variations d'adresse à [jmp ESP] et à chaque fois j'ai pu exploiter la vulnérabilité.

Voici l'exploit.py, notez que j'utilise la DLL RPCRT. Mais nous pouvons également utiliser Shell32.dll et d'autres DLL du système.

https://github.com/shankar-ray/Exploit-Development/blob/master/exploit-py

J'utilise Shell bind shellcode avec quelques NOP supplémentaires.

BTW si le système d'exploitation dispose d'une sorte de protections ou si le compilateur a ajouté des protections lors de la compilation du code src d'origine. Cela deviendra une chasse au trésor pour trouver l'emplacement du shellcode. Nous devrons ensuite utiliser plusieurs sauts pour accéder au shellcode.

J'espère que cela pourra aider!

4