Какое влияние оказывает отвергаемый раздел на драйвер ядра, если он помечен как 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.

Подробнее о проблеме я писал здесь .

Другие вопросы по тегам