基本上我正在寻找一个可以为内核模式执行的功能,VirtualProtect
为用户模式做了什么。
我使用以下简化代码示例的逻辑分配内存。
PMDL mdl = MmAllocatePagesForMdl
(
LowAddress,
HighAddress,
SkipAddress,
size
);
ULONG flags = NormalPagePriority | MdlMappingNoExecute | MdlMappingNoWrite;
PVOID ptr = MmGetSystemAddressForMdlSafe
(
mdl,
flags
);
MdlMappingNoExecute
和MdlMappingNoWrite
标志仅对Win8 +有效。
此外,仅使用MmGetSystemAddressForMdlSafe
我无法为内存区域分配 NoAccess
保护。
我可以使用任何其他或替代API,以便我可以修改已分配内存的页面保护吗?
黑客也会这样做,因为目前这个功能不会在生产代码中使用。
答案 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 ,并更改了该子范围的保护。
如果你绊倒了下面用这种方法保护的内存,那么:
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
);
}