2005-04-10 02:05:43 +00:00
|
|
|
#!/usr/bin/ruby
|
|
|
|
|
2005-07-09 21:18:49 +00:00
|
|
|
require 'rex/post/meterpreter/packet_response_waiter'
|
2005-04-10 02:05:43 +00:00
|
|
|
|
|
|
|
module Rex
|
|
|
|
module Post
|
|
|
|
module Meterpreter
|
|
|
|
|
2005-07-19 04:21:15 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Exception thrown when a request fails.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class RequestError < ArgumentError
|
|
|
|
def initialize(method, result)
|
|
|
|
@method = method
|
|
|
|
@result = result
|
|
|
|
end
|
|
|
|
def to_s
|
|
|
|
"#{@method}: Operation failed: #{@result}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-04-10 02:05:43 +00:00
|
|
|
###
|
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
# Handles packet transmission, reception, and correlation,
|
|
|
|
# and processing
|
2005-04-10 02:05:43 +00:00
|
|
|
#
|
|
|
|
###
|
|
|
|
module PacketDispatcher
|
|
|
|
|
2005-04-12 05:37:11 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Transmission
|
|
|
|
#
|
|
|
|
##
|
2005-04-10 02:05:43 +00:00
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Sends a packet without waiting for a response.
|
|
|
|
#
|
2005-04-10 02:05:43 +00:00
|
|
|
def send_packet(packet, completion_routine = nil, completion_param = nil)
|
|
|
|
if (completion_routine)
|
|
|
|
add_response_waiter(packet, completion_routine, completion_param)
|
|
|
|
end
|
|
|
|
|
|
|
|
bytes = 0
|
|
|
|
raw = packet.to_r
|
|
|
|
|
|
|
|
if (raw)
|
|
|
|
bytes = self.sock.write(raw)
|
|
|
|
end
|
|
|
|
|
|
|
|
return bytes
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Sends a packet and waits for a timeout for the given time interval.
|
|
|
|
#
|
2005-07-08 00:28:52 +00:00
|
|
|
def send_request(packet, t = self.response_timeout)
|
2005-04-10 16:21:53 +00:00
|
|
|
response = send_packet_wait_response(packet, t)
|
|
|
|
|
|
|
|
if (response == nil)
|
2005-07-19 04:21:15 +00:00
|
|
|
raise TimeoutError
|
2005-04-10 16:21:53 +00:00
|
|
|
elsif (response.result != 0)
|
2005-07-19 04:21:15 +00:00
|
|
|
e = RequestError.new(packet.method, response.result)
|
|
|
|
|
|
|
|
e.set_backtrace(caller)
|
|
|
|
|
|
|
|
raise e
|
2005-04-10 16:21:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
return response
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Transmits a packet and waits for a response.
|
|
|
|
#
|
2005-04-10 02:05:43 +00:00
|
|
|
def send_packet_wait_response(packet, t)
|
|
|
|
# First, add the waiter association for the supplied packet
|
|
|
|
waiter = add_response_waiter(packet)
|
|
|
|
|
|
|
|
# Transmit the packet
|
|
|
|
if (send_packet(packet) <= 0)
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
# Wait for the supplied time interval
|
|
|
|
waiter.wait(t)
|
|
|
|
|
|
|
|
# Remove the waiter from the list of waiters in case it wasn't
|
|
|
|
# removed
|
|
|
|
remove_response_waiter(waiter)
|
|
|
|
|
|
|
|
# Return the response packet, if any
|
|
|
|
return waiter.response
|
|
|
|
end
|
|
|
|
|
2005-04-12 05:37:11 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Reception
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
# Monitors the PacketDispatcher's sock for data in its own
|
2005-11-15 05:22:13 +00:00
|
|
|
# thread context and parsers all inbound packets.
|
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
def monitor_socket
|
|
|
|
self.waiters = []
|
|
|
|
|
|
|
|
# Spawn a new thread that monitors the socket
|
2005-06-21 01:48:20 +00:00
|
|
|
thr = ::Thread.new {
|
2005-04-12 05:37:11 +00:00
|
|
|
while (true)
|
2005-07-18 05:59:27 +00:00
|
|
|
begin
|
|
|
|
rv = Rex::ThreadSafe.select([ self.sock.fd ], nil, nil, 2)
|
|
|
|
rescue
|
|
|
|
dlog("Exception caught in monitor_socket: #{$!}", 'meterpreter', LEV_1)
|
|
|
|
end
|
2005-04-12 05:37:11 +00:00
|
|
|
|
|
|
|
begin
|
|
|
|
packet = receive_packet
|
|
|
|
rescue EOFError
|
|
|
|
break
|
|
|
|
end
|
|
|
|
|
|
|
|
if (packet)
|
|
|
|
dispatch_inbound_packet(packet)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
# Parses data from the dispatcher's sock and returns a Packet context
|
2005-11-15 05:22:13 +00:00
|
|
|
# once a full packet has been received.
|
|
|
|
#
|
2005-04-10 02:05:43 +00:00
|
|
|
def receive_packet
|
|
|
|
return parser.recv(self.sock)
|
|
|
|
end
|
|
|
|
|
2005-04-12 05:37:11 +00:00
|
|
|
|
|
|
|
##
|
|
|
|
#
|
|
|
|
# Waiter registration
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Adds a waiter association with the supplied request packet.
|
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
def add_response_waiter(request, completion_routine = nil, completion_param = nil)
|
|
|
|
waiter = PacketResponseWaiter.new(request.rid, completion_routine, completion_param)
|
|
|
|
|
|
|
|
self.waiters << waiter
|
|
|
|
|
|
|
|
return waiter
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
# Notifies a whomever is waiting for a the supplied response,
|
2005-11-15 05:22:13 +00:00
|
|
|
# if anyone.
|
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
def notify_response_waiter(response)
|
|
|
|
self.waiters.each() { |waiter|
|
|
|
|
if (waiter.waiting_for?(response))
|
|
|
|
waiter.notify(response)
|
|
|
|
|
|
|
|
remove_response_waiter(waiter)
|
|
|
|
|
|
|
|
break
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Removes a waiter from the list of waiters.
|
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
def remove_response_waiter(waiter)
|
|
|
|
self.waiters.delete(waiter)
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
#
|
|
|
|
# Dispatching
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Initializes the inbound handlers.
|
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
def initialize_inbound_handlers
|
|
|
|
@inbound_handlers = []
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
# Dispatches and processes an inbound packet. If the packet is a
|
|
|
|
# response that has an associated waiter, the waiter is notified.
|
|
|
|
# Otherwise, the packet is passed onto any registered dispatch
|
|
|
|
# handlers until one returns success.
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
def dispatch_inbound_packet(packet, client = nil)
|
|
|
|
handled = false
|
|
|
|
|
|
|
|
# If no client context was provided, return self as PacketDispatcher
|
|
|
|
# is a mixin for the Client instance
|
|
|
|
if (client == nil)
|
|
|
|
client = self
|
|
|
|
end
|
|
|
|
|
2005-07-08 00:28:52 +00:00
|
|
|
#puts "Inbound packet: rid=#{packet.rid} method=#{packet.method}\n"
|
2005-04-12 05:37:11 +00:00
|
|
|
|
|
|
|
# If the packet is a response, try to notify any potential
|
|
|
|
# waiters
|
|
|
|
if ((resp = packet.response?))
|
|
|
|
if (notify_response_waiter(packet))
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Enumerate all of the inbound packet handlers until one handles
|
|
|
|
# the packet
|
|
|
|
@inbound_handlers.each { |handler|
|
|
|
|
|
|
|
|
if (!resp)
|
|
|
|
handled = handler.request_handler(client, packet)
|
|
|
|
else
|
|
|
|
handled = handler.response_handler(client, packet)
|
|
|
|
end
|
|
|
|
|
|
|
|
if (handled)
|
|
|
|
break
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
return handled
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
# Registers an inbound packet handler that implements the
|
|
|
|
# InboundPacketHandler interface.
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
def register_inbound_handler(handler)
|
|
|
|
@inbound_handlers << handler
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Deregisters a previously registered inbound packet handler.
|
|
|
|
#
|
2005-04-12 05:37:11 +00:00
|
|
|
def deregister_inbound_handler(handler)
|
|
|
|
@inbound_handlers.delete(handler)
|
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
attr_accessor :waiters # :nodoc:
|
2005-04-10 02:05:43 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end; end; end
|