Как настроить защиту области памяти в режиме ядра под 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.

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