Допустим, мы хотим поставить хук на библиотечную юзермодную функцию из ядра и эта функция находится в системной библиотеке. Есть вариант вызвать ZwProtectVirtualMemory, но эта функция не экспортируется на Win7 - хотелось бы обойтись без её поиска по сигнатурам. Другой, более правильный и предпочтительный вариант - MmMapLockedPagesSpecifyCache + MmProtectMdlSystemAddress. Однако, т.к. библиотека разделяется между множеством процессов, мы отобразим "общую" память - следовательно, изменения одновременно будут видны во всех процессах. Необходимо как-либо затриггерить Copy-On-Write (и очень желательно сделать это "легальным" способом, обойдясь без вызова неэкспортируемых функций). В структуре PTE есть поле AVL, состоящее из трёх бит, которые ОС может использовать для своих нужд. В Win10 x64 2004 PTE определена следующим образом: Код (Text): struct _HARDWARE_PTE { unsigned __int64 Valid : 1; unsigned __int64 Write : 1; unsigned __int64 Owner : 1; unsigned __int64 WriteThrough : 1; unsigned __int64 CacheDisable : 1; unsigned __int64 Accessed : 1; unsigned __int64 Dirty : 1; unsigned __int64 LargePage : 1; unsigned __int64 Global : 1; unsigned __int64 CopyOnWrite : 1; unsigned __int64 Prototype : 1; unsigned __int64 reserved0 : 1; unsigned __int64 PageFrameNumber : 36; unsigned __int64 reserved1 : 4; unsigned __int64 SoftwareWsIndex : 11; unsigned __int64 NoExecute : 1; }; Поле AVL отведено под поля CopyOnWrite, Prototype и reserved0. Чтобы пометить страницу, как готовую к CoW, система выставляет бит CopyOnWrite, но не выставляет бит Write: страница фактически остаётся Read[Execute]Only. Дальнейшая попытка записи в эту страницу приведёт к генерации исключения и обработчик, видя бит CopyOnWrite, подгрузит страницу в частный рабочий набор процесса. И действительно, после "ручного" триггера (взвести бит CoW, произвести запись в страницу) мы увидим, что физический адрес страницы изменился и данные в ней можно смело менять. Однако, спустя некоторое время после завершения процесса, система падает в синий экран с ошибкой MEMORY_MANAGEMENT (1a). Трейс: Код (Text): nt!DbgBreakPointWithStatus nt!KiBugCheckDebugBreak+0x12 nt!KeBugCheck2+0x946 nt!KeBugCheckEx+0x107 nt!MiGetTopLevelPfn+0x1c664b nt!MiCapturePfnVm+0xdf nt!MiProcessCrcList+0x226 nt!MiCombineAllPhysicalMemory+0x30d nt!MiCombineIdenticalPages+0x214 nt!NtSetSystemInformation+0x59a nt!KiSystemServiceCopyEnd+0x25 ntdll!NtSetSystemInformation+0x14 sysmain!PfsCombineWorker+0x1b0 KERNEL32!BaseThreadInitThunk+0x14 ntdll!RtlUserThreadStart+0x21 Конкретное место краша ничего не проясняет: Может, у кого-то есть идеи, как по-другому (или более правильно) затриггерить CoW? Или как почистить за собой следы, чтобы валидатор памяти не валил систему в синий экран?