Pour développer ce que vonbrand a dit (correctement, +1), la protection de la pile de Linux comporte deux parties.
Empiler les canaris
Les canaris de pile sont la fonctionnalité imposée par le compilateur à laquelle vonbrand fait référence. Ceux-ci ne peuvent pas être désactivés sans recompilation.
Pour vous le prouver et voir comment ils fonctionnent, prenez le code suivant:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
int mybadfunction(char* a_bad_idea)
{
char what[100];
strcpy(what, a_bad_idea);
printf("You passed %s\n", what);
}
int main(int argc, char** argv)
{
printf("Tralalalaala\n");
mybadfunction(argv[1]);
}
Maintenant, compilez cela ( gcc -fstack-protector -masm=intel -S test.c
) en quelque chose de gnu comme il serait heureux d'assembler et de lire la sortie. Le point important est qu'à la sortie de la mybadfunction
fonction, il y a ce petit bout de code:
mov edx, DWORD PTR [ebp-12]
xor edx, DWORD PTR gs:20
je .L2
call __stack_chk_fail
Comme vous pouvez le deviner, cela prend un cookie de pile [ebp-12]
et le compare à la valeur de gs:20
. Ne correspond pas? Il appelle ensuite une fonction __stack_chk_fail
dans glibc qui tue votre programme juste là.
Il existe des moyens de contourner ce problème en termes d'écriture d'exploits, mais le moyen le plus simple pour construire un scénario de test shellcode est de compiler votre programme avec -fno-stack-protector
.
Pages non exécutables
Il existe d'autres considérations sur les systèmes Linux modernes. Si vous prenez le talon de test de shellcode habituel:
char buffer[] = {...};
typedef void (* func)(void);
int main(int argc, char** argv)
{
func f = (func) buffer;
f();
return 0;
}
GCC / Linux moderne mappera la .rodata
section du fichier PE en lecture seule sans autorisation d'exécution. Vous devez désactiver cela, ce qui peut être fait en utilisant l'exemple de code de ce billet de blog . Idée de base: vous utilisez mprotect
pour ajouter les autorisations souhaitées aux pages dans lesquelles résident les données du shellcode.
Piles non exécutables
Si vous allez tester un scénario d'exploitation traditionnel, par exemple mon mauvais code ci-dessus, avec votre shellcode, vous devez également vous assurer que la pile est exécutable pour les cas simples. Le format de fichier PE contient un champ pour déterminer si la pile est exécutable - vous pouvez interroger et contrôler cela avec execstack . Pour activer une pile exécutable, exécutez
execstack -s /path/to/myprog
Cela peut être fait sur des programmes arbitraires sans avoir besoin d'une recompilation, mais ne désactivera pas automatiquement les canaris de la pile car ceux-ci sont intégrés à la compilation.
Bonus supplémentaire: aslr:
Pour éteindre ça, echo 0 > /proc/sys/kernel/randomize_va_space
.
Vous venez de dire à quelqu'un comment exploiter mon précieux pingouin?
Non. Tout exploit doit contourner les canaris de pile (très peu triviaux) et soit trouver un programme avec execstack
set, soit le définir (ce qui signifie qu'il peut déjà exécuter des commandes arbitraires de toute façon) ou encore utiliser des techniques plus difficiles, telles que le retour à libc / return programmation orientée.