首页
社区
课程
招聘
[原创]最近操作物理内存时发现了一个好玩的问题 以及解决方案
发表于: 2019-3-20 02:53 7336

[原创]最近操作物理内存时发现了一个好玩的问题 以及解决方案

2019-3-20 02:53
7336
突然发现一个好玩的事。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编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 606
活跃值: (3270)
能力值: ( LV7,RANK:140 )
在线值:
发帖
回帖
粉丝
2
虽然不太明白但是好厉害的样子
2019-3-20 10:05
0
雪    币: 4006
活跃值: (676)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
ProbeForWrite还有这功能,学习了。如果不考虑效率,我的方法是查询内存 然后字符串比较一发(可提交物理页).另外我自己的测试结果是MmIsAddressVaild对连续的内存进行还是可以的,比如读10个字节,那么判断两次,一个头一个尾,并木有出现异常的情况,可能还是太年轻啊
2019-3-20 10:22
0
雪    币: 634
活跃值: (1149)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
放学打我不 ProbeForWrite还有这功能,学习了。如果不考虑效率,我的方法是查询内存 然后字符串比较一发(可提交物理页).另外我自己的测试结果是MmIsAddressVaild对连续的内存进行还是可以的, ..理解错了。。额 MmIsAddressVaild 可以???.
最后于 2019-3-20 11:46 被BDBig编辑 ,原因:
2019-3-20 11:43
0
雪    币: 634
活跃值: (1149)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
放学打我不 ProbeForWrite还有这功能,学习了。如果不考虑效率,我的方法是查询内存 然后字符串比较一发(可提交物理页).另外我自己的测试结果是MmIsAddressVaild对连续的内存进行还是可以的, ...
kd> !vtop 18289e000  0x400000
Amd64VtoP: Virt 0000000000400000, pagedir 000000018289e000
Amd64VtoP: PML4E 000000018289e000
Amd64VtoP: PDPE 000000019c077000
Amd64VtoP: PDE 000000019c0bb010
Amd64VtoP: PTE 000000019b2fc000
Amd64VtoP: Mapped phys 0000000188fc9000
Virtual address 400000 translates to physical address 188fc9000.
kd> !vtop 186341000  0x400000
Amd64VtoP: Virt 0000000000400000, pagedir 0000000186341000
Amd64VtoP: PML4E 0000000186341000
Amd64VtoP: PDPE 0000000185e53000
Amd64VtoP: PDE 0000000186a57010
Amd64VtoP: PTE 0000000186198000
Amd64VtoP: Mapped phys 0000000188fc9000
Virtual address 400000 translates to physical address 188fc9000.
不行、......
2019-3-20 12:02
0
雪    币: 634
活跃值: (1149)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
写时copy 正确解决方案 最稳定 的还是 MiCopyOnWrite .
2019-3-20 12:08
0
雪    币: 12848
活跃值: (9133)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
7
1:判断是不是 数据段 。是不是数据段 是的话就不需要这样了。
2:改变地址属性为可写可读可执行
3:挂LoadImage对每个模块都执行一下这个函数 进行写入判断 让系统为期分配单独的页面

这不就是标准hook流程么

顺便一提 再loadimage回调里操作vm属性 是作大死
2019-3-20 13:19
0
雪    币: 634
活跃值: (1149)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
hzqst 1:判断是不是 数据段 。是不是数据段 是的话就不需要这样了。 2:改变地址属性为可写可读可执行 3:挂LoadImage对每个模块都执行一下这个函数 进行写入判断 让系统为期分配单独的页面 ...
确实作死。可以说是标准HOOK流程。
但是不是为了做HOOK。只是为了让系统分配单独的页 给代码段
2019-3-20 21:08
0
雪    币: 8
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
所以最靠谱的方案
1:判断是不是 数据段 。是不是数据段 是的话就不需要这样了。
2:改变地址属性为可写可读可执行
3:挂LoadImage对每个模块都执行一下这个函数 进行写入判断 让系统为期分配单独的页面

大佬说的缓存页  就是系统的共享页吗 

还有 大佬 在LoadImage回调里 改变模块的地址为可读可写可执行  地址已经有了可写属性了 还有写时拷贝的效果吗 还是说 只要不是直接改pte里面的属性位 用改属性的函数改模块的地址为可读可写可执行 写时拷贝效果还在对吗      期待大佬的回答 谢谢  

------------------------------------------来自初学内核萌新的问题
2022-7-7 22:35
0
游客
登录 | 注册 方可回帖
返回
//