본문 바로가기

reversing/Windows Driver

[PAE] Linear Address to Physical Address

SMALL

32bit 환경에서 활성화된 page만 가져오는 부분을 진행하다가 PAGE를 찾아가는데 어려움이 있어서 정리하려 한다.


작업 환경

 Win7 32bit [PAE on]

 Windbg


위와 같은 환경에서 calc.exe 선형 주소에서 물리 주소를 찾아가는 내용이다. 


하루 종일 삽질을 한 결과를 낳게한 CR4 를 확인하지 않아서이다.



1.  CR4 확인

여기서 5번째와 4번째 Bit를 확인하여야 한다.

5번째 PAE Bit는 PAE가 적용되어 있는지를 확인 할 수있는 BIT이다.

4번째 PSE Bit는 PAGE SIZE EXTENSION이 적용되어 있는지 확인 하는 것이다. 

1로 셋팅 되어 있으면 페이지 크기가 2MB 0로 셋팅되어 있으면 4KB이다.


Binary로 b11111001로 표현되어 있다. 4번째 bit 5번째 bit 모두 1로 셋팅되어 있었다.

PAE가 활성화 되어있고 PAGE SIZE가 2MB라는 것을 알 수 있다.


위와 같은 내용도 확인하지 않고 PAE off, PAGE SIZE 4KB내용을 기준으로 개발하니 개발이 되지 않았다. ㅠㅠㅠㅠ


2. Linear Address, CR3 확인

확인하고자 하는 Process[Calc.exe]의 VAD Root 내용을 기준으로 해당 Virtual Page Number를 확인하여서 Linear Address를 확인한다.

kd> !process 0 0

**** NT ACTIVE PROCESS DUMP ****

PROCESS 845c4a20  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000

    DirBase: 00185000  ObjectTable: 87e01b88  HandleCount: 545.

    Image: System


PROCESS 84c53d40  SessionId: 1  Cid: 0804    Peb: 7ffd8000  ParentCid: 06b8

    DirBase: 3eb7e4c0  ObjectTable: 95bbf1d8  HandleCount:  95.

    Image: calc.exe


위에서 DirBase는 해당 calc.exe의 CR3의 값을 가지고 있다.


kd> !vad 85399a70 

VAD     level      start      end    commit

84d91af8 ( 7)          10        1f         0 Mapped       READWRITE          Pagefile-backed section

84704480 ( 6)          20        25         0 Mapped       READONLY           Pagefile-backed section

857bfe90 ( 7)          30        33         0 Mapped       READONLY           Pagefile-backed section

...

86aacbf8 ( 5)         2a0       35f         6 Mapped  Exe  EXECUTE_WRITECOPY  \Windows\System32\calc.exe
...


Linear Address 는 0x2a0*0x1000 ~ 0x35f * 0x1000까지 표현되어 있다.

그리고 해당 선형주소가 진짜 맞는지 확인하기 위해서 exe 헤더인 MZ를 확인해 본다.


kd> .process /i 84c53d40  

You need to continue execution (press 'g' <enter>) for the context

to be switched. When the debugger breaks in again, you will be in

the new process context

calc.exe로 context switching을 해주고 해당 메모리의 값을 확인한다!!


kd> dd 2a0*1000
002a0000  00905a4d 00000003 00000004 0000ffff
002a0010  000000b8 00000000 00000040 00000000
002a0020  00000000 00000000 00000000 00000000
002a0030  00000000 00000000 00000000 000000d8
002a0040  0eba1f0e cd09b400 4c01b821 685421cd
002a0050  70207369 72676f72 63206d61 6f6e6e61
002a0060  65622074 6e757220 206e6920 20534f44
002a0070  65646f6d 0a0d0d2e 00000024 00000000

kd> da 2a0*1000
002a0000  "MZ."

값을보니 맞는것 같다.

정리하면 Linear Address : 0x2a0000이고 Cr3 : 0x3eb7e4c0 인 것을 확인하였다.


3. [PAE ON] PTE[Page Table Entry], PDE[Page Directory Entry], PDPE[Page Directory Pointer Entry]

