2015-09-23 2 views
3

En étudiant le noyau Linux, je viens de découvrir que, par défaut, un exécutable a une zone de pile 'exécutable'. J'ai naturellement pensé que la seule zone exécutable (nécessaire) est la section de texte. Y a-t-il une raison historique liée à ceci ou à un usage pratique?Pourquoi la zone de pile Linux a-t-elle une protection exécutable?

+0

GCC sont mises en œuvre de fonctions imbriquées comme trampolines et nécessitent une pile exécutable. Il existe d'autres cas d'utilisation, dont certains sont décrits [ici] (https://wiki.ubuntu.com/SecurityTeam/Roadmap/ExecutableStacks). –

Répondre

5

Une pile exécutable est nécessaire dans certains cas, comme le trampoline GCC pour les fonctions imbriquées. Un trampoline est un petit morceau de code qui est créé lors de l'exécution lorsque l'adresse d'une fonction imbriquée est prise. Il réside normalement sur la pile, dans le cadre de la pile de la fonction conteneur. Ces macros indiquent à GCC comment générer du code pour allouer et initialiser un trampoline.

Dans la plupart des distributions en raison des risques d'attaque et de l'utilisation de la pile pour exécuter un shellcode, cette fonctionnalité est désactivée, bien que vous puissiez compiler un code avec -z execstack pour l'activer. Il est également possible d'utiliser un programme appelé execstack pour activer ou désactiver cette fonctionnalité après la compilation du programme. Pour que cela soit clair j'ai écrit un programme simple pour exécuter exit syscall avec le code de sortie de 32. Si cette fonctionnalité est activée, le code fonctionne, sinon il donne un défaut de segmentation.

#include <stdlib.h> 
#include <unistd.h> 

char shellCode[] = "\xb8\x01\x00\x00\x00" //   mov $0x1,%eax 
        "\xbb\x20\x00\x00\x00" //   mov $0x20,%ebx 
        "\xcd\x80";   //   int $0x80 

int main(){ 
    int *ret; 
    ret = (int*) &ret + 2; 
    *ret = (int) shellCode; 
    return 5; 
} 

Dans ce code ret pointe vers son adresse plus 2. Comme nous le savons de la taille du pointeur de systèmes IA32 est 4bytes et au début de chaque fonction il y a un push ebp après la compilation. Donc, afin d'atteindre l'adresse de retour de main nous devons ajouter 2*stack_chunk_size et en définissant chaque morceau 4byte au moment de la compilation cela fonctionne parfaitement.

compiler le code de ce type d'essai:

gcc -mpreferred-stack-boundary=2 -z execstack -o testShellCode testShellCode.c 

-mpreferred-stack-boundary=2 est d'aligner la pile en 4 morceaux d'octets et -z execstack consiste à compiler en utilisant pile exécutable.

Ce code simple peut donner un aperçu de la raison pour laquelle il existe une protection de pile exécutable.

Regardez les liens suivants pour plus d'informations sur les fonctions imbriquées et execstack commande:

Trampolines

execstack

+0

Wow, je ne m'attendais pas mais c'est tout à fait une histoire. Merci beaucoup! –

+0

Bien sur la seconde, mais sur l'exemple, le contrôle ne devrait pas être transféré à la section de données après l'instruction de retour dans «principal»? Je pense que l'exemple est logique si 'shellCode' a été déclaré dans une portée de fonction. –