세그먼테이션(가상주소->선형주소
변환과정) 및
페이징(선형주소->물리주소
변환과정)
테스트
대상
가상주소: kbdclass.sys 의 DriverObject.DriverName.Buffer
kd> !drvobj kbdclass
Driver object (866bc030) is for:
\Driver\Kbdclass
Driver Extension List: (id , addr)
|
Device Object list:
866b6030 865c6968
kd> dt _driver_object 866bc030
nt!_DRIVER_OBJECT
+0x000 Type : 4
+0x002 Size : 168
+0x004 DeviceObject : 0x866b6030 _DEVICE_OBJECT
+0x008 Flags : 0x12
+0x00c DriverStart : 0xf7b8b000
+0x010 DriverSize : 0x5c80
+0x014 DriverSection : 0x865c7258
+0x018 DriverExtension : 0x866bc0d8 _DRIVER_EXTENSION
+0x01c DriverName : UNICODE_STRING "\Driver\Kbdclass"
+0x024 HardwareDatabase : 0x80691a90 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
+0x028 FastIoDispatch : (null)
+0x02c DriverInit : 0xf7b8f610 long kbdclass!GsDriverEntry+0
+0x030 DriverStartIo : (null)
+0x034 DriverUnload : (null)
+0x038 MajorFunction : [28] 0xf7b8bdd0 long kbdclass!KeyboardClassCreate+0
|
kd> dt _UNICODE_STRING (866bc030 + 01c)
nt!_UNICODE_STRING
"\Driver\Kbdclass"
+0x000 Length : 0x20
+0x002 MaximumLength : 0x20
+0x004 Buffer : 0xe182d4c0 "\Driver\Kbdclass"
|
가상주소 0xe182d4c0 체크
결과
kd> db 0xe182d4c0
e182d4c0 5c 00 44 00 72 00 69 00-76 00 65 00 72 00 5c 00 \.D.r.i.v.e.r.\.
e182d4d0 4b 00 62 00 64 00 63 00-6c 00 61 00 73 00 73 00 K.b.d.c.l.a.s.s.
e182d4e0 05 04 08 0c 50 70 73 75-48 b8 82 e1 08 d0 46 e1 ....PpsuH.....F.
e182d4f0 18 c8 46 e1 01 00 00 00-70 1a 83 e1 a8 63 82 e1 ..F.....p....c..
e182d500 18 00 18 00 88 b8 82 e1-67 5c 02 48 00 00 00 00 ........g\.H....
e182d510 3c 27 cc f7 a8 27 cc f7-1c 27 cc f7 d1 84 4f 80 <'...'...'....O.
e182d520 08 04 01 00 4f 62 53 71-01 04 03 0c 47 67 6c 73 ....ObSq....Ggls
e182d530 ea 4f 00 00 01 00 00 00-00 00 ea 4f 80 ba 01 80 .O.........O....
|
가상주소 0xe182d4c0 를
선형주소로
변환
위
주소공간은 DataSection에
존재하며 DS (데이터
세그먼트) 레지스터와
조합
됨
kd> r ds
ds=00000023
kd> .formats 0x23
Evaluate expression:
Hex: 00000023
Decimal: 35
Octal: 00000000043
Binary: 00000000 00000000 00000000 00100011
Chars: ...#
Time: Thu Jan 01 09:00:35 1970
Float: low 4.90454e-044 high 0
Double: 1.72923e-322
|
세그먼트
레지스터는 16-bit 크기로
아래의
포맷으로
사용
00000000 00100011
의
경우 [00000000 00100] [0] [11] 과
같이
설정됨
kd> .formats 0y0000000000100
Evaluate expression:
Hex: 00000004 // GDT INDEX
Decimal: 4
Octal: 00000000004
Binary: 00000000 00000000 00000000 00000100
Chars: ....
Time: Thu Jan 01 09:00:04 1970
Float: low 5.60519e-045 high 0
Double: 1.97626e-323
|
GDT 확인
kd> r gdtr (or !pcr)
gdtr=8003f000
|
kd> dq 8003f000 + 4 * 8 L1 (gdtr + 인덱스 * sizeof(세그먼트
디스크립터))
8003f020 00cff300`0000ffff
|
GDT의
엔트리 (Segment Descriptor) 포맷
위의
내용을 dg 를
통해
쉽게
볼
수
있음
kd> dg 0x23 (ds)
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0023 00000000 ffffffff Data RW Ac 3 Bg Pg P Nl 00000cf3
|
선형주소는 Base + 가상주소의
형태가
되며, 여기서 Base 는 0 이므로
가상주소 = 선형주소가
됨
(윈도우는
일부
세그먼트레지스터(FS 등)를
제외하고는 Base 가 0이므로, 일반적으로
가상주소 = 선형주소의
식이
성립)
계산된
선형주소:
- 가상주소 : 0xe182d4c0
- 선형주소 : 0xe182d4c0
선형주소의
포맷
- [31 - 22: 페이지
디렉토리
인덱스] [21 - 12: 페이지
테이블
인덱스] [11 - 0: 페이지프레임
오프셋]
선형주소 0xe182d4c0 에서
페이지디렉토리
인덱스, 페이지테이블
인덱스, 페이지프레임
오프셋
계산
kd> .formats 0xe182d4c0
Evaluate expression:
Hex: e182d4c0
Decimal: -511519552
Octal: 34140552300
Binary: 11100001 10000010 11010100 11000000
Chars: ....
Time: ***** Invalid
Float: low -3.01676e+020 high -1.#QNAN
Double: -1.#QNAN
|
(i)[11100001 10] (ii)[000010 1101] (iii)[0100 11000000] 와
같이
나뉘며,
(i) 0y1110000110 (0x386), 페이지
디렉토리
테이블은 4바이트
요소를
가지므로, 실
오프셋은 0x386 * 4 = 0xe18
PAGE DIRECTORY INDEX : 0x386 (offset 0xe18)
(ii) 0y0000101101 (0x2d), 페이지
테이블은 4바이트
요소를
가지므로, 실
오프셋은 0x2d * 4 = 0xb4
PAGE TABLE INDEX : 0x2d (offset 0xb4)
(iii) 0y010011000000 (0x4c0)
PAGE FRAME OFFSET : 0x4c0
- PAGE DIRECTORY BASE 계산
CR3 레지스터에
저장되어
있음(컨텍스트
스위칭이
발생될때마다
각
프로세스의 Page directory base 값이 CR3에
저장)
PAGE DIRECTORY BASE: 00039000
- PAGE TABLE BASE 계산
Page directory base가 00039000이고, 위의 (i)에서 page directory offset 이 0xe18 이므로
kd> dd /p 00039000 + e18 L1 // 이후부터
참조되는
메모리주소는
물리주소이므로 /p 옵션을
사용
00039e18 08edb163
|
여기서, 페이지
디렉토리
및
테이블의
요소는
아래와
같은
포맷을
가짐
[31 - 12: PFN (페이지
프레임
번호) [11 - 0: 기타]
31 - 12 bit 가 BASE 를
가리키게
되므로
PAGE TABLE BASE : 0x08edb000
- PAGE FRAME BASE 계산
Page table base가 08edb000이고,
page table offset 이 0xb4 이므로
kd> dd /p 0x08edb000 + b4 L1
08edb0b4 08f0d163
|
마찬가지로, 31 - 12 비트만
보면
PAGE FRAME BASE : 0x08f0d000
- PHYSICAL ADDRESS 계산
Page frame base로부터 offset은 0x4c0 이므로,
TARGET PHYSICAL ADDRESS : 0x08f0d4c0
kd> db /p 0x08f0d4c0
08f0d4c0 5c 00 44 00 72 00 69 00-76 00 65 00 72 00 5c 00 \.D.r.i.v.e.r.\.
08f0d4d0 4b 00 62 00 64 00 63 00-6c 00 61 00 73 00 73 00 K.b.d.c.l.a.s.s.
08f0d4e0 05 04 08 0c 50 70 73 75-48 b8 82 e1 08 d0 46 e1 ....PpsuH.....F.
08f0d4f0 18 c8 46 e1 01 00 00 00-70 1a 83 e1 a8 63 82 e1 ..F.....p....c..
08f0d500 18 00 18 00 88 b8 82 e1-67 5c 02 48 00 00 00 00 ........g\.H....
08f0d510 3c 27 cc f7 a8 27 cc f7-1c 27 cc f7 d1 84 4f 80 <'...'...'....O.
08f0d520 08 04 01 00 4f 62 53 71-01 04 03 0c 47 67 6c 73 ....ObSq....Ggls
08f0d530 ea 4f 00 00 01 00 00 00-00 00 ea 4f 80 ba 01 80 .O.........O....
|
* 참고 *
nt!NtCreateFile 등의
함수는
실제
물리메모리에
존재하는
것이
아니라 exe파일(ntoskrnl.exe) 자체가
가상메모리
영역에
매핑된
것이므로, 위의
과정으로
확인
불가능