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

时间:2016-07-29 23:22:20

标签: memory-management windows-kernel

基本上我正在寻找一个可以为内核模式执行的功能,VirtualProtect为用户模式做了什么。

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

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

    ULONG flags = NormalPagePriority | MdlMappingNoExecute | MdlMappingNoWrite;
    PVOID ptr = MmGetSystemAddressForMdlSafe
    (
        mdl, 
        flags
    );

MdlMappingNoExecuteMdlMappingNoWrite标志仅对Win8 +有效。
此外,仅使用MmGetSystemAddressForMdlSafe我无法为内存区域分配 NoAccess 保护。

我可以使用任何其他或替代API,以便我可以修改已分配内存的页面保护吗?
黑客也会这样做,因为目前这个功能不会在生产代码中使用。

2 个答案:

答案 0 :(得分:1)

C:\Windows\System32>dumpbin /exports ntdll.dll | find "Protect"
        391  17E 0004C030 NtProtectVirtualMemory
       1077  42C 000CE8F0 RtlProtectHeap
       1638  65D 0004C030 ZwProtectVirtualMemory

我认为你可以从内核模式调用Zw函数,而args通常与相应的Nt函数相同。虽然ZwProtectVirtualMemory没有记录,但有一个记录的ZwAllocateVirtualMemory接受保护标记。

另一种方法可能是在用户模式下分配和保护虚拟内存,将缓冲区传递给驱动程序,然后在那里创建相应的MDL。

答案 1 :(得分:0)

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

如果你绊倒了下面用这种方法保护的内存,那么:

  • at IRQL < DISPATCH_LEVEL您将收到PAGE_FAULT_IN_NONPAGED_AREA错误(引用了无效的系统内存。这不能通过try-except保护, 它必须受探针保护。通常地址只是简单的坏或它 指着释放的记忆。)
  • IRQL == DISPATCH_LEVEL你会得到的 DRIVER_IRQL_NOT_LESS_OR_EQUAL fault (试图访问一个可分页(或完全无效)的地址 中断请求级别(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
            );
        }