Linux arm64 Static Linear Map KASLR Bypass

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Resumen

Los kernels de Android compilados para arm64 casi universalmente habilitan CONFIG_ARM64_VA_BITS=39 (paginación de 3 niveles) y CONFIG_MEMORY_HOTPLUG=y. Con solo 512 GiB de espacio virtual del kernel disponibles, los desarrolladores de Linux escogieron anclar el linear map en la VA del kernel más baja posible para que la RAM añadida mediante hot-plug pueda simplemente extender el mapeo hacia arriba. Desde el commit 1db780bafa4c, arm64 ni siquiera intenta aleatorizar esa ubicación, lo que significa:

  • PAGE_OFFSET = 0xffffff8000000000 está compilado.
  • PHYS_OFFSET se obtiene del memstart_addr exportado, que en dispositivos Android de stock es efectivamente constante (0x80000000 hoy).

Como consecuencia, cada página física tiene una dirección virtual determinista en el linear-map que es independiente del KASLR slide:

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

Si un atacante puede conocer o influir en una dirección física (objeto del kernel, PFN from /proc/pagemap, o incluso una página controlada por el usuario), saben inmediatamente la dirección virtual del kernel correspondiente sin leaking el mapeo primario aleatorizado del kernel.

Leyendo memstart_addr y confirmando la transformación

memstart_addr se exporta en /proc/kallsyms y puede leerse en dispositivos rooteados o mediante cualquier primitiva arbitraria de lectura del kernel. Project Zero usó el tracing-BPF helper de Jann Horn (bpf_arb_read) para volcarlo directamente:

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

Los bytes 00 00 00 80 00 00 00 00 confirman memstart_addr = 0x80000000. Una vez que PAGE_OFFSET y PHYS_OFFSET están fijados, el arm64 linear map es una transformación afín estática de cualquier dirección física.

Derivar direcciones .data estables en dispositivos con physbase de kernel fijo

Muchos Pixel todavía descomprimen el kernel en phys_kernel_base = 0x80010000 en cada arranque (visible en /proc/iomem). Combinar eso con la transformación estática produce direcciones estables entre reinicios para cualquier símbolo de datos:

  1. Registra la dirección virtual del kernel aleatorizada de _stext y de tu símbolo objetivo desde /proc/kallsyms (o desde el vmlinux exacto).
  2. Calcula el offset: offset = sym_virt - _stext_virt.
  3. Suma el physbase estático a tiempo de arranque: phys_sym = 0x80010000 + offset.
  4. Convierte a una VA del linear map: virt_sym = phys_to_virt(phys_sym).

Ejemplo (modprobe_path en un Pixel 9): offset = 0x1fe2398, phys = 0x81ff2398, virt = 0xffffff8001ff2398. Después de múltiples reinicios, bpf_arb_read 0xffffff8001ff2398 devuelve los mismos bytes, por lo que los exploit payloads pueden tratar 0xffffff8000010000 como una base sintética no aleatorizada para todos los offsets de .data.

Este mapeo es RW, por lo que cualquier primitiva que pueda colocar datos del atacante en el espacio virtual del kernel (double free, UAF, non-paged heap write, etc.) puede parchear credenciales, LSM hooks o tablas de despacho sin que se produzca un leak del verdadero KASLR slide. La única limitación es que .text está mapeado como no ejecutable en el linear map, por lo que la búsqueda de gadgets aún requiere un leak tradicional.

PFN spraying when the kernel physbase is randomized

Vendedores como Samsung randomizan el PFN de carga del kernel, pero el static linear map sigue siendo abusable porque la asignación de PFN no es totalmente aleatoria:

  1. Spray user pages: mmap() ~5 GiB, toca cada página para forzar su page fault.
  2. Harvest PFNs: lee /proc/pagemap para cada página (o usa otro PFN leak) para coleccionar la lista de PFNs de respaldo.
  3. Repeat and profile: reinicia, ejecuta de nuevo 100×, y construye un histograma que muestre con qué frecuencia cada PFN estuvo controlado por el atacante. Algunos PFNs son white-hot (asignados 100/100 veces poco después del arranque).
  4. Convert PFN → kernel VA:
  • phys = (pfn << PAGE_SHIFT) + offset_in_page
  • virt = phys_to_virt(phys)
  1. Forge kernel objects in those pages y dirige punteros víctimas (UAF, overflow, etc.) hacia las direcciones conocidas del linear-map.

Debido a que el linear map es memoria identity-mapped y RW, esta técnica permite colocar datos completamente controlados por el atacante en VAs deterministas del kernel incluso cuando la base real del kernel se mueve. Los exploits pueden preconstruir file_operations, cred o estructuras de refcount falsas dentro de las páginas sprayadas y luego pivotar punteros del kernel existentes hacia ellas.

Practical workflow for arm64 Android exploits

  1. Info gathering
  • Obtén root o usa una primitiva de lectura del kernel para volcar memstart_addr, _stext, y el símbolo objetivo desde /proc/kallsyms.
  • En Pixels, confía en el physbase estático de /proc/iomem; en otros dispositivos, prepara el PFN profiler.
  1. Address calculation
  • Aplica la aritmética de offset anterior y almacena en caché las VAs del linear-map resultantes en tu exploit.
  • Para PFN spraying, mantén una lista de PFNs “reliable” que repetidamente caen en la memoria del atacante.
  1. Exploit integration
  • Cuando haya un arbitrary write disponible, parchea directamente objetivos como modprobe_path, init_cred, o arrays de security ops en las direcciones precomputadas.
  • Cuando solo exista una heap corruption, fabrica objetos falsos en las páginas conocidas y reorienta los punteros víctimas hacia esas VAs del linear-map.
  1. Verification
  • Usa bpf_arb_read o cualquier primitiva de lectura segura para verificar que la dirección calculada contiene los bytes esperados antes de realizar escrituras destructivas.

Este flujo de trabajo elimina la etapa de KASLR-leak para exploits del kernel centrados en datos en Android, lo que reduce drásticamente la complejidad del exploit y mejora la fiabilidad.

References

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks