就像我几乎所有的问题一样,我觉得我错过了一些东西/我以错误的方式理解了一些东西,所以请帮助我找出我错在哪里。
当页面错误发生并且 nt!KiTrap0E 来保存 CPU 保存当前状态的那一天时,它会将错误指令的 EIP 和错误代码压入堆栈(x86 上为 32 位,x64 上为 64 位,但只有位 0、1 和 2 在这里相关)并使用引用的虚拟地址加载 CR2?因此,当我们在 KiTrap06 中时,堆栈如下所示:
故障指令EIP
错误代码
这是正确的吗?
因此,如果我在用户模式下有以下代码:
LPVOID address = VirtualAlloc(NULL,
1024,
MEM_COMMIT,
PAGE_READONLY);
*(PDWORD)address = 12;
当 EIP 达到 *(PDWORD)address = 12(好吧,实际上它可能是 mov 地址,0x0B,但让我们简化一下)会发生 Page Fault,CPU 将保存当前状态,将推送该 EIP分配,然后将错误代码压入堆栈(位 2、1 和 0:1(用户进程)1(尝试写入页面)1(并导致保护错误)),并使用分配的地址加载 CR2使用 VirtualAlloc?处理程序将检查错误代码和来自 PDE(CR2 的高 10 位)和/或 (??) PTE(CR2 的中间 10 位)的 Read\Write 字节,看到写入只读页面的尝试是制作并将终止故障过程?
如果页面可写但未加载(错误代码的最后 3 位:110),处理程序将使用 CR2 中的值将页面带入内存并重新执行错误指令?