Какое влияние оказывает отвергаемый раздел на драйвер ядра, если он помечен как RWX?
Я заинтригован DISCARDABLE
флаг в разделе флагов в PE файлах, особенно в контексте драйверов Windows (в данном случае NDIS). Я заметил, что INIT
раздел был помечен как RWX в драйвере, который я рассматриваю, что кажется странным - хорошая практика безопасности говорит, что вы должны принять политику W^X.
Дамп раздела выглядит следующим образом:
Name Virtual Size Virtual Addr Raw Size Raw Addr Reloc Addr LineNums RelocCount LineNumCount Characteristics
INIT 00000B7E 0000E000 00000C00 0000B200 00000000 00000000 0000 0000 E2000020
Карта характеристик для:
IMAGE_SCN_MEM_EXECUTE
IMAGE_SCN_MEM_READ
IMAGE_SCN_MEM_WRITE
IMAGE_SCN_MEM_DISCARDABLE
IMAGE_SCN_CNT_CODE
INIT
кажется, что раздел содержит запись драйвера, что подразумевает, что она может быть использована для обеспечения того, чтобы функция записи драйвера находилась в невыгружаемой памяти, тогда как остальная часть кода может быть выгружена. Я не совсем уверен, хотя. Я не вижу доказательств того, что в коде драйвера сказано, что разработчики явно установили флаги страницы или принудительно установили запись драйвера в отдельный раздел, так что, похоже, компилятор сделал это автоматически. Я также вручную щелкнул флаг записи в двоичном файле драйвера, чтобы проверить его, и он работает нормально, если запись не включена, поэтому подразумевается, что наличие RWX не нужно.
Итак, мои вопросы:
- Для чего используется раздел INIT в контексте драйвера Windows и почему он помечен как отбрасываемый?
- Как обрабатываются отбрасываемые разделы в ядре Windows? У меня есть представление о том, как с ними справляется ReactOS, но это все еще нечетко и не очень полезно.
- Зачем компилятору перемещать запись драйвера в раздел INIT?
- Почему компилятор помечает раздел как RWX, если RX достаточно, а RWX может представлять проблему безопасности?
Ссылки, на которые я смотрел до сих пор:
2 ответа
Для чего используется раздел INIT в контексте Windows...
Обычно используется для функции DriverEntry().
Как обрабатываются отбрасываемые разделы в ядре Windows?
Это позволяет отбрасывать страницы, содержащие код функции DriverEntry(). Они больше не нужны после инициализации драйвера.
Зачем компилятору перемещать запись драйвера в раздел INIT?
Драйвер NDIS обычно содержит
#pragma NDIS_INIT_FUNCTION(DriverEntry)
Который является макросом в заголовочном файле WDK inc/ddk/ndis.h:
#define NDIS_INIT_FUNCTION(_F) alloc_text(INIT,_F)
#pragma alloc_text
это один из способов переместить функцию в определенный раздел. Другой распространенный способ сделать это - заключить в скобки функцию DriverEntry #pragma code_seg(INIT)
а также #pragma code_seg()
,
Почему компилятор помечает раздел как RWX
Это требует археологических раскопок. Многие драйверы были запущены давным-давно и, вероятно, все еще будут использовать ~VS6, тогда, когда жизнь была простой, а программисты носили белые шляпы. Или, возможно, программист использовал раздел #pragma, еще один способ присвоения имен разделам, он позволяет устанавливать атрибуты напрямую. Современный набор инструментов, безусловно, этого не сделает, вы получаете RX от #pragma alloc_text. Существует очень мало смысла беспокоиться об этом, учитывая, что DriverEntry() живет в течение очень короткого времени, и любой вредоносный код, который работает с привилегиями ring0, может нанести гораздо больший практический ущерб.
Я передал эту информацию в Microsoft, и оказалось, что это ошибка компоновщика MSVC. Они по ошибке пометили раздел сброса, содержащий DriverEntry, как RWX. Эта проблема была исправлена в Visual Studio 2015.
Подробнее о проблеме я писал здесь .