Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
일반적으로 가상 메모리를 물리 메모리로 변환해서 확인해야 할 경우가 거의 없지만 공부하는 차원에서 직접 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
누구신가 했는데 미친감자님이시네요~ 책 많이 팔아 주세요 ㅋㅋ 그리고 요즘 블로깅이 뜸하시던데 팍팍 올려 주세요~ 좀 퍼갈께요^^ 책 출판 축하해요^^ 이번달에 살께요 사인해주세요