стековые операции на базовой C-программе - PullRequest
2 голосов
/ 14 сентября 2011

Я разбираю этот базовый код C, пытаясь выяснить, какие операции сделано в стеке. Я делаю в нем на виртуальной машине, 32-битной, GCC 4.4.3, на основе Ubuntu Дистрибутив. Я скомпилировал код с этими флагами.

gcc -ggdb -mpreferred-stack-border = 2 -fno-stack-protector -o ExploitMe ExploitMe.c

#include<stdio.h>
#include<string.h>

main(int argc, char **argv)
{
        char buffer[80];

        strcpy(buffer, argv[1]);

        return 1;
}

Проблема в том, что я не могу понять, почему в операции 3 стек указатель перемещен на 0x58, длина символа 80 символов, не должна ли быть 0x50?

dump of assembler code for function main:
   0x080483e4 <+0>: push   %ebp
   0x080483e5 <+1>: mov    %esp,%ebp
=> 0x080483e7 <+3>: sub    $0x58,%esp
   0x080483ea <+6>: mov    0xc(%ebp),%eax
   0x080483ed <+9>: add    $0x4,%eax
   0x080483f0 <+12>:mov    (%eax),%eax
   0x080483f2 <+14>:mov    %eax,0x4(%esp)
   0x080483f6 <+18>:lea    -0x50(%ebp),%eax
   0x080483f9 <+21>:mov    %eax,(%esp)
   0x080483fc <+24>:call   0x804831c <strcpy@plt>
   0x08048401 <+29>:mov    $0x1,%eax
   0x08048406 <+34>:leave  
   0x08048407 <+35>:ret    
End of assembler dump.

Я застрял на этом, я вижу позже, что берет ожидаемую длину, но что программа создается между этими операциями? 100

  0x080483f6 <+18>:lea    -0x50(%ebp),%eax

Спасибо

Ответы [ 3 ]

1 голос
/ 14 сентября 2011

Остальные 8 байтов предназначены для аргументов strcpy.Вместо того, чтобы помещать их в стек, компилятор понял, что он может просто вычесть дополнительные 8 байтов из указателя стека и затем сохранить регистры в памяти.Это означает, что указатель стека нужно настраивать только один раз.

1 голос
/ 24 сентября 2011

это, вероятно, еще пара мест для хранения переданных параметров (argv, argc).и / или ему нужно больше локального хранилища.Компиляторы делают все, что хотят для реализации кода высокого уровня, один и тот же код будет генерировать десятки / сотни различных последовательностей языка ассемблера в зависимости от параметров компилятора, версии и оптимизации, а также параметров конфигурации / сборки, когда компилятор сам компилировался.

Вы часто видите этот вид стекового фрейма, хотя и обычно из-за сочетания функций / ограничений производительности и набора команд.Гораздо проще кодировать и отлаживать, если вы перемещаете указатель стека один раз или делаете его копию с другим регистром, в пределах функции все ссылаются на одну статическую точку, в то время как предварительное отображение, вызов и очистка функций портятся с указателем реального стека,

Вы также часто будете видеть, что кадр стека оставляет место для переданных параметров и других локальных переменных, даже если оптимизация устранила необходимость того, чтобы эти переменные фактически проводили какое-то время в стеке.Сначала определяется потребность в кадре стека и размере, а оптимизация наступает позже, и компилятор не всегда возвращается назад и понимает, что, если он сделает еще один проход по функции, он может уменьшить размер стека.Аналогично, автору компилятора легче отладить, если он знает, что его кадр стека всегда начинается с переданных параметров, а не локальных переменных по порядку, очень быстро и легко для чтения и отладки кода, просто пример.

BottomХотя строка является ответом Оли, компилятор может делать все, что захочет, при условии, что он реализует ваш код.Мое расширение к этому - вывод из того же самого высокоуровневого кода, широко варьируется в зависимости от компилятора и опций.И это редко идеально оптимизируется.

1 голос
/ 14 сентября 2011

Компилятор может свободно расположить стек, как сочтет нужным.

...