Files
metasploit-gs/lib/msf/core/session/interactive.rb
T
Spencer McIntyre 6c2b441d10 Fix #16684, Set @peer_info in #initialize
This will fail though if #rstream has already been closed which can be
the case when the socket is serving an HTTP request. This attempts to
proactively cache the information and store it for later use.
2022-09-19 13:28:49 -04:00

197 lines
4.3 KiB
Ruby

# -*- coding: binary -*-
module Msf
module Session
###
#
# This class implements the stubs that are needed to provide an interactive
# session.
#
###
module Interactive
#
# Interactive sessions by default may interact with the local user input
# and output.
#
include Rex::Ui::Interactive
#
# Initializes the session.
#
def initialize(rstream, opts={})
# A nil is passed in the case of non-stream interactive sessions (Meterpreter)
if rstream
self.rstream = rstream
begin
@peer_info = rstream.peerinfo
rescue ::Exception
end
end
super()
end
#
# Returns that, yes, indeed, this session supports going interactive with
# the user.
#
def interactive?
true
end
#
# Returns the local information.
#
def tunnel_local
return @local_info if @local_info
begin
@local_info = rstream.localinfo
rescue ::Exception => e
elog('Interactive#tunnel_local error', error: e)
@local_info = '127.0.0.1'
end
end
#
# Returns the remote peer information.
#
def tunnel_peer
return @peer_info if @peer_info
begin
@peer_info = rstream.peerinfo
rescue ::Exception => e
elog('Interactive#tunnel_peer error', error: e)
@peer_info = '127.0.0.1'
end
end
def comm_channel
return @comm_info if @comm_info
if rstream.respond_to?(:channel) && rstream.channel.respond_to?(:client)
@comm_info = "via session #{rstream.channel.client.sid}" if rstream.channel.client.respond_to?(:sid)
end
end
#
# Run an arbitrary command as if it came from user input.
#
def run_cmd(cmd)
end
#
# Terminate the session
#
def kill
self.reset_ui
self.cleanup
super()
end
#
# Closes rstream.
#
def cleanup
begin
self.interacting = false if self.interactive?
rstream.close if (rstream)
rescue ::Exception
end
rstream = nil
super
end
#
# The remote stream handle. Must inherit from Rex::IO::Stream.
#
attr_accessor :rstream
protected
#
# Stub method that is meant to handler interaction.
#
def _interact
framework.events.on_session_interact(self)
end
#
# Check to see if the user wants to abort.
#
def _interrupt
begin
intent = user_want_abort?
# Judge the user wants to abort the reverse shell session
# Or just want to abort the process running on the target machine
# If the latter, just send ASCII Control Character \u0003 (End of Text) to the socket fd
# The character will be handled by the line dicipline program of the pseudo-terminal on target machine
# It will send the SEGINT singal to the foreground process
if !intent
# TODO: Check the shell is interactive or not
# If the current shell is not interactive, the ASCII Control Character will not work
if abort_foreground_supported
print_status("Aborting foreground process in the shell session")
abort_foreground
end
return
end
rescue Interrupt
# The user hit ctrl-c while we were handling a ctrl-c. Ignore
end
true
end
def abort_foreground_supported
true
end
def abort_foreground
self.rstream.write("\u0003")
end
def _usr1
# A simple signal to exit vim in reverse shell
# Just for fun
# Make sure you have already executed `shell` meta-shell command to pop up an interactive shell
self.rstream.write("\x1B\x1B\x1B:q!\r")
end
#
# Check to see if we should suspend.
#
def _suspend
# Ask the user if they would like to background the session
intent = prompt_yesno("Background session #{name}?")
if !intent
# User does not want to background the current session
# Assuming the target is *nix, we'll forward CTRL-Z to the foreground process on the target
if !(self.platform=="windows" && self.type =="shell")
print_status("Backgrounding foreground process in the shell session")
self.rstream.write("\u001A")
end
return
end
self.interacting = false
end
#
# If the session reaches EOF, deregister it.
#
def _interact_complete
framework.events.on_session_interact_completed()
framework.sessions.deregister(self, "User exit")
end
#
# Checks to see if the user wants to abort.
#
def user_want_abort?
prompt_yesno("Abort session #{name}?")
end
end
end
end