위와 같은 그림으로 Physical Address의 PAGE를 찾아간다. 

그리고 PDPE와 PDE, PTE는 4byte가 아니라 8byte의 요소를 가진다.

하지만 PFN은 단지 4ibt만 확장되어 있다. 


4. 따라가기

kd> .formats 2a0*1000

Evaluate expression:

  Hex:     002a0000

  Decimal: 2752512

  Octal:   00012400000

  Binary:  [00] [000000 001] [01010 0000] [0000 00000000]

[2bit] [9bit] [9bit] [12bit] 와 같이 나누어 보면


PDPE 는 0번째 Index

PDE  는 1번째 Index

PTE  는  0xa번째 Index

Offset은 0x00 이다.


kd> !dq cr3   //Page Directory Pointer Table BASE ADDRESS CR3 = 0x3eb7e4c0 

#3eb7e4c0 00000000`09f98801 00000000`01519801

#3eb7e4d0 00000000`0af1a801 00000000`2ba9b801

#3eb7e4e0 00000000`8597e500 00000000`34b3b801

#3eb7e4f0 00000000`362bc801 00000000`332bd801


그리고 0번째 Index이다.  

00000000`09f98801 --> 해당 값에서 PFN0x009F98이다. pae가 꺼져 있으면 0x09f98이지만 4bit 확장되었기 때문이다.


kd> !dq 0x009F98*0x1000 --> PAGE DIRECTORY의 Base주소이다. 

# 9f98000 00000000`08619867 00000000`2ee98867

# 9f98010 00000000`337d2867 00000000`28c65867

# 9f98020 00000000`00000000 00000000`00000000

# 9f98030 00000000`00000000 00000000`00000000


Directory는 1번째 Index이다.

kd> !dq 0x009F98*0x1000 + 0x8*0x1 --> Directory Base Address에서 1번째 Index
# 9f98008 00000000`2ee98867 00000000`337d2867
# 9f98018 00000000`28c65867 00000000`00000000
# 9f98028 00000000`00000000 00000000`00000000

00000000`2ee98867에서 PFN은 0x02ee98이다.


kd> !dq 0x02ee98*0x1000 --> PAGE Table의 Base주소이다. 

#2ee98000 80000000`37df1847 00000000`00000000

#2ee98010 00000000`00000000 00000000`00000000

#2ee98020 00000000`00000000 00000000`00000000

#2ee98030 00000000`00000000 00000000`00000000



Table은 0xa0번째 Index이다.

kd> !dq 0x02ee98*0x1000 + 0x8*0xa0 --> PAGE Table의 Base주소에서 0xa0번째 인덱스
#2ee98500 80000000`12682025 00000000`3b440025
#2ee98510 00000000`16d44025 00000000`16d45005
#2ee98520 00000000`17f06005 00000000`124c7005
#2ee98530 00000000`17088005 00000000`139c9005
#2ee98540 00000000`18eca025 00000000`182cb005


이제 물리 주소의 BASE ADDRESS를 구할수 있고 OFFSET을 더하면 최종 PAGE를 구할수있다.

PFN = 0x012682

Offset = 0x0

최종적으로 확인하면!!!!

kd> !dd 0x12682*0x1000 + 0x00

#12682000 00905a4d 00000003 00000004 0000ffff

#12682010 000000b8 00000000 00000040 00000000

#12682020 00000000 00000000 00000000 00000000

#12682030 00000000 00000000 00000000 000000d8

#12682040 0eba1f0e cd09b400 4c01b821 685421cd

#12682050 70207369 72676f72 63206d61 6f6e6e61

#12682060 65622074 6e757220 206e6920 20534f44

#12682070 65646f6d 0a0d0d2e 00000024 00000000






LIST

'reversing > Windows Driver' 카테고리의 다른 글

[Device Stack] 디바이스 스택  (0) 2017.07.25
MDL(Memory Descriptor List)  (0) 2017.07.21
DPC (Deferred Procedure Calls)  (0) 2017.07.20
PAGED_CODE()  (0) 2016.10.11
DRIVER OBJECT 구조체  (0) 2016.08.11