Skip to content

Commit c7d1e34

Browse files
authored
Land #19471 Add fuzzy-use plugin
This adds a plugin that offers the fzuse command to offer a different UI for the selection of modules. It requires fzf to be present.
2 parents 2ea71c4 + 669ea97 commit c7d1e34

File tree

2 files changed

+154
-3
lines changed

2 files changed

+154
-3
lines changed

docs/metasploit-framework.wiki/How-To-Use-Plugins.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ plugin_name_command --option
1818

1919
The current available plugins for Metasploit can be found by running the `load -l` command, or viewing Metasploit's [plugins](https://github.com/rapid7/metasploit-framework/tree/master/plugins) directory:
2020

21-
| name | Description |
21+
| Name | Description |
2222
|------------------|-----------------------------------------------------------------------------------------------------|
2323
| aggregator | Interacts with the external Session Aggregator |
2424
| alias | Adds the ability to alias console commands |
@@ -30,6 +30,7 @@ The current available plugins for Metasploit can be found by running the `load -
3030
| db_tracker | Monitors socket calls and updates the database backend |
3131
| event_tester | Internal test tool used to verify the internal framework event subscriber logic works |
3232
| ffautoregen | This plugin reloads and re-executes a file-format exploit module once it has changed |
33+
| fzuse | A plugin offering a fuzzy use command |
3334
| ips_filter | Scans all outgoing data to see if it matches a known IPS signature |
3435
| lab | Adds the ability to manage VMs |
3536
| libnotify | Send desktop notification with libnotify on sessions and db events |
@@ -42,12 +43,12 @@ The current available plugins for Metasploit can be found by running the `load -
4243
| request | Make requests from within Metasploit using various protocols. |
4344
| rssfeed | Create an RSS feed of events |
4445
| sample | Demonstrates using framework plugins |
45-
| session_notifier | This plugin notifies you of a new session via SMS |
46+
| session_notifier | This plugin notifies you of a new session via SMS |
4647
| session_tagger | Automatically interacts with new sessions to create a new remote TaggedByUser file |
4748
| socket_logger | Log socket operations to a directory as individual files |
4849
| sounds | Automatically plays a sound when various framework events occur |
4950
| sqlmap | sqlmap plugin for Metasploit |
50-
| thread | Internal test tool for testing thread usage in Metasploit |
51+
| thread | Internal test tool for testing thread usage in Metasploit |
5152
| token_adduser | Attempt to add an account using all connected Meterpreter session tokens |
5253
| token_hunter | Search all active Meterpreter sessions for specific tokens |
5354
| wiki | Outputs stored database values from the current workspace into DokuWiki or MediaWiki format |

plugins/fzuse.rb

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
require 'socket'
2+
3+
# this is the main routine that's executed in the grandchild process (msfconsole -> fzf -> this)
4+
if $PROGRAM_NAME == __FILE__
5+
exit 64 unless ARGV.length == 2
6+
7+
UNIXSocket.open(ARGV[0]) do |sock|
8+
sock.write ARGV[1] + "\n"
9+
sock.flush
10+
11+
puts sock.read
12+
end
13+
exit 0
14+
end
15+
16+
module Msf
17+
class Plugin::FuzzyUse < Msf::Plugin
18+
class ConsoleCommandDispatcher
19+
include Msf::Ui::Console::CommandDispatcher
20+
21+
FZF_THEME = {
22+
'fg' => '-1',
23+
'fg+' => 'white:regular:bold',
24+
'bg' => '-1',
25+
'bg+' => '-1',
26+
'hl' => '-1',
27+
'hl+' => 'red:regular:bold',
28+
'info' => '-1',
29+
'marker' => '-1',
30+
'prompt' => '-1',
31+
'spinner' => '-1',
32+
'pointer' => 'blue:bold',
33+
'header' => '-1',
34+
'border' => '-1',
35+
'label' => '-1',
36+
'query' => '-1'
37+
}.freeze
38+
39+
def initialize(driver)
40+
super
41+
42+
@module_dispatcher = Msf::Ui::Console::CommandDispatcher::Modules.new(driver)
43+
end
44+
45+
def name
46+
'FuzzyUse'
47+
end
48+
49+
#
50+
# Returns the hash of commands supported by this dispatcher.
51+
#
52+
def commands
53+
{
54+
'fzuse' => 'A fuzzy use command added by the FuzzyUse plugin'
55+
}
56+
end
57+
58+
def pipe_server(socket_path)
59+
server = UNIXServer.new(socket_path)
60+
File.chmod(0600, socket_path)
61+
loop do
62+
client = server.accept
63+
begin
64+
unless (input_string = client.gets&.chomp).blank?
65+
if (mod = framework.modules.create(input_string))
66+
client.puts(Serializer::ReadableText.dump_module(mod))
67+
end
68+
end
69+
rescue StandardError
70+
end
71+
client.close
72+
end
73+
rescue EOFError
74+
ensure
75+
server.close if server
76+
File.delete(socket_path) if File.exist?(socket_path)
77+
end
78+
79+
#
80+
# This method handles the fzuse command.
81+
#
82+
def cmd_fzuse(*args)
83+
selection = nil
84+
85+
Dir.mktmpdir('msf-fzuse-') do |dir|
86+
socket_path = File.join(dir, "msf-fzuse.sock")
87+
server_thread = Thread.new { pipe_server(socket_path) }
88+
89+
query = args.empty? ? '' : args.first
90+
ruby = RbConfig::CONFIG['bindir'] + '/' + RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT']
91+
92+
color = "--color=#{FZF_THEME.map { |key, value| "#{key}:#{value}" }.join(',')}"
93+
Open3.popen3('fzf', '--select-1', '--query', query, '--pointer=->', color, '--preview', "'#{ruby}' '#{__FILE__}' '#{socket_path}' '{1}'", '--preview-label', "Module Information") do |stdin, stdout, stderr, wait_thr|
94+
framework.modules.module_types.each do |module_type|
95+
framework.modules.module_names(module_type).each do |module_name|
96+
stdin.puts "#{module_type}/#{module_name}"
97+
end
98+
end
99+
stdin.close
100+
selection = stdout.read
101+
end
102+
103+
server_thread.kill
104+
server_thread.join
105+
end
106+
107+
return if selection.blank?
108+
109+
selection.strip!
110+
@module_dispatcher.cmd_use(selection)
111+
end
112+
end
113+
114+
def initialize(framework, opts)
115+
super
116+
117+
unless defined?(UNIXSocket)
118+
# This isn't a requirement that can be fixed by installing something
119+
print_error("The FuzzyUse plugin has loaded but the Ruby environment does not support UNIX sockets.")
120+
return
121+
end
122+
123+
missing_requirements = []
124+
missing_requirements << 'fzf' unless Msf::Util::Helper.which('fzf')
125+
126+
unless missing_requirements.empty?
127+
print_error("The FuzzyUse plugin has loaded but the following requirements are missing: #{missing_requirements.join(', ')}")
128+
print_error("Please install the missing requirements, then reload the plugin by running: `unload fzuse` and `load fzuse`.")
129+
return
130+
end
131+
132+
add_console_dispatcher(ConsoleCommandDispatcher)
133+
134+
print_status('FuzzyUse plugin loaded.')
135+
end
136+
137+
def cleanup
138+
remove_console_dispatcher('FuzzyUse')
139+
end
140+
141+
def name
142+
'fuzzy_use'
143+
end
144+
145+
def desc
146+
'A plugin offering a fuzzy use command'
147+
end
148+
149+
end
150+
end

0 commit comments

Comments
 (0)