CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/spec/modules/payloads/singles/osx/aarch64/exec_spec.rb
Views: 11791
1
require 'rspec'
2
3
RSpec.describe 'singles/osx/aarch64/exec' do
4
include_context 'Msf::Simple::Framework#modules loading'
5
6
let(:subject) do
7
load_and_create_module(
8
module_type: 'payload',
9
reference_name: 'osx/aarch64/exec',
10
ancestor_reference_names: [
11
'singles/osx/aarch64/exec'
12
]
13
)
14
end
15
let(:cmd) { nil }
16
let(:datastore_values) { { 'CMD' => cmd } }
17
18
before(:each) do
19
subject.datastore.merge!(datastore_values)
20
end
21
22
describe '#create_aarch64_string_in_stack' do
23
context 'when the string is calc.exe' do
24
it 'generates the required stack' do
25
expected = <<~'EOF'
26
// Next 8 bytes of string: "CALC.EXE"
27
movz x1, #0x4143 // "AC"
28
movk x1, #0x434c, lsl #16 // "CL"
29
movk x1, #0x452e, lsl #32 // "E."
30
movk x1, #0x4558, lsl #48 // "EX"
31
str x1, [x9], #8 // Store x1 on x9-stack and increment by 8
32
33
mov x1, x9 // Store the current stack location in the target register
34
sub x1, x1, #8 // Update the target register to point to base of the string
35
EOF
36
expect(subject.create_aarch64_string_in_stack('CALC.EXE', registers: { destination: :x1, stack: :x9 })).to match_table expected
37
end
38
end
39
40
context 'when the string is /bin/bash -c "echo abcdef1234"' do
41
it 'generates the required stack' do
42
expected = <<~'EOF'
43
// Next 8 bytes of string: "/bin/bas"
44
movz x1, #0x622f // "b/"
45
movk x1, #0x6e69, lsl #16 // "ni"
46
movk x1, #0x622f, lsl #32 // "b/"
47
movk x1, #0x7361, lsl #48 // "sa"
48
str x1, [x9], #8 // Store x1 on x9-stack and increment by 8
49
// Next 8 bytes of string: "h -c \"ec"
50
movz x1, #0x2068 // " h"
51
movk x1, #0x632d, lsl #16 // "c-"
52
movk x1, #0x2220, lsl #32 // "\" "
53
movk x1, #0x6365, lsl #48 // "ce"
54
str x1, [x9], #8 // Store x1 on x9-stack and increment by 8
55
// Next 8 bytes of string: "ho abcde"
56
movz x1, #0x6f68 // "oh"
57
movk x1, #0x6120, lsl #16 // "a "
58
movk x1, #0x6362, lsl #32 // "cb"
59
movk x1, #0x6564, lsl #48 // "ed"
60
str x1, [x9], #8 // Store x1 on x9-stack and increment by 8
61
// Next 8 bytes of string: "f1234\""
62
movz x1, #0x3166 // "1f"
63
movk x1, #0x3332, lsl #16 // "32"
64
movk x1, #0x2234, lsl #32 // "\"4"
65
str x1, [x9], #8 // Store x1 on x9-stack and increment by 8
66
67
mov x1, x9 // Store the current stack location in the target register
68
sub x1, x1, #32 // Update the target register to point to base of the string
69
EOF
70
expect(subject.create_aarch64_string_in_stack('/bin/bash -c "echo abcdef1234"', registers: { destination: :x1, stack: :x9 })).to match_table expected
71
end
72
end
73
end
74
75
describe '#generate' do
76
# Verify that the compile command is called with the expected asm string
77
def expect_result_to_match(expected_asm)
78
allow(subject).to receive(:compile_aarch64).and_wrap_original do |original, asm|
79
expect(asm).to match_table(expected_asm)
80
compiled_asm = original.call asm
81
expect(compiled_asm.length).to be > 0
82
'mock-aarch64-compiled'
83
end
84
expect(subject.generate).to eq 'mock-aarch64-compiled'
85
end
86
87
context 'when the CMD is /bin/bash' do
88
let(:cmd) { '/bin/bash' }
89
90
it 'generates the execve system call payload without arguments present' do
91
expected = <<~'EOF'
92
// Set system call SYS_EXECVE 0x200003b in x16
93
mov x16, xzr
94
movk x16, #0x0200, lsl #16
95
movk x16, #0x003b
96
97
mov x9, sp // Temporarily move SP into scratch register
98
99
// Arg 0: execve - const char *path - Pointer to the program name to run
100
// Next 8 bytes of string: "/bin/bas"
101
movz x0, #0x622f // "b/"
102
movk x0, #0x6e69, lsl #16 // "ni"
103
movk x0, #0x622f, lsl #32 // "b/"
104
movk x0, #0x7361, lsl #48 // "sa"
105
str x0, [x9], #8 // Store x0 on x9-stack and increment by 8
106
// Next 8 bytes of string: "h\x00"
107
movz x0, #0x0068 // "\x00h"
108
str x0, [x9], #8 // Store x0 on x9-stack and increment by 8
109
110
mov x0, x9 // Store the current stack location in the target register
111
sub x0, x0, #16 // Update the target register to point to base of the string
112
113
114
115
// Push execve arguments, using x1 as a temporary register
116
117
118
// Arg 1: execve - char *const argv[] - program arguments
119
// argv[0] = create pointer to base of string value "/bin/bash\x00"
120
mov x1, x9
121
sub x1, x1, #16 // Update the target register to point to base of the string
122
str x1, [x9], #8 // Store the pointer in the stack
123
124
125
// argv[1] = NULL
126
str xzr, [x9], #8
127
128
// Set execve arg1 to the base of the argv array of pointers
129
mov x1, x9
130
sub x1, x1, #16
131
132
// Arg 2: execve - char *const envp[] - Environment variables, NULL for now
133
mov x2, xzr
134
// System call
135
svc #0
136
EOF
137
138
expect_result_to_match(expected)
139
end
140
end
141
142
context 'when the CMD is /bin/bash -c "echo abc"' do
143
let(:cmd) { '/bin/bash -c "echo abc"' }
144
145
it 'generates the exece system call payload with arguments present' do
146
expected = <<~'EOF'
147
// Set system call SYS_EXECVE 0x200003b in x16
148
mov x16, xzr
149
movk x16, #0x0200, lsl #16
150
movk x16, #0x003b
151
152
mov x9, sp // Temporarily move SP into scratch register
153
154
// Arg 0: execve - const char *path - Pointer to the program name to run
155
// Next 8 bytes of string: "/bin/bas"
156
movz x0, #0x622f // "b/"
157
movk x0, #0x6e69, lsl #16 // "ni"
158
movk x0, #0x622f, lsl #32 // "b/"
159
movk x0, #0x7361, lsl #48 // "sa"
160
str x0, [x9], #8 // Store x0 on x9-stack and increment by 8
161
// Next 8 bytes of string: "h\x00"
162
movz x0, #0x0068 // "\x00h"
163
str x0, [x9], #8 // Store x0 on x9-stack and increment by 8
164
165
mov x0, x9 // Store the current stack location in the target register
166
sub x0, x0, #16 // Update the target register to point to base of the string
167
168
169
170
// Push execve arguments, using x1 as a temporary register
171
// Push argument 0
172
// Next 8 bytes of string: "-c\x00"
173
movz x1, #0x632d // "c-"
174
movk x1, #0x00, lsl #16 // "\x00"
175
str x1, [x9], #8 // Store x1 on x9-stack and increment by 8
176
177
mov x1, x9 // Store the current stack location in the target register
178
sub x1, x1, #8 // Update the target register to point to base of the string
179
180
181
// Push argument 1
182
// Next 8 bytes of string: "echo abc"
183
movz x1, #0x6365 // "ce"
184
movk x1, #0x6f68, lsl #16 // "oh"
185
movk x1, #0x6120, lsl #32 // "a "
186
movk x1, #0x6362, lsl #48 // "cb"
187
str x1, [x9], #8 // Store x1 on x9-stack and increment by 8
188
// Next 8 bytes of string: "\x00"
189
movz x1, #0x00 // "\x00"
190
str x1, [x9], #8 // Store x1 on x9-stack and increment by 8
191
192
mov x1, x9 // Store the current stack location in the target register
193
sub x1, x1, #16 // Update the target register to point to base of the string
194
195
196
197
// Arg 1: execve - char *const argv[] - program arguments
198
// argv[0] = create pointer to base of string value "/bin/bash\x00"
199
mov x1, x9
200
sub x1, x1, #40 // Update the target register to point to base of the string
201
str x1, [x9], #8 // Store the pointer in the stack
202
203
// argv[1] = create pointer to base of string value "-c\x00"
204
mov x1, x9
205
sub x1, x1, #32 // Update the target register to point to base of the string
206
str x1, [x9], #8 // Store the pointer in the stack
207
208
// argv[2] = create pointer to base of string value "echo abc\x00"
209
mov x1, x9
210
sub x1, x1, #32 // Update the target register to point to base of the string
211
str x1, [x9], #8 // Store the pointer in the stack
212
213
214
// argv[3] = NULL
215
str xzr, [x9], #8
216
217
// Set execve arg1 to the base of the argv array of pointers
218
mov x1, x9
219
sub x1, x1, #32
220
221
// Arg 2: execve - char *const envp[] - Environment variables, NULL for now
222
mov x2, xzr
223
// System call
224
svc #0
225
EOF
226
expect_result_to_match(expected)
227
end
228
end
229
end
230
end
231
232