Land #18144, update capture plugin to be more helpful, and add documentation
This commit is contained in:
commit
88a539a82c
|
@ -0,0 +1,37 @@
|
|||
Capturing credentials is a critical and early phase in the playbook of many offensive security testers. Metasploit has facilitated this for years with protocol-specific modules all under the auxiliary/server/capture. Users can start and configure each of these modules individually, but now the capture plugin can streamline the process. The capture plugin can easily start 13 different services (17 including SSL enabled versions) on the same listening IP address including remote interfaces via Meterpreter. A configuration file can be used to select individual services to start and once finished, all services can easily be stopped using a single command.
|
||||
|
||||
To use the plugin, it must first be loaded. That will provide the captureg command (for Capture-Global) which then offers start and stop subcommands. In the following example, the plugin is loaded, and then all default services are started on the 192.168.159.128 interface.
|
||||
|
||||
```
|
||||
msf6 > load capture
|
||||
[*] Successfully loaded plugin: Credential Capture
|
||||
msf6 > captureg start --ip 192.168.159.128
|
||||
Logging results to /home/smcintyre/.msf4/logs/captures/capture_local_20220325104416_589275.txt
|
||||
Hash results stored in /home/smcintyre/.msf4/loot/captures/capture_local_20220325104416_612808
|
||||
[+] Authentication Capture: DRDA (DB2, Informix, Derby) started
|
||||
[+] Authentication Capture: FTP started
|
||||
[+] HTTP Client MS Credential Catcher started
|
||||
[+] HTTP Client MS Credential Catcher started
|
||||
[+] Authentication Capture: IMAP started
|
||||
[+] Authentication Capture: MSSQL started
|
||||
[+] Authentication Capture: MySQL started
|
||||
[+] Authentication Capture: POP3 started
|
||||
[+] Authentication Capture: PostgreSQL started
|
||||
[+] Printjob Capture Service started
|
||||
[+] Authentication Capture: SIP started
|
||||
[+] Authentication Capture: SMB started
|
||||
[+] Authentication Capture: SMTP started
|
||||
[+] Authentication Capture: Telnet started
|
||||
[+] Authentication Capture: VNC started
|
||||
[+] Authentication Capture: FTP started
|
||||
[+] Authentication Capture: IMAP started
|
||||
[+] Authentication Capture: POP3 started
|
||||
[+] Authentication Capture: SMTP started
|
||||
[+] NetBIOS Name Service Spoofer started
|
||||
[+] LLMNR Spoofer started
|
||||
[+] mDNS Spoofer started
|
||||
[+] Started capture jobs
|
||||
msf6 >
|
||||
```
|
||||
|
||||
This content was originally posted on the [Rapid7 Blog](https://www.rapid7.com/blog/post/2022/03/25/metasploit-weekly-wrap-up-154/).
|
|
@ -623,6 +623,10 @@ NAVIGATION_CONFIG = [
|
|||
path: 'How-to-use-the-Git-mixin-to-write-an-exploit-module.md',
|
||||
title: 'Git Mixin'
|
||||
},
|
||||
{
|
||||
path: 'How-To-Use-The-Capture-Plugin.md',
|
||||
title: 'Capture Plugin'
|
||||
},
|
||||
{
|
||||
title: 'HTTP',
|
||||
folder: 'http',
|
||||
|
|
|
@ -13,14 +13,15 @@ module Msf
|
|||
include Msf::Ui::Console::CommandDispatcher
|
||||
|
||||
class CaptureJobListener
|
||||
def initialize(name, done_event)
|
||||
def initialize(name, done_event, dispatcher)
|
||||
@name = name
|
||||
@done_event = done_event
|
||||
@dispatcher = dispatcher
|
||||
end
|
||||
|
||||
def waiting(_id)
|
||||
self.succeeded = true
|
||||
print_good("#{@name} started")
|
||||
@dispatcher.print_good("#{@name} started")
|
||||
@done_event.set
|
||||
end
|
||||
|
||||
|
@ -29,7 +30,7 @@ module Msf
|
|||
def completed(id, result, mod); end
|
||||
|
||||
def failed(_id, _error, _mod)
|
||||
print_error("#{@name} failed to start")
|
||||
@dispatcher.print_error("#{@name} failed to start")
|
||||
@done_event.set
|
||||
end
|
||||
|
||||
|
@ -82,6 +83,7 @@ module Msf
|
|||
# short circuit the whole deal if they need help
|
||||
return help if args.empty?
|
||||
return help if args.length == 1 && args.first =~ HELP_REGEX
|
||||
return help(args.last) if args.length == 2 && args.first =~ HELP_REGEX
|
||||
|
||||
begin
|
||||
if args.first == 'stop'
|
||||
|
@ -322,7 +324,7 @@ module Msf
|
|||
|
||||
modules_to_run.each do |svc, mod, opts|
|
||||
event = Rex::Sync::Event.new(false, false)
|
||||
job_listener = CaptureJobListener.new(mod.name, event)
|
||||
job_listener = CaptureJobListener.new(mod.name, event, self)
|
||||
|
||||
result = Msf::Simple::Auxiliary.run_simple(mod, opts, job_listener: job_listener)
|
||||
job_id = result[1]
|
||||
|
@ -389,6 +391,8 @@ module Msf
|
|||
print_line(@stop_opt_parser.usage)
|
||||
else
|
||||
print_line('Usage: captureg [start|stop] [options]')
|
||||
print_line('')
|
||||
print_line('Use captureg --help [start|stop] for more detailed usage help')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
require 'spec_helper'
|
||||
require Metasploit::Framework.root.join('plugins/capture.rb').to_path
|
||||
|
||||
RSpec.describe Msf::Plugin::Capture::ConsoleCommandDispatcher do
|
||||
describe '#cmd_captureg' do
|
||||
let(:driver) do
|
||||
double(Object).as_null_object.tap do |dbl|
|
||||
allow(dbl).to receive(:print_line) do |args|
|
||||
args
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
subject { described_class.new(driver) }
|
||||
context 'without args' do
|
||||
it 'returns generic help text' do
|
||||
expect(subject.cmd_captureg).to eql subject.help
|
||||
end
|
||||
end
|
||||
|
||||
context 'single arg matching the HELP regex' do
|
||||
it 'returns generic help text' do
|
||||
expect(subject.cmd_captureg('--help')).to eql subject.help
|
||||
end
|
||||
end
|
||||
|
||||
context 'two args, first one matches HELP regex' do
|
||||
it 'calls `help` with second arg' do
|
||||
expect(subject.cmd_captureg('--help', 'start')).to eql subject.help('start')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.describe Msf::Plugin::Capture::ConsoleCommandDispatcher::CaptureJobListener do
|
||||
let(:dispatcher) do
|
||||
instance_double(
|
||||
Msf::Plugin::Capture::ConsoleCommandDispatcher,
|
||||
print_error: nil,
|
||||
print_good: nil
|
||||
)
|
||||
end
|
||||
let(:done_event) { instance_double(Rex::Sync::Event, set: nil) }
|
||||
let(:name) { 'my-little-module' }
|
||||
|
||||
subject { described_class.new(name, done_event, dispatcher) }
|
||||
|
||||
describe '#waiting' do
|
||||
it 'sets the `succeeded` flag' do
|
||||
subject.waiting('ignored')
|
||||
|
||||
expect(subject.succeeded).to eql true
|
||||
end
|
||||
|
||||
it 'outputs a message via the dispatcher' do
|
||||
expect(dispatcher).to receive(:print_good).with("#{name} started")
|
||||
|
||||
subject.waiting('ignored')
|
||||
end
|
||||
|
||||
it 'sets the done event' do
|
||||
expect(done_event).to receive(:set)
|
||||
|
||||
subject.waiting('ignored')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#failed' do
|
||||
it 'outputs a message via the dispatcher' do
|
||||
expect(dispatcher).to receive(:print_error).with("#{name} failed to start")
|
||||
|
||||
subject.failed('ignored', 'ignored', 'ignored')
|
||||
end
|
||||
|
||||
it 'sets the done event' do
|
||||
expect(done_event).to receive(:set)
|
||||
|
||||
subject.failed('ignored', 'ignored', 'ignored')
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue