2010-10-08 19:36:34 +00:00
|
|
|
##
|
|
|
|
# $Id$
|
|
|
|
##
|
|
|
|
|
2005-07-18 04:07:56 +00:00
|
|
|
require 'msf/base'
|
2011-01-19 02:24:21 +00:00
|
|
|
require 'msf/base/sessions/scriptable'
|
2005-07-18 04:07:56 +00:00
|
|
|
|
|
|
|
module Msf
|
|
|
|
module Sessions
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# This class represents a session compatible interface to a meterpreter server
|
|
|
|
# instance running on a remote machine. It provides the means of interacting
|
|
|
|
# with the server instance both at an API level as well as at a console level.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class Meterpreter < Rex::Post::Meterpreter::Client
|
|
|
|
|
|
|
|
#
|
|
|
|
# The meterpreter session is interactive
|
|
|
|
#
|
|
|
|
include Msf::Session
|
|
|
|
include Msf::Session::Interactive
|
2005-09-30 05:59:44 +00:00
|
|
|
include Msf::Session::Comm
|
2005-07-18 04:07:56 +00:00
|
|
|
|
2011-01-31 05:20:16 +00:00
|
|
|
#
|
|
|
|
# This interface supports interacting with a single command shell.
|
|
|
|
#
|
|
|
|
include Msf::Session::Provider::SingleCommandShell
|
|
|
|
|
2011-01-19 02:24:21 +00:00
|
|
|
include Msf::Session::Scriptable
|
2010-02-23 20:54:18 +00:00
|
|
|
|
2010-06-01 17:00:00 +00:00
|
|
|
# Override for server implementations that can't do ssl
|
|
|
|
def supports_ssl?
|
|
|
|
true
|
|
|
|
end
|
2010-06-18 23:15:48 +00:00
|
|
|
def supports_zlib?
|
|
|
|
true
|
|
|
|
end
|
2010-02-23 20:54:18 +00:00
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Initializes a meterpreter session instance using the supplied rstream
|
|
|
|
# that is to be used as the client's connection to the server.
|
|
|
|
#
|
2010-04-03 05:21:15 +00:00
|
|
|
def initialize(rstream, opts={})
|
2005-07-18 04:07:56 +00:00
|
|
|
super
|
|
|
|
|
2010-06-18 23:15:48 +00:00
|
|
|
opts[:capabilities] = {
|
|
|
|
:ssl => supports_ssl?,
|
|
|
|
:zlib => supports_zlib?
|
|
|
|
}
|
2010-06-01 17:00:00 +00:00
|
|
|
if not opts[:skip_ssl]
|
|
|
|
# the caller didn't request to skip ssl, so make sure we support it
|
|
|
|
opts.merge!(:skip_ssl => (not supports_ssl?))
|
|
|
|
end
|
|
|
|
|
2005-07-18 05:59:27 +00:00
|
|
|
#
|
|
|
|
# Initialize the meterpreter client
|
|
|
|
#
|
2010-04-03 05:21:15 +00:00
|
|
|
self.init_meterpreter(rstream, opts)
|
2005-07-18 05:59:27 +00:00
|
|
|
|
2005-07-18 04:07:56 +00:00
|
|
|
#
|
|
|
|
# Create the console instance
|
|
|
|
#
|
2005-07-18 05:13:21 +00:00
|
|
|
self.console = Rex::Post::Meterpreter::Ui::Console.new(self)
|
2010-02-24 01:19:59 +00:00
|
|
|
end
|
2005-07-18 04:07:56 +00:00
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Returns the session type as being 'meterpreter'.
|
|
|
|
#
|
2011-01-19 02:24:21 +00:00
|
|
|
def self.type
|
2005-07-19 14:33:25 +00:00
|
|
|
"meterpreter"
|
|
|
|
end
|
2010-02-23 20:16:45 +00:00
|
|
|
|
2011-01-19 02:24:21 +00:00
|
|
|
#
|
|
|
|
# Calls the class method
|
|
|
|
#
|
|
|
|
def type
|
|
|
|
self.class.type
|
|
|
|
end
|
|
|
|
|
2011-01-31 05:20:16 +00:00
|
|
|
def shell_init
|
|
|
|
return true if @shell
|
|
|
|
|
|
|
|
# COMSPEC is special-cased on all meterpreters to return a viable
|
|
|
|
# shell.
|
|
|
|
sh = fs.file.expand_path("%COMSPEC%")
|
|
|
|
@shell = sys.process.execute(sh, nil, { "Hidden" => true, "Channelized" => true })
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Read from the command shell.
|
|
|
|
#
|
|
|
|
def shell_read(length=nil, timeout=1)
|
|
|
|
shell_init
|
|
|
|
|
|
|
|
length = nil if length < 0
|
|
|
|
begin
|
|
|
|
rv = nil
|
|
|
|
# Meterpreter doesn't offer a way to timeout on the victim side, so
|
|
|
|
# we have to do it here. I'm concerned that this will cause loss
|
|
|
|
# of data.
|
|
|
|
Timeout.timeout(timeout) {
|
|
|
|
rv = @shell.channel.read(length)
|
|
|
|
}
|
|
|
|
framework.events.on_session_output(self, rv) if rv
|
|
|
|
return rv
|
|
|
|
rescue ::Timeout::Error
|
|
|
|
return nil
|
|
|
|
rescue ::Exception => e
|
|
|
|
shell_close
|
|
|
|
raise e
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Write to the command shell.
|
|
|
|
#
|
|
|
|
def shell_write(buf)
|
|
|
|
shell_init
|
|
|
|
|
|
|
|
begin
|
|
|
|
framework.events.on_session_command(self, buf.strip)
|
|
|
|
len = @shell.channel.write(buf + "\r\n")
|
|
|
|
rescue ::Exception => e
|
|
|
|
shell_close
|
|
|
|
raise e
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def shell_close
|
|
|
|
@shell.close
|
|
|
|
@shell = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def shell_command(cmd)
|
|
|
|
# Send the shell channel's stdin.
|
|
|
|
shell_write(cmd + "\n")
|
|
|
|
|
|
|
|
timeout = 5
|
|
|
|
etime = ::Time.now.to_f + timeout
|
|
|
|
buff = ""
|
|
|
|
|
|
|
|
# Keep reading data until no more data is available or the timeout is
|
|
|
|
# reached.
|
|
|
|
while (::Time.now.to_f < etime)
|
|
|
|
res = shell_read(-1, 0.1)
|
|
|
|
buff << res if res
|
|
|
|
end
|
|
|
|
|
|
|
|
buff
|
|
|
|
end
|
|
|
|
|
2010-10-19 22:53:15 +00:00
|
|
|
#
|
|
|
|
# Called by PacketDispatcher to resolve error codes to names.
|
|
|
|
# This is the default version (return the number itself)
|
|
|
|
#
|
|
|
|
def lookup_error(code)
|
|
|
|
"#{code}"
|
|
|
|
end
|
|
|
|
|
2005-07-18 04:07:56 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Msf::Session overrides
|
|
|
|
#
|
|
|
|
##
|
2005-11-15 15:11:43 +00:00
|
|
|
|
2006-09-17 23:12:46 +00:00
|
|
|
#
|
|
|
|
# Cleans up the meterpreter client session.
|
|
|
|
#
|
|
|
|
def cleanup
|
|
|
|
cleanup_meterpreter
|
2006-09-19 03:15:25 +00:00
|
|
|
|
|
|
|
super
|
2006-09-17 23:12:46 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 15:11:43 +00:00
|
|
|
#
|
|
|
|
# Returns the session description.
|
|
|
|
#
|
2005-07-18 04:07:56 +00:00
|
|
|
def desc
|
|
|
|
"Meterpreter"
|
|
|
|
end
|
|
|
|
|
2011-01-19 02:24:21 +00:00
|
|
|
|
|
|
|
##
|
|
|
|
#
|
|
|
|
# Msf::Session::Scriptable implementors
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
#
|
|
|
|
# Runs the meterpreter script in the context of a script container
|
|
|
|
#
|
|
|
|
def execute_file(full_path, args)
|
|
|
|
o = Rex::Script::Meterpreter.new(self, full_path)
|
|
|
|
o.run(args)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2005-07-18 04:07:56 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Msf::Session::Interactive implementors
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Initializes the console's I/O handles.
|
2005-07-18 04:07:56 +00:00
|
|
|
#
|
|
|
|
def init_ui(input, output)
|
2010-02-24 16:46:47 +00:00
|
|
|
self.user_input = input
|
|
|
|
self.user_output = output
|
2005-07-18 05:13:21 +00:00
|
|
|
console.init_ui(input, output)
|
2005-10-02 03:21:26 +00:00
|
|
|
console.set_log_source(log_source)
|
2005-12-07 03:40:09 +00:00
|
|
|
|
|
|
|
super
|
2005-07-18 04:07:56 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Resets the console's I/O handles.
|
2005-07-18 04:07:56 +00:00
|
|
|
#
|
|
|
|
def reset_ui
|
2005-10-02 03:21:26 +00:00
|
|
|
console.unset_log_source
|
2005-07-18 04:07:56 +00:00
|
|
|
console.reset_ui
|
|
|
|
end
|
|
|
|
|
2010-03-21 04:24:27 +00:00
|
|
|
#
|
|
|
|
# Terminates the session
|
|
|
|
#
|
|
|
|
def kill
|
|
|
|
begin
|
|
|
|
cleanup_meterpreter
|
|
|
|
self.sock.close
|
|
|
|
rescue ::Exception
|
|
|
|
end
|
|
|
|
framework.sessions.deregister(self)
|
|
|
|
end
|
|
|
|
|
2005-11-19 15:09:41 +00:00
|
|
|
#
|
|
|
|
# Run the supplied command as if it came from suer input.
|
|
|
|
#
|
|
|
|
def queue_cmd(cmd)
|
|
|
|
console.queue_cmd(cmd)
|
|
|
|
end
|
|
|
|
|
2006-08-15 04:07:25 +00:00
|
|
|
#
|
2011-01-31 05:20:16 +00:00
|
|
|
# Explicitly runs a command in the meterpreter console.
|
2006-08-15 04:07:25 +00:00
|
|
|
#
|
|
|
|
def run_cmd(cmd)
|
|
|
|
console.run_single(cmd)
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Load the stdapi extension.
|
|
|
|
#
|
|
|
|
def load_stdapi()
|
|
|
|
original = console.disable_output
|
|
|
|
console.disable_output = true
|
2011-04-16 13:59:57 +00:00
|
|
|
console.run_single('load stdapi')
|
2006-08-15 04:07:25 +00:00
|
|
|
console.disable_output = original
|
|
|
|
end
|
|
|
|
|
2008-03-02 23:07:33 +00:00
|
|
|
#
|
|
|
|
# Load the priv extension.
|
|
|
|
#
|
|
|
|
def load_priv()
|
|
|
|
original = console.disable_output
|
|
|
|
|
|
|
|
console.disable_output = true
|
2011-04-16 13:59:57 +00:00
|
|
|
console.run_single('load priv')
|
2008-03-02 23:07:33 +00:00
|
|
|
console.disable_output = original
|
|
|
|
end
|
|
|
|
|
2010-03-10 22:02:27 +00:00
|
|
|
#
|
|
|
|
# Populate the session information.
|
|
|
|
#
|
2011-04-13 23:03:00 +00:00
|
|
|
# Also reports a session_fingerprint note for host os normalization.
|
|
|
|
#
|
2010-03-10 22:02:27 +00:00
|
|
|
def load_session_info()
|
2011-05-03 04:49:18 +00:00
|
|
|
return if not (framework.db and framework.db.active)
|
2010-03-10 22:02:27 +00:00
|
|
|
begin
|
2010-10-08 04:11:47 +00:00
|
|
|
::Timeout.timeout(60) do
|
2010-03-10 22:06:52 +00:00
|
|
|
username = self.sys.config.getuid
|
|
|
|
sysinfo = self.sys.config.sysinfo
|
2011-04-07 21:59:32 +00:00
|
|
|
framework.db.report_note({
|
|
|
|
:type => "host.os.session_fingerprint",
|
|
|
|
:host => self,
|
|
|
|
:workspace => workspace,
|
|
|
|
:data => {
|
|
|
|
:name => sysinfo["Computer"],
|
|
|
|
:os => sysinfo["OS"],
|
|
|
|
:arch => sysinfo["Architecture"],
|
|
|
|
}
|
|
|
|
})
|
2011-02-28 21:39:25 +00:00
|
|
|
safe_info = "#{username} @ #{sysinfo['Computer']}"
|
|
|
|
safe_info.force_encoding("ASCII-8BIT") if safe_info.respond_to?(:force_encoding)
|
2011-04-07 21:59:32 +00:00
|
|
|
# Should probably be using Rex::Text.ascii_safe_hex but leave
|
|
|
|
# this as is for now since "\xNN" is arguably uglier than "_"
|
|
|
|
# showing up in various places in the UI.
|
2011-02-28 21:39:25 +00:00
|
|
|
safe_info.gsub!(/[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]+/n,"_")
|
|
|
|
self.info = safe_info
|
2011-04-14 18:28:44 +00:00
|
|
|
if self.db_record
|
|
|
|
self.db_record.desc = safe_info
|
|
|
|
self.db_record.save!
|
|
|
|
end
|
2010-03-10 22:06:52 +00:00
|
|
|
end
|
2010-03-10 22:02:27 +00:00
|
|
|
rescue ::Interrupt
|
|
|
|
raise $!
|
|
|
|
rescue ::Exception => e
|
2011-04-13 23:03:00 +00:00
|
|
|
# Log the error but otherwise ignore it so we don't kill the
|
|
|
|
# session if reporting failed for some reason
|
|
|
|
elog("Error loading sysinfo: #{e.class}: #{e}")
|
|
|
|
dlog("Call stack:\n#{e.backtrace.join("\n")}")
|
2010-03-10 22:02:27 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-07-18 04:07:56 +00:00
|
|
|
#
|
2005-11-15 15:11:43 +00:00
|
|
|
# Interacts with the meterpreter client at a user interface level.
|
2005-07-18 04:07:56 +00:00
|
|
|
#
|
|
|
|
def _interact
|
2009-12-22 18:52:48 +00:00
|
|
|
framework.events.on_session_interact(self)
|
2005-07-18 04:07:56 +00:00
|
|
|
# Call the console interaction subsystem of the meterpreter client and
|
|
|
|
# pass it a block that returns whether or not we should still be
|
|
|
|
# interacting. This will allow the shell to abort if interaction is
|
|
|
|
# canceled.
|
2005-12-07 03:40:09 +00:00
|
|
|
console.interact { self.interacting != true }
|
2005-07-18 05:13:21 +00:00
|
|
|
|
|
|
|
# If the stop flag has been set, then that means the user exited. Raise
|
|
|
|
# the EOFError so we can drop this bitch like a bad habit.
|
|
|
|
raise EOFError if (console.stopped? == true)
|
2005-07-18 04:07:56 +00:00
|
|
|
end
|
|
|
|
|
2005-09-30 05:59:44 +00:00
|
|
|
|
|
|
|
##
|
|
|
|
#
|
|
|
|
# Msf::Session::Comm implementors
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
|
|
|
#
|
|
|
|
# Creates a connection based on the supplied parameters and returns it to
|
|
|
|
# the caller. The connection is created relative to the remote machine on
|
|
|
|
# which the meterpreter server instance is running.
|
|
|
|
#
|
|
|
|
def create(param)
|
2005-11-15 20:33:55 +00:00
|
|
|
sock = nil
|
|
|
|
|
|
|
|
# Notify handlers before we create the socket
|
|
|
|
notify_before_socket_create(self, param)
|
|
|
|
|
2010-02-09 16:45:46 +00:00
|
|
|
sock = net.socket.create(param)
|
2010-02-23 20:16:45 +00:00
|
|
|
|
2010-02-09 16:45:46 +00:00
|
|
|
# sf: unsure if we should raise an exception or just return nil. returning nil for now.
|
|
|
|
#if( sock == nil )
|
|
|
|
# raise Rex::UnsupportedProtocol.new(param.proto), caller
|
|
|
|
#end
|
2005-11-15 20:33:55 +00:00
|
|
|
|
|
|
|
# Notify now that we've created the socket
|
|
|
|
notify_socket_created(self, sock, param)
|
|
|
|
|
2008-06-16 05:39:36 +00:00
|
|
|
# Return the socket to the caller
|
2005-11-15 20:33:55 +00:00
|
|
|
sock
|
2005-09-30 05:59:44 +00:00
|
|
|
end
|
|
|
|
|
2010-01-22 19:47:36 +00:00
|
|
|
attr_accessor :platform
|
|
|
|
attr_accessor :binary_suffix
|
2010-01-06 05:06:12 +00:00
|
|
|
attr_accessor :console # :nodoc:
|
2010-04-03 05:21:15 +00:00
|
|
|
attr_accessor :skip_ssl
|
|
|
|
attr_accessor :target_id
|
2010-01-06 05:06:12 +00:00
|
|
|
|
2005-07-18 04:07:56 +00:00
|
|
|
protected
|
|
|
|
|
2010-01-06 05:06:12 +00:00
|
|
|
attr_accessor :rstream # :nodoc:
|
2005-07-18 04:07:56 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
2009-08-01 03:50:40 +00:00
|
|
|
end
|
2010-03-10 22:02:27 +00:00
|
|
|
|