在开启PAE之后,32位的线性地址的结构发生了变化,具体结构如下
30-31位:页目录指针表索引
21-29位:页目录索引
12-20位:页表索引
0-11位:页内偏移
在开启PAE之后,表中地址都是物理地址,所有表项的大小变为8Byte,具体格式如下:
结合Windows Server 2008中calc.exe中数字的地址分析PAE的地址转化机制
我们在虚拟机中打开calc.exe,然后输入“1234567890”,然后我们打开windbg,附加到calc.exe进程中,用“x calc!gp*”查看calc.exe中gp开头的所有符号的虚拟地址
0:002> x calc!g*
000b4aad calc!GroupDigits = <no type information>
000c4edc calc!ghwndTimeOutDlg = <no type information>
000c4d70 calc!g_fHighContrast = <no type information>
000b5682 calc!GetKeyColor = <no type information>
000c4ecc calc!gfExiting = <no type information>
000b56cc calc!GetHelpID = <no type information>
000c4b80 calc!ghnoPrecNum = <no type information>
000c4be8 calc!ghnoParNum = <no type information>
000c4038 calc!gszSep = <no type information>
000c4ec0 calc!ghcurOld = <no type information>
000c4b6c calc!g_ahnoChopNumbers = <no type information>
000c4ed4 calc!ghCalcDone = <no type information>
000c4d84 calc!gpszNum = <no type information>
000c4ee0 calc!gnPendingError = <no type information>
000c402c calc!gszDec = <no type information>
000c4000 calc!gnDecGrouping = <no type information>
000c4d98 calc!gcio = <no type information>
000c4d6c calc!ghnoLastNum = <no type information>
000c4ed8 calc!ghDogThread = <no type information>
000c4d54 calc!g_hDecMenu = <no type information>
000c4efc calc!gbinexact = <no type information>
000c4d50 calc!g_hHexMenu = <no type information>
000c4ed0 calc!ghCalcStart = <no type information>
000c4d74 calc!g_fLayoutRTL = <no type information>
000c4d90 calc!gbRecord = <no type information>
000c4d88 calc!gcchNum = <no type information>
000c4c4c calc!gcIntDigits = <no type information>
000c4d40 calc!g_hwndDlg = <no type information>
000c4f10 calc!gfHalt = <no type information>
000c4d20 calc!gbUseSep = <no type information>
000c4d68 calc!ghnoMem = <no type information>
000c4f00 calc!gllfact = <no type information>
000c4d64 calc!ghnoNum = <no type information>
000c4070 calc!gldPrevious = <no type informatio
其中calc!gpszNum就是数字的变量名,其虚拟地址为000c4d84,用!dd 000c4d84查看该变量所指向的地址
0:002> dd 000c4d84
000c4d84 00428378 0000000c 00000000 00000001
00428378就是字符串“1234567890”的虚拟地址
0:002> dc 00428378
00428378 00320031 00340033 00360035 00380037 1.2.3.4.5.6.7.8.
00428388 00300039 0000002e 5da02f60 88000000 9.0.....`/.]....
我们使用虚拟地址00428378转化为物理地址,首先使用.formats命令将该地址转化为二进制形式
0:002> .formats 00428378
Evaluate expression:
Hex: 00428378
Decimal: 4359032
Octal: 00020501570
Binary: 00000000 01000010 10000011 01111000
Chars: .B.x
Time: Fri Feb 20 18:50:32 1970
Float: low 6.1083e-039 high 0
Double: 2.15365e-317
根据PAE32位线性地址的结构我们得出:
页目录指针表索引为 00 = 0x0
页目录索引为000000 010 = 0x2
页表索引为00010 1000 = 0x28
页内偏移为0011 01111000 = 0x378
我们使用!process 0 0,找到calc.exe的EPROCESS结构体,其中DirBase就是CR3的值,即页目录指针表的基地址
PROCESS 8340c9f0 SessionId: 1 Cid: 0a34 Peb: 7ffdd000 ParentCid: 0278
DirBase: 3ed32440 ObjectTable: 8fa64808 HandleCount: 46.
Image: calc.exe
由于CR3低5位值全为0,所以页目录指针表基地址为3ed32440,使用!dq 3ed32440查看该表的内容
kd> !dq 3ed32440
#3ed32440 00000000`06a49801 00000000`0698a801
#3ed32450 00000000`0638b801 00000000`0630c801
页目录指针表的虚拟地址为0,所以我们要考察的表项为00000000`06a49801
该值的12-35位为页目录表的基地址高24位,故页目录表的基地址为06a49000,页目录索引为0x2,故输入!dq 06a49000+0x2*8(每个表项大小为8Byte)
kd> !dq 06a49000+0x2*8
# 6a49010 00000000`06b31867 00000000`06d7e867
该值为00000000`06b31867,12-35位为页表基地址高24位,故页表基地址为06b31000,页表索引为0x28,故输入!dq 06b31000+0x28*8
kd> !dq 06b31000+0x28*8
# 6b31140 80000000`0620b867 00000000`00000000
该值为80000000`0620b867,12-35位为页面基地址高24位,故页面基地址为0620b000,页内偏移为0x378,故输入!dc 0620b000+0x378
kd> !dc 0620b000+0x378
# 620b378 00320031 00340033 00360035 00380037 1.2.3.4.5.6.7.8.
# 620b388 00300039 0000002e 5da02f60 88000000 9.0.....`/.]....
因此,物理地址为0620b378