Overflow minimal
Zur Navigation springen
Zur Suche springen
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.