Linux arm64 Static Linear Map KASLR Bypass
Tip
AWSハッキングを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
概要
arm64向けにビルドされた Android カーネルは、ほぼ例外なく CONFIG_ARM64_VA_BITS=39(3レベルページング)と CONFIG_MEMORY_HOTPLUG=y を有効にしています。カーネル仮想空間が 512 GiB しかないため、将来ホットプラグされる RAM が単に上方向にマッピングを拡張できるように、Linux 開発者は linear map を可能な限り低いカーネル VA にアンカーすることを選びました。コミット 1db780bafa4c 以降、arm64 はその配置のランダム化すら行わなくなり、つまり次のことを意味します:
PAGE_OFFSET = 0xffffff8000000000が組み込まれています。PHYS_OFFSETはエクスポートされたmemstart_addrから取得され、stock Android デバイスでは事実上一定(今日では 0x80000000)です。
その結果、すべての物理ページは KASLR スライドに依存しない決定論的な linear-map 仮想アドレスを持つ:
#define phys_to_virt(p) (((unsigned long)(p) - 0x80000000UL) | 0xffffff8000000000UL)
もし攻撃者が物理アドレス(kernel object、PFN from /proc/pagemap、あるいはユーザー制御のページ)を取得または操作できるなら、randomized primary kernel mappingをleakすることなく、対応するカーネル仮想アドレスを即座に知ることができます。
memstart_addr の読み取りと変換の確認
memstart_addr は /proc/kallsyms にエクスポートされており、root権限のあるデバイス上、または任意の kernel-read primitive を介して読み取ることができます。Project Zero は Jann Horn の 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.
Deriving stable .data addresses on devices with a fixed kernel physbase
Many Pixels still decompress the kernel at phys_kernel_base = 0x80010000 on every boot (visible in /proc/iomem). Combining that with the static transform yields cross-reboot-stable addresses for any data symbol:
- Record the randomized kernel virtual address of
_stextand of your target symbol from/proc/kallsyms(or from the exactvmlinux). - Compute the offset:
offset = sym_virt - _stext_virt. - Add the static boot-time physbase:
phys_sym = 0x80010000 + offset. - Convert to a linear-map VA:
virt_sym = phys_to_virt(phys_sym).
Example (modprobe_path on a Pixel 9): offset = 0x1fe2398, phys = 0x81ff2398, virt = 0xffffff8001ff2398. After multiple reboots, bpf_arb_read 0xffffff8001ff2398 returns the same bytes, so exploit payloads can treat 0xffffff8000010000 as a synthetic, non-randomized base for all .data offsets.
This mapping is RW, so any primitive that can place attacker data in kernel virtual space (double free, UAF, non-paged heap write, etc.) can patch credentials, LSM hooks, or dispatch tables without ever leaking the true KASLR slide. The only limitation is that .text is mapped non-executable in the linear map, so gadget hunting still requires a traditional leak.
PFN spraying when the kernel physbase is randomized
Vendors such as Samsung randomize the kernel load PFN, but the static linear map is still abusable because PFN allocation is not fully random:
- Spray user pages:
mmap()~5 GiB, touch every page to fault it in. - Harvest PFNs: read
/proc/pagemapfor each page (or use another PFN leak) to collect the backing PFN list. - Repeat and profile: reboot, rerun 100×, build a histogram showing how often each PFN was attacker-controlled. Some PFNs are white-hot (allocated 100/100 times shortly after boot).
- Convert PFN → kernel VA:
phys = (pfn << PAGE_SHIFT) + offset_in_pagevirt = phys_to_virt(phys)
- Forge kernel objects in those pages and steer victim pointers (UAF, overflow, etc.) to the known linear-map addresses.
Because the linear map is identity-mapped RW memory, this technique lets you place fully attacker-controlled data at deterministic kernel VAs even when the real kernel base moves. Exploits can prebuild fake file_operations, cred, or refcount structures inside the sprayed pages and then pivot existing kernel pointers into them.
Practical workflow for arm64 Android exploits
- Info gathering
- Root or use a kernel read primitive to dump
memstart_addr,_stext, and the target symbol from/proc/kallsyms. - On Pixels, trust the static physbase from
/proc/iomem; on other devices, prepare the PFN profiler.
- Address calculation
- Apply the offset math above and cache the resulting linear-map VAs in your exploit.
- For PFN spraying, keep a list of “reliable” PFNs that repeatedly land in attacker memory.
- Exploit integration
- When an arbitrary write is available, directly patch targets such as
modprobe_path,init_cred, or security ops arrays at the precomputed addresses. - When only a heap corruption exists, craft fake objects in the known-supervised pages and repoint victim pointers to those linear-map VAs.
- Verification
- Use
bpf_arb_reador any safe read primitive to sanity-check that the computed address contains the expected bytes before destructive writes.
This workflow eliminates the KASLR-leak stage for data-centric kernel exploits on Android, which drastically lowers exploit complexity and improves reliability.
References
Tip
AWSハッキングを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。


