Buffer Overflow Problem



  • Ich habe folgeden Code aus http://insecure.org/stf/smashstack.html:
    Der Code soll nach 0x08048398 springen.

    void function(int a, int b, int c) {
       char buffer1[5];
       char buffer2[10];
       int *ret;
    
       ret = buffer1 + 12;
       (*ret) += 8;
    }
    
    void main() {
      int x;
    
      x = 0;
      function(1,2,3);
      x = 1;
      printf("%d\n",x);
    }
    

    Die Distanzen scheinen zu stimmen:

    (gdb) disas main
    Dump of assembler code for function main:
    0x08048372 <main+0>:    lea    0x4(%esp),%ecx
    0x08048376 <main+4>:    and    $0xfffffff0,%esp
    0x08048379 <main+7>:    pushl  -0x4(%ecx)
    0x0804837c <main+10>:   push   %ebp
    0x0804837d <main+11>:   mov    %esp,%ebp
    0x0804837f <main+13>:   push   %ecx
    0x08048380 <main+14>:   sub    $0x14,%esp
    0x08048383 <main+17>:   movl   $0x0,-0x8(%ebp)
    0x0804838a <main+24>:   push   $0x3
    0x0804838c <main+26>:   push   $0x2
    0x0804838e <main+28>:   push   $0x1
    0x08048390 <main+30>:   call   0x8048354 <function>
    0x08048395 <main+35>:   add    $0xc,%esp
    0x08048398 <main+38>:   movl   $0x1,-0x8(%ebp)
    0x0804839f <main+45>:   sub    $0x8,%esp
    0x080483a2 <main+48>:   pushl  -0x8(%ebp)
    0x080483a5 <main+51>:   push   $0x8048480
    0x080483aa <main+56>:   call   0x80482b8 <printf@plt>
    0x080483af <main+61>:   add    $0x10,%esp
    0x080483b2 <main+64>:   mov    -0x4(%ebp),%ecx
    0x080483b5 <main+67>:   leave
    0x080483b6 <main+68>:   lea    -0x4(%ecx),%esp
    0x080483b9 <main+71>:   ret
    End of assembler dump.
    (gdb) disas function
    Dump of assembler code for function function:
    0x08048354 <function+0>:        push   %ebp
    0x08048355 <function+1>:        mov    %esp,%ebp
    0x08048357 <function+3>:        sub    $0x20,%esp
    0x0804835a <function+6>:        lea    -0x9(%ebp),%eax
    0x0804835d <function+9>:        add    $0xc,%eax
    0x08048360 <function+12>:       mov    %eax,-0x4(%ebp)
    0x08048363 <function+15>:       mov    -0x4(%ebp),%eax
    0x08048366 <function+18>:       mov    (%eax),%eax
    0x08048368 <function+20>:       lea    0x8(%eax),%edx
    0x0804836b <function+23>:       mov    -0x4(%ebp),%eax
    0x0804836e <function+26>:       mov    %edx,(%eax)
    0x08048370 <function+28>:       leave
    0x08048371 <function+29>:       ret
    End of assembler dump.
    

    Und trotzdem bekomme ich ein Segmentation fault.
    gcc version 4.2.3
    HOffe jemand kann mir helfen .
    Danke



  • Habe vergessen zu sagen wo der bof eintritt:
    Program received signal SIGSEGV, Segmentation fault.
    0x08048398 in main ()
    Dort will ich ja hin springen laut tutorial , aber trotzdem der bof.
    Dnake



  • Hey,
    damit hatte ich kürzlich auch Probleme, ich bin mir aber nicht sicher ob es sich dabei wirklich um einen Fehler handelt oder um eine gewollt "Falsche Angabe" im Source. Da ich annehme das letzteres der Fall ist, möchte ich dir nicht direkt helfen. Trotzdem kleiner Tip: Schau dir einmal den Stack an, also wie die Variablen etc. genau organisiert sind, dann wirst du das Problem vielleicht finden 🙂

    lg elefant1990



  • seaht schrieb:

    void function(int a, int b, int c) {
       char buffer1[5];
       char buffer2[10];
       int *ret;
    
       ret = buffer1 + 12;
       (*ret) += 8;
    }
    
    void main() {
      int x;
    
      x = 0;
      function(1,2,3);
      x = 1;
      printf("%d\n",x);
    }
    

    Mit char buffer1[5] sucht das Betriebssystem für dich irgendwo einen zusammenhängenden Arbeitsspeicher von der größe 5 Byte.
    Durch buffer1+12 bist du aber außerhalb von dem revervierten Speicherbereich, denn dieses geht schließlich nur von buffer1+0 bis buffer1+4.
    Naja, dann zeigt ret also auf irgendwas im Arbeitsspeicher.
    Und nun sagst du mit (*ret) += 8; :

    Addiere zu dem Irgendwas eine 8.



  • jeder "normale" compiler hat da ein 4 byte alignment also wird aus dem
    5 byte array ein 8 byte array (intern nur)
    buffer1 + 8 würde über das ende des arrays auf ebp zeigen
    und buffer1 + 12 auf eip
    sofern ist das richtig



  • helferlein schrieb:

    jeder "normale" compiler hat da ein 4 byte alignment also wird aus dem
    5 byte array ein 8 byte array (intern nur)
    buffer1 + 8 würde über das ende des arrays auf ebp zeigen
    und buffer1 + 12 auf eip
    sofern ist das richtig

    Wieso sollte der Compiler denn mehr adressieren wollen (buffer1+12) als nötig ist?

    Bzw. so oder so: buffer1 ist nicht initialisiert und mit *ret = *ret + 8 versucht er einem unbekannten Wert eine 8 hinzuzuaddieren.



  • johny_legend schrieb:

    helferlein schrieb:

    jeder "normale" compiler hat da ein 4 byte alignment also wird aus dem
    5 byte array ein 8 byte array (intern nur)
    buffer1 + 8 würde über das ende des arrays auf ebp zeigen
    und buffer1 + 12 auf eip
    sofern ist das richtig

    Wieso sollte der Compiler denn mehr adressieren wollen (buffer1+12) als nötig ist?

    Bzw. so oder so: buffer1 ist nicht initialisiert und mit *ret = *ret + 8 versucht er einem unbekannten Wert eine 8 hinzuzuaddieren.

    Nein, der Wert ist nicht unbekannt, siehe das ASM Listings.

    Um Plattformunabhängigkeit geht es hier nicht.



  • buffer1 muss auch nicht initialisiert werden, er dient nur dazu eine addresse zu bekommen.

    arbeitsspeicher:
    /-------------------------------------------------\
    | buffer2  | buffer1 | alter ebp | returnaddresse |
    \-------------------------------------------------/
    buffer1-12 |buffer1  |buffer1+8  |buffer1+12
    

    kann sein dass dein compiler da noch zusätzliche befehle einfügt
    (push esi und sowas)

    ist der dump den du gepostet hast wirklich der von dem code ?


  • Mod

    buffer1 + 12
    

    Das ist schlicht undefiniert.
    Will man sich auf solche Dinge einlassen, gibt es bessere Möglichkeiten.
    Ist die Aufrufkonvention bekannt und kann man den Compiler irgendwie dazu zwingen, keine Inlinesubstitution durchzuführen (andernfalls ist die Frage nach der Rücksprungadresse sowieso sinnlos), bietet sich die Adresse der Funktionsparameter als Ausgangspunkt an. Denn an dieser Stelle kann der Compiler dann nicht (unter diesen Voraussetzungen) beliebig optimieren.
    Bei

    void function(int a, int b, int c) {
        void* ret = (void**)&a - 1;
        ...
    }
    

    besteht eine gewisse Chance, das gesuchte Ergebnis zu erhalten.



  • http://insecure.org/stf/smashstack.html
    Von dort ist das ganze und jetzt funkt es auch , ich musste einfach buffer1[] um 13 erhöhen nicht bloss um 12.

    void function(int a, int b, int c) {
       char buffer1[5];
       char buffer2[10];
       int *ret;
    
       ret = buffer1 + 13;
       (*ret) += 8;
    }
    
    void main() {
      int x;
    
      x = 0;
      function(1,2,3);
      x = 1;
      printf("%d\n",x);
    }
    

    buffer1 muss auch nicht initialisiert werden, er dient nur dazu eine addresse zu bekommen.

    Meines Wissens nach ist das absolt korekt und wird so auch in smashthestack gesagt.
    Bei dem Tutorial ist eine umfassende Erklärung wie man auf den wert kommt ,
    sucht einfach nach example3 .
    Danke an alle.


Anmelden zum Antworten