물리 메모리 분석을 위해서는 가상 주소를 물리 주소로의 변환이 필수적입니다. 당연하게도, 커널 혹은 유저 레벨에서의 모든 주소 표현은 가상 주소로 이루어집니다. 즉, 표현된 모든 주소를 물리 주소로 변환해야 물리 메모리 덤프에서의 오프셋을 구할 수 있습니다.

Non-PAE 환경에서의 가상-물리 주소 변환 과정
위의 그림은 Non-PAE(Physical Address Extension:물리주소확장)환경에서의 물리 주소 변환 과정을 나타냅니다. 그림을 통해 보면 생각보다 상당히 간단합니다. PAE는 XP 이상의 운영체제에서 일반적인 경우에 활성화 되므로 앞으로의 설명은 PAE 환경을 기준으로 하겠습니다.

PAE 환경에서의 가상-물리 주소 변환 과정
현재 사용되는 대부분의 운영체제는 메모리 사용의 효율성을 위해 페이징Paging 기법을 사용하며, 관리의 최소 단위로 페이지Page를 사용합니다. 일반적으로 페이지는 4096 바이트의 크기를 가지며, 일부의 경우 큰 페이지Large Page, 즉 2-4MB 이상의 크기를 가질 수 있습니다.

위의 그림을 참조해보면 가상 주소는 비트 단위로 2-4개로 나뉘어지며, 각 단위는 페이지 디렉토리Page Directory, 페이지 테이블Page Table, 혹은 실제 요구된 바이트 주소를 나타내면서 여러 단계를 거치게 됩니다. (PAE 환경의 경우 페이지 디렉토리 포인터 테이블Page-Directory-Pointer-Table을 추가로 거치게됩니다.)

우선 페이지 디렉토리(이하 PD) 혹은 페이지 디렉토리 포인터 테이블(이하 PDPT)을 가리키기 위해 CR3 레지스터가 사용됩니다. 이 값을 Directory Table Base라 부르는데, DTB는 _EPROCESS.Pcr.DirectoryTableBase 필드에도 존재합니다. (이와 관련한 내용은 다음에 정리해 포스팅합니다.)

CR3 레지스터의 DTB로 PDPT 또는 PD의 물리 주소를 가리키는데, PDPT, PD 혹은 PT는 8 바이트 단위의 엔트리Entry의 집합으로 표현됩니다. 이 엔트리의 구조는 아래 그림과 같습니다. 

Page Directory Entry, Page Table Entry의 구조
각 엔트리의 최하위비트는 다음 단계의 페이지가 메모리에 존재하는지를 나타내며, 1인 경우에만 물리 메모리 내의 주소로 변환할 수 있습니다. 또한 앞서 설명한 것과 같이, 페이지는 큰 페이지 크기를 가지는 경우가 존재하며, 이는 PDE의 7번째 비트(0부터 시작하는 인덱스)인 PS 플래그에 따라 구분됩니다. 31:12비트는 다음 단계의 페이지 프레임 넘버Page Frame Number를 표현합니다.

설명이 길어지면서 조금 난해하게 되었는데요, 실제로 가상 주소를 물리 주소로 변환하는 과정을 WinDbg를 통해 보여드리겠습니다. 변환할 주소는 커널 베이스 주소인 0x804d9000입니다.

----------------------------------------------------------------------------

0: kd> db 804d9000 
804d9000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............
804d9010  b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
804d9020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
804d9030  00 00 00 00 00 00 00 00-00 00 00 00 e0 00 00 00  ................
804d9040  0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68  ........!..L.!Th
804d9050  69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f  is program canno
804d9060  74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20  t be run in DOS 
804d9070  6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00  mode....$.......

// 가상 주소 804d9000는 커널 베이스임을 나타내고 있습니다. DOS 헤더가 보이시죠?

0: kd> .formats 804d9000 
Evaluate expression:
  Hex:     804d9000
  Decimal: -2142400512
  Octal:   20023310000
  Binary:  10000000 01001101 10010000 00000000
  Chars:   .M..
  Time:    ***** Invalid
  Float:   low -7.12299e-039 high -1.#QNAN
  Double:  -1.#QNAN

// 가상 주소를 이진수로 변환하였습니다. 
// 이를 주소 변환에 쉽게 이용할 수 있도록 다시 나누어보았습니다.
// 10 000000010 011011001 000000000000
//  2         2        D9            0 
// PDPTE    PDE       PTE  Byte Offset

0: kd> r cr3
cr3=00b37000
0: kd> dd /p 00b37000 L8
00b37000  00b38001 00000000 00b39001 00000000
00b37010  00b3a001 00000000 00b3b001 00000000

// 앞서 구한 PDPTE Number가 2이기 때문에 00b3a001를 이용합니다. 
// 31:12 비트가 PD의 주소를 나타내기 때문에 00b3a000가 PD의 주소가 됩니다.

0: kd> dd /p 00b3a000+8*2 L2
00b3a010  004009e3 00000000
0: kd> .formats 004009e3 
Evaluate expression:
  Hex:     004009e3
  Decimal: 4196835
  Octal:   00020004743
  Binary:  00000000 01000000 00001001 11100011
  Chars:   .@..
  Time:    Wed Feb 18 22:47:15 1970
  Float:   low 5.88102e-039 high 0
  Double:  2.07351e-317

// 00b3a000에 엔트리 크기인 8과 PDE Number인 2을 곱한 값을 더하여 PDE를 구합니다.
// PDE를 보기 쉽게 나누면 다음과 같습니다.
// 00000000010000000000 100111100011
//                  400
//        Address of PT        Flags
// 최하위 비트가 1이기 때문에 Valid하며, PS 플래그가 1이기 때문에 큰 페이지입니다.
// 실제 페이지의 주소는 0x400에 페이지 기본 크기인 0x1000을 곱하여 구합니다.
// 아참, 큰 페이지이니 실제 요구된 바이트 주소를 다시 계산해야겠네요.
// 10 000000010 011011001000000000000
//  2         2                 D9000
// PDPTE    PDE           Byte Offset
// 이제 요구된 페이지의 주소인 0x400000에 0xD9000을 더하면 우리가 원하는 물리 주소가 됩니다.

0: kd> db /p 4d9000
004d9000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............
004d9010  b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
004d9020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
004d9030  00 00 00 00 00 00 00 00-00 00 00 00 e0 00 00 00  ................
004d9040  0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68  ........!..L.!Th
004d9050  69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f  is program canno
004d9060  74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20  t be run in DOS 
004d9070  6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00  mode....$.......
0: kd> db 804d9000 
804d9000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............
804d9010  b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
804d9020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
804d9030  00 00 00 00 00 00 00 00-00 00 00 00 e0 00 00 00  ................
804d9040  0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68  ........!..L.!Th
804d9050  69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f  is program canno
804d9060  74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20  t be run in DOS 
804d9070  6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00  mode....$.......

// 물리 주소와 가상 주소로 확인한 커널 베이스가 같음을 확인할 수 있습니다.




Leave a Reply