Skip to content

Commit 0d61200

Browse files
committed
Show session/rhost options separate from each other
1 parent 5ea35c9 commit 0d61200

File tree

6 files changed

+109
-55
lines changed

6 files changed

+109
-55
lines changed

lib/msf/base/serializer/readable_text.rb

+58-43
Original file line numberDiff line numberDiff line change
@@ -569,53 +569,19 @@ def self.dump_generic_module(mod, indent = '')
569569
# @param missing [Boolean] dump only empty required options.
570570
# @return [String] the string form of the information.
571571
def self.dump_options(mod, indent = '', missing = false)
572-
options = mod.options.map { |_name, option| option }
573-
options_grouped_by_conditions = options.group_by(&:conditions)
572+
all_options = mod.options.map { |_name, option| option }
573+
574+
# separate mutually exclusive options from conditional options to format them differently
575+
mutually_exclusive_options, conditional_options = all_options.partition { |option| option.mutual_exclusions.any? }
576+
options_grouped_by_conditions = conditional_options.group_by(&:conditions)
577+
options_grouped_by_mutual_exclusivity = mutually_exclusive_options.group_by(&:mutual_exclusions)
574578

575579
options_with_conditions = ''.dup
576580
options_without_conditions = ''.dup
581+
options_with_mutual_exclusivity = ''.dup
577582

578583
options_grouped_by_conditions.each do |conditions, options|
579-
tbl = Rex::Text::Table.new(
580-
'Indent' => indent.length,
581-
'Columns' =>
582-
[
583-
'Name',
584-
'Current Setting',
585-
'Required',
586-
'Description'
587-
])
588-
589-
options.sort_by(&:name).each do |opt|
590-
name = opt.name
591-
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
592-
val = mod.datastore[name]
593-
else
594-
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
595-
end
596-
597-
next if (opt.advanced?)
598-
next if (opt.evasion?)
599-
next if (missing && opt.valid?(val))
600-
601-
desc = opt.desc.dup
602-
603-
# Hint at RPORT proto by regexing mixins
604-
if name == 'RPORT' && opt.kind_of?(Msf::OptPort)
605-
mod.class.included_modules.each do |m|
606-
case m.name
607-
when /tcp/i, /HttpClient$/
608-
desc << ' (TCP)'
609-
break
610-
when /udp/i
611-
desc << ' (UDP)'
612-
break
613-
end
614-
end
615-
end
616-
617-
tbl << [ name, opt.display_value(val), opt.required? ? "yes" : "no", desc ]
618-
end
584+
tbl = options_table(missing, mod, options, indent)
619585

620586
next if conditions.any? && tbl.rows.empty?
621587

@@ -627,10 +593,59 @@ def self.dump_options(mod, indent = '', missing = false)
627593
end
628594
end
629595

630-
result = "#{options_without_conditions}#{options_with_conditions}"
596+
options_grouped_by_mutual_exclusivity.each do |mutual_exclusions, options|
597+
tbl = options_table(missing, mod, options, indent)
598+
options_with_mutual_exclusivity << "\n\n#{indent}When not using #{mutual_exclusions.join(', ')}:\n\n"
599+
options_with_mutual_exclusivity << tbl.to_s
600+
end
601+
602+
result = "#{options_without_conditions}#{options_with_conditions}#{options_with_mutual_exclusivity}"
631603
result
632604
end
633605

606+
def self.options_table(missing, mod, options, indent)
607+
tbl = Rex::Text::Table.new(
608+
'Indent' => indent.length,
609+
'Columns' =>
610+
[
611+
'Name',
612+
'Current Setting',
613+
'Required',
614+
'Description'
615+
])
616+
options.sort_by(&:name).each do |opt|
617+
# Skip over advanced or evasion options
618+
next if (opt.advanced? || opt.evasion?)
619+
620+
name = opt.name
621+
if mod.datastore.is_a?(Msf::DataStoreWithFallbacks)
622+
val = mod.datastore[name]
623+
else
624+
val = mod.datastore[name].nil? ? opt.default : mod.datastore[name]
625+
end
626+
next if (missing && opt.valid?(val))
627+
628+
desc = opt.desc.dup
629+
630+
# Hint at RPORT proto by regexing mixins
631+
if name == 'RPORT' && opt.kind_of?(Msf::OptPort)
632+
mod.class.included_modules.each do |m|
633+
case m.name
634+
when /tcp/i, /HttpClient$/
635+
desc << ' (TCP)'
636+
break
637+
when /udp/i
638+
desc << ' (UDP)'
639+
break
640+
end
641+
end
642+
end
643+
644+
tbl << [name, opt.display_value(val), opt.required? ? "yes" : "no", desc]
645+
end
646+
tbl
647+
end
648+
634649
# Dumps the advanced options associated with the supplied module.
635650
#
636651
# @param mod [Msf::Module] the module.

