Как настроить защиту области памяти в режиме ядра под Windows 7
По сути, я ищу функцию, которая могла бы сделать для режима ядра, что VirtualProtect
делает для пользовательского режима.
Я выделяю память, используя логику, приведенную в следующем упрощенном коде.
PMDL mdl = MmAllocatePagesForMdl
(
LowAddress,
HighAddress,
SkipAddress,
size
);
ULONG flags = NormalPagePriority | MdlMappingNoExecute | MdlMappingNoWrite;
PVOID ptr = MmGetSystemAddressForMdlSafe
(
mdl,
flags
);
MdlMappingNoExecute
а также MdlMappingNoWrite
флаги будут действовать только на Win8+.
Кроме того, используя только MmGetSystemAddressForMdlSafe
Я не могу назначить например NoAccess
защита для области памяти.
Существуют ли какие-либо дополнительные или альтернативные API-интерфейсы, которые я мог бы использовать, чтобы изменить защиту страницы выделенной памяти?
Хак тоже подойдет, так как в настоящее время эта функциональность не будет использоваться в рабочем коде.
2 ответа
Код, который я сейчас использовал, приведен ниже.
Все используемые API являются официальными.
Здесь я создаю еще один MDL для поддиапазона выделенной памяти и меняю защиту этого поддиапазона.
Если Вы запутались в памяти, защищенной этим способом ниже, то:
- в
IRQL < DISPATCH_LEVEL
Ты получишьPAGE_FAULT_IN_NONPAGED_AREA
ошибка (на недействительную системную память ссылались. Это не может быть защищено с помощью try, за исключением того, что оно должно быть защищено датчиком. Обычно адрес просто неверный или указывает на освобожденную память.) - в
IRQL == DISPATCH_LEVEL
Ты получишьDRIVER_IRQL_NOT_LESS_OR_EQUAL
ошибка (была сделана попытка получить доступ к адресу страницы (или полностью неверному) на слишком высоком уровне запроса прерывания (IRQL). Обычно это вызвано драйверами, использующими неправильные адреса.)
Обратите внимание, что изменение защиты может закончиться неудачей, если поддиапазон является частью большого выделения страниц. Тогда status
будет вероятно STATUS_NOT_SUPPORTED
,
Распределение больших страниц может произойти, если первоначально выделенный размер области памяти и выравнивание (которое зависит от SkipAddress
переменные в вопросе) и некоторые дополнительные предварительные условия выполняются, с которыми я не знаком (возможно, начиная с определенной версии ОС).
PMDL guard_mdl = IoAllocateMdl
(
NULL,
PAGE_SIZE * guardPageCount,
FALSE,
FALSE,
NULL
);
if (guard_mdl)
{
IoBuildPartialMdl
(
mdl,
guard_mdl,
(PVOID)(0), // **offset** from the beginning of allocated memory ptr
PAGE_SIZE * guardPageCount
);
status = MmProtectMdlSystemAddress
(
guard_mdl,
PAGE_NOACCESS
);
}
C:\Windows\System32>dumpbin /exports ntdll.dll | find "Protect"
391 17E 0004C030 NtProtectVirtualMemory
1077 42C 000CE8F0 RtlProtectHeap
1638 65D 0004C030 ZwProtectVirtualMemory
Я думаю, что вы можете позвонить Zw
функции из режима ядра, и аргументы, как правило, такие же, как для соответствующего Nt
функции. И пока ZwProtectVirtualMemory
недокументировано, есть документированная ZwAllocateVirtualMemory, которая принимает флаги защиты.
Другой подход может состоять в том, чтобы выделить и защитить виртуальную память в пользовательском режиме, передать буфер вашему драйверу, а затем создать соответствующий MDL.