用windbg为无效页面建立页面映射
来源:互联网 发布:apache 支持php 编辑:程序博客网 时间:2024/05/16 07:19
前几天和同事扯淡,说调试驱动时访问无效内存会蓝屏,好麻烦,应该让windbg自动建立一个有效的页面,这样就不用蓝屏重启了。虽然说这是扯淡,但仔细想想貌似也不是不可能实现。
首先回顾一下OS解决内存缺页时简单步骤:1.搜索物理页面;2.修改虚拟地址对应的pte表的值;3.重新执行访存失败的指令。基于这样的思路,我也试了一下在windbg中手工建立内存映射(环境:win7 x32)
1.在内核空间中找一个无效地址。先枚举内核中所有已加载的模块,各模块之间的内存间隙应该有不少无效地址.
kd> lmstart end module name82a06000 82a3d000 hal (deferred) 82a3d000 82e4d000 nt (pdb symbols) kd> dd 82a06000-0x100082a05000 ???????? ???????? ???????? ????????kd> ed 82a05000 0x00 ^ Memory access error in 'ed 82a05000 0x00'模块nt加载在0x82a0d000,从这开始是模块nt的PE头/text区...要在这些位置中找到一段无效内存还是有点难度的,但是往前搜索一个内存页,说不定能找到无效内存。而windbg以????的形式显示无效地址。果然,我在0x82a05000处找到一块无效内存。往这块内存写入值就报出了错误"^ Memory access error in 'ed 82a05000 0x00'"
2.找一块物理地址,用于建立映射到虚拟内存上。我猜想模块nt的PE头应该是有效内存.验证一下:
kd> !pte 82a06000 VA 82a06000PDE at C06020A8 PTE at C0415030contains 00000000001D1063 contains 0000000002A06963pfn 1d1 ---DA--KWEV pfn 2a06 -G-DA--KWEVkd> dd 82a06000 L4 ;虚拟页面的内容82a06000 00905a4d 00000003 00000004 0000ffffkd> !dd 2A06000 ;物理页面的内容# 2a06000 00905a4d 00000003 00000004 0000ffffnt的PE头位于0x82a06000,通过!pte命令查看其页表项,我们知道0x82a06000所在的页面是有效页面,页面物理地址是0x2a06000。另外,虚拟页面的内容和其所映射的物理页面的内容是一致的。接下来,我会用这个物理页面映射到虚拟地址0x82a05000上。(移花接木之术)
3.定位虚拟地址0x82a05000的pte,然后修改pte中存储的值为物理页面0x2a06000。
kd> !pte 82a05000 VA 82a05000PDE at C06020A8 PTE at C0415028contains 00000000001D1063 contains 0000000000000000pfn 1d1 ---DA--KWEV not validkd> ed C0415028 2A06963kd> !pte 82a05000 VA 82a05000PDE at C06020A8 PTE at C0415028contains 00000000001D1063 contains 0000000002A06963pfn 1d1 ---DA--KWEV pfn 2a06 -G-DA--KWEV修改前,0x82a05000对应的pte (位于C0415028)是无效pte;修改后,变成了有效pte
4.看看修改的结果。
kd> dd 82a05000 82a05000 00905a4d 00000003 00000004 0000ffff82a05010 000000b8 00000000 00000040 0000000082a05020 00000000 00000000 00000000 00000000以前0x82a05000处是无效内存,结果页面映射,现在已经有除????以外的数值。恩,页面映射成功
------------------------------------------------------------------------------
后记:
这次修改有2个有意思的地方:
1.修改后,有时候执行
dd 0x82a05000,还是会看到????,不要以为这是映射失败。要经过一段时间或者编辑一下内存才能看到内存值被修改了。我问过群里的大神,他们的回复这种现象是由于Cpu TLB(快表)的存在,要使TLB中的页表失效,才能重新获得新的页表
2.现在虚拟地址0x82a05000和0x82a06000两个页面的确指向同一块物理页面。理论上,修改其中一个页面的值,势必会影响另一个页面的值,然而,调试过程中并非如此:
我尝试修改页面0x82a05000的值,却并没有影响到页面0x82a06000的值。开始时,我以为发生了写时复制,可是查看0x82a05000的页表项,其值并没有改变。
kd> ed 82a05000 90909090 ;修改虚拟内存的内容kd> dd 82a05000 L482a05000 90909090 00000003 00000004 0000ffffkd> dd 82a06000 L4 ;查看nt模块的pe头,值没有改变82a06000 00905a4d 00000003 00000004 0000ffffkd> !pte 82a05000 ;查看两个虚拟地址对应的pte,也没有发生改变,仍然指向相同的物理地址 VA 82a05000PDE at C06020A8 PTE at C0415028contains 00000000001D1063 contains 0000000002A06963pfn 1d1 ---DA--KWEV pfn 2a06 -G-DA--KWEVkd> !pte 82a06000 VA 82a06000PDE at C06020A8 PTE at C0415030contains 00000000001D1063 contains 0000000002A06963pfn 1d1 ---DA--KWEV pfn 2a06 -G-DA--KWEVkd> !dd 2A06000 ;前面修改82a05000的值已经成功,物理页面的内容已经被改变# 2a06000 90909090 00000003 00000004 0000ffff
对于这个现象,我实在无法解释,只能等路过的大神帮忙解答了
- 用windbg为无效页面建立页面映射
- servlet 映射为 页面文件使用
- 页面映射
- js页面跳转无效
- 页面修改 路径无效
- 页面计数器改进版,刷新页面无效
- 用WebWork、JSP、Velocity建立注册页面
- 用ASP建立WEB页面计数器
- 用WebWork、JSP、Velocity建立注册页面
- 用WebWork、JSP、Velocity建立注册页面
- 用ASP建立WEB页面计数器
- 用ASP建立WEB页面计数器
- 用WebWork、JSP、Velocity建立注册页面
- jsp页面的建立
- 页面的建立(-)
- 页面的建立
- 微信小程序页面跳转无效
- play 的action映射页面
- 初始使用Fedora的几点记录
- 学习小记 - Flask Web (4) MySQL中文编码
- Ubuntu环境安装mosquitto
- 魔术师发牌 Java实现
- 单独用js获取项目根路径
- 用windbg为无效页面建立页面映射
- to be a better me--hello 2017
- 策略模式(python)
- Mac下Sublime安装配置Emmet插件
- 深度思考
- UNICODE全志tinav2.1的编译工具链的设置.txt
- <mvc:default-servlet-handler />及<mvc:resources />的用途
- 268. Missing Number
- 关于使用扩展列表ExpandableList数据接口问题(一)