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/ui/console/command_dispatcher/exploit.rb
Views: 1904
1
# -*- coding: binary -*-
2
module Msf
3
module Ui
4
module Console
5
module CommandDispatcher
6
7
###
8
#
9
# Exploit module command dispatcher.
10
#
11
###
12
class Exploit
13
14
include Msf::Ui::Console::ModuleCommandDispatcher
15
include Msf::Ui::Console::ModuleArgumentParsing
16
include Msf::Ui::Console::ModuleOptionTabCompletion
17
18
#
19
# Returns the hash of exploit module specific commands.
20
#
21
def commands
22
super.update({
23
"exploit" => "Launch an exploit attempt",
24
"rcheck" => "Reloads the module and checks if the target is vulnerable",
25
"rexploit" => "Reloads the module and launches an exploit attempt",
26
"run" => "Alias for exploit",
27
"recheck" => "Alias for rcheck",
28
"rerun" => "Alias for rexploit",
29
"reload" => "Just reloads the module"
30
})
31
end
32
33
#
34
# Returns the name of the command dispatcher.
35
#
36
def name
37
"Exploit"
38
end
39
40
#
41
# Launches an exploitation single attempt.
42
#
43
def exploit_single(mod, opts)
44
begin
45
session = mod.exploit_simple(opts)
46
rescue ::Interrupt
47
raise $!
48
rescue ::Msf::OptionValidateError => e
49
::Msf::Ui::Formatter::OptionValidateError.print_error(mod, e)
50
rescue ::Exception => e
51
print_error("Exploit exception (#{mod.refname}): #{e.class} #{e}")
52
if e.class.to_s != 'Msf::OptionValidateError'
53
print_error("Call stack:")
54
e.backtrace.each do |line|
55
break if line =~ /lib.msf.base.simple/
56
print_error(" #{line}")
57
end
58
end
59
end
60
61
return session
62
end
63
64
#
65
# Tab completion for the run command
66
#
67
def cmd_run_tabs(str, words)
68
fmt = {
69
'-e' => [ framework.encoders.module_refnames ],
70
'-f' => [ nil ],
71
'-h' => [ nil ],
72
'-j' => [ nil ],
73
'-J' => [ nil ],
74
'-n' => [ framework.nops.module_refnames ],
75
'-o' => [ true ],
76
'-p' => [ framework.payloads.module_refnames ],
77
'-r' => [ nil ],
78
'-t' => [ true ],
79
'-z' => [ nil ]
80
}
81
flags = tab_complete_generic(fmt, str, words)
82
options = tab_complete_option(active_module, str, words)
83
flags + options
84
end
85
86
#
87
# Tab completion for the exploit command
88
#
89
alias cmd_exploit_tabs cmd_run_tabs
90
91
#
92
# Launches exploitation attempts.
93
#
94
def cmd_exploit(*args, opts: {})
95
if (args.include?('-r') || args.include?('--reload-libs')) && !opts[:previously_reloaded]
96
driver.run_single('reload_lib -a')
97
end
98
99
return false unless (args = parse_exploit_opts(args))
100
101
any_session = false
102
force = args[:force] || false
103
104
minrank = RankingName.invert[framework.datastore['MinimumRank']] || 0
105
if minrank > mod.rank
106
if force
107
print_status("Forcing #{mod.refname} to run despite MinimumRank '#{framework.datastore['MinimumRank']}'")
108
ilog("Forcing #{mod.refname} to run despite MinimumRank '#{framework.datastore['MinimumRank']}'", 'core')
109
else
110
print_error("This exploit is below the minimum rank, '#{framework.datastore['MinimumRank']}'.")
111
print_error("If you really want to run it, do 'exploit -f' or")
112
print_error("setg MinimumRank to something lower ('manual' is")
113
print_error("the lowest and would allow running all exploits).")
114
return
115
end
116
end
117
118
mod_with_opts = mod.replicant
119
mod_with_opts.datastore.import_options_from_hash(args[:datastore_options])
120
rhosts = mod_with_opts.datastore['RHOSTS']
121
has_rhosts_option = mod.options.include?('RHOSTS') ||
122
mod.options.include?('RHOST') ||
123
mod.options.include?('rhost') ||
124
mod.options.include?('rhosts')
125
126
opts = {
127
'Encoder' => args[:encoder] || mod_with_opts.datastore['ENCODER'],
128
'Payload' => args[:payload] || mod_with_opts.datastore['PAYLOAD'],
129
'Target' => args[:target] || mod_with_opts.datastore['TARGET'],
130
'Nop' => args[:nop] || mod_with_opts.datastore['NOP'],
131
'LocalInput' => driver.input,
132
'LocalOutput' => driver.output,
133
'RunAsJob' => args[:jobify] || mod_with_opts.passive?,
134
'Background' => args[:background] || false,
135
'Force' => force,
136
'Quiet' => args[:quiet] || false
137
}
138
139
begin
140
mod_with_opts.validate
141
rescue ::Msf::OptionValidateError => e
142
::Msf::Ui::Formatter::OptionValidateError.print_error(mod_with_opts, e)
143
return false
144
end
145
146
driver.run_single('reload_lib -a') if args[:reload_libs]
147
148
if rhosts && has_rhosts_option
149
rhosts_walker = Msf::RhostsWalker.new(rhosts, mod_with_opts.datastore)
150
rhosts_walker_count = rhosts_walker.count
151
rhosts_walker = rhosts_walker.to_enum
152
end
153
154
# For multiple targets exploit attempts.
155
if rhosts_walker && rhosts_walker_count > 1
156
opts[:multi] = true
157
rhosts_walker.with_index do |datastore, index|
158
nmod = mod_with_opts.replicant
159
nmod.datastore.merge!(datastore)
160
# If rhost is the last target, let exploit handler stop.
161
is_last_target = (index + 1) == rhosts_walker_count
162
opts["multi"] = false if is_last_target
163
# Catch the interrupt exception to stop the whole module during exploit
164
begin
165
print_status("Exploiting target #{datastore['RHOSTS']}")
166
session = exploit_single(nmod, opts)
167
rescue ::Interrupt
168
print_status("Stopping exploiting current target #{datastore['RHOSTS']}...")
169
print_status("Control-C again to force quit exploiting all targets.")
170
begin
171
Rex.sleep(1)
172
rescue ::Interrupt
173
raise $!
174
end
175
end
176
# If we were given a session, report it.
177
if session
178
print_status("Session #{session.sid} created in the background.")
179
any_session = true
180
end
181
end
182
# For single target or no rhosts option.
183
else
184
nmod = mod_with_opts.replicant
185
if rhosts_walker && rhosts_walker_count == 1
186
nmod.datastore.merge!(rhosts_walker.next)
187
end
188
session = exploit_single(nmod, opts)
189
# If we were given a session, let's see what we can do with it
190
if session
191
any_session = true
192
if !opts['Background'] && session.interactive?
193
# If we aren't told to run in the background and the session can be
194
# interacted with, start interacting with it by issuing the session
195
# interaction command.
196
print_line
197
198
driver.run_single("sessions -q -i #{session.sid}")
199
# Otherwise, log that we created a session
200
else
201
# Otherwise, log that we created a session
202
print_status("Session #{session.sid} created in the background.")
203
end
204
205
elsif opts['RunAsJob'] && nmod.job_id
206
# Indicate if he exploit as a job, indicate such so the user doesn't
207
# wonder what's up.
208
print_status("Exploit running as background job #{nmod.job_id}.")
209
# Worst case, the exploit ran but we got no session, bummer.
210
end
211
end
212
213
# If we didn't get any session and exploit ended launch.
214
unless any_session
215
# If we didn't run a payload handler for this exploit it doesn't
216
# make sense to complain to the user that we didn't get a session
217
unless mod_with_opts.datastore["DisablePayloadHandler"]
218
fail_msg = 'Exploit completed, but no session was created.'
219
print_status(fail_msg)
220
begin
221
framework.events.on_session_fail(fail_msg)
222
rescue ::Exception => e
223
wlog("Exception in on_session_open event handler: #{e.class}: #{e}")
224
wlog("Call Stack\n#{e.backtrace.join("\n")}")
225
end
226
end
227
end
228
end
229
230
alias cmd_run cmd_exploit
231
232
def cmd_exploit_help
233
print_module_run_or_check_usage(command: :run, options: @@exploit_opts)
234
end
235
236
alias cmd_run_help cmd_exploit_help
237
238
#
239
# Reloads an exploit module and checks the target to see if it's
240
# vulnerable.
241
#
242
def cmd_rcheck(*args)
243
opts = {}
244
if args.include?('-r') || args.include?('--reload-libs')
245
driver.run_single('reload_lib -a')
246
opts[:previously_reloaded] = true
247
end
248
249
reload()
250
251
cmd_check(*args, opts: opts)
252
end
253
254
alias cmd_recheck cmd_rcheck
255
256
#
257
# Reloads an exploit module and launches an exploit.
258
#
259
def cmd_rexploit(*args)
260
opts = {}
261
if args.include?('-r') || args.include?('--reload-libs')
262
driver.run_single('reload_lib -a')
263
opts[:previously_reloaded] = true
264
end
265
266
return cmd_rexploit_help if args.include?('-h') || args.include?('--help')
267
268
# Stop existing job and reload the module
269
if reload(true)
270
# Delegate to the exploit command unless the reload failed
271
cmd_exploit(*args, opts: opts)
272
end
273
end
274
275
alias cmd_rerun cmd_rexploit
276
alias cmd_rerun_tabs cmd_run_tabs
277
alias cmd_rexploit_tabs cmd_exploit_tabs
278
279
def cmd_rexploit_help
280
print_module_run_or_check_usage(
281
command: :rexploit,
282
description: 'Reloads a module, stopping any associated job, and launches an exploitation attempt.',
283
options: @@exploit_opts
284
)
285
end
286
287
alias cmd_rerun_help cmd_rexploit_help
288
289
# Select a reasonable default payload and minimally configure it
290
# @param [Msf::Module] mod
291
def self.choose_payload(mod)
292
Msf::Payload.choose_payload(mod)
293
end
294
295
end
296
297
end end end end
298
299