Le débordement de tampon fonctionne dans gdb mais pas sans lui

Je suis sur CentOS 6.4 32 bit et j'essaye de causer un dépassement de tampon dans un programme. Au sein de GDB, cela fonctionne. Voici le résultat:

[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 quand j'exécute la pile de programme juste sur son propre il seg défauts. Pourquoi cela peut-il être?

37
demandé sur jww 2013-07-21 21:55:38

7 réponses

exploiter le développement peut causer de graves maux de tête si vous ne tenez pas compte de façon adéquate des facteurs qui introduisent non-déterminisme dans le processus de débogage. En particulier, les adresses de la pile dans le débogueur peuvent ne pas correspondre aux adresses pendant l'exécution normale. Cet artefact se produit parce que le chargeur de système d'exploitation place les variables d'environnement et les arguments de programme avant le début de la pile:

Process layout

puisque votre programme vulnérable ne prend aucun argument, les variables d'environnement sont probablement le coupable. Mare est sûre qu'ils sont les mêmes dans les invocations, dans le shell et dans le débogueur. À cette fin, vous pouvez envelopper 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 y a deux variables d'environnement définies par gdb, que vous pouvez désactiver:

unset env LINES
unset env COLUMNS

show env devrait retourner une liste vide. À ce stade, vous pouvez lancer le processus de débogage pour trouver l'adresse de pile absolue à laquelle vous envisagez de sauter (e.g.,0xbffffa8b), et hardcode dans votre exploit.

un autre détail subtil mais important: il y a une différence entre appeler ./stack et /path/to/stack: depuis argv[0] tient le programme exactement comme vous l'avez invoqué, vous devez assurer des chaînes d'invocation égales. C'est pourquoi j'ai utilisé /path/to/stack dans les exemples ci-dessus, et pas seulement ./stack et gdb stack.

lorsque vous apprenez à exploiter des vulnérabilités de sécurité de mémoire, je vous recommande d'utiliser le programme wrapper ci-dessous, qui fait le levage lourd et assure des offsets 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 )
      exit 0
      ;;
    t)
      tty=1
      gdb=1
      ;;
    d)
      gdb=1
      ;;
    e)
      env=$OPTARG
      ;;
  esac
done

shift $(expr $OPTIND - 1)
prog=$(readlink -f )
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
84
répondu mavam 2014-06-04 08:42:51

l'adresse du pointeur stack frame lors de l'exécution du code dans gdb est différente de son exécution normale. Ainsi, vous pouvez corrompre l'adresse de retour en mode gdb, mais elle peut ne pas être correcte en mode normal. La raison principale en est que les variables d'environnement diffèrent entre les deux situation.

comme ce n'est qu'une démo, vous pouvez changer le code victime, et imprimer l'adresse du tampon. Puis changez votre adresse de retour en offset+adresse de buffer.

dans la réalité, cependant,vous avez besoin de deviner l'adresse de retour ajouter NOP sled 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.

7
répondu York 2015-04-13 17:29:03

la raison pour laquelle votre débordement de tampon fonctionne sous gdb et segfaults autrement est que gdb désactive la randomisation de la disposition de l'espace d'adresse. Je crois que cela a été activé par défaut dans la version 7 de gdb.

vous pouvez vérifier ceci en lançant cette commande:

show disable-randomization

Et avec

set disable-randomization on

ou

set disable-randomization off
6
répondu LogicG8 2013-07-21 18:10:51

Voici une façon simple d'exécuter votre programme avec des piles identiques dans le terminal et en 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

NOTE: la valeur par défaut sur ma machine était 2, notez la vôtre avant de la modifier.

puis lancez votre programme comme so (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

à l'intérieur de gdb, assurez-vous de unsetLINES et COLUMNS.

Note: j'ai obtenu ces variables d'environnement en jouant avec un programme de test.

ces deux passages vous donneront des pointeurs identiques vers le haut de la pile, donc pas besoin de shenanigans de script distant si vous essayez d'exploiter un binaire hébergé à distance.

5
répondu Aralox 2017-05-16 00:32:04

j'ai essayé la solution acceptée ici et Ça ne fonctionne pas (pour moi). Je savais que gdb avait 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 aussi essayé le script posté dans la solution acceptée).

Mais la recherche dans le web j'ai trouvé d'autres scripts qui fonctionnent pour moi: https://github.com/hellman/fixenv/blob/master/r.sh

L'utilisation est fondamentalement la même ce script dans la solution retenue:

  • r. sh gdb ./programme [args] pour exécuter le programme dans gdb
  • r. sh ./programme [args] pour exécuter le programme sans gdb

et ce script marche pour moi.

2
répondu RdlP 2016-10-12 15:58:13

une des principales choses que gdb fait qui n'arrive pas en dehors de gdb est la mémoire zéro. Il est plus que probable que quelque part dans le code, vous n'initialisiez pas votre mémoire et qu'elle recevait des valeurs d'ordures. Gdb efface automatiquement toute la mémoire que vous attribuez cachant ces types d'erreurs.

Par exemple: les éléments suivants doivent travailler dans gdb, mais pas en dehors d'elle:

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 si il peut détecter ce problème.

0
répondu chacham15 2013-07-21 18:19:50

Je suis sur CentOS 6.4 32 bit et j'essaie de provoquer un débordement de tampon dans un programme... Cependant quand j'exécute la pile de programme juste sur son propre il seg défauts.

vous devez également vous assurer que FORTIFY_SOURCE n'affecte pas vos résultats. La faille de seg ressemble à FORTIFY_SOURCE pourrait être le problème car FORTIFY_SOURCE insérera des appels de fonction" safer " 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 le la taille est vérifié et abort() est appelé sur une violation (i.e., votre erreur seg).

pour désactiver FORTIFY_SOURCE for testing, vous devez compiler avec -U_FORTIFY_SOURCE ou -D_FORTIFY_SOURCE=0.

0
répondu jww 2014-09-12 12:41:11