как узнать расположение обратного адреса в стеке c / c ++ - PullRequest
5 голосов
/ 19 апреля 2010

Я читал о функции, которая может перезаписать свой адрес возврата.

void foo(const char* input)
{
    char buf[10];

    //What? No extra arguments supplied to printf?
    //It's a cheap trick to view the stack 8-)
    //We'll see this trick again when we look at format strings.
    printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n% p\n\n"); //%p ie expect pointers

    //Pass the user input straight to secure code public enemy #1.
    strcpy(buf, input);
    printf("%s\n", buf);

    printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
}  

Предполагалось, что так будет выглядеть стек

Адрес foo = 00401000

Мой стек выглядит так:
00000000
00000000
7FFDF000
0012FF80
0040108A <- Мы хотим перезаписать адрес возврата для foo. </strong>
00410EDE

Вопрос:
-. Почему автор произвольно выбрал второе последнее значение в качестве адреса возврата функции foo ()?

-. Добавляются ли значения в стек снизу или сверху?

  • Кроме адреса возврата функции, какие другие значения я, очевидно, вижу в стеке? то есть почему он не заполнен нулями

Спасибо.

1 Ответ

3 голосов
/ 19 апреля 2010

Над ним находится предыдущий EBP (0012FF80). Значение выше prev-EBP всегда является адресом возврата.

(Это, очевидно, предполагает двоичный файл без FPO и 32-битную Windows) 1 .

Если вы помните, пролог выглядит так:

push ebp      ; back up the previous ebp on the stack
mov ebp, esp  ; set up the new frame pointer

и когда вызывается функция, например,

call 0x00401000

Текущий EIP помещается в стек (используется как адрес возврата), поэтому стек после пролога выглядит следующим образом:

[ebp+0xc]  ; contains parameter 1, etc
[ebp+0x8]  ; contains parameter 0
[ebp+0x4]  ; contains return address
[ebp]      ; contains prev-EBP

Таким образом, для каждого %p printf использует следующие 4 байта, начиная с [ebp+0xc] (первый параметр %p). В конце концов вы попадаете на предыдущее значение EBP, хранящееся в стеке, которое (0012FF80), а затем следующее - Обратный адрес.

Обратите внимание, что эти адреса должны «иметь смысл», что они явно делают здесь (хотя это может быть не «понятно» для всех).

Re Q2) Стек растет. Таким образом, когда вы push eax, 4 вычитается из esp, тогда значение eax перемещается в [esp], эквивалентно в коде:

push eax
;  <=>
sub esp, 4
mov [esp], eax

  1. Книга Написание безопасного кода , да?
...