Pufferüberlauf funktioniert in gdb, aber nicht ohne

Lesezeit: 8 Minuten

Benutzeravatar von thaweatherman
der Wettermann

Ich verwende CentOS 6.4 32 Bit und versuche, einen Pufferüberlauf in einem Programm zu verursachen. Innerhalb von GDB funktioniert es. Hier ist die Ausgabe:

[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#

Wenn ich jedoch den Programmstapel nur alleine ausführe, werden Seg-Fehler angezeigt. Warum könnte das sein?

  • seg faults ist auf einen Pufferüberlauf zurückzuführen, Sie haben es richtig gemacht. Wenn Sie Ihr Code-Betriebssystem ausführen, senden Sie SIGSEGV an Ihren Prozess (= Programm in Ausführung) bei einer Speicherverletzung, die Ihnen einen Nachrichtensegmentierungsfehler gibt – dieses Signal ist darauf zurückzuführen, dass Sie einen ungültigen Zugriff ausführen zu gültiger Erinnerung. (Ich nehme an, Sie versuchen, zu schreiben / zu ändern "constantstring" Am Ende)

    – Grijesh Chauhan

    21. Juli 2013 um 17:58 Uhr


  • …Ich weiß das. Es soll eine Shell ausführen. In GDB führt es die Shell aus. Wenn ich das Programm außerhalb von GDB ausführe, wird die Shell nicht ausgeführt, daher der Segfault

    – der Wettermann

    21. Juli 2013 um 18:01 Uhr

  • Dies liegt daran, dass, wenn Sie Ihren Code außerhalb von GDB ausführen, es – es undefiniertes Verhalten im C-Standard ist. Während GDB das Signal SIGSEGV handhabt, damit es Ihnen einen Hinweis auf einen Segmentierungsfehler geben kann

    – Grijesh Chauhan

    21. Juli 2013 um 18:04 Uhr


  • @GrijeshChauhan: GDB würde den SIGSEGV handhaben und berichten, dass es passiert ist. Hier gibt es keinen solchen Bericht. Ich würde es danach voll und ganz erwarten bash kehrt zurück, aber der Segfault würde passieren, bevor er überhaupt beginnt

    – chao

    21. Juli 2013 um 19:46 Uhr


  • @cHao 🙁 🙂 (: 🙂 Keine Ahnung, weiß nicht, ich muss selbst ein Experiment versuchen.

    – Grijesh Chauhan

    21. Juli 2013 um 20:10 Uhr

Benutzeravatar von mavam
mavam

Die Exploit-Entwicklung kann zu ernsthaften Kopfschmerzen führen, wenn Sie die einfließenden Faktoren nicht angemessen berücksichtigen Nichtdeterminismus in den Debugging-Prozess. Insbesondere die Stapeladressen im Debugger stimmen möglicherweise nicht mit den Adressen während der normalen Ausführung überein. Dieses Artefakt tritt auf, weil das Ladeprogramm des Betriebssystems sowohl Umgebungsvariablen als auch Programmargumente platziert Vor Anfang des Stacks:

Prozesslayout

Da Ihr verwundbares Programm keine Argumente akzeptiert, sind wahrscheinlich die Umgebungsvariablen der Übeltäter. Stellen Sie sicher, dass sie in beiden Aufrufen gleich sind, in der Shell und im Debugger. Zu diesem Zweck können Sie Ihren Aufruf einschließen env:

env - /path/to/stack

Und mit dem Debugger:

env - gdb /path/to/stack
($) show env
LINES=24
COLUMNS=80

Im obigen Beispiel gibt es zwei von gdb gesetzte Umgebungsvariablen, die Sie weiter deaktivieren können:

unset env LINES
unset env COLUMNS

Jetzt show env sollte eine leere Liste zurückgeben. An diesem Punkt können Sie den Debugging-Prozess starten, um die absolute Stack-Adresse zu finden, zu der Sie springen möchten (z. B. 0xbffffa8b) und fest in Ihren Exploit codieren.

Ein weiteres subtiles, aber wichtiges Detail: Es gibt einen Unterschied zwischen Anrufen ./stack und /path/to/stack: seit argv[0] das Programm genau so enthält, wie Sie es aufgerufen haben, müssen Sie sicherstellen, dass die Aufrufzeichenfolgen gleich sind. Deshalb habe ich verwendet /path/to/stack in den obigen Beispielen und nicht nur ./stack und gdb stack.

Wenn Sie lernen, Sicherheitslücken im Speicher auszunutzen, empfehle ich die Verwendung des folgenden Wrapper-Programms, das die schwere Arbeit übernimmt und gleiche Stack-Offsets gewährleistet:

$ invoke stack         # just call the executable
$ invoke -d stack      # run the executable in GDB

Hier ist das Skript:

#!/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

  • Ich habe das getan, was Sie vorgeschlagen haben, und das Programm als /root/bufferflow/stack ausgeführt, und es hat ordnungsgemäß funktioniert. Vielen Dank

    – der Wettermann

    21. Juli 2013 um 21:05 Uhr

  • Das Beispiel ist falsch. Statt ‘–gdb’ sollte ‘-d’ stehen.

    – molnarg

    27. Mai 2014 um 19:56 Uhr

  • @molnarg: Danke, behoben.

    – mavam

    4. Juni 2014 um 8:43 Uhr

  • Sehr nützliche Informationen! Vielen Dank, dass Sie auch das Skript geteilt haben.

    – alecov

    10. November 2015 um 18:47 Uhr

  • Bei mir funktioniert das nicht. Zuerst versuche ich, die Umgebungsvariablen zu entfernen, und es funktioniert nicht, dann habe ich das in diesem Formular gepostete Skript verwendet: ./invoke -d exploitme und dann (in gdb) run MY_SHELLCODE Ich kann meinen Shelcode in gdb ausführen, aber wenn ich laufe ./invoke exploitme MY_SHELLCODE Ich kann den Shellcode nicht ausführen, bekomme ich Welcome ��^�1��F�F � ����V 1ۉ�@�����/bin/shP��� [1] 13626 segmentation fault (core dumped) ./invoke exploitme wo MY_SHELLCODE ist mein Shellcode-String.

    – RdlP

    12. Oktober 2016 um 15:09 Uhr


Benutzeravatar von Aralox
Aralox

Hier ist eine einfache Möglichkeit, Ihr Programm mit identischen Stacks im Terminal und in auszuführen gdb:

Stellen Sie zunächst sicher, dass Ihr Programm ohne Stapelschutz kompiliert ist.

gcc -m32 -fno-stack-protector -z execstack -o shelltest shelltest.c -g

und und ASLR ist deaktiviert:

echo 0 > /proc/sys/kernel/randomize_va_space

HINWEIS: Der Standardwert auf meinem Computer war 2, beachten Sie Ihren, bevor Sie dies ändern.

Führen Sie dann Ihr Programm wie folgt aus (Terminal bzw. gdb):

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

Innerhalb gdbstellen Sie sicher, dass unset LINES und COLUMNS.

Hinweis: Ich habe diese Umgebungsvariablen erhalten, indem ich mit a herumgespielt habe Testprogramm.

Diese beiden Läufe geben Ihnen identische Zeiger auf die Spitze des Stacks, sodass Sie keine entfernten Skript-Spielereien benötigen, wenn Sie versuchen, eine entfernt gehostete Binärdatei auszunutzen.

Benutzeravatar von York
York

Die Adresse des Stack-Frame-Zeigers beim Ausführen des Codes in gdb unterscheidet sich von der normalen Ausführung. Sie können also die Rücksendeadresse direkt im gdb-Modus beschädigen, aber möglicherweise nicht, wenn Sie im normalen Modus ausgeführt werden. Der Hauptgrund dafür ist, dass sich die Umgebungsvariablen zwischen den beiden Situationen unterscheiden.

Da dies nur eine Demo ist, können Sie den Opfercode ändern und die Adresse des Puffers drucken. Ändern Sie dann Ihre Rücksendeadresse in Offset + Adresse des Puffers.

In Wirklichkeit müssen Sie jedoch die Absenderadresse hinzufügen NOP-Schlitten vor Ihrem bösartigen Code. Und Sie können mehrmals raten, um eine korrekte Adresse zu erhalten, da Ihre Vermutung falsch sein kann.

Hoffe das kann dir helfen.

Der Grund, warum Ihr Pufferüberlauf ansonsten unter gdb und segfaults funktioniert, ist, dass gdb die Randomisierung des Adressraumlayouts deaktiviert. Ich glaube, dies war in gdb Version 7 standardmäßig aktiviert.

Sie können dies überprüfen, indem Sie diesen Befehl ausführen:

show disable-randomization

Und setze es mit

set disable-randomization on

oder

set disable-randomization off

Ich habe die hier akzeptierte Lösung ausprobiert und sie funktioniert (für mich) nicht. Ich wusste, dass gdb Umgebungsvariablen hinzugefügt hat und aus diesem Grund die Stapeladresse nicht übereinstimmt, aber selbst wenn ich diese Variablen entferne, kann ich meinen Exploit nicht ohne gdb ausführen (ich habe auch das in der akzeptierten Lösung gepostete Skript ausprobiert).

Aber bei der Suche im Internet habe ich andere Skripte gefunden, die für mich funktionieren: https://github.com/hellman/fixenv/blob/master/r.sh

Die Verwendung ist im Grunde dieselbe wie das Skript in der akzeptierten Lösung:

  • r.sh gdb ./program [args] um das Programm in gdb auszuführen
  • r.sh ./programm [args] um das Programm ohne gdb auszuführen

Und dieses Skript funktioniert für mich.

Benutzeravatar von jww
jww

Ich verwende CentOS 6.4 32 Bit und versuche, einen Pufferüberlauf in einem Programm zu verursachen … Wenn ich jedoch den Programmstapel nur alleine ausführe, werden Fehler angezeigt.

Sie sollten auch sicherstellen, dass FORTIFY_SOURCE Ihre Ergebnisse nicht beeinflusst. Der Seg-Fehler klingt so, als ob FORTIFY_SOURCE das Problem sein könnte, da FORTIFY_SOURCE „sicherere“ Funktionsaufrufe einfügt, um vor einigen Arten von Pufferüberläufen zu schützen. Wenn der Compiler Zielpuffergrößen ableiten kann, wird die Größe geprüft und abort() wird bei einer Verletzung (dh Ihrem Seg-Fehler) aufgerufen.

Um FORTIFY_SOURCE zum Testen auszuschalten, sollten Sie mit kompilieren -U_FORTIFY_SOURCE oder -D_FORTIFY_SOURCE=0.

Eines der wichtigsten Dinge, die gdb tut, die außerhalb von gdb nicht passieren, ist null Speicher. Höchstwahrscheinlich initialisieren Sie irgendwo im Code Ihren Speicher nicht und es werden Müllwerte angezeigt. Gdb löscht automatisch den gesamten Speicher, den Sie zuweisen, um diese Art von Fehlern zu verbergen.

Zum Beispiel: Folgendes sollte in gdb funktionieren, aber nicht außerhalb:

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;
}

Versuchen Sie, Ihr Programm unter valgrind auszuführen, um zu sehen, ob es dieses Problem erkennen kann.

  • Das verwundbare Programm liest tatsächlich eine Datei in einen Puffer ein, also ist die Datei der Exploit-String. Dann ruft es eine Funktion auf, die einen Strcpy des ursprünglichen Puffers in einen viel kleineren Puffer durchführt. Es initialisiert also niemals den Speicher außerhalb dieser Funktionen

    – der Wettermann

    21. Juli 2013 um 18:36 Uhr

1410650cookie-checkPufferüberlauf funktioniert in gdb, aber nicht ohne

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy