주소에는 다음과 같은 기준이 사용
- Code
- Stack
- Data
Code의 몇 번지, Data의 몇 번지가 정확한 표현
Code, Stack, Data 별로 별도의 영역이 지정
Program을 동작(해석)하는 역할은 CPU(Microprocessor)가 담당하며, 해석되는 항목 중 하나가 Address
CPU 안에는 Address를 이해하기 위해서 몇 가지 Register가 위치 : CS(Code Segment), SS(Stack Segment), DS(Data Segment) Register
Address 표현 할 때는 Segment Register를 반드시 활용해야 함
CS의 0x1234 offset, SS의 0x5678 offset과 같은 표현이 정확한 주소 표현
어떤 Segment는 정의한 후 Base Address로부터 얼마나 떨어져 있는지 Offset으로 표현
위 그림은 실제로 CS:[1234]와 같은 문법으로 표현 → 이러한 표현 방식을 Segmentation
Segmentation 방식을 채택하는 목적은 Segment간 서로 다른 성격 때문에 Protected Mode를 사용하기 위함
예를 들어, Code Segment 영역을 넘어서는 위치로 Control을 변경하는 경우 제한
Segment에는 Base Address와 Size 정의가 필요
예를 들어, DS:[10]은 DS의 Base Address에 offset인 10을 더한 값이 실제 Address → 이를 Linear Address(선형 주소)라고 부름
DS:[offset] = DS의 Base Address + Offset = Linear Address
Windows의 사용 방식(x64 기준)
x64에서는 Offset 또한 64bit까지 표현 가능
문제는 CS, DS, SS + Offset(64bit) 를 계산한 값인 Linear Address도 64bit가 될 수 있는데 Windows는 Offset과 Linear Address가 모두 64bit를 선택
이 말인 즉슨, CS, DS, SS의 Base Address를 0x0으로 이용
즉, Offset과 Linear Address를 동일한 값으로 계산
CS, DS, SS가 아닌 다른 Segment Register들(FS, GS, ES)은 Base Address가 0x0이 아닐 수 있음
CS:[123456789ABCDEF0] = DS:[123456789ABCDEF0] = SS:[123456789ABCDEF0] = 123456789ABCDEF0(Linear Address)
※ 결국, Virtual Address는 Segmentation Unit을 통해 Linear Address로 해석되며, Windows의 경우에는 Segment의 Base Address를 0x으로 사용하기 때문에 Virtual Address와 Linear Address가 동일
예제) Segment Register와 종류 확인 방법
3: kd> r rax=000000000003f801 rbx=ffff8f8035180180 rcx=0000000000000001 rdx=000000b000000000 rsi=0000000000000002 rdi=ffff8f8035190100 rip=fffff80751e79601 rsp=fffff88600c45748 rbp=0000000000000000 r8=000000000000002a r9=ffffd282297c6000 r10=0000000000000014 r11=0000000000000000 r12=ffffd2822a285100 r13=0000000000000000 r14=00000000915f8d00 r15=00000000915acea1 iopl=0 nv up di pl nz na pe nc cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00000002 nt!DbgBreakPointWithStatus+0x1: fffff807`51e79601 c3 ret 3: kd> dg 0x10 P Si Gr Pr Lo Sel Base Limit Type l ze an es ng Flags ---- ----------------- ----------------- ---------- - -- -- -- -- -------- 0010 00000000`00000000 00000000`00000000 Code RE Ac 0 Nb By P Lo 0000029b 0: kd> dg 18 P Si Gr Pr Lo Sel Base Limit Type l ze an es ng Flags ---- ----------------- ----------------- ---------- - -- -- -- -- -------- 0018 00000000`00000000 00000000`00000000 Data RW Ac 0 Bg By P Nl 00000493 0: kd> dg 2b P Si Gr Pr Lo Sel Base Limit Type l ze an es ng Flags ---- ----------------- ----------------- ---------- - -- -- -- -- -------- 002B 00000000`00000000 00000000`ffffffff Data RW Ac 3 Bg Pg P Nl 00000cf3 |
CPU가 Memory와 주변장치를 읽고 쓸 수 있기 위해서는 Physical Address(=Real Address)가 필요
CPU 바깥 쪽을 접근하기 위해서는 Physical Address 사용
Virtual Address(=Linear Address)는 CPU 내에서만 사용되는 주소
그렇다면, Virtual Address(=Linear Address)가 어떻게 Physical Address로 변환되는지를 확인해야 함
이전 과정을 Segmentation이라고 불렀다면, Virtual Address → Physical Address로 변환하는 과정을 Paging이라고 부름
x64 에서는 64bit를 모두 Address로 해석할 수 없고, 48bit 까지만 해석 가능하며 나머지 16bit는 부호 확장 개념으로 사용
따라서, 64bit라고 하면, Address Range가 0000 0000 0000 0000 ~ FFFF FFFF FFFF FFFF
이를 구분하기 위해서 47번째 bit가 0이면 양수, 1이면 음수로 구분하여 관리
47번째 bit 까지 구분하면 Address Range는 다음과 같이 더 상세하게 구분
0x0000 0000 0000 0000 ~ 0x0000 7FFF FFFF FFFF : 47번째 bit가 0인 경우 → User Level Address Space
0xFFFF 8000 0000 0000 ~ 0xFFFF FFFF FFFF FFFF : 47번째 bit가 1인 경우 → Kernel Level Address Space
※ Windows OS의 경우에는 Interlocked Opcode(CPU 수준의 동기화)를 지원하기 위해서 실제로는 44bit까지만 지원
간단한 예제)
Linear Address(Virtual Address)가 0x1234(16bit)인 경우,
실제 예제)
Page map level 4를 가리키는 CR3 Format
https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
※ ESXi OS인 VMKernel은 다를까?
ESXi OS인 VMKernel도 Windows OS와 다를 수 없다. 기존 x64 CPU Architecture 기반으로 동작하기 때문에 동일한 방식으로 이해할 수 없음
그렇다면, CPU(Microprocessor)는 왜 이렇게 Address 변환 과정을 가지는가?
- 서로 다른 Process로부터 각자의 Physical Memory 보호 목적 : CR3 Register가 가리키는 Table 주소를 Process 별로 다르게 하여 각 Process 별 사용하는 Physical Memory 보호
- 실제 보유하는 Physical Memory 보다 더 큰 공간을 요구하는 Program을 동작시키기 위해서
PTE는 Page Table Entry로 Physical Memory의 Page Number를 획득하기 위해 사용하는 Entry
PTE 상세 Field
PTE 중 가장 중요한 Field는 Valid Field
Valid Field가 0이면 Page Fault Exception 발생, 사용되고 있는 PTE는 1
Page Frame Number의 경우에는 Windows가 별도로 관리하는 PFN Database에서 참조하여 PTE 구성
Process의 Memory 사용 현황 확인
VAD(Virtual Address Descriptor) 사용
1: kd> !process 0 1 notepad.exe PROCESS ffff9f87130ac080 SessionId: 2 Cid: 110c Peb: bc6b7ee000 ParentCid: 0d8c DirBase: 55d1a000 ObjectTable: ffffcb83a638e540 HandleCount: 295. Image: notepad.exe VadRoot ffff9f8713b63090 Vads 122 Clone 0 Private 767. Modified 8. Locked 0. DeviceMap ffffcb83a465cb90 Token ffffcb83a64c1770 ElapsedTime 00:01:36.761 UserTime 00:00:00.000 KernelTime 00:00:00.000 QuotaPoolUsage[PagedPool] 298544 QuotaPoolUsage[NonPagedPool] 17112 Working Set Sizes (now,min,max) (4994, 50, 345) (19976KB, 200KB, 1380KB) PeakWorkingSetSize 4921 VirtualSize 2101433 Mb PeakVirtualSize 2101435 Mb PageFaultCount 5096 MemoryPriority FOREGROUND BasePriority 8 CommitCharge 921 1: kd> .process ffff9f87130ac080 Implicit process is now ffff9f87`130ac080 WARNING: .cache forcedecodeuser is not enabled 1: kd> .thread ffff9f871310e080 Implicit thread is now ffff9f87`1310e080 ## Start, End에 있는 값은 12bit(offset)을 제외한 Virtual Page Number ## 예를 들어서 Start가 17ec0이고 End가 17ec0인 경우 실제 Start Address는 17ec0 000이고, End Address는 17ec0 fff --> 이 경우는 총 1 Page를 의미 1: kd> !vad ffff9f8713b63090 VAD Level Start End Commit ffff9f8712d384e0 6 17ec0 17ec0 1 Private READWRITE ffff9f8713a21280 5 7ffe0 7ffe0 1 Private READONLY ffff9f8713a21370 4 7ffe3 7ffe3 1 Private READONLY ffff9f8713a21500 5 bc6b4e0 bc6b55f 20 Private READWRITE ffff9f8713a21140 3 bc6b600 bc6b7ff 11 Private READWRITE ffff9f8713a21a00 5 bc6b900 bc6b97f 20 Private READWRITE ffff9f8712d36730 4 bc6b980 bc6b9ff 20 Private READWRITE ffff9f8712d36a50 6 bc6ba00 bc6ba7f 20 Private READWRITE ffff9f8712d38030 5 bc6bb00 bc6bb7f 20 Private READWRITE ffff9f8713b62870 2 23857ec0 23857ecf 0 Mapped READWRITE Pagefile section, shared commit 0x10 ... ffff9f8713b65d90 4 7ffaeee10 7ffaeee3d 3 Mapped Exe EXECUTE_WRITECOPY \Windows\System32\imm32.dll ffff9f8713b63130 5 7ffaeee70 7ffaef05c 16 Mapped Exe EXECUTE_WRITECOPY \Windows\System32\ntdll.dll Total VADs: 122, average level: 6, maximum depth: 7 Total private commit: 0x304 pages (3088 KB) Total shared commit: 0x15eb pages (22444 KB) |
Virtual Address에 있는 Memory 내용 확인
PTE 찾기
※ PTE는 64bit
1: kd> !pte 17ec0000 VA 0000000017ec0000 PXE at FFFF884422110000 PPE at FFFF884422000000 PDE at FFFF8844000005F8 PTE at FFFF8800000BF600 >>> contains 8A00000004593867 contains 0000000000000000 pfn 4593 ---DA--UW-V contains 0000000000000000 not valid 1: kd> dq FFFF8800000BF600 ffff8800`000bf600 81000000`5930a847 00000000`00000000 ffff8800`000bf610 00000000`00000000 00000000`00000000 ffff8800`000bf620 00000000`00000000 00000000`00000000 ffff8800`000bf630 00000000`00000000 00000000`00000000 ffff8800`000bf640 00000000`00000000 00000000`00000000 ffff8800`000bf650 00000000`00000000 00000000`00000000 ffff8800`000bf660 00000000`00000000 00000000`00000000 ffff8800`000bf670 00000000`00000000 00000000`00000000 1: kd> dt nt!_MMPTE ffff8800`000bf600 -r2 +0x000 u : <unnamed-tag> +0x000 Long : 0x81000000`5930a847 +0x000 VolatileLong : 0x81000000`5930a847 +0x000 Hard : _MMPTE_HARDWARE >>> +0x000 Valid : 0y1 >>> +0x000 Dirty1 : 0y1 +0x000 Owner : 0y1 +0x000 WriteThrough : 0y0 +0x000 CacheDisable : 0y0 +0x000 Accessed : 0y0 +0x000 Dirty : 0y1 +0x000 LargePage : 0y0 +0x000 Global : 0y0 +0x000 CopyOnWrite : 0y0 +0x000 Unused : 0y0 +0x000 Write : 0y1 +0x000 PageFrameNumber : 0y000000000000000001011001001100001010 (0x5930a) +0x000 ReservedForHardware : 0y0000 +0x000 ReservedForSoftware : 0y0000 +0x000 WsleAge : 0y0001 +0x000 WsleProtection : 0y000 +0x000 NoExecute : 0y1 ... |
Physical Address로 변환 및 조회
※ Virtual Address에 있는 Memory 내용과 Physical Address에 있는 Memory 내용이 동일한 것을 확인
[Virtual Address] 0000000017ec0 000 [Page Table Entry] 81000000`5930a847 [Physical Address] 12번째 bit부터 39번째 bit 아래 005930a 00`5930a 847(12bit) 00`5930a + Virtual Address의 12bit(000) 00`5930a000 1: kd> !db 00`5930a000 #5930a000 32 00 00 00 f8 3d 8d 60-28 81 a7 4a a4 28 f5 5e 2....=.`(..J.(.^ #5930a010 49 26 72 91 00 00 08 00-0b 00 00 00 54 00 65 00 I&r.........T.e. #5930a020 78 00 74 00 20 00 45 00-64 00 69 00 74 00 6f 00 x.t. .E.d.i.t.o. #5930a030 72 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 r............... #5930a040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ #5930a050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ #5930a060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ #5930a070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ |
'Debugging > Windows' 카테고리의 다른 글
Thread State Transition (0) | 2023.06.05 |
---|---|
Registry (0) | 2023.05.16 |
Security (0) | 2023.05.03 |
Objects and Handles (2) | 2023.04.15 |
프로세스(EPROCESS, KPROCESS, PEB, HANDLE...) - (2) (0) | 2023.02.05 |