Linux arm64 Static Linear Map KASLR Bypass

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Pregled

Android kerneli izgrađeni za arm64 gotovo univerzalno omogućavaju CONFIG_ARM64_VA_BITS=39 (3-level paging) i CONFIG_MEMORY_HOTPLUG=y. Sa samo 512 GiB dostupnog kernel virtualnog prostora, Linux developeri su odlučili da pričvrste linear map na najniži mogući kernel VA tako da buduća hot-plugovana RAM memorija može jednostavno proširiti mapiranje naviše. Od commita 1db780bafa4c, arm64 više ne pokušava da randomizuje to postavljanje, što znači:

  • PAGE_OFFSET = 0xffffff8000000000 je kompajlirano u kernel.
  • PHYS_OFFSET se dobija iz eksportovanog memstart_addr, koji na stock Android uređajima praktično ostaje konstantan (0x80000000 danas).

Kao posledica, svaka fizička stranica ima determinističku linear-map virtuelnu adresu koja je nezavisna od KASLR slide-a:

#define phys_to_virt(p) (((unsigned long)(p) - 0x80000000UL) | 0xffffff8000000000UL)

Ako napadač može da sazna ili utiče na fizičku adresu (kernel object, PFN from /proc/pagemap, or even a user-controlled page), on/ona odmah zna odgovarajuću kernel virtual address bez leaking the randomized primary kernel mapping.

Čitanje memstart_addr i potvrđivanje transformacije

memstart_addr je eksportovan u /proc/kallsyms i može se pročitati na rooted devices ili putem bilo kog arbitrary kernel-read primitive. Project Zero je koristio Jann Horn’s tracing-BPF helper (bpf_arb_read) da ga direktno dump-uje:

grep memstart /proc/kallsyms
# ... obtains memstart_addr virtual address
./bpf_arb_read <addr_of_memstart_addr> 8

The bytes 00 00 00 80 00 00 00 00 confirm memstart_addr = 0x80000000. Once PAGE_OFFSET and PHYS_OFFSET are pinned, the arm64 linear map is a static affine transform of any physical address.

Deriving stable .data addresses on devices with a fixed kernel physbase

Mnogi Pixel uređaji i dalje dekompresuju kernel na phys_kernel_base = 0x80010000 pri svakom bootu (vidljivo u /proc/iomem). Kombinacija toga sa statičnim transformom daje adrese za bilo koji data simbol koje su stabilne preko reboot-a:

  1. Zabeležite randomizovanu kernel virtuelnu adresu _stext i ciljane simbole iz /proc/kallsyms (ili iz tačnog vmlinux).
  2. Izračunajte offset: offset = sym_virt - _stext_virt.
  3. Dodajte statički boot-time physbase: phys_sym = 0x80010000 + offset.
  4. Konvertujte u linear-map VA: virt_sym = phys_to_virt(phys_sym).

Primer (modprobe_path na Pixel 9): offset = 0x1fe2398, phys = 0x81ff2398, virt = 0xffffff8001ff2398. Nakon više reboot-ova, bpf_arb_read 0xffffff8001ff2398 vraća iste bajtove, tako da exploit payload-i mogu tretirati 0xffffff8000010000 kao sintetičku, nerenomizovanu bazu za sve .data offset-e.

Ovo mapiranje je RW, tako da bilo koji primitive koji može postaviti podatke napadača u kernel virtuelni prostor (double free, UAF, non-paged heap write, itd.) može zakrpatchi kredencijale, LSM hook-ove ili dispatch tabele bez ikada otkrivanja pravog KASLR slide-a. Jedino ograničenje je što je .text mapiran kao non-executable u linear map-u, pa pronalaženje gadget-a i dalje zahteva tradicionalni leak.

PFN spraying when the kernel physbase is randomized

Vendors kao što su Samsung randomizuju kernel load PFN, ali statični linear map je i dalje zloupotrebljiv zato što PFN alokacija nije potpuno random:

  1. Spray user pages: mmap() ~5 GiB, touch svakog page-a da se zatim fault-uje.
  2. Harvest PFNs: čitajte /proc/pagemap za svaku stranicu (ili koristite drugi PFN leak) da sakupite listu backing PFN-ova.
  3. Repeat and profile: reboot, pokrenite ponovo 100×, napravite histogram koji pokazuje koliko često je svaki PFN bio pod kontrolom napadača. Neki PFN-ovi su izuzetno učestali (alocirani 100/100 puta ubrzo posle boota).
  4. Convert PFN → kernel VA:
  • phys = (pfn << PAGE_SHIFT) + offset_in_page
  • virt = phys_to_virt(phys)
  1. Forge kernel objects in those pages i usmerite victim pokazivače (UAF, overflow, itd.) ka poznatim linear-map adresama.

Pošto je linear map identity-mapped RW memorija, ova tehnika omogućava postavljanje potpuno kontrolisanih podataka napadača na determinističke kernel VA čak i kada se pravi kernel base pomera. Exploiti mogu unapred izgraditi lažne file_operations, cred ili refcount strukture unutar sprayed stranica i zatim pivotirati postojeće kernel pokazivače na njih.

Practical workflow for arm64 Android exploits

  1. Info gathering
  • Root-ujte ili koristite kernel read primitive da dump-ujete memstart_addr, _stext, i ciljani simbol iz /proc/kallsyms.
  • Na Pixel uređajima, verujte statičkom physbase iz /proc/iomem; na drugim uređajima, pripremite PFN profiler.
  1. Address calculation
  • Primijenite gore navedenu offset matematiku i keširajte rezultujuće linear-map VA u exploit-u.
  • Za PFN spraying, držite listu “reliable” PFN-ova koji se ponavljaju i završavaju u memoriji napadača.
  1. Exploit integration
  • Kada je arbitrary write dostupan, direktno patch-ujte ciljeve kao što su modprobe_path, init_cred, ili security ops nizovi na prethodno izračunatim adresama.
  • Kada postoji samo heap korupcija, kreirajte lažne objekte u poznatim nadgledanim stranicama i repoint-ujte victim pokazivače na te linear-map VA.
  1. Verification
  • Koristite bpf_arb_read ili bilo koji safe read primitive da sanity-check-ujete da izračunata adresa sadrži očekivane bajtove pre destruktivnih write-ova.

Ovaj workflow eliminiše KASLR-leak fazu za data-centrične kernel exploite na Android-u, što značajno smanjuje kompleksnost exploita i poboljšava pouzdanost.

References

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks