Если ваш стек и куча не исполняются, как ваш код может работать?

Я прочитал книгу о переполнении буфера, и это предлагает следующее:

Выполнение неиспользуемого стека (и кучи) обеспечивает высокую степень защита от многих типов атак переполнения буфера для существующих программы.

Но я не понимаю, как мы можем это сделать - где выполняется выполнение, если не в куче или в стеке?

Ответы

Ответ 1

Если я правильно понимаю ваш вопрос, ни один из других ответов не обращается к нему. Ответ заключается в том, что выполнение происходит в секции кода, которая не является ни стеком, ни кучей. В типичной системе выгружаемой памяти код из файла программы (например,.exe в Windows) загружается в исполняемые, но только для чтения страницы. Дополнительные записываемые (и исполняемые) страницы выделяются процессу для стека и кучи. Предложение здесь состоит в том, что операционная система и аппаратное обеспечение должны взаимодействовать, чтобы отметить эти страницы, доступные для записи, но не исполняемые (ответ rgngl объясняет, как это сделать в Windows).

Даже при неисполняемой куче и стеке все еще возможны эксплойты, которые используют обратное ориентированное программирование, упомянутое в ответе Алексея Фрунзе, но есть методы защиты, которые замалчивают даже такие, как ранняя ранжирование с разбивкой по стеклу и адресная пространственная компоновка - см. http://en.wikipedia.org/wiki/Return-to-libc_attack#Protection_from_return-to-libc_attacks

Ответ 2

Вот что называется подпрограммой типа "обратное ориентированное программирование" (AKA ROP).

Злоумышленник находит, как сделать его злой код из разных частей используемой программы.

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

Затем, используя ошибку кода, злоумышленник заставляет программу начать выполнение цепочки тех микро-подпрограмм, которые выполняют все зло.

Итак, теперь хороший код превращается в злой код. Ничего не выполняется в стеке или в куче.

Также следует отметить, что на процессорах, где инструкции охватывают несколько байтов и имеют переменную длину, даже непосредственные операнды команд (IOW, численные константы), которые являются частью инструкций, могут стать кодом, и поэтому шансы найти используемые байтовые последовательности выше, чем на "более простых" процессорах.

Также часто можно создавать вредоносный код, который изменит защиту памяти, и эксплойт уже не будет ограничиваться существующим кодом приложения.

Ответ 3

Очень конкретный пример: упорядочьте адрес возврата, чтобы указать на system, а следующий слот в стеке (или первый регистр аргумента на перекрестных регистрах) должен быть указателем на строку "/bin/sh".

Ответ 4

Такая защита обеспечивается ОС и не может быть выполнена на прикладном уровне.

См. статью wikipedia, в которой также рассказывается, как включить ее под Windows: http://en.wikipedia.org/wiki/Data_Execution_Prevention

Ответ 5

вы можете перейти в любое другое место, которое является исполняемым сегментом, и запустить ваш злой код...

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

Ответ 6

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

Ответ 7

Ваш код выполняется в текстовом сегменте, а не в стеке или куче (оба из них предназначены для хранения данных). Таким образом, организация:

<highest addresses>
stack
...
heap
data section (initialized data & bss - uninitialized data) 
code section (text)
<lowest addresses> 

Раздел кода является исполняемым, но неизменным. Эта статья в Википедии содержит более подробную информацию: https://en.wikipedia.org/wiki/Data_segment