Linux arm64 Static Linear Map KASLR Bypass

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Vue d’ensemble

Les kernels Android compilés pour arm64 activent presque universellement CONFIG_ARM64_VA_BITS=39 (pagination à 3 niveaux) et CONFIG_MEMORY_HOTPLUG=y. Avec seulement 512 GiB d’espace virtuel kernel disponibles, les développeurs Linux ont choisi d’ancrer la linear map à la plus basse VA kernel possible afin que la RAM ajoutée à chaud puisse simplement étendre le mapping vers le haut. Depuis le commit 1db780bafa4c, arm64 n’essaie même plus de randomiser cet emplacement, ce qui signifie :

  • PAGE_OFFSET = 0xffffff8000000000 est compilé en dur.
  • PHYS_OFFSET provient de l’export memstart_addr, qui sur les appareils Android stock est effectivement constant (0x80000000 aujourd’hui).

En conséquence, chaque page physique possède une adresse virtuelle dans la linear-map déterministe indépendante du KASLR slide :

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

Si un attaquant peut apprendre ou influencer une adresse physique (objet kernel, PFN depuis /proc/pagemap, ou même une page contrôlée par l’utilisateur), il connaît instantanément l’adresse virtuelle kernel correspondante sans leak le mappage kernel primaire randomisé.

Lecture de memstart_addr et confirmation de la transformation

memstart_addr est exporté dans /proc/kallsyms et peut être lu sur des appareils rootés ou via n’importe quelle primitive de lecture kernel arbitraire. Project Zero a utilisé l’helper tracing-BPF de Jann Horn (bpf_arb_read) pour le dumper directement:

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

Les octets 00 00 00 80 00 00 00 00 confirment memstart_addr = 0x80000000. Une fois PAGE_OFFSET et PHYS_OFFSET fixés, la linear map arm64 est une transformée affine statique de toute adresse physique.

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

Beaucoup de Pixels décompressent encore le kernel à phys_kernel_base = 0x80010000 à chaque boot (visible dans /proc/iomem). Combinée à la transformée statique, cela fournit des adresses stables entre redémarrages pour n’importe quel symbole de données :

  1. Enregistrez l’adresse virtuelle randomisée de _stext et celle du symbole cible depuis /proc/kallsyms (ou depuis le vmlinux exact).
  2. Calculez l’offset : offset = sym_virt - _stext_virt.
  3. Ajoutez le physbase boot-time statique : phys_sym = 0x80010000 + offset.
  4. Convertissez en VA de la linear-map : virt_sym = phys_to_virt(phys_sym).

Exemple (modprobe_path sur un Pixel 9) : offset = 0x1fe2398, phys = 0x81ff2398, virt = 0xffffff8001ff2398. Après plusieurs redémarrages, bpf_arb_read 0xffffff8001ff2398 retourne les mêmes octets, donc les payloads d’exploit peuvent considérer 0xffffff8000010000 comme une base synthétique non-randomisée pour tous les offsets .data.

Cette mapping est RW, donc tout primitive capable de placer des données attaquantes dans l’espace virtuel kernel (double free, UAF, écriture heap non paginée, etc.) peut patcher des credentials, des hooks LSM, ou des dispatch tables sans jamais révéler le vrai KASLR slide. La seule limitation est que .text est mappé non-exécutable dans la linear map, donc la recherche de gadgets nécessite toujours un leak traditionnel.

PFN spraying when the kernel physbase is randomized

Des vendeurs comme Samsung randomisent le PFN de chargement du kernel, mais la linear map statique reste exploitable car l’allocation de PFN n’est pas totalement aléatoire :

  1. Spray user pages : mmap() ~5 GiB, touchez chaque page pour la provoquer en fault.
  2. Harvest PFNs : lisez /proc/pagemap pour chaque page (ou utilisez un autre PFN leak) pour collecter la liste des PFN sous-jacents.
  3. Repeat and profile : redémarrez, relancez 100×, construisez un histogramme montrant la fréquence à laquelle chaque PFN était contrôlé par l’attaquant. Certains PFN sont très chauds (alloc 100/100 fois peu après le boot).
  4. Convert PFN → kernel VA :
  • phys = (pfn << PAGE_SHIFT) + offset_in_page
  • virt = phys_to_virt(phys)
  1. Forge kernel objects in those pages et orientez les pointeurs victimes (UAF, overflow, etc.) vers les adresses connues de la linear-map.

Parce que la linear map est de la mémoire identity-mapped RW, cette technique permet de placer des données entièrement contrôlées par l’attaquant à des VAs kernel déterministes même quand la vraie base du kernel bouge. Les exploits peuvent préconstruire des file_operations factices, cred, ou des structures de refcount dans les pages sprayées puis pivoter des pointeurs kernel existants vers elles.

Practical workflow for arm64 Android exploits

  1. Info gathering
  • Obtenez root ou utilisez un kernel read primitive pour dumper memstart_addr, _stext, et le symbole cible depuis /proc/kallsyms.
  • Sur les Pixels, faites confiance au physbase statique dans /proc/iomem ; sur d’autres appareils, préparez le profiler PFN.
  1. Address calculation
  • Appliquez le calcul d’offset ci-dessus et mettez en cache les VA de la linear-map résultantes dans votre exploit.
  • Pour le PFN spraying, conservez une liste de PFN « fiables » qui retombent régulièrement dans la mémoire attaquante.
  1. Exploit integration
  • Quand un write arbitraire est disponible, patcher directement des cibles comme modprobe_path, init_cred, ou les security ops arrays aux adresses pré-calculées.
  • Quand seule une corruption heap existe, construisez des objets factices dans les pages connues et redirigez les pointeurs victimes vers ces VA de la linear-map.
  1. Verification
  • Utilisez bpf_arb_read ou tout primitive de lecture sûre pour vérifier que l’adresse calculée contient les octets attendus avant des écritures destructrices.

Ce workflow élimine l’étape de KASLR-leak pour les exploits kernel centrés sur les données sur Android, ce qui réduit drastiquement la complexité des exploits et améliore la fiabilité.

References

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks