Verständnisfrage Buffer overflow



  • Hi Leute,

    hätte eine Frage bezüglich des Buffer (stack) overflows.
    Auf wikipedia gibt es hier ein Beispiel http://en.wikipedia.org/wiki/Stack_buffer_overflow

    float My_Float = 10.5; // Addr = 0x0023FF4C
       char  c[28];           // Addr = 0x0023FF30
    
       // Will print 10.500000
       printf("My Float value = %f\n", My_Float);
    
       memcpy(c, bar, strlen(bar));  // no bounds checking...
    
       // Will print 96.031372
       printf("My Float value = %f\n", My_Float);
    

    Hier wird nun offensichtlich my float überschrieben.

    Dann gibt es hier wieder ein Beispiel
    http://en.wikipedia.org/wiki/Buffer_overflow

    char           A[8] = {};
    unsigned short B    = 1979;
    strcpy(A, "excessive");
    

    Hier wird nun B überschrieben?
    Was ich nicht genau verstehe werden die Variablen über dem Buffer wie im ersten Beispiel oder die darunter wie im 2. Beispiel überschrieben 😕
    Eigentlich müssten die darüber ja überschrieben werden, da das letzte Array Element an der höchsten Addresse steht.
    Danke im Voraus!


  • Mod

    Was hat die Frage mit Assembler zu tun?

    Wie genau ein Compiler die Variablen zueinander anordnet (sofern Variablen überhaupt noch irgendwie einer bestimmten Speicherposition zugeschrieben werden können, was oftmals nicht mehr der Fall ist) ist im C-Standard nicht vorgeschrieben. Es ist nicht einmal klar, ob überhaupt so etwas wie ein Stack existiert. Manche Compiler haben eine (für eben diesen speziellen Compiler) dokumentierte Anordnung im Falle von unoptimierten Code. Dieses Verhalten kann und wird sich daher von Fall zu Fall unterscheiden und die Beispielcodes auf Wikipedia sind daher hochgradig unportabel. Die sollen auch gar nicht wirklich ausgeführt werden, sondern bloß die Problemstellung verdeutlichen.

    Ein kleines bisschen portabler geht es, wenn man die Daten in ein struct packt:

    struct 
    {
      char string[8];
      float number;
    } foo;
    

    Hier ist garantiert, dass &foo.string < &foo.number. Zumindest sofern man diese Adressen im Programm explizit benutzt*. Denn wie schon gesagt ist gar nicht klar, ob eine Instanz dieses structs im fertigen Maschinencode überhaupt noch irgendeine Repräsentation im Speicher des Computers hat. Ein C-Compiler hat sehr weitreichende Freiheiten bei der Erzeugung des Codes und wird diese auch großzügig nutzen, wenn er Optimierungen durchführt. Sofern das Programm am Ende sich so verhält als ob es dem C-Standard folgt, darf der Compiler so ziemlich alles machen. Und die Folgen eines Pufferüberlaufs sind im C-Standard explizit undefiniert, dass heißt der C-Compiler muss den Code nicht so erzeugen, dass bei einem Pufferüberlauf das Verhalten auftritt, von dem du denkst, dass es auftreten sollte. Wie schon gesagt existiert ein foo.string eventuell gar nicht mehr wirklich und es passiert wer weiß was, wenn du über dessen Grenzen schreibst.

    *: Ein ganz cleverer Compiler könnte natürlich auch diesen Effekt irgendwie simulieren, um die Variablen weg zu optimieren, aber ich denke nicht, dass irgendein real existierender Compiler dies tut.



  • Hi,

    alles klar, vielen Dank! Dachte die Frage passt hier ganz gut rein, da es so low level ist und entfernt was mit Assembler zu tun hat.
    So schlimm ist ein Buffer overflow ja gar nicht, wenn man nicht voraussehen kann, wo die anderen Variablen liegen zum überschreiben. Aber die größere Gefahr ist wohl, dass Shellcode eingeschleust wird.

    Viele Grüße
    Rafael


  • Mod

    Rafael81 schrieb:

    So schlimm ist ein Buffer overflow ja gar nicht, wenn man nicht voraussehen kann, wo die anderen Variablen liegen zum überschreiben.

    😕 Das macht die Sache doch noch viel schlimmer! 😮

    Dein Hacker weiß genau, was passiert, wenn er den Overflow verursacht. Er hat schließlich das fertig übersetzte Programm vorliegen (und wenn nicht, dann kann er leicht raten, was ungefähr passieren wird und ein bisschen ausprobieren). Zur Programmerstellungszeit kannst du nicht genau voraussagen, was passieren wird.



  • am besten du schaust dir das im Debugger an.
    Dann siehst du wo welche Variablen im Speicher liegen.

    Habs z.B. mit deinem Programm kurz probiert.
    Egal ob ich zuerst A und dann B definiere oder umgekehrt - der Compiler legt die Variablen immer in der gleichen Reihenfolge auf den Stack.
    Das "oben" und "unten" korrespondiert also nicht mit "oben" oder "unten" am Stack!

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
    
    	unsigned short B    = 1979;
    	char           A[8] = {0};
    
    	printf("\nA=%p",A);
    	printf("\nB=%p",&B);
    
    	strcpy(A, "excessive");
    
    	return 0;
    }
    
    ; die Zuweisung unsigned short B = 1979 verrät die Position von B am Stack
    MOV ECX,7BB ; 7BB=1979 in ECX schreiben
    MOV WORD PTR SS:[EBP-0x4],CX ; und auf Stackposition EBP-4 schreiben
    
    ; und die Parameterübergabe am Stack für strcpy verrät die Position von A am Stack
    PUSH test.0040C010  ; Adresse von "excessive" auf Stack schreiben
    LEA ECX,DWORD PTR SS:[EBP-0x10] ; Adresse von char A[] laden und in ECX speichern
    PUSH ECX ; ECX auf Stack schreiben
    CALL test.00401070 ; strcpy aufrufen
    

    Somit kennen wir das Stacklayout für deine Funktionsvariablen, 4byte pro Zeile:

    EBP-0x10 | char A[8]: Byte 0 bis 3
    EBP-0xC  | char A[8]: Byte 4 bis 7
    EBP-0x8  | nicht für Funktionsvariablen verwendet
    EBP-0x4  | unsigned short B (2byte) | nicht für Funktionsvariablen verwendet(2byte)
    EBP      | nicht für Funktionsvariablen verwendet
    

    Shellcode wird meist auf Programmfehler in bestimmten Versionen ausgerichtet - durchaus möglich dass der gleiche Shellcode nicht mehr funktioniert, wenn das angegriffene Programm mit einer anderen Compilerversion nochmal erstellt wird.
    Außerdem bauen viele Compiler Code ins Programm ein, welcher checkt, ob der Stack überschrieben wurde.



  • okay danke, ist mir jetzt klar! 🙂



  • Hab ne frage:
    Was tun bei dieser Fehlermeldung (hab gerade erst angefangen :))

    1>LINK : fatal error LNK1123: Fehler bei der Konvertierung in COFF: Datei ist ungültig oder beschädigt.
    ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========

    bitte um Antwort danke



  • Statt sich an einen anderen Thread anzuhängen wäre es besser gewesen. einen neuen Beitrag zu verfassen.

    Wahrscheinlich ist dein Visual Studio falsch eingestellt. Ich habe vor etwas längerer Zeit eine Installationsanleitung auf Stackoverflow gepostet:

    http://stackoverflow.com/questions/31037176/running-asm-procedure-in-cpp-file/31056748#31056748

    und für 64 bit:

    http://stackoverflow.com/questions/33751509/external-assembly-file-in-visual-studio/33757749#33757749

    HTH

    viele grüße
    ralph


Anmelden zum Antworten