diff --git a/lib/msf/base/simple/exploit.rb b/lib/msf/base/simple/exploit.rb index 156e2d1d3a..b081e8ebeb 100644 --- a/lib/msf/base/simple/exploit.rb +++ b/lib/msf/base/simple/exploit.rb @@ -51,30 +51,17 @@ module Exploit # job. # def self.exploit_simple(exploit, opts) - target_idx = opts['Target'] || exploit.default_target - # Make sure parameters are valid. if (opts['Payload'] == nil) raise MissingPayloadError, "You must specify a payload.", caller end - # Convert it to an integer if it's valid - if (target_idx) - target_idx = target_idx.to_i - end - - if (target_idx == nil or target_idx < 0) - raise MissingTargetError, - "You must select a target.", caller - end - # Start it up driver = ExploitDriver.new(exploit.framework) # Initialize the driver instance driver.exploit = exploit - driver.target_idx = target_idx driver.payload = exploit.framework.modules.create(opts['Payload']) # Set the force wait for session flag if the caller requested force @@ -91,6 +78,25 @@ module Exploit # Force the payload to share the exploit's datastore driver.payload.share_datastore(driver.exploit.datastore) + # If we still have no target index, try to use the datastore's index + target_idx = opts['Target'] || exploit.default_target + + if (target_idx == nil) + driver.exploit.target_idx = exploit.datastore['TARGET'] + end + + # Convert it to an integer if it's valid + if (target_idx) + target_idx = target_idx.to_i + end + + if (target_idx == nil or target_idx < 0) + raise MissingTargetError, + "You must select a target.", caller + end + + driver.target_idx = target_idx + # Set the payload and exploit's subscriber values driver.exploit.init_ui(opts['LocalInput'], opts['LocalOutput']) driver.payload.init_ui(opts['LocalInput'], opts['LocalOutput']) diff --git a/lib/msf/core/encoder.rb b/lib/msf/core/encoder.rb index b67ba5a0dc..ef3b95d617 100644 --- a/lib/msf/core/encoder.rb +++ b/lib/msf/core/encoder.rb @@ -142,7 +142,7 @@ class Encoder < Module # an exception will be thrown if an error is encountered during the # encoding process. # - def encode(buf, badchars, state = nil) + def encode(buf, badchars = nil, state = nil) # Initialize an empty set of bad characters badchars = '' if (!badchars) diff --git a/lib/msf/ui/console/driver.rb b/lib/msf/ui/console/driver.rb index 24b8e1caaf..9a77da24a1 100644 --- a/lib/msf/ui/console/driver.rb +++ b/lib/msf/ui/console/driver.rb @@ -21,6 +21,9 @@ class Driver < Msf::Ui::Driver ConfigCore = "framework/core" ConfigGroup = "framework/ui/console" + DefaultPrompt = "%umsf" + DefaultPromptChar = ">%c" + # # The console driver processes various framework notified events. # @@ -33,11 +36,12 @@ class Driver < Msf::Ui::Driver # # Initializes a console driver instance with the supplied prompt string and - # prompt character. + # prompt character. The optional hash can take extra values that will + # serve to initialize the console driver. # - def initialize(prompt = "%umsf", prompt_char = ">%c") + def initialize(prompt = DefaultPrompt, prompt_char = DefaultPromptChar, opts = {}) # Call the parent - super + super(prompt, prompt_char) # Temporarily disable output self.disable_output = true @@ -46,7 +50,15 @@ class Driver < Msf::Ui::Driver load_preconfig # Initialize attributes - self.framework = Msf::Simple::Framework.create + self.framework = opts['Framework'] || Msf::Simple::Framework.create + + # Initialize the user interface to use a different input and output + # handle if one is supplied + if (opts['LocalInput'] or opts['LocalOutput']) + init_ui( + opts['LocalInput'], + opts['LocalOutput']) + end # Add the core command dispatcher as the root of the dispatcher # stack diff --git a/lib/rex/ui/text/input.rb b/lib/rex/ui/text/input.rb index 73493a2221..40dbcc311c 100644 --- a/lib/rex/ui/text/input.rb +++ b/lib/rex/ui/text/input.rb @@ -15,11 +15,19 @@ class Input require 'rex/ui/text/input/stdio' require 'rex/ui/text/input/readline' + require 'rex/ui/text/input/socket' def initialize self.eof = false end + # + # Whether or not the input medium supports readline. + # + def supports_readline + true + end + # # Gets a line of input # diff --git a/lib/rex/ui/text/input/socket.rb b/lib/rex/ui/text/input/socket.rb new file mode 100644 index 0000000000..27c1fc9692 --- /dev/null +++ b/lib/rex/ui/text/input/socket.rb @@ -0,0 +1,58 @@ +require 'rex/ui' + +module Rex +module Ui +module Text + +### +# +# This class implements input against a socket. +# +### +class Input::Socket < Rex::Ui::Text::Input + + def initialize(sock) + @sock = sock + end + + # + # Sockets do not currently support readline. + # + def supports_readline + false + end + + # + # Wait for a line of input to be read from a socket. + # + def gets + return @sock.gets + end + + # + # Print a prompt and flush to the socket. + # + def _print_prompt(prompt) + @sock.write(prompt) + @sock.flush + prompt + end + + # + # Returns whether or not EOF has been reached on stdin. + # + def eof? + @sock.closed? + end + + # + # Returns the file descriptor associated with a socket. + # + def fd + return @sock + end +end + +end +end +end diff --git a/lib/rex/ui/text/output.rb b/lib/rex/ui/text/output.rb index 970a18bdba..c6508cc3e9 100644 --- a/lib/rex/ui/text/output.rb +++ b/lib/rex/ui/text/output.rb @@ -13,6 +13,7 @@ module Text class Output < Rex::Ui::Output require 'rex/ui/text/output/stdio' + require 'rex/ui/text/output/socket' require 'rex/ui/text/output/buffer' def print_error(msg = '') diff --git a/lib/rex/ui/text/output/socket.rb b/lib/rex/ui/text/output/socket.rb new file mode 100644 index 0000000000..5045c82d90 --- /dev/null +++ b/lib/rex/ui/text/output/socket.rb @@ -0,0 +1,31 @@ +require 'rex/ui' + +module Rex +module Ui +module Text + +### +# +# This class implements the output interface against a socket. +# +### +class Output::Socket < Rex::Ui::Text::Output + + def initialize(sock) + @sock = sock + end + + # + # Prints the supplied message to the socket. + # + def print(msg = '') + @sock.write(msg) + @sock.flush + + msg + end +end + +end +end +end diff --git a/lib/rex/ui/text/shell.rb b/lib/rex/ui/text/shell.rb index 74055e4229..f5ac940f14 100644 --- a/lib/rex/ui/text/shell.rb +++ b/lib/rex/ui/text/shell.rb @@ -53,7 +53,9 @@ module Shell if (self.input) begin - self.input = Input::Readline.new(lambda { |str| tab_complete(str) }) + if (self.input.supports_readline) + self.input = Input::Readline.new(lambda { |str| tab_complete(str) }) + end rescue end diff --git a/msfd b/msfd new file mode 100755 index 0000000000..21db365c75 --- /dev/null +++ b/msfd @@ -0,0 +1,62 @@ +#!/usr/bin/ruby + +$:.unshift(File.join(File.dirname(__FILE__), '../lib')) + +require 'msf/base' +require 'msf/ui' + +# Declare the argument parser for msfweb +arguments = Rex::Parser::Arguments.new( + "-a" => [ true, "Bind to this IP address instead of loopback" ], + "-p" => [ true, "Bind to this port instead of 55554" ], + "-h" => [ false, "Help banner" ]) + +opts = {} +foreground = false + +# Parse command line arguments. +arguments.parse(ARGV) { |opt, idx, val| + case opt + when "-a" + opts['ServerHost'] = val + when "-p" + opts['ServerPort'] = val + when "-f" + foreground = true + when "-h" + print( + "\nUsage: #{File.basename(__FILE__)} \n" + + arguments.usage) + exit + end +} + +# Create an instance of the framework +$framework = Msf::Simple::Framework.create + +server = Rex::Socket::TcpServer.create( + 'LocalHost' => opts['ServerHost'], + 'LocalPort' => opts['ServerPort'] || 55554) + +exit if (Process.fork()) unless foreground + +begin + client = server.accept + + Thread.new { + begin + Msf::Ui::Console::Driver.new( + Msf::Ui::Console::Driver::DefaultPrompt, + Msf::Ui::Console::Driver::DefaultPromptChar, + 'Framework' => $framework, + 'LocalInput' => Rex::Ui::Text::Input::Socket.new(client), + 'LocalOutput' => Rex::Ui::Text::Output::Socket.new(client)).run + + client.shutdown + client.close + rescue + puts "Error: #{$!}\n\n#{$@.join("\n")}" + end + } + +end while true