가상 메모리를 물리 메모리로 변환
일반적으로 가상 메모리를 물리 메모리로 변환해서 확인해야 할 경우가 거의 없지만 공부하는 차원에서 직접 Virtual address 를 physical address 로 변환하는 것을 Windbg 를 통해 확인해 보고자 합니다.
x86 system 을 기준으로 설명 합니다. x64 의 경우 내용이 좀 다르며 다음 번에 설명하기로 합니다.
Windows 에서는 Virtual address 를 관리하기 위해 page 라는 개념을 사용하는데 일반적인 경우 4KB 의 page 를 관리하게 됩니다. 하지만 Image 를 올리는 것과 같이 큰 Data 를 물리 메모리에 올릴때는 4MB ㅇ의 Large page 라는 것을 사용합니다.
일반 page 의 경우
virtual address 0xb742a310 을 기준으로 설명 합니다.
!pte 명령을 사용해서 virtual address 의 정보를 확인할 수 있습니다.
7: kd> !pte b742a310
VA b742a310
PDE at C0300B74 PTE at C02DD0A8
contains 00BA7963 contains 28857963
pfn ba7 -G-DA--KWEV pfn 28857 -G-DA-KWEV
이 메모리의 내용을 확인해 보도록 하겠습니다.
7: kd> dd b742a310
b742a310 b742a3ac f7123166 b742a730 e51f7cd8
b742a320 00000080 b742a3cc 00000000 b742a2f3
자 이제부터 본격적으로 변환 작업을 진행 해 보도록 하겠습니다.
rm ff 명령을 사용해서 register mask 를 변환해서 모든 register 값을 볼 수 있도록 합니다.
kd> rm ff
Last set context:
r 명령으로 register 값을 확인 합니다. Page Directory 의 주소를 가지고 있는 cr3 레지스터의 값을 확인 합니다. 여기서는 0x3edb1000 입니다.
7: kd> r
Last set context:
eax=83000aec ebx=84d128d8 ecx=00000000 edx=83000ae4 esi=84d12830 edi=84d128a8
eip=8083df4c esp=b742a224 ebp=b742a264 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246
fpcw=0000: rn 24 ------ fpsw=0000: top=0 cc=0000 -------- fptw=0000
fopcode=0000 fpip=0000:00000000 fpdp=0000:00000000
st0= 0.000000000000000000000e+0000 st1= 0.000000000000000000000e+0000
st2= 0.000000000000000000000e+0000 st3= 0.000000000000000000000e+0000
st4= 0.000000000000000000000e+0000 st5= 0.000000000000000000000e+0000
st6= 0.000000000000000000000e+0000 st7= 0.000000000000000000000e+0000
mm0=0000000000000000 mm1=0000000000000000
mm2=0000000000000000 mm3=0000000000000000
mm4=0000000000000000 mm5=0000000000000000
mm6=0000000000000000 mm7=0000000000000000
xmm0=0 0 0 0
xmm1=0 0 0 0
xmm2=0 0 0 0
xmm3=0 0 0 0
xmm4=0 0 0 0
xmm5=0 0 0 0
xmm6=0 0 0 0
xmm7=0 0 0 0
cr0=8001003b cr2=00000000 cr3=3edb1000
dr0=00000000 dr1=00000000 dr2=00000000
dr3=00000000 dr6=00000000 dr7=00000000 cr4=000006d9
nt!KeWaitForSingleObject+0x24f:
8083df4c 8919 mov dword ptr [ecx],ebx ds:0023:00000000=????????
찾고자 하는 virtual address 를 bit 단위로 쪼갭니다.
7: kd> .formats b742a310
Evaluate expression:
Hex: b742a310
Decimal: -1220369648
Octal: 26720521420
Binary: 10110111 01000010 10100011 00010000
Chars: .B..
Time: ***** Invalid
Float: low -1.16013e-005 high -1.#QNAN
Double: -1.#QNAN
Virtual address 값을 확인해 보면 다음과 같습니다.
1011011101 2DD Page Directory index
0000101010 2A Page Table Index
001100010000 310 Offset
CR3 에서 얻은 값으로 Page Directory index 로 물리 메모리 확인합니다. dd 는 메모리를 보여주는 명령이고 /p 는 physical memory 를 보여주는 것 입니다.
Page directory address + page directory index * size
7: kd> dd /p 3edb1000+2dd*4
3edb1b74 00ba7963 00ba8963 00ba9963 00baa963 !pte 명령의 결과중 첫 번째 Contains 에 있는 값과 동일합니다.
3edb1b84 00bab963 00bac963 00bad963 00bae963
가상 메모리에 동일 내용 들어 있는 것을 확인합니다.
7: kd> dd C0300B74
c0300b74 00ba7963 00ba8963 00ba9963 00baa963
c0300b84 00bab963 00bac963 00bad963 00bae963
ba7963 을 bit 단위로 확인하여 일반 page 인지 Large page 인지 확인 합니다.
7: kd> .formats 00ba7963
Evaluate expression:
Hex: 00ba7963
Decimal: 12220771
Octal: 00056474543
Binary: 00000000 10111010 01111001 01100011 PS Field가 set 되어 있지 않기 때문에 일반 page 로 4KB 단위
Chars: ..yc
Time: Fri May 22 19:39:31 1970
Float: low 1.71249e-038 high 0
Double: 6.03786e-317
Page Table Index 로 물리메모리 확인 두번째 Contains 에 있는 값과 동일합니다.
Page table address + page table index * size
7: kd> dd /p ba7000+2a*4
00ba70a8 28857963 00000000 00000000 00000000
00ba70b8 00000000 00000000 00000000 00000000
마지막으로 Offset 을 사용해서 물리 메모리 확인합니다.
page start address + offset
7: kd> dd /p 28857000+310
28857310 b742a3ac f7123166 b742a730 e51f7cd8
28857320 00000080 b742a3cc 00000000 b742a2f3
가상 메모리를 확인하여 동일함을 확인 합니다.
7: kd> dd b742a310
b742a310 b742a3ac f7123166 b742a730 e51f7cd8
b742a320 00000080 b742a3cc 00000000 b742a2f3
Large page
가상메모리 0x83002634 를 확인해 보고자 합니다.
!pte 명령을 통해 정보를 확인해 봅니다. 일반 페이지와는 다르게 LARGE PAGE 라고 나옵니다.
7: kd> !pte 83002634
VA 83002634
PDE at C0300830 PTE at C020C008
contains 030009E3 contains 00000000
pfn 3000 -GLDA--KWEV LARGE PAGE pfn 3002
0x83002634 에 어떤 값이 있는지 확인해 봅니다.
7: kd> dd 83002634
83002634 02110201 03021103 11030211 02110301
83002644 04011102 11020211 01110403 02011104
0x83002634 를 Bit 단위로 쪼개 봅니다.
7: kd> .formats 83002634
Evaluate expression:
Hex: 83002634
Decimal: -2097142220
Octal: 20300023064
Binary: 10000011 00000000 00100110 00110100
Chars: ..&4
Time: ***** Invalid
Float: low -3.76597e-037 high -1.#QNAN
Double: -1.#QNAN
Large Page 이기 때문에 뒤의 22Byte 가 Offset 입니다.
1000001100 20C Page Directory Index
0000000010011000110100 2634 Offset
r 명령을 사용해서 cr3 register 값을 확인 합니다. 이전과 동일하게 3edb1000 입니다.
7: kd> r
Last set context:
eax=83000aec ebx=84d128d8 ecx=00000000 edx=83000ae4 esi=84d12830 edi=84d128a8
eip=8083df4c esp=b742a224 ebp=b742a264 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246
fpcw=0000: rn 24 ------ fpsw=0000: top=0 cc=0000 -------- fptw=0000
fopcode=0000 fpip=0000:00000000 fpdp=0000:00000000
st0= 0.000000000000000000000e+0000 st1= 0.000000000000000000000e+0000
st2= 0.000000000000000000000e+0000 st3= 0.000000000000000000000e+0000
st4= 0.000000000000000000000e+0000 st5= 0.000000000000000000000e+0000
st6= 0.000000000000000000000e+0000 st7= 0.000000000000000000000e+0000
mm0=0000000000000000 mm1=0000000000000000
mm2=0000000000000000 mm3=0000000000000000
mm4=0000000000000000 mm5=0000000000000000
mm6=0000000000000000 mm7=0000000000000000
xmm0=0 0 0 0
xmm1=0 0 0 0
xmm2=0 0 0 0
xmm3=0 0 0 0
xmm4=0 0 0 0
xmm5=0 0 0 0
xmm6=0 0 0 0
xmm7=0 0 0 0
cr0=8001003b cr2=00000000 cr3=3edb1000
dr0=00000000 dr1=00000000 dr2=00000000
dr3=00000000 dr6=00000000 dr7=00000000 cr4=000006d9
nt!KeWaitForSingleObject+0x24f:
8083df4c 8919 mov dword ptr [ecx],ebx ds:0023:00000000=????????
cr3 레지스터에 있는 값인 Page directory address 를 사용해서 Page Table 위치를 찾습니다.
page directory + page directory index * size
7: kd> dd /p 3edb1000+20c*4
3edb1830 030009e3 034009e3 038009e3 03c009e3
3edb1840 040009e3 044009e3 048009e3 04c009e3
가상 메모리에 동일한 값이 있는지 확인 합니다.
7: kd> dd C0300830
c0300830 030009e3 034009e3 038009e3 03c009e3
c0300840 040009e3 044009e3 048009e3 04c009e3
확인된 내용을 Bit 단위로 쪼개서 내용을 확인해 보니 Large page 로 설정되어 있습니다.
7: kd> .formats 030009e3
Evaluate expression:
Hex: 030009e3
Decimal: 50334179
Octal: 00300004743
Binary: 00000011 00000000 00001001 11100011 Large Page
Chars: ....
Time: Fri Aug 06 22:42:59 1971
Float: low 3.76272e-037 high 0
Double: 2.48684e-316
물리 메모리 확인 PS field가 1로 설정되어 있기 때문에 직접 물리 메모리를 가리키는 것입니다. 즉 0x03000000 이 시작 주소 입니다.
Page 시작 address + offset
7: kd> dd /p 03000000 + 2634
03002634 02110201 03021103 11030211 02110301
03002644 04011102 11020211 01110403 02011104
Large page 의 처음에서 확인한 Virtual address 의 내용과 일치 합니다.
Comments
Anonymous
March 12, 2009
The comment has been removedAnonymous
March 16, 2009
Page 테이블이 있는 주소를 알아내기 위해서 "7: kd> dd /p 3edb1000+2dd4 " 로 찾았을 때 00ba7963 이 나왔는데요. 그런데, 왜 그 이후에는 "7: kd> dd /p ba7000+2a4 " 와 같이 ba7963 이 아닌 ba7000 이 사용되는 건가요? 정렬이 된 것 같은데, 어떤 기준으로 정렬이 된 것인지 궁금해서 댓글 답니다. ^^Anonymous
May 03, 2009
처음 덧글이 달린것 같네요 ^^ 관심 가져 주셔서 감사합니다. 00ba7963 자체가 물리 주소를 나타내는 것은 아니고 일부 bit 가 address 를 나타내는 것 입니다. 이번 예제에서는 00ba7 이 물리 Address 를 나타내고 Page Directory 가 4kb 단위 이므로 ba7000 를 가지고 다시 계산하게 됩니다. 즉 ba7000 이 Page Table 의 Start address 이고 2a 가 index 그리고 4 가 Page Table 의 각 Entry 의 길이가 되는 것 입니다.Anonymous
July 25, 2009
누구신가 했는데 미친감자님이시네요~ 책 많이 팔아 주세요 ㅋㅋ 그리고 요즘 블로깅이 뜸하시던데 팍팍 올려 주세요~ 좀 퍼갈께요^^ 책 출판 축하해요^^ 이번달에 살께요 사인해주세요