Как указано в этом Agner Fog document on calling conventions, Глава 5:
В Компилятор Gnu версии 3.x и более поздних версий для 32-разрядных Linux и Mac OS X делает указатель стека , выровненный по 16 в каждой команде вызова функции.
Так что, как объяснил @Anty в своем ответе, значение по умолчанию -mpreferred-stack-boundary
4, чтобы получить выравнивание 2 .
При проверке выравнивания стека полезно принять соглашение, которое явно показывает, насколько указатель стека не равен.
я придумал сам, что принимает форму @ т + п (например, @ 16 + 4) и означает, что указатель стека находится и адрес п байт меньше чем кратное м (например, 4 байта меньше, чем кратное 16, например 0x000c, 0x001c, 0x002c и т. Д.).
Это полезно, потому что стек растет вниз, поэтому, если указатель стека равен, скажем, @ 16 + 4, то после push ebp
он находится на @ 16 + 8 и т. Д. (Учитывая модульный характер выравнивания).
До vuln
называется стеком в @ 16 + 0 (как это предусмотрено компилятором).
Сразу после вызова, из-за неявного нажатия обратного адреса, это как @ 16 + 4.
Пролог является:
;Every annotation shows the alignment of the stack
; AFTER the annotated instruction has executed
push %ebp ;@16+8
mov %esp, %ebp
Теперь компилятор должен выделить 0x100 байт, но он хочет, чтобы они были распределены на предпочтительном выравнивании, просто делает sub $0x108,%esp
приведет указатель стека на @ 16 + 8 + 0x100 = @ 16 + 0x108 === @ 16 + 8.
Чтобы перейти к следующей границе 16 байтов, потребуется еще восемь байтов, таким образом размер 0x108.
sub $0x108,%esp ;@16+0, Aligned
Далее необходимо выполнить вызов, при выполнении команды вызова необходимо снова выровнять стопку.
Пока это так, но после нажатия параметров его больше не будет.
Поскольку strcpy
имеет два 32-битных параметров, восемь байтов в общей сложности, компилятор перемещает указатель стека еще восемь байт вниз (8 + 8 = 16) соблюдать выравнивание ограничения
sub $0x8,%esp ;@16+8
pushl 0x8(%ebp) ;@16+12
lea -0x108(%ebp),%eax
push %eax ;@16+0, Aligned
call 8048300 <[email protected]>
Теперь, C calling convention мандаты что он является вызывающим, который очищает стек.
Два параметра были сдвинуты, поэтому требуется add $0x8,%esp
.
Плюс другой add $0x8,%esp
, чтобы сбалансировать sub $0x8,%esp
выше.
Эти две комбинации объединены в одну инструкцию.
add $0x10,%esp ;@16+0, Aligned
Обратите внимание, что это не имеет никакого отношения к возвращаемому значению и типу функции.
Это аргументы толкнули, что считать.
Наконец пролог
leave ;@16+8
ret ;@16+4
Вы забыли скомпилировать с оптимизацией включен. В противном случае компилятор будет генерировать код мусора. Обратите внимание, что вы все равно можете выделить больше выделенной памяти, которая обычно используется для выравнивания. – Jester