NX bit

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

Атрибут (бит) NX-Bit (англ. no execute bit в терминологии фирмы AMD) или XD-Bit (англ. execute disable bit в терминологии фирмы Intel) — бит запрета исполнения, добавленный в страницы (см. таблицы страниц) для реализации возможности предотвращения выполнения данных как кода. Используется для предотвращения уязвимости типа «переполнение буфера», позволяющей выполнять произвольный код на атакуемой системе локально или удалённо. Технология требует программной поддержки (см. DEP) со стороны ядра операционной системы.

Основные сведения

[править | править код]

Технология NX-bit может работать только при соблюдении следующих условий:

  • наличие поддержки NX-bit со стороны процессора. NX-bit поддерживают процессоры фирмы Intel, начиная с Pentium 4 серии 6xx, и процессоры фирмы AMD, начиная с Athlon 64;
  • наличие поддержки NX-bit со стороны операционной системы. NX-bit поддерживают ОС Linux, начиная с ядра версии 2.3.23, и ОС Windows, начиная с Windows XP SP2;
  • использование PAE для процессоров архитектуры x86 или использование процессоров архитектуры x86-64 (бит запрета исполнения доступен в таблице страниц).

Некоторое ПО несовместимо с технологией NX-bit, поэтому BIOS предоставляет возможность отключения технологии.

NX (XD) — атрибут (бит) страницы памяти в архитектурах x86 и x86-64, добавленный для защиты системы от ошибок программ, а также использующих их вирусов, троянских коней и прочих вредоносных программ.

Фирма AMD назвала бит «NX» от англ. no execute. Фирма Intel назвала тот же бит «XD» от англ. execution disable.

Поскольку в современных компьютерных системах память разделяется на страницы, имеющие определённые атрибуты, разработчики процессоров добавили ещё один: запрет исполнения кода на странице. То есть, такая страница может быть использована для хранения данных, но не программного кода. При попытке передать управление на такую страницу возникнет прерывание, ОС получит управление и завершит программу. Атрибут защиты от исполнения давно присутствовал в других[каких?] микропроцессорных архитектурах; однако, в x86-системах такая защита реализовывалась только на уровне программных сегментов, механизм которых давно не используется современными ОС. Теперь она добавлена ещё и на уровне отдельных страниц.

Современные программы чётко разделяют на сегменты кода («text»), данных («data»), неинициализированных данных («bss»), а также динамически распределяемую область памяти, которая подразделяется на кучу («heap») и программный стек («stack»). Если программа написана без ошибок, указатель команд никогда не выйдет за пределы сегментов кода; однако, в результате программных ошибок, управление может быть передано в другие области памяти. При этом процессор перестанет выполнять какие-то запрограммированные действия, а будет выполнять случайную последовательность команд, за которые он будет принимать хранящиеся в этих областях данные, до тех пор, пока не встретит недопустимую последовательность, или не попытается выполнить операцию, нарушающую целостность системы, которая вызовет срабатывание системы защиты. В обоих случаях программа завершится аварийно. Также процессор может встретить последовательность, интерпретируемую как команды перехода к уже пройденному адресу. В таком случае процессор войдёт в бесконечный цикл, и программа «зависнет», забрав 100 % процессорного времени. Для предотвращения подобных случаев и был введён этот дополнительный атрибут: если некоторая область памяти не предназначена для хранения программного кода, то все её страницы должны помечаться NX-битом, и в случае попытки передать туда управление процессор сформирует исключение и ОС тут же аварийно завершит программу, сигнализировав выход за пределы сегмента (SIGSEGV).

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

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

Технические детали

[править | править код]

Переполнение буфера часто возникает, когда разработчик программы выделяет некоторую область данных (буфер) фиксированной длины, считая, что этого будет достаточно, но потом, манипулируя данными, никак не проверяет выход за её границы. В результате поступающие данные займут области памяти, им не предназначенные, уничтожив имеющуюся там информацию. Очень часто временные буферы выделяются внутри процедур (подпрограмм), память для которых выделяется в программном стеке, в котором также хранятся адреса возвратов в вызывающую подпрограмму. Тщательно исследовав код программы, злоумышленник может обнаружить такой баг, и теперь ему достаточно передать в программу такую последовательность данных, обработав которую программа ошибочно заменит адрес возврата в стеке на адрес, нужный злоумышленнику, который также передал под видом данных некоторый программный код. После завершения подпрограммы команда возврата (RET) из процедуры передаст управление не вызывающей процедуре, а процедуре злоумышленника, — контроль над компьютером получен.

Благодаря атрибуту NX такое становится невозможным. Область стека помечается NX-битом и любое выполнение кода в нём запрещено. Теперь же, если передать управление стеку, то сработает защита. Хоть программу и можно заставить аварийно завершиться, но использовать её для выполнения произвольного кода становится очень сложно (для этого потребуется ошибочное снятие программой NX-защиты).

Однако, некоторые программы используют выполнение кода в стеке или куче. Такое решение может быть связано с оптимизацией, динамической компиляцией или просто оригинальным техническим решением. Обычно, операционные системы предоставляют системные вызовы для запроса памяти с разрешённой функцией исполнения как раз для таких целей, однако многие старые программы всегда считают всю память исполнимой. Для запуска таких программ под Windows приходится отключать функцию NX на весь сеанс работы, и чтобы включить её вновь, требуется перезагрузка. Хотя в Windows и предусмотрен механизм белого списка программ, для которых отключён DEP, тем не менее данный метод не всегда работает корректно[источник не указан 5248 дней]. Примером такой программы может служить Iris.

NX-бит является самым старшим разрядом элемента 64-битных таблиц страниц, используемых процессором для распределения памяти в адресном пространстве. 64-разрядные таблицы страниц используются операционными системами, работающими в 64-битном режиме, либо с включённым расширением физических адресов (PAE). Если ОС использует 32-разрядные таблицы, то возможности использовать защиту страниц от исполнения нет.

Обязательность и распространённость

[править | править код]

Все современные процессоры для ПК от Intel и AMD – поддерживают данную технологию. Для установки Windows 10 – её наличие является обязательным, иначе программа установки не позволит установить систему.