Skip to content

Commit

Permalink
Land #19471 Add fuzzy-use plugin
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jheysel-r7 authored Oct 1, 2024
2 parents 2ea71c4 + 669ea97 commit c7d1e34
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 3 deletions.
7 changes: 4 additions & 3 deletions docs/metasploit-framework.wiki/How-To-Use-Plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ plugin_name_command --option

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:

| name | Description |
| Name | Description |
|------------------|-----------------------------------------------------------------------------------------------------|
| aggregator | Interacts with the external Session Aggregator |
| alias | Adds the ability to alias console commands |
Expand All @@ -30,6 +30,7 @@ The current available plugins for Metasploit can be found by running the `load -
| db_tracker | Monitors socket calls and updates the database backend |
| event_tester | Internal test tool used to verify the internal framework event subscriber logic works |
| ffautoregen | This plugin reloads and re-executes a file-format exploit module once it has changed |
| fzuse | A plugin offering a fuzzy use command |
| ips_filter | Scans all outgoing data to see if it matches a known IPS signature |
| lab | Adds the ability to manage VMs |
| libnotify | Send desktop notification with libnotify on sessions and db events |
Expand All @@ -42,12 +43,12 @@ The current available plugins for Metasploit can be found by running the `load -
| request | Make requests from within Metasploit using various protocols. |
| rssfeed | Create an RSS feed of events |
| sample | Demonstrates using framework plugins |
| session_notifier | This plugin notifies you of a new session via SMS |
| session_notifier | This plugin notifies you of a new session via SMS |
| session_tagger | Automatically interacts with new sessions to create a new remote TaggedByUser file |
| socket_logger | Log socket operations to a directory as individual files |
| sounds | Automatically plays a sound when various framework events occur |
| sqlmap | sqlmap plugin for Metasploit |
| thread | Internal test tool for testing thread usage in Metasploit |
| thread | Internal test tool for testing thread usage in Metasploit |
| token_adduser | Attempt to add an account using all connected Meterpreter session tokens |
| token_hunter | Search all active Meterpreter sessions for specific tokens |
| wiki | Outputs stored database values from the current workspace into DokuWiki or MediaWiki format |
Expand Down
150 changes: 150 additions & 0 deletions plugins/fzuse.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
require 'socket'

# this is the main routine that's executed in the grandchild process (msfconsole -> fzf -> this)
if $PROGRAM_NAME == __FILE__
exit 64 unless ARGV.length == 2

UNIXSocket.open(ARGV[0]) do |sock|
sock.write ARGV[1] + "\n"
sock.flush

puts sock.read
end
exit 0
end

module Msf
class Plugin::FuzzyUse < Msf::Plugin
class ConsoleCommandDispatcher
include Msf::Ui::Console::CommandDispatcher

FZF_THEME = {
'fg' => '-1',
'fg+' => 'white:regular:bold',
'bg' => '-1',
'bg+' => '-1',
'hl' => '-1',
'hl+' => 'red:regular:bold',
'info' => '-1',
'marker' => '-1',
'prompt' => '-1',
'spinner' => '-1',
'pointer' => 'blue:bold',
'header' => '-1',
'border' => '-1',
'label' => '-1',
'query' => '-1'
}.freeze

def initialize(driver)
super

@module_dispatcher = Msf::Ui::Console::CommandDispatcher::Modules.new(driver)
end

def name
'FuzzyUse'
end

#
# Returns the hash of commands supported by this dispatcher.
#
def commands
{
'fzuse' => 'A fuzzy use command added by the FuzzyUse plugin'
}
end

def pipe_server(socket_path)
server = UNIXServer.new(socket_path)
File.chmod(0600, socket_path)
loop do
client = server.accept
begin
unless (input_string = client.gets&.chomp).blank?
if (mod = framework.modules.create(input_string))
client.puts(Serializer::ReadableText.dump_module(mod))
end
end
rescue StandardError
end
client.close
end
rescue EOFError
ensure
server.close if server
File.delete(socket_path) if File.exist?(socket_path)
end

#
# This method handles the fzuse command.
#
def cmd_fzuse(*args)
selection = nil

Dir.mktmpdir('msf-fzuse-') do |dir|
socket_path = File.join(dir, "msf-fzuse.sock")
server_thread = Thread.new { pipe_server(socket_path) }

query = args.empty? ? '' : args.first
ruby = RbConfig::CONFIG['bindir'] + '/' + RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT']

color = "--color=#{FZF_THEME.map { |key, value| "#{key}:#{value}" }.join(',')}"
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|
framework.modules.module_types.each do |module_type|
framework.modules.module_names(module_type).each do |module_name|
stdin.puts "#{module_type}/#{module_name}"
end
end
stdin.close
selection = stdout.read
end

server_thread.kill
server_thread.join
end

return if selection.blank?

selection.strip!
@module_dispatcher.cmd_use(selection)
end
end

def initialize(framework, opts)
super

unless defined?(UNIXSocket)
# This isn't a requirement that can be fixed by installing something
print_error("The FuzzyUse plugin has loaded but the Ruby environment does not support UNIX sockets.")
return
end

missing_requirements = []
missing_requirements << 'fzf' unless Msf::Util::Helper.which('fzf')

unless missing_requirements.empty?
print_error("The FuzzyUse plugin has loaded but the following requirements are missing: #{missing_requirements.join(', ')}")
print_error("Please install the missing requirements, then reload the plugin by running: `unload fzuse` and `load fzuse`.")
return
end

add_console_dispatcher(ConsoleCommandDispatcher)

print_status('FuzzyUse plugin loaded.')
end

def cleanup
remove_console_dispatcher('FuzzyUse')
end

def name
'fuzzy_use'
end

def desc
'A plugin offering a fuzzy use command'
end

end
end

0 comments on commit c7d1e34

Please sign in to comment.