module Msf module Session ### # # Basic # ----- # # This class implements an interactive session using raw input/output in # only the most basic fashion. # ### module Basic include Session include Interactive # # Initialize's the raw session # def initialize(rstream) self.rstream = rstream end # # Returns that, yes, indeed, this session supports going interactive with # the user. # def interactive? true end # # Closes rstream. # def cleanup rstream.close if (rstream) rstream = nil end # # Starts interacting with the session at the most raw level, simply # forwarding input from linput to rstream and forwarding input from # rstream to loutput. # def interact callcc { |ctx| while true begin _interact # If we get an interrupt exception, ask the user if they want to # abort the interaction. If they do, then we return out of # the interact function and call it a day. rescue Interrupt loutput.print("\nStop interacting with session #{sname}? [y/N] ") r = linput.gets # Break out of the continuation ctx.call if (r =~ /^y/i) rescue EOFError loutput.print_line("Session #{sname} terminating...") ctx.call end end } end # # The local input handle. Must inherit from Rex::Ui::Text::Input. # attr_accessor :linput # # The local output handle. Must inherit from Rex::Ui::Output. # attr_accessor :loutput # # The remote stream handle. Must inherit from Rex::IO::Stream. # attr_accessor :rstream protected # # Performs the actual raw interaction with the remote side. This can be # overriden by derived classes if they wish to do this another way. # def _interact while true # Select input and rstream sd = select([ linput.fd, rstream.fd ], nil, nil, 0.5) # Cycle through the items that have data # From the rstream? Write to linput. sd[0].each { |s| if (s == rstream.fd) data = rstream.get loutput.print(data) # From linput? Write to rstream. elsif (s == linput.fd) data = linput.gets rstream.put(data) end } if (sd) end end end end end