Impossible d’exécuter le shellcode -> (Speicherzugriffsfehler (Speicherabzug geschrieben))

J’ai cette fonction:

char code[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f"; int main(int argc, char **argv) { int (*func)(); func = (int (*)()) code; (int)(*func)(); } 

(ce code provient de: shellcode tutorial )

donc je l’ai compilé et exécuté, mais je ne reçois que ce message: Speicherzugriffsfehler (Speicherabzug geschrieben).

Pourquoi je ne récupère pas quelque chose, seulement ce message d’erreur?

ps: mon système est un pc ubuntu x86. le shellcode devrait fonctionner avec. Je l’ai compilé avec gcc et avec gcc-4.5, les mêmes erreurs …

Par défaut, gcc comstackra les applications avec des stacks non-exécutables. Ce que vous voyez est une violation de segmentation car votre stack est marquée comme non exécutable, mais vous essayez d’exécuter du code sur la stack. Vous pouvez vérifier en exécutant votre application dans gdb et en vérifiant où elle meurt, par exemple:

=> 0x601060: jmp 0x60107b

C’est le point d’entrée de votre shellcode. Pour éviter les segfault, vous pouvez désactiver exectstack en procédant comme suit:

gcc -z execstack source.c

Votre variable de code est un tableau faisant partie du segment de données initialisé ( .data ) de votre programme. Lorsque votre programme est chargé par le système d’exploitation, le chargeur lit et exécute les commandes de chargement à partir de votre fichier exécutable. Une de ces commandes est “charger les données suivantes (un segment nommé .data ) en mémoire”.

Normalement, le segment .data est chargé en tant que segment non exécutable , ce qui signifie que la mémoire ne peut pas être exécutée. Par conséquent, si vous essayez d’exécuter du code à partir de là en y accédant, comme vous l’avez fait, il se plantera avec une erreur de segmentation.

Il y a plusieurs façons de contourner ce problème. Vous pouvez .data à l’éditeur de liens de rendre le segment .data exécutable (ce n’est pas une bonne idée). Vous pouvez indiquer au compilateur de placer la variable de code dans le segment .text (le segment utilisé pour tout le code normal de votre programme). Vous pouvez demander au compilateur et à l’éditeur de liens de créer un nouveau segment exécutable et d’y insérer du code . Tout cela est délicat.

La meilleure solution consiste à allouer spécifiquement votre propre mémoire exécutable au moment de l’exécution et à copier le shellcode dans celle-ci. Cela évite complètement les problèmes potentiels du compilateur / éditeur de liens, bien que cela ajoute une petite pénalité d’exécution. Mais certains systèmes d’exploitation ne permettent pas à la mémoire d’être à la fois accessible en écriture et exécutable; vous devez donc d’abord le rendre accessible en écriture, copier le shellcode, puis le rendre exécutable.

Vous pouvez contrôler les permissions de la mémoire au moment de l’exécution à l’aide de l’ appel de mprotect(2) . Alors voici un bon moyen de le faire:

 #include  #include  char shellcode[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f"; // Error checking omitted for expository purposes int main(int argc, char **argv) { // Allocate some read-write memory void *mem = mmap(0, sizeof(shellcode), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); // Copy the shellcode into the new memory memcpy(mem, shellcode, sizeof(shellcode)); // Make the memory read-execute mprotect(mem, sizeof(shellcode), PROT_READ|PROT_EXEC); // Call the shellcode int (*func)(); func = (int (*)())mem; (int)(*func)(); // Now, if we managed to return here, it would be prudent to clean up the memory: munmap(mem, sizeof(shellcode)); return 0; }