lib/msf/core/opt.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ def self.RHOSTS(default= nil, required=true, desc="The target host(s), see https
4444
Msf::OptRhosts.new('RHOSTS', [ required, desc, default ], aliases: [ 'RHOST' ])
4545
end
4646

47-
def self.RHOST(default=nil, required=true, desc="The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html")
48-
Msf::OptRhosts.new('RHOSTS', [ required, desc, default ], aliases: [ 'RHOST' ])
47+
def self.RHOST(default=nil, required=true, desc="The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html", **kwargs)
48+
Msf::OptRhosts.new('RHOSTS', [ required, desc, default ], aliases: [ 'RHOST' ], **kwargs)
4949
end
5050

5151
# @return [OptPort]

lib/msf/core/opt_base.rb

+7-1
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,15 @@ class OptBase
2626
#
2727
def initialize(in_name, attrs = [],
2828
required: false, desc: nil, default: nil, conditions: [], enums: [], regex: nil, aliases: [], max_length: nil,
29-
fallbacks: [])
29+
fallbacks: [], mutual_exclusions: [])
3030
self.name = in_name
3131
self.advanced = false
3232
self.evasion = false
3333
self.aliases = aliases
3434
self.max_length = max_length
3535
self.conditions = conditions
3636
self.fallbacks = fallbacks
37+
self.mutual_exclusions = mutual_exclusions
3738

3839
if attrs.is_a?(String) || attrs.length == 0
3940
self.required = required
@@ -230,6 +231,11 @@ def invalid_value_length?(value)
230231
#
231232
attr_accessor :max_length
232233

234+
#
235+
# Array of options that are mutually exclusive with this one
236+
#
237+
attr_accessor :mutual_exclusions
238+
233239
protected
234240

235241
attr_writer :required, :desc, :default # :nodoc:

lib/msf/core/opt_session.rb

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# -*- coding: binary -*-
2+
3+
module Msf
4+
###
5+
#
6+
# Session option.
7+
#
8+
###
9+
class OptSession < OptInt
10+
def type
11+
'session'
12+
end
13+
14+
def valid?(value, check_empty: false)
15+
return false unless super
16+
17+
return true if @owner.framework.sessions.get(value)
18+
19+
false
20+
end
21+
end
22+
end

lib/msf/core/optional_session.rb

+19-8
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,43 @@ module Msf::OptionalSession
99

1010
def initialize(info = {})
1111
super
12-
if framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)
12+
if any_enabled?
1313
register_options(
1414
[
15-
Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]),
16-
Msf::Opt::RHOST(nil, false),
15+
Msf::OptSession.new('SESSION', [ false, 'The session to run this module on' ], mutual_exclusions: ['RHOST']),
16+
Msf::Opt::RHOST(nil, false, mutual_exclusions: ['SESSION']),
1717
Msf::Opt::RPORT(nil, false)
1818
]
1919
)
2020
end
2121

22-
if framework.features.enabled?(Msf::FeatureManager::POSTGRESQL_SESSION_TYPE)
22+
if postgres_enabled?
2323
register_options(
2424
[
25-
Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]),
2625
Msf::OptString.new('DATABASE', [ false, 'The database to authenticate against', 'postgres']),
2726
Msf::OptString.new('USERNAME', [ false, 'The username to authenticate as', 'postgres']),
28-
Msf::Opt::RHOST(nil, false),
29-
Msf::Opt::RPORT(nil, false)
3027
]
3128
)
3229
end
3330
end
3431

3532
def session
36-
return nil unless (framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE) || framework.features.enabled?(Msf::FeatureManager::POSTGRESQL_SESSION_TYPE))
33+
return nil unless any_enabled?
3734

3835
super
3936
end
37+
38+
def any_enabled?
39+
smb_enabled? || postgres_enabled?
40+
end
41+
42+
private
43+
44+
def smb_enabled?
45+
framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)
46+
end
47+
48+
def postgres_enabled?
49+
framework.features.enabled?(Msf::FeatureManager::POSTGRESQL_SESSION_TYPE)
50+
end
4051
end

modules/auxiliary/scanner/smb/smb_enumshares.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def initialize(info = {})
4747

4848
register_options(
4949
[
50-
OptBool.new('SpiderShares', [false, 'Spider shares recursively', false]),
50+
OptBool.new('SpiderShares', [false, 'Spider shares recursively', false], mutual_exclusions: ['SESSION']),
5151
OptBool.new('ShowFiles', [true, 'Show detailed information when spidering', false]),
5252
OptString.new('Share', [ false, 'Show only the specified share']),
5353
OptRegexp.new('HIGHLIGHT_NAME_PATTERN', [true, 'PCRE regex of resource names to highlight', 'username|password|user|pass|Groups.xml']),

0 commit comments

Comments
 (0)