突然发现一个好玩的事。R3直接对指定物理内存进行操作时,会出现读写不同步的问题。比如0X400000你用CE改变他为1 但是读出来的内容还是原来的MZ.
这是为什么呢。是因为读的是缓存里的内容。这就涉及到windows 经典设计之一的woc(写时拷贝)
https://blog.csdn.net/junbopengpeng/article/details/38072223
写时copy是什么呢。当你进程加载的时候像代码段什么的。都是可以说是没有真正物理页的。因为他们公用的是系统的缓存页,当你去改写他的时候 系统才会给你分配一个单独的物理页 保证你不去影响其他程序。
1: kd> !vtop 161629000 0x400000
Amd64VtoP: Virt 0000000000400000, pagedir 0000000161629000
Amd64VtoP: PML4E 0000000161629000
Amd64VtoP: PDPE 000000015150a000
Amd64VtoP: PDE 000000015014e010
Amd64VtoP: PTE 000000014fa4f000
Amd64VtoP: Mapped phys 00000001a2a2f000
Virtual address 400000 translates to physical address 1a2a2f000.
1: kd> !vtop 14f68e000 0x400000
Amd64VtoP: Virt 0000000000400000, pagedir 000000014f68e000
Amd64VtoP: PML4E 000000014f68e000
Amd64VtoP: PDPE 000000015048d000
Amd64VtoP: PDE 0000000152091010
Amd64VtoP: PTE 0000000150892000
Amd64VtoP: Mapped phys 00000001a2a2f000
Virtual address 400000 translates to physical address 1a2a2f000.
如果你一但修改缓存 就会发现 下次进程启动 上次写入的值还在,这样子可以做很多事。自行脑补。(比如说不HOOK内核 实现内核HOOK一样的效果/滑稽)
虽然绕过这个机制可以做很多事。但肯定有时候肯定不是要绕过这个机制 而是让这个机制 继续去正常运作。我只是无意的让R3绕过了这个机制。本来是要R3任意位数的一个进程里可以直接指针操作读写执行整个系统。虽然实现了 但是这样就出现了WOC问题。我改写进程内存 发现 我写到缓存里了。这个问题让我蛋疼了几天。
先说我第一个方案:
1.直接自己去实现去代替老的WOC机制 结果发现 可以读 但是写入就蓝屏。定期稳定蓝屏。
具体实现 通过我和(@天下肥猫的分)分析发现woc实际是改变了 PT里的物理内存指针。判断PTE的几个标志位。然后进行判断是不是已经copy走。然后按照他的那一套我自己构造了缓存里的内存 然后给PT替换。刚开始以为正常了。当我试着写入 就发现 稳定蓝屏。如果内核访问 改写都是正常的。无关权限--。不明白为什么。这个方案我给PASS掉了。如果有兴趣的小伙伴可以自己去写一下试试看 。(挂的时间长了也会蓝屏哦 10分钟稳定 )
2.第二套借用系统函数
ProbeForWrite 发现一样可以让系统从新分配页面
具体为什么可以看看这个函数的实现。
所以最靠谱的方案
1:判断是不是
数据段
。是不是数据段 是的话就不需要这样了。
2:改变地址属性为可写可读可执行
3:挂LoadImage对每个模块都执行一下这个函数 进行写入判断 让系统为期分配单独的页面
最后说一下。一切R0读写R3不用
ProbeForXXXX 都是在玩蛇皮 MMISXXXX 更是在玩蛇皮
通过我这几天对系统内存的分配函数的种种分析 的出来的结论
最后于 2019-3-20 03:09
被BDBig编辑
,原因: