'Leave' behavior after stack overflow.

From: Vinay A. Mahadik (vamahadiat_private)
Date: Tue Apr 23 2002 - 23:45:22 PDT

  • Next message: Robert A. Seace: "Re: /lib/ld-2.2.4.so"

    Hi,
    
    I was going through Mixter's tutorial on Buffer Overflows and ran into
    some unexpected behavior I would like to know the why's of. In what
    follows, I overwrite both EBP and RET on the stack with a new instruction
    address.(ix86)
    
    # cat blah.c
    #define BUF_SIZE 30 // bytes
    
    void lame (void) {
     char small[BUF_SIZE];
    
     gets (small); // Exploitable user i/p function
    
     printf("%s\n", small);
    }
    
    main() {
     lame ();
     return 0;
    }
    
    # cat ret.c
    main()
    {
     int i=0; char buf[48];
     for (i=0;i<=44;i+=4)
     *(long *) &buf[i] = 0x80484ba;
     puts(buf);
    }
    
    # gcc -O2 -ggdb ret.c -o ret
    
    # ./ret > input
    
    # gdb blah
    (gdb) break main
    Breakpoint 1 at 0x80484ba: file blah.c, line 12.
    (gdb) run < input
    Starting program: /root/security/bufferoverflows/blah < input
    
    Breakpoint 1, main () at blah.c:12
    12       lame ();
    (gdb) disas main
    Dump of assembler code for function main:
    0x80484b4 <main>:       push   %ebp
    0x80484b5 <main+1>:     mov    %esp,%ebp
    0x80484b7 <main+3>:     sub    $0x8,%esp
    0x80484ba <main+6>:     call   0x8048490 <lame>
    0x80484bf <main+11>:    xor    %eax,%eax
    0x80484c1 <main+13>:    leave
    0x80484c2 <main+14>:    ret
    End of assembler dump.
    (gdb) display /i $pc
    1: x/i $eip  0x80484ba <main+6>:        call   0x8048490 <lame>
    (gdb) nexti
    ?'@
    
    Breakpoint 1, main () at blah.c:12
    12       lame ();
    1: x/i $eip  0x80484ba <main+6>:        call   0x8048490 <lame>
    (gdb) nexti
    ?'@
    13       return 0;
    1: x/i $eip  0x80484bf <main+11>:       xor    %eax,%eax
    (gdb) nexti
    14      }
    1: x/i $eip  0x80484c1 <main+13>:       leave
    (gdb) print /x $ebp
    $1 = 0x80484ba
    (gdb) print /x $esp
    $2 = 0xbffff9c0
    (gdb) x /4xb $ebp
    0x80484ba <main+6>:     0xe8    0xd1    0xff    0xff
    (gdb) nexti
    0x080484c2 in main () at blah.c:14
    14      }
    1: x/i $eip  0x80484c2 <main+14>:       ret
    (gdb) print /x $ebp
    $3 = 0xffffd1cc
    (gdb) print /x $esp
    $4 = 0x80484be
    (gdb)
    
    ----------
    
    What I couldn't get is the effect of the "leave" instruction on $ebp.
    Clearly if leave = movl %ebp, %esp & popl %ebp, $ebp should have been
    0xffffd1e8 as displayed above right? Where might it be getting that other
    address?
    
    Basically, I want to cause the buffer overflow to recall lame() as above
    but only without seg faulting later on. (I know the code can be modified
    to achieve that) It _is_ seg-faulting with this unexplained new EBP.
    Why isn't the EBP picking up the old EBP saved/placed in the immediate 4
    upward bytes from the present EBP value? (as it does when the EBP isn't
    corrupted)
    
    Could you throw some light on this please? I am new to
    assembly/disassembly btw.
    
    Thanks,
    Vinay.
    
    --
    Vinay A. Mahadik
    http://hickory.csc.ncsu.edu/
    



    This archive was generated by hypermail 2b30 : Wed Apr 24 2002 - 14:55:34 PDT