Je suis sur CentOS 6.4 32 bits et j'essaye de provoquer un débordement de tampon dans un programme. Au sein de GDB, cela fonctionne. Voici la sortie:
[root@localhost bufferoverflow]# gdb stack
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/bufferoverflow/stack...done.
(gdb) r
Starting program: /root/bufferoverflow/stack
process 6003 is executing new program: /bin/bash
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.107.el6_4.2.i686
sh-4.1#
Cependant, lorsque j'exécute la pile de programmes seule, les erreurs de segmentation se produisent. Pourquoi est-ce possible?
Le développement des exploits peut entraîner de sérieux maux de tête si vous ne tenez pas suffisamment compte des facteurs qui introduisent non-déterminisme dans le processus de débogage. En particulier, les adresses de pile dans le débogueur peuvent ne pas correspondre aux adresses pendant l'exécution normale. Cet artefact se produit car le chargeur du système d'exploitation place à la fois les variables d'environnement et les arguments du programme avant le début de la pile:
Étant donné que votre programme vulnérable ne prend aucun argument, les variables d'environnement sont probablement le coupable. Jument sûr qu'ils sont les mêmes dans les deux invocations, dans le Shell et dans le débogueur. À cette fin, vous pouvez encapsuler votre invocation dans env
:
env - /path/to/stack
Et avec le débogueur:
env - gdb /path/to/stack
($) show env
LINES=24
COLUMNS=80
Dans l'exemple ci-dessus, il existe deux variables d'environnement définies par gdb, que vous pouvez désactiver davantage:
unset env LINES
unset env COLUMNS
Maintenant show env
devrait renvoyer une liste vide. À ce stade, vous pouvez démarrer le processus de débogage pour trouver l'adresse de pile absolue vers laquelle vous envisagez d'accéder (par exemple, 0xbffffa8b
), et codez-le en dur dans votre exploit.
Un autre détail subtil mais important: il y a une différence entre appeler ./stack
et /path/to/stack
: puisque argv[0]
contient le programme exactement comme vous l'avez appelé, vous devez garantir des chaînes d'invocation égales. Voilà pourquoi j'ai utilisé /path/to/stack
dans les exemples ci-dessus et pas seulement ./stack
et gdb stack
.
Lorsque vous apprenez à exploiter avec des vulnérabilités de sécurité de la mémoire, je recommande d'utiliser le programme wrapper ci-dessous, qui fait le gros du travail et assure des décalages de pile égaux:
$ invoke stack # just call the executable
$ invoke -d stack # run the executable in GDB
Voici le script:
#!/bin/sh
while getopts "dte:h?" opt ; do
case "$opt" in
h|\?)
printf "usage: %s -e KEY=VALUE prog [args...]\n" $(basename $0)
exit 0
;;
t)
tty=1
gdb=1
;;
d)
gdb=1
;;
e)
env=$OPTARG
;;
esac
done
shift $(expr $OPTIND - 1)
prog=$(readlink -f $1)
shift
if [ -n "$gdb" ] ; then
if [ -n "$tty" ]; then
touch /tmp/gdb-debug-pty
exec env - $env TERM=screen PWD=$PWD gdb -tty /tmp/gdb-debug-pty --args $prog "$@"
else
exec env - $env TERM=screen PWD=$PWD gdb --args $prog "$@"
fi
else
exec env - $env TERM=screen PWD=$PWD $prog "$@"
fi
L'adresse du pointeur de cadre de pile lors de l'exécution du code dans gdb est différente de son exécution normale. Vous pouvez donc corrompre l'adresse de retour en mode gdb, mais elle peut ne pas fonctionner correctement en mode normal. La raison principale en est que les variables d'environnement diffèrent entre les deux situations.
Comme il ne s'agit que d'une démo, vous pouvez modifier le code victime et imprimer l'adresse du tampon. Changez ensuite votre adresse de retour en offset + adresse de tampon.
En réalité, cependant, vous devez deviner l'adresse de retour ajouter traîneau NOP avant votre code malveillant. Et vous pouvez deviner plusieurs fois pour obtenir une adresse correcte, car votre supposition peut être incorrecte.
J'espère que cela peut vous aider.
Voici une manière simple d'exécuter votre programme avec des piles identiques dans le terminal et dans gdb
:
Tout d'abord, assurez-vous que votre programme est compilé sans protection de pile,
gcc -m32 -fno-stack-protector -z execstack -o shelltest shelltest.c -g
et et ASLR est désactivé:
echo 0 > /proc/sys/kernel/randomize_va_space
REMARQUE: la valeur par défaut sur ma machine était 2, notez la vôtre avant de changer cela.
Exécutez ensuite votre programme comme ceci (terminal et gdb respectivement):
env -i PWD="/root/Documents/MSec" Shell="/bin/bash" SHLVL=0 /root/Documents/MSec/shelltest
env -i PWD="/root/Documents/MSec" Shell="/bin/bash" SHLVL=0 gdb /root/Documents/MSec/shelltest
Dans gdb
, assurez-vous de unset
LINES
et COLUMNS
.
Remarque: j'ai obtenu ces variables d'environnement en jouant avec programme de test .
Ces deux exécutions vous donneront des pointeurs identiques vers le haut de la pile, donc pas besoin de manigances de script à distance si vous essayez d'exploiter un binaire hébergé à distance.
La raison pour laquelle votre débordement de tampon fonctionne sous gdb et segfaults sinon, c'est que gdb désactive la randomisation de la disposition de l'espace d'adressage. Je crois que cela a été activé par défaut dans gdb version 7.
Vous pouvez vérifier cela en exécutant cette commande:
show disable-randomization
Et le régler avec
set disable-randomization on
ou
set disable-randomization off
J'ai essayé la solution acceptée ici et ça ne marche pas (pour moi). Je savais que gdb a ajouté des variables d'environnement et pour cette raison, l'adresse de la pile ne correspond pas, mais même en supprimant ces variables, je ne peux pas travailler mon exploit sans gdb (j'ai également essayé le script publié dans la solution acceptée).
Mais en cherchant sur le Web, j'ai trouvé un autre script qui fonctionne pour moi: https://github.com/hellman/fixenv/blob/master/r.sh
L'utilisation est essentiellement la même que celle du script dans la solution acceptée:
Et ce script fonctionne pour moi.
Je suis sur CentOS 6.4 32 bits et j'essaye de provoquer un débordement de tampon dans un programme ... Cependant, lorsque j'exécute la pile de programmes seule, cela provoque des erreurs.
Vous devez également vous assurer que FORTIFY_SOURCE n'affecte pas vos résultats. La faute de segment sonne comme FORTIFY_SOURCE pourrait être le problème car FORTIFY_SOURCE insérera des appels de fonction "plus sûrs" pour se prémunir contre certains types de débordements de tampon. Si le compilateur peut déduire des tailles de tampon de destination, alors la taille est vérifiée et abort()
est appelée en cas de violation (c'est-à-dire votre faute de segmentation).
Pour désactiver FORTIFY_SOURCE pour les tests, vous devez compiler avec -U_FORTIFY_SOURCE
ou -D_FORTIFY_SOURCE=0
.
L'une des principales choses que gdb fait qui ne se produit pas en dehors de gdb est la mémoire nulle. Plus que probablement quelque part dans le code, vous n'initialisez pas votre mémoire et il obtient des valeurs de déchets. Gdb efface automatiquement toute la mémoire que vous allouez en masquant ces types d'erreurs.
Par exemple: ce qui suit devrait fonctionner dans gdb, mais pas en dehors:
int main(){
int **temp = (int**)malloc(2*sizeof(int*)); //temp[0] and temp[1] are NULL in gdb, but not outside
if (temp[0] != NULL){
*temp[0] = 1; //segfault outside of gdb
}
return 0;
}
Essayez d'exécuter votre programme sous valgrind pour voir s'il peut détecter ce problème.