Skip to content

Exploit crashes on ARM64 (Ubuntu 24.04, kernel 6.8.0-106) #53

Description

@4dollar4

Environment

  • OS: Ubuntu 24.04 (ARM64)
  • Kernel: 6.8.0-106-generic
  • Hardware: QEMU Virtual Machine

Summary

To run the exploit on ARM64, I replaced the tiny shellcode with an ARM64 equivalent and adjusted the payload length accordingly. The exploit then fails with a kernel oops at the rxrpc stage.

Reproduction

  1. Replace the embedded x86_64 tiny shellcode with an ARM64 equivalent and adjust the payload-length constant.
  2. Run ./exploit -v as a regular user (uid=1000).

Expected

A root shell.

Observed

  • During the /usr/bin/su overwrite step, [su] post-write verify failed (target unchanged) is printed — the write does not stick.
  • During the rxrpc spray, the kernel oopses at flush_dcache_page+0x18/0x58.
  • Call path: flush_dcache_pageskcipher_walk_donecrypto_pcbc_encrypt [pcbc]rxkad_secure_packet [rxrpc]rxrpc_send_datarxrpc_sendmsgsendmsg(2).
  • The faulting address fffffe00021538c8 is in the ARM64 vmemmap region, suggesting a corrupted struct page pointer reaches flush_dcache_page (pgd=0, level-0 translation fault).

Why I think the shellcode itself isn’t the problem

With AppArmor disabled, the same build produces a root shell as expected. That suggests the replaced ARM64 shellcode itself is correct, and the failure occurs in the rxrpc spray / SU overwrite path under ARM64 + AppArmor enabled. Whether this is an rxrpc bug, or whether the ARM64 + AppArmor combination causes the spray to land on the wrong page, I cannot say definitively.

Code modifications I made for the ARM64 port

For reference, here are the diffs I applied to exp.c. None of them touch the rxrpc / kmalloc-spray logic itself.

1. Payload structure and size (x86_64 → ARM64 Tiny ELF)

  • Original: x86_64 shellcode targeting /usr/bin/su combined with a minimal ELF header.
  • Modified: The shell_elf array now contains ARM64 root shellcode combined with an ARM64 Tiny ELF header crafted to satisfy the kernel loader. Because ARM64 uses fixed 4-byte instructions, the payload is larger, so PAYLOAD_LEN was bumped to 240 bytes.

2. File-overwrite verification logic (inside su_lpe_main)

  • Original: After overwriting the page cache, the code reads the byte at offset 0x78 (entry point) and checks it against the first byte of the x86_64 shellcode.
  • Modified: The verification bytes were changed to the ARM64 opcode bytes 0xe0 and 0x03.
