WinDbg演示IA-32 CPU下的Windows 分页机制下的地址转换过程

转自:http://blog.csdn.net/whatday/article/details/7270300

今天在学习《软件调试》的时候,练习虚拟地址转物理地址的时候遇到了一个问题。用windbg本地调试内核功能时,!dd无法使用

用windbg命令dd的时候出现了以下错误:

kd> !dd 0b3c03c0
Physical memory read at b3c03c0 failed
If you know the caching attributes used for the memory,
try specifying [c], [uc] or [wc], as in !dd [c] .
WARNING: Incorrect use of these flags will cause unpredictable
processor corruption. This may immediately (or at any time in
the future until reboot) result in a system hang, incorrect data
being displayed or other strange crashes and corruption.

我们知道,

Page Directory ( Page Directory  其高20(10)为该页目录的起始地址。

Page Table  Page Table Virtual Address

 

Step1:

Step2:

Step3:

Step4:

Step5:

 下面用windbg展示地址转换过程

以windows计算器(calc.exe)为例

1.打开calc.exe,输入数字,如123456, 然后在user mode下开始调试calc.exe

0:002> x calc!g*
01014f08 calc!ghwndTimeOutDlg =
01014d9c calc!g_fHighContrast =
0100514d calc!GetKeyColor =
01014ef8 calc!gfExiting =
0100518d calc!GetHelpID =
01014c70 calc!ghnoPrecNum =
01014c08 calc!ghnoParNum =
01014038 calc!gszSep =
01014eec calc!ghcurOld =
01014d38 calc!g_ahnoChopNumbers =
01014f00 calc!ghCalcDone =
01014db0 calc!gpszNum =
01014f0c calc!gnPendingError =
01014000 calc!gnDecGrouping =
01014dc0 calc!gcio =
01014d98 calc!ghnoLastNum =
01014f04 calc!ghDogThread =
01014d80 calc!g_hDecMenu =
01014f48 calc!gbinexact =
01014d7c calc!g_hHexMenu =
01014efc calc!ghCalcStart =
01014da0 calc!g_fLayoutRTL =
01014db8 calc!gbRecord =
010149d8 calc!gcIntDigits =
01014d6c calc!g_hwndDlg =
01014d4c calc!gbUseSep =
01014d94 calc!ghnoMem =
010044b4 calc!GroupDigits =
01014f4c calc!gllfact =
01014d90 calc!ghnoNum =
01014064 calc!gldPrevious =

0:002> dd 01014db0 
01014db0  000b2ee0 00000000 00000001 00000000
01014dc0  00000000 ffffffff 00000000 00000000
01014dd0  00000006 00320031 00340033 00360035
01014de0  00000000 00000000 00000000 00000000
01014df0  00000000 00000000 00000000 00000000
01014e00  00000000 00000000 00000000 00000000
01014e10  00000000 00000000 00000000 00000000
01014e20  00000000 00000000 00000000 00000000

我们可以看看000b2ee0附近 连续内存空间里面的内容:

0:002> dd 000b2ee0 
000b2ee0  00320031 00340033 00360035 0000002e
000b2ef0  00030025 0008013d 000b3060 000b2f14
000b2f00  00000000 00000000 00000000 00000000
000b2f10  00000000 5443534d 614d2e46 61687372
000b2f20  746e496c 61667265 462e6563 4d656c69
000b2f30  412e7061 462e4c4d 4545482e 00464945
000b2f40  00000000 00000000 00000000 00000000
000b2f50  00000000 00000000 00000000 00000000

输入字符串变量的地址就在000b2ee0内存里面
0:002> du 000b2ee0 
000b2ee0  “123456.”

该地址000b2ee0 里面存放的正是我们所输入的数字:123456。而000b2ee0  为 virtual address。那么其physical address 到底是什么呢前面的介绍,一个32bit的virtual address由3部分组成,我们可以具体看看每一部分的值

0:002> .formats 000b2ee0 
Evaluate expression:
  Hex:     000b2ee0
  Decimal: 732896
  Octal:   00002627340
  Binary:  00000000 00001011 00101110 11100000
  Chars:   ….
  Time:    Fri Jan 09 03:34:56 1970
  Float:   low 1.02701e-039 high 0
  Double:  3.62099e-318

由以上可以看出,其PDE index为高10 :0, PTE index(中间10bit): B2, 页内偏移地址:EE0

下面找出该虚地址的absolute address

再启动一个kernal model debug -> local

lkd> !process 0 0

……

PROCESS 85185288  SessionId: 0  Cid: 0b8c    Peb: 7ffde000  ParentCid: 021c
    DirBase: 1d386000  ObjectTable: e1ff17e0  HandleCount: 187.
    Image: dllhost.exe

PROCESS 84f10da0  SessionId: 0  Cid: 049c    Peb: 7ffde000  ParentCid: 0508
    DirBase: 093ee000  ObjectTable: e2ace720  HandleCount:  49.
    Image: calc.exe

PROCESS 847e6220  SessionId: 0  Cid: 0840    Peb: 7ffde000  ParentCid: 02c4
    DirBase: 15297000  ObjectTable: e2b1fe30  HandleCount: 161.
    Image: msmsgs.exe

其中DirBase所指向的地址高20位 即为该进程calc.exe的页目录基地址:093ee000(低12固定为0)

下面来看PD中具体的PDE

lkd> !dd 093ee000  (显示指定地址的页目录表项内容)
# 93ee000 093fb067 0c765067 1803b067 00000000
# 93ee010 14240067 00000000 00000000 00000000
# 93ee020 00000000 00000000 00000000 00000000
# 93ee030 00000000 00000000 00000000 00000000
# 93ee040 00000000 00000000 00000000 00000000
# 93ee050 00000000 00000000 00000000 00000000
# 93ee060 00000000 00000000 00000000 00000000
# 93ee070 00000000 00000000 00000000 00000000
根据virtual address中的 PDE index:0, 故其在PD中查找PDT的index为0, 即为第1个PDE :093fb067 。

在该093fb067 地址里面, 其高20bit (即093fb000)为其page table(页表)起始地址,低12bit为页表属性,至于每个Bit代表什么属性,在此不作赘述。

页表起始地址 + 页表项在页表内的索引,即可以得到该PTE的物理地址。从以上我们已经知道,该virtual address在PT中的索引值为B2,故PTE的地址为:

093fb000 + B2*4 (因为每个表项占4个byte)

lkd> !dd 093fb000 + B2 * 4
# 93fb2c8 105eb067 148ec886 18aed886 0dcee886
# 93fb2d8 00000080 00000000 00000000 00000000
# 93fb2e8 00000000 00000000 00000000 00000000
# 93fb2f8 00000000 00000000 00000000 00000000
# 93fb308 00000000 00000000 00000000 00000000
# 93fb318 00000000 00000000 00000000 00000000
# 93fb328 00000000 00000000 00000000 00000000
# 93fb338 00000000 00000000 00000000 00000000

可以得到该地址内的PTE地址为105eb067 ,而该地址的高20bit( 105eb000 )为所在物理内存页的起始地址,低12bit为内存页属性。

得到该物理页的起始地址后 + virtual address的offset,即可得到其物理地址

即105eb000 + EE0 =105ebee0

下面我们看看该地址内的内容是什么:

lkd> !dd 105ebee0
#105ebee0 00320031 00340033 00360035 0000002e
#105ebef0 00030025 0008013d 000b3060 000b2f14
#105ebf00 00000000 00000000 00000000 00000000
#105ebf10 00000000 5443534d 614d2e46 61687372
#105ebf20 746e496c 61667265 462e6563 4d656c69
#105ebf30 412e7061 462e4c4d 4545482e 00464945
#105ebf40 00000000 00000000 00000000 00000000
#105ebf50 00000000 00000000 00000000 00000000

lkd> !du 105ebee0
#105ebee0 “123456.”

比对user mode下的dd 000b2ee0 ,我们可以看到, 其内容是完全相同的。

也就是说我们找到了virtual address : 000b2ee0 的准确物理地址:105ebee0。

只不过我们在user mode下使用dd时,这个转换过程自动完成了。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2018年1月6日
下一篇 2018年1月6日

相关推荐