Skip to content

Commit d420bf1

Browse files
author
RageLtMan
committed
Pull out HTTP-specific code from PacketDispatcher
PacketDispatcher has some hardcoded assumptions about utilizing HTTP services as the async resource. With C2 and DNS tunnels in the pipeline, these elements need to be separated from the core functions of async packet dispatch and moved into their own module. This creates a new namespace for Meterpreter::HttpPacketDispatcher, meant to be mixed in after PacketDispatcher. The module implements only three of the original module's methods - init, shutdown, and the :on_passive_request callback; with the first two using :super, with the expectation of having a PacketDispatcher mixin or API compatible namespace already in the mix.
1 parent 8c2c30c commit d420bf1

File tree

1 file changed

+70
-53
lines changed

1 file changed

+70
-53
lines changed

lib/rex/post/meterpreter/packet_dispatcher.rb

Lines changed: 70 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -80,71 +80,23 @@ def initialize_passive_dispatcher
8080
self.recv_queue = []
8181
self.waiters = []
8282
self.alive = true
83-
84-
# Ensure that there is only one leading and trailing slash on the URI
85-
resource_uri = "/" + self.conn_id.to_s.gsub(/(^\/|\/$)/, '') + "/"
86-
87-
self.passive_service = self.passive_dispatcher
88-
self.passive_service.remove_resource(resource_uri)
89-
self.passive_service.add_resource(resource_uri,
90-
'Proc' => Proc.new { |cli, req| on_passive_request(cli, req) },
91-
'VirtualDirectory' => true
92-
)
9383
end
9484

9585
def shutdown_passive_dispatcher
96-
return if not self.passive_service
97-
98-
# Ensure that there is only one leading and trailing slash on the URI
99-
resource_uri = "/" + self.conn_id.to_s.gsub(/(^\/|\/$)/, '') + "/"
100-
101-
self.passive_service.remove_resource(resource_uri)
102-
103-
# If there are no more resources registered on the service, stop it entirely
104-
if self.passive_service.resources.empty?
105-
Rex::ServiceManager.stop_service(self.passive_service)
106-
end
107-
10886
self.alive = false
10987
self.send_queue = []
11088
self.recv_queue = []
11189
self.waiters = []
112-
113-
self.passive_service = nil
11490
end
11591

11692
def on_passive_request(cli, req)
117-
11893
begin
119-
120-
resp = Rex::Proto::Http::Response.new(200, "OK")
121-
resp['Content-Type'] = 'application/octet-stream'
122-
resp['Connection'] = 'close'
123-
124-
self.last_checkin = Time.now
125-
126-
if req.method == 'GET'
127-
rpkt = send_queue.shift
128-
resp.body = rpkt || ''
129-
begin
130-
cli.send_response(resp)
131-
rescue ::Exception => e
132-
send_queue.unshift(rpkt) if rpkt
133-
elog("Exception sending a reply to the reader request: #{cli.inspect} #{e.class} #{e} #{e.backtrace}")
134-
end
135-
else
136-
resp.body = ""
137-
if req.body and req.body.length > 0
138-
packet = Packet.new(0)
139-
packet.add_raw(req.body)
140-
packet.parse_header!
141-
dispatch_inbound_packet(packet)
142-
end
94+
self.last_checkin = Time.now
95+
resp = send_queue.shift
14396
cli.send_response(resp)
144-
end
145-
146-
rescue ::Exception => e
147-
elog("Exception handling request: #{cli.inspect} #{req.inspect} #{e.class} #{e} #{e.backtrace}")
97+
rescue => e
98+
send_queue.unshift(resp) if resp
99+
elog("Exception sending a reply to the reader request: #{cli.inspect} #{e.class} #{e} #{e.backtrace}")
148100
end
149101
end
150102

@@ -625,5 +577,70 @@ def deregister_inbound_handler(handler)
625577
attr_accessor :waiters # :nodoc:
626578
end
627579

580+
module HttpPacketDispatcher
581+
def initialize_passive_dispatcher
582+
super
583+
584+
# Ensure that there is only one leading and trailing slash on the URI
585+
resource_uri = "/" + self.conn_id.to_s.gsub(/(^\/|\/$)/, '') + "/"
586+
self.passive_service = self.passive_dispatcher
587+
self.passive_service.remove_resource(resource_uri)
588+
self.passive_service.add_resource(resource_uri,
589+
'Proc' => Proc.new { |cli, req| on_passive_request(cli, req) },
590+
'VirtualDirectory' => true
591+
)
592+
end
593+
594+
def shutdown_passive_dispatcher
595+
if self.passive_service
596+
# Ensure that there is only one leading and trailing slash on the URI
597+
resource_uri = "/" + self.conn_id.to_s.gsub(/(^\/|\/$)/, '') + "/"
598+
self.passive_service.remove_resource(resource_uri) if self.passive_service
599+
600+
if self.passive_service.resources.empty?
601+
Rex::ServiceManager.stop_service(self.passive_service)
602+
end
603+
self.passive_service = nil
604+
end
605+
super
606+
end
607+
608+
def on_passive_request(cli, req)
609+
610+
begin
611+
612+
resp = Rex::Proto::Http::Response.new(200, "OK")
613+
resp['Content-Type'] = 'application/octet-stream'
614+
resp['Connection'] = 'close'
615+
616+
self.last_checkin = Time.now
617+
618+
if req.method == 'GET'
619+
rpkt = send_queue.shift
620+
resp.body = rpkt || ''
621+
begin
622+
cli.send_response(resp)
623+
rescue ::Exception => e
624+
send_queue.unshift(rpkt) if rpkt
625+
elog("Exception sending a reply to the reader request: #{cli.inspect} #{e.class} #{e} #{e.backtrace}")
626+
end
627+
else
628+
resp.body = ""
629+
if req.body and req.body.length > 0
630+
packet = Packet.new(0)
631+
packet.add_raw(req.body)
632+
packet.parse_header!
633+
dispatch_inbound_packet(packet)
634+
end
635+
cli.send_response(resp)
636+
end
637+
638+
rescue ::Exception => e
639+
elog("Exception handling request: #{cli.inspect} #{req.inspect} #{e.class} #{e} #{e.backtrace}")
640+
end
641+
end
642+
643+
end
644+
628645
end; end; end
629646

0 commit comments

Comments
 (0)