/* [modified] ARM64 entry-point opcode verification (0xe0, 0x03) */
if (verify_byte(TARGET_PATH, ENTRY_OFFSET, 0xe0) != 0 ||
    verify_byte(TARGET_PATH, ENTRY_OFFSET + 1, 0x03) != 0) {

3. “Already patched” marker check

  • Original: Before running the exploit, the su_marker array (used to detect whether the system has already been compromised) held x86_64 instruction bytes.
  • Modified: The marker array was replaced wholesale so that it matches the first 8 bytes of the injected ARM64 shellcode.

Full log

ubuntu@poc-vm:~$ ./exploit -v
[su] installed 60 xfrm SAs
[su] wrote 240 bytes to /usr/bin/su starting at 0x0
[su] post-write verify failed (target unchanged)
=== rxrpc/rxkad LPE EXPLOIT (uid=1000 → root) ===
[+] K_A found after 37782 iters in 0.01s
[+] K_B found after 381323 iters in 0.07s
[+] K_C found after 26935928 iters in 4.85s
[ 6625.068388] Unable to handle kernel paging request at virtual address fffffe00021538c8
[ 6625.069626] Mem abort info:
[ 6625.070239]   ESR = 0x0000000096000004
[ 6625.070455]   EC = 0x25: DABT (current EL), IL = 32 bits
[ 6625.070823]   SET = 0, FnV = 0
[ 6625.071212]   EA = 0, S1PTW = 0
[ 6625.071336]   FSC = 0x04: level 0 translation fault
[ 6625.071594] Data abort info:
[ 6625.071749]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[ 6625.072229]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[ 6625.072691]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[ 6625.073198] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000131b1d000
[ 6625.074379] [fffffe00021538c8] pgd=0000000000000000, p4d=0000000000000000
[ 6625.075427] Internal error: Oops: 0000000096000004 [#2] SMP
[ 6625.076666] Modules linked in: fcrypt pcbc rxrpc ip6_udp_tunnel udp_tunnel authencesn authenc echainiv esp4 xfrm_user xfrm_algo algif_skcipher af_alg tls isofs binfmt_misc nls_iso8859_1 sch_fq_codel dm_multipath efi_pstore nfnetlink dmi_sysfs ip_tables x_tables autofs4 btrfs blake2b_generic raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor xor_neon raid6_pq libcrc32c raid1 raid0 crct10dif_ce polyval_ce polyval_generic ghash_ce sm4 sha3_ce sha2_ce sha256_arm64 sha1_ce aes_neon_bs aes_neon_blk aes_ce_blk aes_ce_cipher
[ 6625.088058] CPU: 1 PID: 1850 Comm: exploit Tainted: G      D            6.8.0-106-generic #106-Ubuntu
[ 6625.090266] Hardware name: QEMU QEMU Virtual Machine, BIOS edk2-stable202408-prebuilt.qemu.org 08/13/2024
[ 6625.092876] pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
[ 6625.094826] pc : flush_dcache_page+0x18/0x58
[ 6625.095579] lr : skcipher_walk_done+0x188/0x308
[ 6625.096262] sp : ffff8000854e34d0
[ 6625.096746] x29: ffff8000854e34d0 x28: ffff0000c8629800 x27: 0000000000000008
[ 6625.097795] x26: ffff0000c86298c0 x25: ffff0000c60a60c0 x24: ffff0000c53fa880
[ 6625.098905] x23: 0000000000000008 x22: 0000000000000008 x21: 0000000000000000
[ 6625.100073] x20: 0000000000000000 x19: ffff8000854e3510 x18: ffff800083a7b090
[ 6625.101130] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
[ 6625.102231] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
[ 6625.103516] x11: 0000000000000000 x10: 0000000000000000 x9 : ffff80008082b090
[ 6625.104785] x8 : 0000000000000000 x7 : 0000000000000000 x6 : 0000000000000000
[ 6625.106065] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000
[ 6625.107230] x2 : 0000000000000000 x1 : 0000000000000670 x0 : fffffe00021538c0
[ 6625.108289] Call trace:
[ 6625.108640]  flush_dcache_page+0x18/0x58
[ 6625.109302]  skcipher_walk_done+0x188/0x308
[ 6625.109888]  crypto_pcbc_encrypt+0xe8/0x168 [pcbc]
[ 6625.110754]  crypto_skcipher_encrypt+0x12c/0x198
[ 6625.111519]  rxkad_secure_packet+0x104/0x2b8 [rxrpc]
[ 6625.112388]  rxrpc_send_data+0x23c/0x658 [rxrpc]
[ 6625.112881]  rxrpc_do_sendmsg+0x1d8/0x398 [rxrpc]
[ 6625.113496]  rxrpc_sendmsg+0x134/0x1a8 [rxrpc]
[ 6625.114098]  __sock_sendmsg+0x80/0x108
[ 6625.114720]  ____sys_sendmsg+0x28c/0x348
[ 6625.115266]  ___sys_sendmsg+0xbc/0x140
[ 6625.115813]  __sys_sendmsg+0x94/0x120
[ 6625.116429]  __arm64_sys_sendmsg+0x30/0x60
[ 6625.116997]  invoke_syscall+0x7c/0x130
[ 6625.117579]  el0_svc_common.constprop.0+0x4c/0x140
[ 6625.118461]  do_el0_svc+0x28/0x58
[ 6625.119084]  el0_svc+0x40/0x1c0
[ 6625.119560]  el0t_64_sync_handler+0x148/0x158
[ 6625.120403]  el0t_64_sync+0x1b0/0x1b8
[ 6625.120877] Code: d503233f f800865e a9bf7bfd 910003fd (f9400401)
[ 6625.121532] ---[ end trace 0000000000000000 ]---
Segmentation fault

Questions

Is ARM64 within the officially intended scope of this PoC, or is it x86_64-only? If specific debug data would help (KASAN build output, particular sysctls, etc.), let me know and I can rerun and attach it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions