windows写时复制处理流程
windows写时复制流程
处理流程
1.当指令试图写入一条地址时,cpu会先判断此虚拟地址对应的PTE的U/S有效位属性,如果此位为0表示还没有为此虚拟地址映射对应的物理内存,触发页访问异常返回0xC0000005。
2.如果U/S位有效就继续判断PTE的R/W位,如果R/W位为1就直接写入。如果R/W位为0就表示此虚拟地址不可写,触发页保护异常。
3. 页保护异常处理程序会先判断此PTE的第9位是否为1,如果为1就直接为此虚拟地址分配新的物理内存,修正PTE后将PTE的R/W位置1,接着返回到原指令处继续执行。
4. 如果页保护异常判断PTE的第9位为0就会去查询此地址对应的VAD描述符是否包含PAGE_WRITEPAGE属性,如果不包含此属性就返回访问错误,如果判断包含此属性就将PTE的第9位置1然后返回到原指令继续执行。
总结
- 一个虚拟地址页面的属性是由cpu层面的PTE和操作系统层面的VAD共同决定的。
- windows的写时复制机制是基于页保护异常处理程序的。
- PTE的第9位是inter保留的,windows利用此位来实现写时复制并通过页保护异常来实现。
写时复制的绕过
- 基于windows写时复制的处理流程,可以通过设置CR0的wp位为0或者设置对应页面的PTE的R/W位为1。
- 也可以通过MDI为此页面对应的物理地址映射新的虚拟内存并设置R/W位为1来绕过。
写时复制验证
现在有两个进程都映射了0x00007ffe85620000 开始0x3000大小的内存块。属性为PAGE_WRITECOPY。
查看两个进程此虚拟地址对应同一块物理地址
然后修改其中一个进程此地址对应的内存
再次查看发现修改的进程此虚拟地址对应的物理地址与原来的不一样,说明操作系统已经为此虚拟地址分配了新的物理内存。
对于一些需要多次映射的模块的代码段也是一样,以ntdll.dll为例,两个程序都加载ntdll.dll,其ntdll.dll一开始虚拟地址对应的物理地址是相同的,但是当我们调试其中一个程序并在ntdll.dll的代码段下断点(相当于修改了代码)则其会分配新的物理内存。