Исполняемые разделы, помеченные как "выполнить" И "прочитать"?
Я заметил (по крайней мере на Win32), что в исполняемых файлах разделы кода (.text) имеют установленный бит доступа "чтение", а также бит доступа "выполнение". Существуют ли какие-либо законные причины для того, чтобы код сам читал, а не выполнял себя? Я думал, что это было то, для чего были другие разделы (такие как.rdata).
(Конкретно я про IMAGE_SCN_MEM_READ
.)
3 ответа
IMAGE_SCN_MEM_EXECUTE |IMAGE_SCN_MEM_READ
отображаются в память как PAGE_EXECUTE_READ
, что эквивалентно PAGE_EXECUTE_WRITECOPY. Это необходимо для обеспечения доступа при копировании при записи. Копирование при записи означает, что любые попытки изменить страницу приводят к созданию новой, приватной копии процесса создаваемой страницы.
Есть несколько разных причин необходимости записи-копирования:
- Код, который должен быть перемещен загрузчиком, должен иметь этот набор, чтобы загрузчик мог делать исправления. Это очень распространено.
- Разделы, которые содержат код и данные в одном разделе, также потребуются, чтобы можно было изменять глобальные переменные процесса. Код и данные в одном разделе могут сэкономить пространство и, возможно, улучшить локальность, имея код и глобальные переменные, которые использует код, на одной странице.
- Код, который пытается изменить себя. Я считаю, что это довольно редко.
Константы времени компиляции, особенно для длинных или длинных значений, часто загружаются с помощью регистра mov, оператора адреса из сегмента кода.
Один из примеров, который я могу вспомнить по причине чтения кода, - это возможность самоизменения кода. Код должен обязательно быть в состоянии прочитать себя, чтобы быть самоизменяющимся.
Также рассмотрим противоположную сторону. Какие преимущества дает запрет на чтение кода? Я немного боролся с этим, но не вижу никакой выгоды от этого.