CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/base/simple/exploit.rb
Views: 1904
1
# -*- coding: binary -*-
2
3
module Msf
4
module Simple
5
6
###
7
#
8
# A simplified exploit wrapper.
9
#
10
###
11
module Exploit
12
13
include Module
14
15
#
16
# Wraps the exploitation process in a simple single method. The options
17
# hash can have the following values passed in it:
18
#
19
# Encoder
20
#
21
# The encoder module that should be used.
22
#
23
# Payload
24
#
25
# The payload module name that should be used.
26
#
27
# Target
28
#
29
# The selected target index.
30
#
31
# Nop
32
#
33
# The NOP generator that should be used in preference.
34
#
35
# OptionStr
36
#
37
# A string of comma separated option values that should be imported into
38
# the datastore.
39
#
40
# Options
41
#
42
# A hash of values to be imported directly into the datastore.
43
#
44
# LocalInput
45
#
46
# The local input handle that data can be read in from.
47
#
48
# LocalOutput
49
#
50
# The local output through which data can be displayed.
51
#
52
# RunAsJob
53
#
54
# Whether or not the exploit should be run in the context of a background
55
# job.
56
#
57
def self.exploit_simple(oexploit, opts, &block)
58
exploit = oexploit.replicant
59
# Trap and print errors here (makes them UI-independent)
60
begin
61
# Clone the module to prevent changes to the original instance
62
63
Msf::Simple::Framework.simplify_module(exploit)
64
yield(exploit) if block_given?
65
66
# Import options from the OptionStr or Option hash.
67
exploit._import_extra_options(opts)
68
opts['Payload'] ||= exploit.datastore['Payload']
69
70
unless opts['Quiet']
71
exploit.init_ui(opts['LocalInput'] || exploit.user_input, opts['LocalOutput'] || exploit.user_output)
72
else
73
exploit.init_ui(nil, nil)
74
end
75
76
# Make sure parameters are valid.
77
if (opts['Payload'] == nil)
78
raise MissingPayloadError, 'A payload has not been selected.', caller
79
end
80
81
# Verify the options
82
exploit.options.validate(exploit.datastore)
83
84
# Start it up
85
driver = Msf::ExploitDriver.new(exploit.framework)
86
87
# Keep the handler of driver running if exploiting multiple targets.
88
driver.keep_handler = true if opts['multi']
89
90
# Initialize the driver instance
91
driver.exploit = exploit
92
driver.payload = exploit.framework.payloads.create(opts['Payload'])
93
94
# Set the force wait for session flag if the caller requested force
95
# blocking. This is so that passive exploits can be blocked on from
96
# things like the cli.
97
driver.force_wait_for_session = true if (opts['ForceBlocking'] == true)
98
99
# Was the payload valid?
100
if (driver.payload == nil)
101
raise MissingPayloadError,
102
"You specified an invalid payload: #{opts['Payload']}", caller
103
end
104
105
# Use the supplied encoder, if any. If one was not specified, then
106
# nil will be assigned causing the exploit to default to picking the
107
# best encoder.
108
exploit.datastore['ENCODER'] = opts['Encoder'] if opts['Encoder']
109
110
# Use the supplied NOP generator, if any. If one was not specified, then
111
# nil will be assigned causing the exploit to default to picking a
112
# compatible NOP generator.
113
exploit.datastore['NOP'] = opts['Nop'] if opts['Nop']
114
115
# Force the payload to share the exploit's datastore
116
driver.payload.share_datastore(driver.exploit.datastore)
117
118
# Verify the payload options
119
driver.payload.options.validate(driver.payload.datastore)
120
121
# Set the target and then work some magic to derive index
122
exploit.datastore['TARGET'] = opts['Target'] if opts['Target']
123
target_idx = exploit.target_index
124
125
if (target_idx == nil or target_idx < 0)
126
raise MissingTargetError,
127
"You must select a target.", caller
128
end
129
130
driver.target_idx = target_idx
131
132
# Set the payload and exploit's subscriber values
133
unless opts['Quiet']
134
driver.payload.init_ui(opts['LocalInput'] || exploit.user_input, opts['LocalOutput'] || exploit.user_output)
135
else
136
driver.payload.init_ui(nil, nil)
137
end
138
139
if (opts['RunAsJob'])
140
driver.use_job = true
141
end
142
143
# Let's rock this party
144
driver.run
145
146
# Save the job identifier this exploit is running as
147
exploit.job_id = driver.job_id
148
149
# Propagate this back to the caller for console mgmt
150
oexploit.job_id = exploit.job_id
151
rescue ::Interrupt
152
exploit.error = $!
153
raise $!
154
rescue ::Msf::OptionValidateError => e
155
exploit.error = e
156
::Msf::Ui::Formatter::OptionValidateError.print_error(exploit, e)
157
return false
158
rescue ::Exception => e
159
exploit.error = e
160
exploit.print_error("Exploit failed: #{e}")
161
elog("Exploit failed (#{exploit.refname})", error: e)
162
end
163
164
return driver.session if driver
165
nil
166
end
167
168
#
169
# Calls the class method.
170
#
171
def exploit_simple(opts, &block)
172
Msf::Simple::Exploit.exploit_simple(self, opts, &block)
173
end
174
175
alias run_simple exploit_simple
176
#
177
# Initiates a check, setting up the exploit to be used. The following
178
# options can be specified:
179
#
180
# LocalInput
181
#
182
# The local input handle that data can be read in from.
183
#
184
# LocalOutput
185
#
186
# The local output through which data can be displayed.
187
#
188
def self.check_simple(mod, opts, job_listener: Msf::Simple::NoopJobListener.instance)
189
Msf::Simple::Framework.simplify_module(mod)
190
mod._import_extra_options(opts)
191
192
if opts['LocalInput']
193
mod.init_ui(opts['LocalInput'], opts['LocalOutput'])
194
end
195
196
unless mod.has_check?
197
# Bail out early if the module doesn't have check
198
raise ::NotImplementedError.new(Msf::Exploit::CheckCode::Unsupported.message)
199
end
200
201
# Validate the option container state so that options will
202
# be normalized
203
mod.validate
204
205
run_uuid = Rex::Text.rand_text_alphanumeric(24)
206
job_listener.waiting run_uuid
207
ctx = [mod, run_uuid, job_listener]
208
209
if opts['RunAsJob']
210
mod.job_id = mod.framework.jobs.start_bg_job(
211
"Exploit: #{mod.refname} check",
212
ctx,
213
Proc.new { |ctx_| self.job_check_proc(ctx_) },
214
Proc.new { |ctx_| nil }
215
)
216
[run_uuid, mod.job_id]
217
else
218
self.job_check_proc(ctx)
219
end
220
end
221
222
#
223
# Calls the class method.
224
#
225
def check_simple(opts)
226
Msf::Simple::Exploit.check_simple(self, opts)
227
end
228
229
protected
230
231
def self.job_check_proc(ctx)
232
mod = ctx[0]
233
run_uuid = ctx[1]
234
job_listener = ctx[2]
235
begin
236
job_listener.start run_uuid
237
mod.setup
238
result = mod.check
239
job_listener.completed(run_uuid, result, mod)
240
rescue => e
241
job_listener.failed(run_uuid, e, mod)
242
mod.handle_exception e
243
ensure
244
mod.cleanup
245
end
246
247
return result
248
end
249
end
250
251
end
252
end
253
254