Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/base/simple/auxiliary.rb
19516 views
1
# -*- coding: binary -*-
2
module Msf
3
module Simple
4
5
###
6
#
7
# A simplified auxiliary wrapper.
8
#
9
###
10
module Auxiliary
11
12
include Module
13
14
#
15
# Wraps the auxiliary process in a simple single method. The options
16
# hash can have the following values passed in it:
17
#
18
# Action
19
#
20
# The selected action name.
21
#
22
# OptionStr
23
#
24
# A string of comma separated option values that should be imported into
25
# the datastore.
26
#
27
# Options
28
#
29
# A hash of values to be imported directly into the datastore.
30
#
31
# LocalInput
32
#
33
# The local input handle that data can be read in from.
34
#
35
# LocalOutput
36
#
37
# The local output through which data can be displayed.
38
#
39
# RunAsJob
40
#
41
# Whether or not the exploit should be run in the context of a background
42
# job.
43
#
44
def self.run_simple(omod, opts = {}, job_listener: Msf::Simple::NoopJobListener.instance, &block)
45
46
# Clone the module to prevent changes to the original instance
47
mod = omod.replicant
48
Msf::Simple::Framework.simplify_module(mod)
49
yield(mod) if block_given?
50
51
# Import options from the OptionStr or Option hash.
52
mod._import_extra_options(opts)
53
54
mod.datastore['ACTION'] = opts['Action'] if opts['Action']
55
56
# Verify the ACTION
57
if (mod.actions.length > 0 and not mod.action)
58
raise MissingActionError, "Please use: #{mod.actions.collect {|e| e.name} * ", "}"
59
end
60
61
# Validate the option container state so that options will
62
# be normalized
63
mod.validate
64
65
# Initialize user interaction
66
if ! opts['Quiet']
67
mod.init_ui(opts['LocalInput'] || mod.user_input, opts['LocalOutput'] || mod.user_output)
68
else
69
mod.init_ui(nil, nil)
70
end
71
72
run_uuid = Rex::Text.rand_text_alphanumeric(24)
73
job_listener.waiting run_uuid
74
ctx = [mod, run_uuid, job_listener]
75
run_as_job = opts['RunAsJob'].nil? ? mod.passive? : opts['RunAsJob']
76
if run_as_job
77
mod.job_id = mod.framework.jobs.start_bg_job(
78
"Auxiliary: #{mod.refname}",
79
ctx,
80
Proc.new { |ctx_| self.job_run_proc(ctx_, &:run) },
81
Proc.new { |ctx_| self.job_cleanup_proc(ctx_) }
82
)
83
# Propagate this back to the caller for console mgmt
84
omod.job_id = mod.job_id
85
return [run_uuid, mod.job_id]
86
else
87
result = self.job_run_proc(ctx, &:run)
88
self.job_cleanup_proc(ctx)
89
90
return result
91
end
92
end
93
94
#
95
# Calls the class method.
96
#
97
def run_simple(opts = {}, &block)
98
Msf::Simple::Auxiliary.run_simple(self, opts, &block)
99
end
100
101
#
102
# Initiates a check, setting up the exploit to be used. The following
103
# options can be specified:
104
#
105
# LocalInput
106
#
107
# The local input handle that data can be read in from.
108
#
109
# LocalOutput
110
#
111
# The local output through which data can be displayed.
112
#
113
def self.check_simple(mod, opts, job_listener: Msf::Simple::NoopJobListener.instance)
114
Msf::Simple::Framework.simplify_module(mod)
115
116
mod._import_extra_options(opts)
117
if opts['LocalInput']
118
mod.init_ui(opts['LocalInput'], opts['LocalOutput'])
119
end
120
121
unless mod.has_check?
122
# Bail out early if the module doesn't have check
123
raise ::NotImplementedError.new(Msf::Exploit::CheckCode::Unsupported.message)
124
end
125
126
# Validate the option container state so that options will
127
# be normalized
128
mod.validate
129
130
run_uuid = Rex::Text.rand_text_alphanumeric(24)
131
job_listener.waiting run_uuid
132
ctx = [mod, run_uuid, job_listener]
133
134
if opts['RunAsJob']
135
mod.job_id = mod.framework.jobs.start_bg_job(
136
"Auxiliary: #{mod.refname} check",
137
ctx,
138
Proc.new do |ctx_|
139
self.job_run_proc(ctx_) do |m|
140
m.check
141
end
142
end,
143
Proc.new { |ctx_| self.job_cleanup_proc(ctx_) }
144
)
145
146
[run_uuid, mod.job_id]
147
else
148
# Run check if it exists
149
result = self.job_run_proc(ctx) do |m|
150
m.check
151
end
152
self.job_cleanup_proc(ctx)
153
154
result
155
end
156
end
157
158
#
159
# Calls the class method.
160
#
161
def check_simple(opts = {})
162
Msf::Simple::Auxiliary.check_simple(self, opts)
163
end
164
165
166
protected
167
168
#
169
# Job run proc, sets up the module and kicks it off.
170
#
171
def self.job_run_proc(ctx, &block)
172
mod = ctx[0]
173
run_uuid = ctx[1]
174
job_listener = ctx[2]
175
begin
176
begin
177
job_listener.start run_uuid
178
mod.setup
179
mod.framework.events.on_module_run(mod)
180
result = block.call(mod)
181
job_listener.completed(run_uuid, result, mod)
182
rescue ::Exception => e
183
job_listener.failed(run_uuid, e, mod)
184
raise
185
end
186
rescue Msf::Auxiliary::Complete
187
mod.cleanup
188
return
189
rescue Msf::Auxiliary::Failed => e
190
mod.error = e
191
mod.print_error("Auxiliary aborted due to failure: #{e.message}")
192
193
# The caller should have already set mod.fail_reason
194
if mod.fail_reason == Msf::Module::Failure::None
195
mod.fail_reason = Msf::Module::Failure::Unknown
196
end
197
mod.fail_detail ||= e.to_s
198
199
mod.cleanup
200
return
201
rescue ::Timeout::Error => e
202
mod.error = e
203
mod.fail_reason = Msf::Module::Failure::TimeoutExpired
204
mod.fail_detail ||= e.to_s
205
mod.print_error("Auxiliary triggered a timeout exception")
206
mod.cleanup
207
return
208
rescue ::Interrupt => e
209
mod.error = e
210
mod.fail_reason = Msf::Module::Failure::UserInterrupt
211
mod.fail_detail ||= e.to_s
212
mod.print_error("Stopping running against current target...")
213
mod.cleanup
214
mod.print_status("Control-C again to force quit all targets.")
215
begin
216
Rex.sleep(0.5)
217
rescue ::Interrupt
218
raise $!
219
end
220
return
221
rescue ::Msf::OptionValidateError => e
222
mod.error = e
223
mod.fail_reason = Msf::Module::Failure::BadConfig
224
mod.fail_detail ||= e.to_s
225
::Msf::Ui::Formatter::OptionValidateError.print_error(mod, e)
226
rescue ::Exception => e
227
mod.error = e
228
mod.fail_reason = Msf::Module::Failure::Unknown
229
mod.fail_detail ||= e.to_s
230
mod.print_error("Auxiliary failed: #{e.class} #{e}")
231
if(e.class.to_s != 'Msf::OptionValidateError')
232
mod.print_error("Call stack:")
233
e.backtrace.each do |line|
234
break if line =~ /lib.msf.base.simple.auxiliary.rb/
235
mod.print_error(" #{line}")
236
end
237
end
238
239
elog('Auxiliary failed', error: e)
240
mod.cleanup
241
242
end
243
return result
244
ensure
245
# Register an attempt in the database (an `Mdm::ExploitAttempt` (and
246
# possibly an `Mdm::VulnAttempt`).
247
#
248
# Since auxiliary modules don't report clearly when it is a success or a
249
# failure, we are calling #report_failure keeping the `mod.fail_reason`
250
# value unchanged. This value is set to `Msf::Module::Failure::None` when
251
# no error was reported. It should be set to another
252
# `Msf::Module::Failure::*` value otherwise.
253
mod.report_failure
254
end
255
256
#
257
# Clean up the module after the job completes.
258
#
259
def self.job_cleanup_proc(ctx)
260
mod = ctx[0]
261
mod.framework.events.on_module_complete(mod)
262
# Allow the exploit to cleanup after itself, that messy bugger.
263
mod.cleanup
264
end
265
266
end
267
268
end
269
end
270
271