前提
如图,csrss系统进程的CR3值与启动时的值不同

通过调试的栈最终引用函数的是MmStealTopLevelPage
__int64 __fastcall MmStealTopLevelPage(__int64 a1)
{
struct _KTHREAD *CurrentThread; // r15
_EPROCESS *Process; // r15
__int64 v5; // rdx
unsigned int v6; // ebp
__int64 v7; // rsi
unsigned __int64 v8; // r12
ULONG_PTR v9; // rbx
unsigned __int64 v10; // rsi
ULONG_PTR v11; // r14
__int64 v12; // rbx
unsigned __int64 v13; // rdi
unsigned __int64 v14; // rsi
bool v15; // zf
ULONG_PTR *BugCheckParameter2; // [rsp+70h] [rbp+8h]
CurrentThread = KeGetCurrentThread();
if ( *(struct _KTHREAD **)(a1 + 40) != CurrentThread )
return 0;
Process = CurrentThread->ApcState.Process;
MiLockWorkingSetExclusiveAtDpc(&Process->Vm);
MiReplacePageTablePage(a1);
v6 = 0;
if ( *(int *)(a1 + 56) >= 0 )
{
v7 = *(_QWORD *)(a1 + 32);
++dword_140EF4AA8;
v8 = MiMapPageInHyperSpaceWorker(*(_QWORD *)(a1 + 32), 0, 0x80000000LL);
BugCheckParameter2 = (ULONG_PTR *)(v8
+ 8
* (((((*(_QWORD *)(a1 + 8) >> 9) & 0x7FFFFFFFF8uLL) - 0x98000000000LL) >> 3) & 0x1FF));
v9 = (v7 << 12) ^ ((v7 << 12) ^ ((__int64 (*)(void))MI_READ_PTE_LOCK_FREE)()) & 0xFFF0000000000FFFuLL;
*BugCheckParameter2 = CLFS_LSN_NULL_EXT;
if ( _bittest64(&MiFlags, 0x24u)
&& (v9 & 0x20) == 0
&& (unsigned __int64)BugCheckParameter2 >= 0xFFFFF6C000000000uLL )
{
MiCheckLinearProtectedPteAccessedBit((ULONG_PTR)BugCheckParameter2, v9);
}
v5 = 0x7FFFFFFFF8LL;
*BugCheckParameter2 = v9;
*(_QWORD *)KeGetCurrentPrcb()->MmInternal = 0;
*(_QWORD *)(((v8 >> 9) & 0x7FFFFFFFF8LL) - 0x98000000000LL) = CLFS_LSN_NULL_EXT;
if ( *(_DWORD *)(a1 + 64) )
{
v11 = (((unsigned __int64)Process->Vm.Shared.ShadowMapping >> 9) & 0x7FFFFFFFF8LL) - 0x98000000000LL;
v12 = MI_READ_PTE_LOCK_FREE(v11);
*(_QWORD *)v11 = CLFS_LSN_NULL_EXT;
MiFlushSingleTbEntry((__int64)(v11 << 25) >> 16, 2, 1);
v13 = (v7 << 12) ^ (v12 ^ (v7 << 12)) & 0xFFF0000000000FFFuLL;
if ( _bittest64(&MiFlags, 0x24u) && (v12 & 0x20) == 0 && v11 >= 0xFFFFF6C000000000uLL )
MiCheckLinearProtectedPteAccessedBit(v11, (v7 << 12) ^ (v12 ^ (v7 << 12)) & 0xFFF0000000000FFFuLL);
v14 = v7 << 12;
v15 = KiFlushPcid == 0;
*(_QWORD *)v11 = v13;
if ( !v15 )
v14 |= 1u;
Process->Pcb.UserDirectoryTableBase = v14;
}
else
{
v10 = v7 << 12;
if ( KiFlushPcid )
v10 |= 2u;
Process->Pcb.DirectoryTableBase = v10;
}
v6 = 1;
}
LOBYTE(v5) = 17;
MiUnlockWorkingSetExclusive(&Process->Vm, v5);
return v6;
}是谁做的
目前已知的有
任务计划程序 -> MemoryDiagnostic
NTPAI->NtSetSystemInformation->SystemScrubPhysicalMemoryInformation
什么情况会引发这种情况

如果一个进程占用大量内存,可能会触发物理内存回收整合
可能的影响
不能依赖保存的CR3的值,因为随时可能回收导致CR3的物理地址失效。
如何防止CR3更变
锁定