Windows 7内核模式下如何设置内存区域保护

Rol*_*kas 5 memory-management windows-kernel

本质上,我正在寻找一个可以为内核模式做什么的函数,它可以VirtualProtect为用户模式做什么。

我正在使用以下简化代码示例的逻辑分配内存。

    PMDL mdl = MmAllocatePagesForMdl    
    (
        LowAddress,
        HighAddress,
        SkipAddress,
        size
    );

    ULONG flags = NormalPagePriority | MdlMappingNoExecute | MdlMappingNoWrite;
    PVOID ptr = MmGetSystemAddressForMdlSafe
    (
        mdl, 
        flags
    );
Run Code Online (Sandbox Code Playgroud)

MdlMappingNoExecuteMdlMappingNoWrite标志只会对Win8的+效果。
此外,仅使用MmGetSystemAddressForMdlSafeI 无法NoAccess为内存区域分配例如保护。

是否有任何额外的或替代的 API-s 我可以使用,以便我可以修改分配内存的页面保护?
hack 也可以,因为目前此功能不会在生产代码中使用。

Rol*_*kas 2

我当前最终使用的代码如下。
所有使用的API都是官方的。 在这里,我为分配的内存的子范围
创建另一个mdl ,并更改该子范围的保护。

如果您遇到使用以下方法保护的内存,则:

  • 你会IRQL < DISPATCH_LEVEL得到PAGE_FAULT_IN_NONPAGED_AREA错误(引用了无效的系统内存。这不能由 try- except 保护,它必须由探测器保护。通常该地址只是简单的错误或者它指向已释放的内存。)
  • 你会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
            );
        }
Run Code Online (Sandbox Code Playgroud)