GCC, wie Stack-Pufferüberlauf zu erkennen

8

Da es eine Option -fstack-protector-strong in gcc gibt, um Stack-Smashing zu erkennen. Es kann jedoch nicht immer Stapelpufferüberlauf erkennen. Für die erste Funktion func, wenn ich eine Zeichenfolge mit 10 Zeichen mehr eingabe, stürzt das Programm nicht immer ab. Meine Frage ist, wo es einen Weg gibt, Stapelpufferüberlauf zu entdecken.

%Vor%     
Michael D 30.09.2013, 10:12
quelle

4 Antworten

6

Überläufe auf dem Stapel sind entweder schwer zu entdecken oder sehr teuer zu erkennen - wähle dein Gift.

Kurz gesagt, wenn Sie folgendes haben:

%Vor%

dann ist das technisch legal: Auf dem Stack ist Platz, der zu der Funktion gehört. Es ist nur sehr gefährlich.

Die Lösung könnte also sein, eine Lücke zwischen a und b hinzuzufügen und diese mit einem Muster zu füllen. Aber, einige Leute schreiben Code wie oben. Das muss Ihr Compiler erkennen.

Alternativ könnten wir eine Bitmap aller Bytes erstellen, die Ihr Code wirklich zugewiesen hat, und dann den gesamten Code instrumentieren, um diese Karte zu überprüfen. Sehr sicher, ziemlich langsam, bläht den Speicherverbrauch auf. Auf der positiven Seite gibt es Werkzeuge, die dabei helfen können (wie Valgrind ).

Siehst du, wohin ich gehe?

Fazit: In C gibt es keinen guten Weg, viele Speicherprobleme automatisch zu erkennen, weil die Sprache und die API oft zu schlampig sind. Die Lösung besteht darin, Code in Hilfsfunktionen zu überführen, die ihre Parameter rigoros und immer auf das Richtige überprüfen und eine gute Unit-Test-Abdeckung bieten.

Verwenden Sie immer snprintf() Versionen von Funktionen, wenn Sie die Wahl haben. Wenn alter Code die unsicheren Versionen verwendet, ändern Sie ihn.

    
Aaron Digulla 30.09.2013, 11:49
quelle
2

Sie können ein Werkzeug namens Valgrind

verwenden

Ссылка

    
Mark Nicolle 30.09.2013 11:48
quelle
1
  

Meine Frage ist, wo es einen Weg gibt, Stapelpufferüberlauf zu entdecken ...

%Vor%

Da Sie GCC verwenden, können Sie FORTIFY_SOURCES verwenden.

FORTIFY_SOURCE verwendet "sicherere" Varianten von Hochrisikofunktionen wie memcpy , strcpy und gets . Der Compiler verwendet die sichereren Varianten, wenn er die Zielpuffergröße ermitteln kann. Wenn die Kopie die Zielpuffergröße überschreiten würde, ruft das Programm abort() auf. Wenn der Compiler die Zielpuffergröße nicht ableiten kann, werden die "safer" Varianten nicht verwendet.

Um FORTIFY_SOURCE zum Testen zu deaktivieren, sollten Sie das Programm mit -U_FORTIFY_SOURCE oder -D_FORTIFY_SOURCE=0 kompilieren.

Der C-Standard hat "sicherere" Funktionen über ISO / IEC TR 24731- 1, Grenzen, die Schnittstellen prüfen . Auf entsprechenden Plattformen können Sie einfach gets_s und sprintf_s aufrufen. Sie bieten konsistentes Verhalten (wie immer sicherstellen, dass eine Zeichenfolge NULL beendet ist) und konsistente Rückgabewerte (wie 0 bei Erfolg oder errno_t ).

Leider stimmen gcc und glibc nicht mit dem C-Standard überein. Ulrich Drepper (einer der Glibc-Betreuer) nannte Grenzüberprüfung Schnittstellen "schrecklich ineffiziente BSD Mist " , und sie wurden nie hinzugefügt. Hoffentlich wird sich das in Zukunft ändern.

    
jww 12.09.2014 15:14
quelle
0

Als erstes benutze nicht gets.By jetzt kennt fast jeder die Sicherheit und Zuverlässigkeit Probleme, die mit Gets auftreten können. Aber es ist hier auch aus historischen Gründen enthalten, weil es ein sehr gutes Beispiel für schlechte Programmierung ist.

Schauen wir uns alle Probleme mit dem Code an:

%Vor%

Da gets keine Grenzen setzt, wird beim Überprüfen einer Zeichenfolge mit mehr als 100 Zeichen der Speicher überschrieben. Wenn Sie Glück haben, wird das Programm einfach abstürzen Oder es kann seltsames Verhalten zeigen.

Die Get-Funktion ist so schlecht, dass der GNU gcc Linker bei jeder Verwendung eine Warnung ausgibt.

%Vor%

Schützen Sie Array-Zugriffe mit der Bestätigung

C / C ++ führt keine Überprüfung durch.

zum Beispiel:

%Vor%

Verwenden Sie die Assert-Funktion für den obigen Code

%Vor%

Array-Überläufe gehören zu den häufigsten Programmierfehlern und sind extrem frustrierend zu versuchen und zu lokalisieren. Dieser Code beseitigt sie nicht, aber es führt dazu, dass buggy Code vorzeitig abbricht, so dass das Problem erheblich leichter zu finden ist.

Und benutze Snprintf (buffer, sizeof (buffer), "% s", "abcdefghpapeas") und einige Tools wie valgrind, GDB.

Hoffe das hilft dir ..

    
Stuxnet78 12.09.2014 15:55
quelle