diff --git a/documentation/TODO b/documentation/TODO index d6cfbe46a8..519fa6d697 100644 --- a/documentation/TODO +++ b/documentation/TODO @@ -59,4 +59,4 @@ N - dupe input instance when passing to sessions - etc X - fix module loading order X - problems with dllinject getting loaded after meterpreter due to dependencies -- fix default handle inheritance in meterp process execution +X - fix default handle inheritance in meterp process execution diff --git a/lib/msf/base/simple/exploit.rb b/lib/msf/base/simple/exploit.rb index efce1eef7f..23cf0d5cda 100644 --- a/lib/msf/base/simple/exploit.rb +++ b/lib/msf/base/simple/exploit.rb @@ -40,6 +40,12 @@ module Exploit driver.target_idx = target_idx driver.payload = exploit.framework.modules.create(opts['Payload']) + # Was the payload valid? + if (driver.payload == nil) + raise MissingPayloadError, + "You specified an invalid payload: #{opts['Payload']}", caller + end + # Force the payload to share the exploit's datastore driver.payload.share_datastore(driver.exploit.datastore) diff --git a/lib/msf/core/exploit/brute.rb b/lib/msf/core/exploit/brute.rb index 759ded61f3..790dbf1953 100644 --- a/lib/msf/core/exploit/brute.rb +++ b/lib/msf/core/exploit/brute.rb @@ -42,8 +42,8 @@ module Exploit::Brute bf = target.bruteforce # Get the start and stop address hashes - start = (bf.start_addresses && bf.start_address.dup) || {} - stop = (bf.stop_addresses && bf.stop_address.dup) || {} + start = bf.start_addresses ? bf.start_address.dup : {} + stop = bf.stop_addresses ? bf.stop_address.dup : {} step = bf.step_size delay = bf.delay diff --git a/lib/msf/core/exploit/tcp.rb b/lib/msf/core/exploit/tcp.rb index 92512e7e65..3f5bad9695 100644 --- a/lib/msf/core/exploit/tcp.rb +++ b/lib/msf/core/exploit/tcp.rb @@ -111,4 +111,87 @@ protected end + +### +# +# TcpServer +# --------- +# +# This mixin provides a generic interface for running a TCP server of some +# sort that is designed to exploit clients. Exploits that include this mixin +# automatically take a passive stance. +# +### +module Exploit::Remote::TcpServer + + def initialize(info = {}) + super(update_info(info, + 'Stance' => Msf::Exploit::Stance::Passive)) + + register_options( + [ + OptAddress.new('SRVHOST', [ true, "The local host to listen on." ]), + OptPort.new('SRVPORT', [ true, "The local port to listen on." ]) + ], Msf::Exploit::Remote::TcpServer) + end + + # + # This mixin overrides the exploit method so that it can initiate the + # service that corresponds with what the client has requested. + # + def exploit + start_service + end + + # + # Stops the service, if one was created. + # + def cleanup + stop_service + end + + # + # Starts the service. + # + def start_service + if (service_klass) + else + end + end + + # + # Stops the service. + # + def stop_service + end + + # + # Returns the local host that is being listened on. + # + def srvhost + datastore['SRVHOST'] + end + + # + # Returns the local port that is being listened on. + # + def srvport + datastore['SRVPORT'] + end + +protected + + # + # Returns the protocol class that should be used as an implementator for + # the service for this mixin. If it's nil then we just use the + # Rex::Socket::TcpServer class to implement a TCP server. + # + def service_klass + nil + end + + attr_accessor :service + +end + end diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index 5ed35114f9..27893ed332 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -541,6 +541,14 @@ protected def show_options(mod) print("\n" + Serializer::ReadableText.dump_options(mod) + "\n") + + if (mod.exploit?) + p = framework.modules.create(mod.datastore['PAYLOAD']) + + if (p) + print(" Payload options:\n\n" + Serializer::ReadableText.dump_options(p) + "\n"); + end + end end def show_advanced_options(mod) diff --git a/lib/rex.rb b/lib/rex.rb index e2037b2548..3386073a0d 100644 --- a/lib/rex.rb +++ b/lib/rex.rb @@ -12,6 +12,7 @@ require 'rex/string_utils' # Thread safety and synchronization require 'rex/thread_safe' +require 'rex/ref' require 'rex/read_write_lock' require 'rex/sync/event' diff --git a/lib/rex/proto/http/server.rb.ut.rb b/lib/rex/proto/http/server.rb.ut.rb index 1f54371fc0..72b8910b4a 100644 --- a/lib/rex/proto/http/server.rb.ut.rb +++ b/lib/rex/proto/http/server.rb.ut.rb @@ -33,15 +33,15 @@ class Rex::Proto::Http::Server::UnitTest < Test::Unit::TestCase begin s = start_srv c = CliKlass.new(ListenHost, ListenPort) - p = Proc.new { |cli, req| - resp = Rex::Proto::Http::Response::OK.new - resp.body = "Chickens everywhere" - - cli.send_response(resp) - } + s.add_resource('/foo', + 'Proc' => Proc.new { |cli, req| + resp = Rex::Proto::Http::Response::OK.new - s.add_resource('/foo', 'Proc' => p) + resp.body = "Chickens everywhere" + + cli.send_response(resp) + }) 1.upto(10) { req = Rex::Proto::Http::Request::Get.new('/foo') @@ -52,16 +52,11 @@ class Rex::Proto::Http::Server::UnitTest < Test::Unit::TestCase } s.remove_resource('/foo') - - # - # This stuff crashes ruby, possibly because, specifically sending the - # request to the removed resource. Seems like it causes it to - # reference something that's been marked for GC - # - #req = Rex::Proto::Http::Request::Get.new('/foo') - #res = c.send_request(req) - #assert_not_nil(res) - #assert_equal(404, res.code) + + req = Rex::Proto::Http::Request::Get.new('/foo') + res = c.send_request(req) + assert_not_nil(res) + assert_equal(404, res.code) ensure stop_srv end diff --git a/lib/rex/ref.rb b/lib/rex/ref.rb index f981a2cb75..6da3c14436 100644 --- a/lib/rex/ref.rb +++ b/lib/rex/ref.rb @@ -40,9 +40,21 @@ module Ref # def deref @_references_mutex.synchronize { - ((@_references -= 1) == 0) ? true : false + if ((@_references -= 1) == 0) + cleanup + + true + else + false + end } end + # + # Called to clean up resources once the ref count drops to zero. + # + def cleanup + end + end end diff --git a/lib/rex/service.rb b/lib/rex/service.rb index 13ad4b06f2..32041db5fc 100644 --- a/lib/rex/service.rb +++ b/lib/rex/service.rb @@ -17,6 +17,13 @@ module Rex ### module Service include Ref + + # + # Calls stop on the service once the ref count drops. + # + def cleanup + stop + end end end diff --git a/lib/rex/service_manager.rb b/lib/rex/service_manager.rb index 04926e89c8..9c6e26ba80 100644 --- a/lib/rex/service_manager.rb +++ b/lib/rex/service_manager.rb @@ -80,8 +80,6 @@ class ServiceManager < Hash # references has dropped to zero if ((inst = self[als]) and (inst.deref)) - inst.stop - # Since the instance may have multiple aliases, scan through # all the pairs for matching stuff. self.each_pair { |cals, cinst|