Pour développer ce que vonbrand a (correctement, +1) dit, il y a deux parties dans la protection de la pile de Linux.
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 une 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]);
}
Compilez maintenant cela (gcc -fstack-protector -masm=intel -S test.c
) en quelque chose de gnu car serait heureux d'assembler et de lire la sortie. Le point important est qu'en sortie du 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 de [ebp-12]
et en le comparant à la valeur à 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 en termes de construction d'un cas de test de 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 habituel du shellcode :
char buffer[] = {...};
typedef void (* func)(void);
int main(int argc, char** argv)
{
func f = (func) buffer;
f();
return 0;
}
GCC/Linux moderne mappera le .rodata
section du fichier PE en lecture seule sans autorisation d'exécution. Vous devez désactiver cela, ce qui peut être fait à l'aide de l'exemple de code de cet article de blog. Idée de base :vous utilisez mprotect
pour ajouter les autorisations que vous souhaitez aux pages dans lesquelles résident les données du shellcode.
Piles non exécutables
Si vous allez tester un scénario d'exploit traditionnel, par ex. 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 permettant de 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 pile car ils sont intégrés à la compilation.
Bonus supplémentaire :aslr :
Pour désactiver cela, echo 0 > /proc/sys/kernel/randomize_va_space
.
Venez-vous dire à quelqu'un comment exploiter mon précieux pingouin ?
Non. Tout exploit doit contourner les canaris de pile (très peu trivial) et soit trouver un programme avec execstack
set, ou set it (ce qui signifie qu'il peut déjà exécuter des commandes arbitraires de toute façon) ou bien utiliser des techniques plus difficiles, telles que le retour à la programmation orientée libc/return.
La protection de la pile est effectuée par le compilateur (ajoutez des données supplémentaires à la pile et cachez-en quelques-unes à l'appel, vérifiez l'intégrité au retour). Impossible de désactiver cela sans recompiler. Cela fait partie du problème, vraiment...