Overflow minimal: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
(Die Seite wurde neu angelegt: „= Buffer Overflow: Die unsichtbare Gefahr in 6 Bytes = ;Autor: Thomas Schmidt ;Datum: 2025-11-03 *Kurzbeschreibung * :Ein winziger Programmierfehler kann verh…“)
 
 
(13 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
 
= Buffer Overflow: Die unsichtbare Gefahr in 6 Bytes =
 
= Buffer Overflow: Die unsichtbare Gefahr in 6 Bytes =
;Autor: Thomas Schmidt
+
==Kurzbeschreibung==
;Datum: 2025-11-03
+
Dieses Lehrbeispiel zeigt, wie ein unsicherer Kopiervorgang in C bei einem 6-Byte-Puffer zu einem Stack-Buffer-Overflow und damit zu einem Absturz führen kann. Nur Analyse/Lehre in einer isolierten VM. Kein Exploit.
  
*Kurzbeschreibung
+
=Voraussetzungen=
* :Ein winziger Programmierfehler kann verheerende Folgen haben. Das Beispielprogramm '''overflow_minimal.c''' zeigt, wie bereits 6 Bytes ausreichen, um eine kritische Schwachstelle zu erzeugen.
+
Debian/Ubuntu oder eine ähnliche Linux-Distribution mit gcc, gdb und python3.
* :Zweck: Lehrbeispiel für Trainings und Code-Reviews. Nur in einer isolierten Labor-VM ausführen.
 
 
 
*Voraussetzungen
 
* :Debian/Ubuntu oder andere Linux-Distribution mit gcc, gdb und python3 installiert.
 
 
 
== Das gefährliche Programm ==
 
* :Datei: overflow_minimal.c
 
* :Hinweis: Der Code ist absichtlich unsicher, um den Überlauf sichtbar zu machen. Nur zu Lehrzwecken in eigenen Laboren verwenden.
 
  
 +
== Beispielcode (kopierbar) ==
 +
*cat overflow_minimal.c
 
   /* overflow_minimal.c - Buffer Overflow Demonstration */
 
   /* overflow_minimal.c - Buffer Overflow Demonstration */
 
   #include <stdio.h>
 
   #include <stdio.h>
 
   #include <string.h>
 
   #include <string.h>
 
+
 
   void func(char *input)
 
   void func(char *input)
 
   {
 
   {
       char buffer[6];  // Nur 6 Bytes Puffer!
+
       char buffer[6];  // Nur 6 Bytes Puffer (einschließlich NUL)
       strcpy(buffer, input);  // Keine Längenprüfung!
+
       strcpy(buffer, input);  // Absichtlich unsicher: keine Längenprüfung
 
       printf("Du hast eingegeben: %s\n", buffer);
 
       printf("Du hast eingegeben: %s\n", buffer);
 
   }
 
   }
 
+
 
   int main(int argc, char *argv[])
 
   int main(int argc, char *argv[])
 
   {
 
   {
Zeile 36: Zeile 30:
  
 
== Kompilieren ==
 
== Kompilieren ==
* :Stack-Protector deaktiviert, Debug-Symbole aktiv:
+
Stack-Protector deaktiviert, Debug-Symbole aktiv:
  gcc -fno-stack-protector -z execstack -g -o overflow_minimal overflow_minimal.c
+
* gcc -fno-stack-protector -z execstack -g -o overflow_minimal overflow_minimal.c
* :Analyse mit AddressSanitizer:
+
Analyse mit AddressSanitizer:
  gcc -g -fsanitize=address -fno-omit-frame-pointer -o overflow_minimal_asan overflow_minimal.c
+
* gcc -g -fsanitize=address -fno-omit-frame-pointer -o overflow_minimal_asan overflow_minimal.c
  
 
== Testen ==
 
== Testen ==
* :Normale Eingabe (≤ 6 Zeichen):
+
Normale Eingabe (≤ 6 Zeichen):
  ./overflow_minimal ABCDEF
+
* ./overflow_minimal ABCDEF
  # Ausgabe: Du hast eingegeben: ABCDEF
+
Ausgabe: Du hast eingegeben: ABCDEF
* :Kurze Überschreitung (7 Zeichen):
+
* echo $?
  ./overflow_minimal ABCDEFG
+
0
* :Zuverlässiger Crash (lange Eingabe):
+
Kurze Überschreitung (7 Zeichen):
  ./overflow_minimal "$(python3 -c 'print(\"A\"*200)')"
+
* ./overflow_minimal ABCDEFG
 +
Du hast eingegeben: ABCDEFG
 +
Segmentation fault
 +
* echo $?
 +
139
 +
 
 +
== Analyse mit GDB ==
 +
Das GNU Debugger (gdb) ist ein Werkzeug, um den Programmablauf zu verstehen und Fehler (wie hier durch Buffer Overflow) gezielt zu untersuchen. 
 +
Alle folgenden Schritte dienen der Analyse, nicht der Ausnutzung.
 +
 
 +
* gdb --args ./overflow_minimal "$(python3 -c 'print("A"*200)')"
 +
  # Startet gdb mit dem Programm und einem 200-Byte-String als Argument.
 +
* run
 +
  # Programm starten
 +
* bt
 +
  # Backtrace anzeigen (zeigt Aufrufkette zum Absturz)
 +
* info registers
 +
  # Registerstatus (RIP, RSP, RBP usw.)
 +
* frame 0
 +
  # In das aktuelle Stackframe wechseln
 +
* info locals
 +
  # Lokale Variablen (z. B. buffer) anzeigen
 +
* x/64bx $rsp
 +
  # 64 Bytes Speicher ab Stackpointer anzeigen (hex)
 +
* x/s $rsp
 +
  # Speicher als String anzeigen
 +
* disassemble func
 +
  # Assemblercode der Funktion anzeigen
 +
 
 +
=== Erklärung der wichtigsten GDB-Befehle ===
 +
* run 
 +
  Startet das Programm unter gdb-Kontrolle. Stoppt bei Absturz (Segmentation fault).
 +
 
 +
* bt 
 +
  Zeigt die komplette Aufrufkette vom main() über func() bis zur Absturzstelle.
 +
 
 +
* info registers 
 +
  Zeigt CPU-Register an, z. B. rip (Instruktionszeiger), rbp/rsp (Stackpointer). Überprüfen, ob der Overflow Rücksprungadressen überschrieben hat.
 +
 
 +
* x/64bx $rsp 
 +
  Dump des Stackinhalts (64 Bytes, Byteweise). Praktisch, um zu sehen, wie der Eingabestring den Stack überschreibt.
 +
 
 +
* x/s $rsp 
 +
  Speicher als String anzeigen. Hier erkennt man oft endlose "A"-Zeichen bei Overflow.
 +
 
 +
* info frame 
 +
  Zeigt Stackframe-Größe, Rücksprungadresse und Lage der lokalen Variablen.
 +
 
 +
* disassemble func 
 +
  Zeigt CPU-Instruktionen der Funktion func. Hilfreich, um den Absturzpunkt zu lokalisieren.
 +
 
 +
* break func 
 +
  Setzt einen Breakpoint vor der gefährlichen Stelle.
 +
 
 +
* next / step / finish 
 +
  next: nächste Zeile ausführen, step: Funktionsaufruf betreten, finish: Funktion bis Ende ausführen.
  
== Beobachtbares Verhalten ==
+
* info locals / info args 
* :Kurze Überläufe treffen oft nur lokale Variablen; das Programm kann noch Ausgaben machen und später abstürzen.
+
  Zeigt lokale Variablen und Funktionsargumente an, z. B. den Inhalt von buffer.
* :Lange Eingaben überschreiben saved registers / return address und führen meist zu SIGSEGV.
 
* :Mit ASAN-Kompilation erhältst du eine klare Meldung („stack-buffer-overflow“) mit Backtrace.
 
  
== Analyse mit GDB ==
+
* print buffer 
* :Beispiel:
+
  Inhalt von Variablen anzeigen.
  gdb --args ./overflow_minimal "$(python3 -c 'print(\"A\"*200)')"
+
 
  # in gdb: run
+
* x/32x $rbp-0x20 
   # nach Crash: bt
+
  Zeigt Stackbereich unterhalb des Framepointers, um zu sehen, wie viele Bytes überschrieben wurden.
  # ggf.: info registers, x/24x $rsp, disas
+
 
* :Trainer-Hinweis: Stack-Layout (saved RBP, return address, lokale Variablen) erklären.
+
=== Beispielanalyse ===
 +
* gdb --args ./overflow_minimal "$(python3 -c 'print("A"*40)')"
 +
* run
 +
   Program received signal SIGSEGV, Segmentation fault.
 +
* bt
 +
  #0  func (input=0x7fffffffde80 "AAAAAAAAAAAA...") at overflow_minimal.c:9
 +
  #1  0x00005555555551a2 in main (argc=2, argv=0x7fffffffe2d8) at overflow_minimal.c:18
 +
* info registers
 +
  rip = 0x4141414141414141  ← Rücksprungadresse durch "AAAA" überschrieben
 +
* x/32bx $rsp
 +
  0x7fffffffdc80: 0x41 0x41 0x41 0x41 ...
 +
  → Der Stack wurde mit 0x41 (ASCII 'A') gefüllt – typisches Overflow-Symptom.
 +
 
 +
=== Weitere nützliche Befehle ===
 +
* x/200bc $rsp      → zeigt 200 Bytes als char 
 +
* x/10i $rip        → zeigt 10 Instruktionen ab aktueller Codeadresse 
 +
* info proc mappings → zeigt Speicherbereiche (Text, Stack, Heap)
 +
* quit              → gdb beenden
  
 
== Sicherer Fix (Kontrast) ==
 
== Sicherer Fix (Kontrast) ==
Zeile 72: Zeile 136:
  
 
== Fazit ==
 
== Fazit ==
* :Schon minimale Programmierfehler können massive Sicherheits- oder Stabilitätsprobleme verursachen.
+
* Schon minimale Programmierfehler können massive Sicherheits- oder Stabilitätsprobleme verursachen.
* :Sorgfalt bei Puffergrößen, Eingabevalidierung und das Nutzen moderner Schutzmechanismen sind Pflicht in der sicheren Softwareentwicklung.
+
* Sorgfalt bei Puffergrößen, Eingabevalidierung und das Nutzen moderner Schutzmechanismen sind Pflicht in der sicheren Softwareentwicklung.
 +
* gdb ist ein starkes Werkzeug, um den Ablauf zu verstehen: Stack-Frames, Register und Speicher lassen sich genau untersuchen.
 +
* AddressSanitizer ist die sichere Alternative für automatische Overflow-Erkennung.

Aktuelle Version vom 3. November 2025, 20:22 Uhr

Buffer Overflow: Die unsichtbare Gefahr in 6 Bytes

Kurzbeschreibung

Dieses Lehrbeispiel zeigt, wie ein unsicherer Kopiervorgang in C bei einem 6-Byte-Puffer zu einem Stack-Buffer-Overflow und damit zu einem Absturz führen kann. Nur Analyse/Lehre in einer isolierten VM. Kein Exploit.

Voraussetzungen

Debian/Ubuntu oder eine ähnliche Linux-Distribution mit gcc, gdb und python3.

Beispielcode (kopierbar)

  • cat overflow_minimal.c
 /* overflow_minimal.c - Buffer Overflow Demonstration */
 #include <stdio.h>
 #include <string.h>

 void func(char *input)
 {
     char buffer[6];   // Nur 6 Bytes Puffer (einschließlich NUL)
     strcpy(buffer, input);  // Absichtlich unsicher: keine Längenprüfung
     printf("Du hast eingegeben: %s\n", buffer);
 }

 int main(int argc, char *argv[])
 {
     if (argc < 2) {
         printf("Usage: %s <input>\n", argv[0]);
         return 1;
     }
     func(argv[1]);
     return 0;
 }

Kompilieren

Stack-Protector deaktiviert, Debug-Symbole aktiv:

  • gcc -fno-stack-protector -z execstack -g -o overflow_minimal overflow_minimal.c

Analyse mit AddressSanitizer:

  • gcc -g -fsanitize=address -fno-omit-frame-pointer -o overflow_minimal_asan overflow_minimal.c

Testen

Normale Eingabe (≤ 6 Zeichen):

  • ./overflow_minimal ABCDEF
Ausgabe: Du hast eingegeben: ABCDEF
  • echo $?
0

Kurze Überschreitung (7 Zeichen):

  • ./overflow_minimal ABCDEFG
Du hast eingegeben: ABCDEFG
Segmentation fault
  • echo $?
139

Analyse mit GDB

Das GNU Debugger (gdb) ist ein Werkzeug, um den Programmablauf zu verstehen und Fehler (wie hier durch Buffer Overflow) gezielt zu untersuchen. Alle folgenden Schritte dienen der Analyse, nicht der Ausnutzung.

  • gdb --args ./overflow_minimal "$(python3 -c 'print("A"*200)')"
 # Startet gdb mit dem Programm und einem 200-Byte-String als Argument.
  • run
 # Programm starten
  • bt
 # Backtrace anzeigen (zeigt Aufrufkette zum Absturz)
  • info registers
 # Registerstatus (RIP, RSP, RBP usw.)
  • frame 0
 # In das aktuelle Stackframe wechseln
  • info locals
 # Lokale Variablen (z. B. buffer) anzeigen
  • x/64bx $rsp
 # 64 Bytes Speicher ab Stackpointer anzeigen (hex)
  • x/s $rsp
 # Speicher als String anzeigen
  • disassemble func
 # Assemblercode der Funktion anzeigen

Erklärung der wichtigsten GDB-Befehle

  • run
 Startet das Programm unter gdb-Kontrolle. Stoppt bei Absturz (Segmentation fault).
  • bt
 Zeigt die komplette Aufrufkette vom main() über func() bis zur Absturzstelle.
  • info registers
 Zeigt CPU-Register an, z. B. rip (Instruktionszeiger), rbp/rsp (Stackpointer). Überprüfen, ob der Overflow Rücksprungadressen überschrieben hat.
  • x/64bx $rsp
 Dump des Stackinhalts (64 Bytes, Byteweise). Praktisch, um zu sehen, wie der Eingabestring den Stack überschreibt.
  • x/s $rsp
 Speicher als String anzeigen. Hier erkennt man oft endlose "A"-Zeichen bei Overflow.
  • info frame
 Zeigt Stackframe-Größe, Rücksprungadresse und Lage der lokalen Variablen.
  • disassemble func
 Zeigt CPU-Instruktionen der Funktion func. Hilfreich, um den Absturzpunkt zu lokalisieren.
  • break func
 Setzt einen Breakpoint vor der gefährlichen Stelle.
  • next / step / finish
 next: nächste Zeile ausführen, step: Funktionsaufruf betreten, finish: Funktion bis Ende ausführen.
  • info locals / info args
 Zeigt lokale Variablen und Funktionsargumente an, z. B. den Inhalt von buffer.
  • print buffer
 Inhalt von Variablen anzeigen.
  • x/32x $rbp-0x20
 Zeigt Stackbereich unterhalb des Framepointers, um zu sehen, wie viele Bytes überschrieben wurden.

Beispielanalyse

  • gdb --args ./overflow_minimal "$(python3 -c 'print("A"*40)')"
  • run
 Program received signal SIGSEGV, Segmentation fault.
  • bt
  #0  func (input=0x7fffffffde80 "AAAAAAAAAAAA...") at overflow_minimal.c:9
  #1  0x00005555555551a2 in main (argc=2, argv=0x7fffffffe2d8) at overflow_minimal.c:18
  • info registers
  rip = 0x4141414141414141  ← Rücksprungadresse durch "AAAA" überschrieben
  • x/32bx $rsp
  0x7fffffffdc80: 0x41 0x41 0x41 0x41 ...
 → Der Stack wurde mit 0x41 (ASCII 'A') gefüllt – typisches Overflow-Symptom.

Weitere nützliche Befehle

  • x/200bc $rsp → zeigt 200 Bytes als char
  • x/10i $rip → zeigt 10 Instruktionen ab aktueller Codeadresse
  • info proc mappings → zeigt Speicherbereiche (Text, Stack, Heap)
  • quit → gdb beenden

Sicherer Fix (Kontrast)

 void func_safe(char *input)
 {
     char buffer[6];
     snprintf(buffer, sizeof buffer, "%s", input);
     printf("Du hast eingegeben: %s\n", buffer);
 }

Fazit

  • Schon minimale Programmierfehler können massive Sicherheits- oder Stabilitätsprobleme verursachen.
  • Sorgfalt bei Puffergrößen, Eingabevalidierung und das Nutzen moderner Schutzmechanismen sind Pflicht in der sicheren Softwareentwicklung.
  • gdb ist ein starkes Werkzeug, um den Ablauf zu verstehen: Stack-Frames, Register und Speicher lassen sich genau untersuchen.
  • AddressSanitizer ist die sichere Alternative für automatische Overflow-Erkennung.