Linux arm64 Static Linear Map KASLR Bypass

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Огляд

Ядра Android, зібрані для arm64, майже повсюдно вмикають CONFIG_ARM64_VA_BITS=39 (3-level paging) та CONFIG_MEMORY_HOTPLUG=y. Маючи в наявності лише 512 GiB віртуального простору ядра, розробники Linux вирішили заякорити linear map на найнижчому можливому VA ядра, щоб майбутня додаткова оперативна пам’ять могла просто розширити мапінг вгору. З комітом 1db780bafa4c arm64 взагалі більше не намагається рандомізувати це розміщення, що означає:

  • PAGE_OFFSET = 0xffffff8000000000 is compiled in.
  • PHYS_OFFSET is sourced from the exported memstart_addr, which on stock Android devices is effectively constant (0x80000000 today).

Внаслідок цього кожна фізична сторінка має детермінований віртуальний адрес у linear-map, який незалежний від KASLR slide:

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

Якщо зловмисник може дізнатися або вплинути на фізичну адресу (kernel object, PFN з /proc/pagemap, або навіть сторінку під контролем користувача), він миттєво знає відповідну віртуальну адресу ядра без leaking the randomized primary kernel mapping.

Читання memstart_addr та підтвердження перетворення

memstart_addr експортується в /proc/kallsyms і його можна прочитати на рутованих пристроях або через будь-який довільний примітив читання ядра. Project Zero використали Jann Horn’s tracing-BPF helper (bpf_arb_read) для безпосереднього його зчитування:

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.

Отримання стабільних адрес .data на пристроях з фіксованим kernel physbase

У багатьох Pixel ядро все ще розпаковується до phys_kernel_base = 0x80010000 при кожному завантаженні (видно в /proc/iomem). Комбінування цього з статичним перетворенням дає крос-перезавантажувально-стабільні адреси для будь-якого data символу:

  1. Занотуйте рандомізовану віртуальну адресу ядра _stext і цільового символу з /proc/kallsyms (або з точного vmlinux).
  2. Обчисліть зсув: offset = sym_virt - _stext_virt.
  3. Додайте статичний boot-time physbase: phys_sym = 0x80010000 + offset.
  4. Перетворіть в лінійну VA: virt_sym = phys_to_virt(phys_sym).

Приклад (modprobe_path на Pixel 9): offset = 0x1fe2398, phys = 0x81ff2398, virt = 0xffffff8001ff2398. Після кількох перезавантажень bpf_arb_read 0xffffff8001ff2398 повертає ті самі байти, тож експлойт-пейлоади можуть трактувати 0xffffff8000010000 як синтетичну, нерандомізовану базу для всіх .data зсувів.

Ця мапа є RW, тому будь-який примітив, що може розмістити дані атакуючого у віртуальному просторі ядра (double free, UAF, non-paged heap write тощо), може підправляти credentials, LSM hooks або dispatch tables без фактичного розкриття реального KASLR slide. Єдина обмеження — .text в лінійній мапі промаплений як non-executable, тож gadget hunting все ще вимагає традиційного leak.

PFN spraying коли kernel physbase рандомізований

Вендори, такі як Samsung, рандомізують PFN завантаження ядра, але статичну лінійну мапу все одно можна зловживати, бо розподіл PFN не є повністю випадковим:

  1. Spray user pages: mmap() ~5 GiB, доступіться до кожної сторінки, щоб спричинити page fault.
  2. Harvest PFNs: читайте /proc/pagemap для кожної сторінки (або використайте інший PFN leak) щоб зібрати список бекінґ PFN.
  3. Repeat and profile: перезавантажте, запустіть знову 100×, збудуйте гістограму, яка показує як часто кожен PFN контролювався атакуючим. Деякі PFN гарячі (allocated 100/100 разів незабаром після 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 і спрямовуйте вказівники цілі (UAF, overflow тощо) на відомі linear-map адреси.

Оскільки linear map є identity-mapped RW пам’яттю, ця техніка дозволяє розмістити повністю контрольовані атакуючим дані в детерміністичних kernel VA навіть коли реальна база ядра рухається. Експлойти можуть попередньо побудувати фейкові file_operations, cred або refcount структури всередині sprayed сторінок і потім переприсвоїти існуючі вказівники ядра на них.

Практичний workflow для arm64 Android експлойтів

  1. Info gathering
  • Отримайте root або використайте kernel read primitive щоб здампити memstart_addr, _stext та цільовий символ з /proc/kallsyms.
  • На Pixel довіряйтесь статичному physbase з /proc/iomem; на інших пристроях підготуйте PFN profiler.
  1. Address calculation
  • Застосуйте наведені вище математичні операції і кешуйте отримані linear-map VA в вашому експлойті.
  • Для PFN spraying зберігайте список “надійних” PFN, які повторно потрапляють у пам’ять атакуючого.
  1. Exploit integration
  • Коли доступний arbitrary write, безпосередньо підправляйте цілі такі як modprobe_path, init_cred або security ops масиви за попередньо обчисленими адресами.
  • Коли є лише heap corruption, створюйте фейкові об’єкти в відомих сторінках-під наглядом і перенаправляйте вказівники жертви на ці linear-map VA.
  1. Verification
  • Використовуйте bpf_arb_read або будь-який безпечний read primitive щоб перевірити, що обчислена адреса містить очікувані байти перед деструктивним записом.

Цей workflow усуває стадію KASLR-leak для data-орієнтованих kernel експлойтів на Android, що радикально знижує складність експлойтів і підвищує надійність.

References

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks