2013-02-17 4 views
1

Предполагая систему x86 без aslr, я хотел бы спросить следующее:Переполнение стека теоретически .. и сборка

1) Теория говорит, что когда мы выполняем атаку переполнения стека, значение, указанное регистром ebp, также перезаписывается новым адресом возврата.

Теперь, поскольку мы никогда не возвращаемся к функции вызова, нам действительно не нужно исходное значение ebp для восстановления предыдущего фрейма стека, но, тем не менее, регистр ebp должен указывать где-то в любое время. Как ebp устанавливается после запуска регистра eip, указывающего на наш новый шеллкод? Более конкретно, какая из двух инструкций по сборке (leave-ret) вызывает дополнительную микроинструкцию, которая восстанавливает значение ebp до значения?

2) И последнее, но не менее важное: я также хотел бы спросить, как мы можем убедиться, что в случаях, когда наш шеллкод должен нажимать пару значений в стеке, эти значения не будут перезаписывать какую-либо часть шеллкода ? Другими словами, как мы можем быть уверены, что любые генерируемые шеллкодом переменные будут помещены только до начала шеллкода и, например, не где-то посередине?

Благодарим вас заблаговременно.

+0

Я не уверен, что обсуждение механики атаки переполнения стека на открытом форуме - хорошая идея - я что-то упускаю? – Floris

+0

'leave' - это тот, который делает вещь с' ebp'. – harold

+3

@Floris Почему бы и нет? Безопасность, пряча голову в песок, никогда не помогала никому в долгосрочной перспективе. – Thomas

ответ

1

В ответ на часть 2 вашего вопроса: в зависимости от того, что вы делаете, вы можете поместить значение в esp (в виде массива arg). Если это конец шеллкода, тогда вы в порядке. Однако, если есть больше кода оболочки, и вы, возможно, делаете pushи, то esp, как оказалось, находится где-то в остальной части вашего шеллкода, у вас могут быть проблемы (потому что в этот момент вы будете писать по своим собственным инструкциям). Простое исправление - сделать что-то вроде sub $0x99, %esp в самом начале шеллкода.

EDIT (в ответ на комментарии)

Может быть, я неправильно понял вопрос. Когда вы сказали «переполнение стека», я предположил, что вы имели в виду переполнение буфера. Если я правильно понял, тогда читайте дальше. Предполагая, что вы действительно говорите о классической эксплоите с разбивкой стека (что, по-видимому, основано на картине, с которой вы связались), вы заполняете буфер с помощью санки nop, shellcode и, наконец, перезаписываете возвращаемый указатель , Код оболочки - «независимый от позиции код».Это означает, что это серия инструкций, которые могут быть выполнены независимо от текущего состояния регистров, флагов и т. Д.

Как правило, это также ссылка, которую вы размещаете, она заполняет буфер nops, за которым следует шеллкод, и, наконец, обратный адрес, который указывает где-то в tho nop sled. Когда выполняется команда ret, адрес в %esp вводится в %eip, а %esp увеличивается на 4 (на x86). Проблема заключается в том, что если ваш шеллкод имеет несколько команд push, это имеет побочный эффект декремент%esp. Если у вас их достаточно и, ваш шелл-код будет полностью в конце (т. Е. Рядом с обратным адресом), то вы можете в конечном итоге переписать свой шелл-код с помощью инструкций push.

Итак, чтобы ответить на ваш вопрос. Нет, нет «механизма», чтобы отделить ваш шеллкод от «его стека». Это связано с тем, что для вашего шеллкода нет стека per-se. Помните, что это независимый от позиции код. Он должен иметь возможность запускать независимо от состояния машины. Любое управление стеком, которое должно произойти, должно выполняться самим шеллкодеком. Вот почему я предложил sub $0x99, %esp в начале шеллкода, если в коде есть много операторов push. Другим вариантом является наличие достаточного пространства между обратным адресом (который укажет %esp-4) и вашим шеллкодом.

+0

Пожалуйста, подождите несколько минут вашего времени и взгляните на график, который я вырвал из Интернета и соответствующим образом адаптирован для демонстрационных целей. http://i46.tinypic.com/amis9.jpg – kstratis

+0

На этом рисунке вы можете четко видеть стек. Стек растет вниз. Однако, когда мы читаем наши данные, мы делаем это наоборот. -Так, в соответствии с вашим ответом, если «отправить» указатель esp далеко вниз по стеку, некоторые переменные шеллкода, которые может потребовать толчок шеллкода, не будут проблемой, так как у нас будет 153 байта в нашем распоряжении. Тем не менее, что мешает системе помещать shell-код-сгенерированный стек (при условии, что он ned = eds, чтобы самостоятельно локализовать локальные переменные) в адресном пространстве, которое шеллкод уже хранится сам? – kstratis

+0

Другими словами, существует ли какой-либо механизм, препятствующий наложению адресного пространства между шелковым кодом и его собственным стеком? P.S Я считаю, что это не было проблемой, поскольку код обычно хранится в текстовом сегменте, и любое необходимое пространство стека зарезервировано через функцию «ENTER». – kstratis

2

1.При функция вызывается получает значение esp получает копируется на ebp, то кадр стека для этой конкретной функции получает выделены за счет уменьшения стоимости esp (через ENTER инструкции или push ebp; mov ebp,esp; sub esp, SIZE; последовательность команд). С этого момента значение esp строго растет вверх и, таким образом, не мешает кадру стека текущей функции.

Когда функция достигает своего конца, она освобождает фрейм стека, пройдя шаги, описанные выше, но назад, то есть через команду LEAVE или mov esp, ebp; pop ebp; последовательность команд. На этом этапе значение esp указывает на адрес возврата, и это адрес, который злоумышленник хочет изменить. Как только это значение будет изменено, после выполнения команды RET измененный адрес возврата будет выбит, а eip теперь укажет на измененный адрес.

2.Несмотря на то, что все, что находится над вашим шеллкодеком, было «освобождено», вам просто нужно выделить фрейм стека для вашего кода оболочки, пройдя те же действия, которые описаны выше.

+0

Вы писали, что LEAVE равно добавляет esp SIZE и pop ebp. Как реестр ebp должен восстановить прежнее значение, так как нет i. e mov ebp DWORD PTR (esp) в этот момент? Что касается (2) фрейма стека Шелкового кода, на который вы ссылаетесь, может фактически перекрываться в адресном пространстве с тем, который используется шеллкодом. – kstratis

+0

@ Konos5 значение 'ebp' было нажато на стек во время' ENTER'. Что касается 2) Нет, это не будет. shellcode должен лежать * после * измененного обратного адреса. В противном случае программа, вероятно, сработает еще до того, как функция достигнет конца. – JosephH

+0

Да, но поп только не возвращает возвращенное значение обратно в регистр ebp ...Вам, скорее всего, понадобится инструкция, подобная той, которую я упомянул в предыдущем комментарии. В (2) шеллкод действительно находится после измененного адреса возврата, но так же делают любые локальные переменные, происходящие из шеллкода. Обратный адрес -> сохраненный указатель кадра -> локальные переменные. Что останавливает рамку стека в шелковом слое между двумя последними? – kstratis

Смежные вопросы