Virtual Memory & Page Tables
Virtual memory subsystem quαΊ£n lΓ½ translation giα»―a virtual addresses (mΓ code dΓΉng) vΓ physical addresses (RAM thαΊt). Page tables lΓ data structure chα»©a mapping nΓ y. Bugs trong VM subsystem dαΊ«n ΔαΊΏn physical read/write β primitive mαΊ‘nh nhαΊ₯t.
TαΊ‘i Sao CαΊ§n Hiα»u VM
- Physical UAF (PUAF) exploits khai thΓ‘c bugs trong VM subsystem
- Page table manipulation lΓ cΓ‘ch bypass PPL/SPTM
- physrw (physical read/write) ΔαΊ‘t Δược qua dangling page table entries
- KASLR dα»±a vΓ o VM β hiα»u VM = hiα»u cΓ‘ch leak kernel base
- pmap code lΓ target cho nhiα»u kernel bugs
ARM64 Address Translation
Translation Table Walk
Virtual Address (48-bit):
ββββββββββ¬βββββββββ¬βββββββββ¬βββββββββ¬βββββββββββββββ
β L1 idx β L2 idx β L3 idx β Page β Page offset β
β [47:39]β [38:30]β [29:25]β [24:14]β [13:0] β
β 9 bits β 9 bits β 5 bits β 11 bitsβ 14 bits β
ββββββββββ΄βββββββββ΄βββββββββ΄βββββββββ΄βββββββββββββββ
(iOS dΓΉng 16KB pages β offset = 14 bits)
Translation:
TTBR1_EL1 (kernel) hoαΊ·c TTBR0_EL1 (user)
β
βΌ
L1 Table ββ[L1 idx]βββ L1 Entry β L2 Table base
β
βΌ
L2 Table ββ[L2 idx]βββ L2 Entry β L3 Table base
β
βΌ
L3 Table ββ[L3 idx]βββ L3 Entry
β
βΌ
Physical Page
+ offset
β
βΌ
Physical Address
Page Table Entry (PTE) Format
L3 Page Table Entry (arm64, 16KB granule):
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 63 59β58 55β54 52β51 14β13 12β11 10β9 8β...β
β ignored β SW β res β Output Addr β res β AP β SH β...β
β by HW β use β β (phys page) β β β β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β ...β7 6β5β4 2β1β0β
β β resβ βMAIRβ βVβ
β β β βidx β βaβ
β β β β β βlβ
β β β β β βiβ
β β β β β βdβ
βββββββββββββββββββββββ
Key fields:
Bit 0 (Valid) : 1 = entry valid, 0 = fault on access
Bits 4:2 (AttrIdx): Memory attribute index (MAIR register)
Bits 7:6 (AP) : Access Permission
00 = EL1 R/W, EL0 no access
01 = EL1 R/W, EL0 R/W
10 = EL1 R/O, EL0 no access
11 = EL1 R/O, EL0 R/O
Bits 9:8 (SH) : Shareability (Inner/Outer/None)
Bit 10 (AF) : Access Flag (set by HW on first access)
Bit 54 (XN) : Execute Never (EL1)
Bit 53 (PXN) : Privileged Execute Never
Bits 51:14 : Physical address of page (shifted)
Address Permissions Summary
| AP[7:6] | EL1 (kernel) | EL0 (user) |
|---|---|---|
| 00 | Read/Write | No access |
| 01 | Read/Write | Read/Write |
| 10 | Read-only | No access |
| 11 | Read-only | Read-only |
XNU Virtual Memory Subsystem
VM Map
// vm_map = address space representation
struct vm_map {
struct vm_map_header hdr; // Sorted list of vm_map_entry
pmap_t pmap; // Machine-dependent page tables
vm_map_size_t size; // Virtual size
// ...
};
// vm_map_entry = one contiguous mapping
struct vm_map_entry {
struct vm_map_entry *prev, *next; // Doubly-linked list
vm_map_offset_t vme_start; // Start virtual address
vm_map_offset_t vme_end; // End virtual address
vm_prot_t protection; // Current protection
vm_prot_t max_protection; // Maximum allowed protection
// ...
union {
vm_object_t vme_object; // Backing object (file, anonymous)
};
};
Pmap (Physical Map)
// pmap = machine-dependent page table management
struct pmap {
tt_entry_t *tte; // Top-level page table pointer
uint64_t asid; // Address Space ID (for TLB)
// ...
};
Key pmap functions:
// Create mapping: virtual β physical
pmap_enter_options(pmap, va, pa, prot, fault_type, flags, options);
// Remove mapping
pmap_remove(pmap, start, end);
// Change protection
pmap_protect(pmap, start, end, prot);
// Query mapping
pmap_find_phys(pmap, va); // Returns physical page number
TLB (Translation Lookaside Buffer)
TLB = cache cho page table entries. CPU khΓ΄ng walk page tables mα»i memory access β nΓ³ check TLB trΖ°α»c.
CPU needs virtual β physical translation
βββ Check TLB (fast path)
β βββ TLB hit: use cached translation
β βββ TLB miss: walk page tables (slow path)
β βββ Insert result into TLB
βββ Access physical memory
TLB invalidation (TLBI instruction) cαΊ§n thiαΊΏt khi:
- Thay Δα»i page table entries
- Context switch (ASID change)
Bug pattern: Kernel thay Δα»i PTE nhΖ°ng quΓͺn invalidate TLB β stale translation vαΊ«n dΓΉng β security violation.
Physical Use-After-Free (PUAF)
Concept
1. Process A maps virtual address VA β physical page P
2. Bug: kernel frees physical page P nhΖ°ng KHΓNG remove mapping tα»« process A's page tables
3. Kernel reallocates physical page P cho purpose khΓ‘c (kernel object, page table, ...)
4. Process A vαΊ«n Δα»c/ghi P thΓ΄ng qua VA β Δα»c/ghi kernel data!
PUAF β physrw Escalation
NαΊΏu page P trα» thΓ nh Level 3 page table:
βββ Process A ghi vΓ o P = modify page table entries
βββ TαΊ‘o PTE mα»i trα» ΔαΊΏn BαΊ€T Kα»² physical address
βββ Map toΓ n bα» DRAM vΓ o address space
βββ Full physical read/write!
NαΊΏu page P trα» thΓ nh kernel object:
βββ Process A ghi vΓ o P = corrupt kernel object
βββ Escalate to kread/kwrite
Defenses (iOS 17+ SPTM)
SPTM ensures:
- Physical pages track their "type" (user, kernel, page table, ...)
- User pages CANNOT be reallocated as kernel pages until next boot
- Page table modifications MUST go through SPTM (EL2)
β PUAF from user β kernel is blocked
β PUAF user β user still possible (less useful)
Page Lifecycle
Free page pool
β
ββ vm_page_grab() β Allocate physical page
β ββ pmap_enter() β Map into address space
β
ββ pmap_remove() β Remove mapping
β ββ vm_page_free() β Return to free pool
β
ββ PUAF bug: vm_page_free() WITHOUT pmap_remove()
β Page returned to free pool but still mapped!
Kernel Memory Regions
βββββββββββββββββββββββββββββββββββββββββββ
β Kernel Virtual Address Space β
β β
β βββββββββββββββββββββββ β
β β Kernelcache β Fixed mapping β
β β (__TEXT, __DATA) β KASLR slide β
β βββββββββββββββββββββββ β
β βββββββββββββββββββββββ β
β β Zone maps β Dynamic β
β β (kalloc, ipc, ...) β β
β βββββββββββββββββββββββ β
β βββββββββββββββββββββββ β
β β Kernel map β General β
β β (large allocations) β purpose β
β βββββββββββββββββββββββ β
β βββββββββββββββββββββββ β
β β MMIO regions β Device β
β β (hardware registers)β mappings β
β βββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββ
TΓ i NguyΓͺn
- XNU source:
osfmk/vm/vm_map.c,osfmk/arm64/pmap.c - Apple β Memory and Virtual Memory
- Project Zero β The Core of Apple is PPL
- Alfie CG β Kernel Exploit Guide (VM exploitation sections)
- ARM Architecture Reference Manual β Chapter D5 (Address Translation)
BΓ i TαΊp
- Manual page table walk: Cho virtual address, TTBR value, vΓ page table dumps β compute physical address by hand
- Read pmap.c: Trace
pmap_enter_options()β hiα»u mα»i parameter lΓ m gΓ¬ - Analyze PUAF exploit: Δα»c kfd source code, trace PUAF primitive (smith/landa/physpuppet)
- Draw memory map: Cho 1 running process, dΓΉng
vmmap(macOS) vαΊ½ full address space layout - Compute PTE values: Cho physical address + desired permissions, construct PTE value by hand