class Rex::Post::Meterpreter::Ui::Console::CommandDispatcher::Core

Core meterpreter client commands that provide only the required set of commands for having a functional meterpreter client<->server instance.

Constants

CommDispatcher

Public Class Methods

add_client_extension_search_path(path) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1403
def self.add_client_extension_search_path(path)
  @@client_extension_search_paths << path unless @@client_extension_search_paths.include?(path)
end
client_extension_search_paths() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1406
def self.client_extension_search_paths
  @@client_extension_search_paths
end
new(shell) click to toggle source

Initializes an instance of the core command set using the supplied shell for interactivity.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 24
def initialize(shell)
  super

  self.extensions = []
  self.bgjobs     = []
  self.bgjob_id   = 0

  # keep a lookup table to refer to transports by index
  @transport_map = {}
end

Public Instance Methods

cmd_background() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 120
def cmd_background
  print_status "Backgrounding session #{client.name}..."
  client.interacting = false
end
cmd_background_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 113
def cmd_background_help
  print_line "Usage: background"
  print_line
  print_line "Stop interacting with this session and return to the parent prompt"
  print_line
end
cmd_bgkill(*args) click to toggle source

Kill a background job

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1195
def cmd_bgkill(*args)
  if args.length == 0
    print_line("Usage: bgkill [id]")
    return
  end

  args.each do |jid|
    jid = jid.to_i
    if self.bgjobs[jid]
      print_status("Killing background job #{jid}...")
      self.bgjobs[jid].kill
      self.bgjobs[jid] = nil
    else
      print_error("Job #{jid} was not running")
    end
  end
end
cmd_bglist(*args) click to toggle source

List background jobs

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1216
def cmd_bglist(*args)
  self.bgjobs.each_index do |jid|
    if self.bgjobs[jid]
      print_status("Job #{jid}: #{self.bgjobs[jid][:args].inspect}")
    end
  end
end
cmd_bgrun(*args) click to toggle source

Executes a script in the context of the meterpreter session in the background

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1156
def cmd_bgrun(*args)
  if args.length == 0
    print_line(
      "Usage: bgrun <script> [arguments]\n\n" +
      "Executes a ruby script in the context of the meterpreter session.")
    return true
  end

  jid = self.bgjob_id
  self.bgjob_id += 1

  # Get the script name
  self.bgjobs[jid] = Rex::ThreadFactory.spawn("MeterpreterBGRun(#{args[0]})-#{jid}", false, jid, args) do |myjid,xargs|
    ::Thread.current[:args] = xargs.dup
    begin
      # the rest of the arguments get passed in through the binding
      client.execute_script(args.shift, args)
    rescue ::Exception
      print_error("Error in script: #{$!.class} #{$!}")
      elog("Error in script: #{$!.class} #{$!}")
      dlog("Callstack: #{$@.join("\n")}")
    end
    self.bgjobs[myjid] = nil
    print_status("Background script with Job ID #{myjid} has completed (#{::Thread.current[:args].inspect})")
  end

  print_status("Executed Meterpreter with Job ID #{jid}")
end
cmd_bgrun_tabs(*args) click to toggle source

Map this to the normal run command tab completion

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1188
def cmd_bgrun_tabs(*args)
  cmd_run_tabs(*args)
end
cmd_channel(*args) click to toggle source

Performs operations on the supplied channel.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 147
def cmd_channel(*args)
  if args.empty? or args.include?("-h") or args.include?("--help")
    cmd_channel_help
    return
  end

  mode = nil
  chan = nil

  # Parse options
  @@channel_opts.parse(args) { |opt, idx, val|
    case opt
    when "-l"
      mode = :list
    when "-c", "-k"
      mode = :close
      chan = val
    when "-i"
      mode = :interact
      chan = val
    when "-r"
      mode = :read
      chan = val
    when "-w"
      mode = :write
      chan = val
    end
    if @@channel_opts.arg_required?(opt)
      unless chan
        print_error("Channel ID required")
        return
      end
    end
  }

  case mode
  when :list
    tbl = Rex::Ui::Text::Table.new(
      'Indent'  => 4,
      'Columns' =>
        [
          'Id',
          'Class',
          'Type'
        ])
    items = 0

    client.channels.each_pair { |cid, channel|
      tbl << [ cid, channel.class.cls, channel.type ]
      items += 1
    }

    if (items == 0)
      print_line("No active channels.")
    else
      print("\n" + tbl.to_s + "\n")
    end
  when :close
    cmd_close(chan)
  when :interact
    cmd_interact(chan)
  when :read
    cmd_read(chan)
  when :write
    cmd_write(chan)
  else
    # No mode, no service.
    return true
  end
end
cmd_channel_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 137
def cmd_channel_help
  print_line "Usage: channel [options]"
  print_line
  print_line "Displays information about active channels."
  print_line @@channel_opts.usage
end
cmd_channel_tabs(str, words) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 218
def cmd_channel_tabs(str, words)
  case words.length
  when 1
    @@channel_opts.fmt.keys
  when 2
    case words[1]
    when "-k", "-c", "-i", "-r", "-w"
      tab_complete_channels
    else
      []
    end
  else
    []
  end
end
cmd_close(*args) click to toggle source

Closes a supplied channel.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 244
def cmd_close(*args)
  if (args.length == 0)
    cmd_close_help
    return true
  end

  cid     = args[0].to_i
  channel = client.find_channel(cid)

  if (!channel)
    print_error("Invalid channel identifier specified.")
    return true
  else
    channel._close # Issue #410

    print_status("Closed channel #{cid}.")
  end
end
cmd_close_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 234
def cmd_close_help
  print_line "Usage: close <channel_id>"
  print_line
  print_line "Closes the supplied channel."
  print_line
end
cmd_close_tabs(str, words) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 263
def cmd_close_tabs(str, words)
  return [] if words.length > 1

  return tab_complete_channels
end
Also aliased as: cmd_interact_tabs, cmd_read_tabs
cmd_detach(*args) click to toggle source

Disconnects the session

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 295
def cmd_detach(*args)
  client.shutdown_passive_dispatcher
  shell.stop
end
cmd_detach_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 281
def cmd_detach_help
  print_line "Detach from the victim. Only possible for non-stream sessions (http/https)"
  print_line
  print_line "The victim will continue to attempt to call back to the handler until it"
  print_line "successfully connects (which may happen immediately if you have a handler"
  print_line "running in the background), or reaches its expiration."
  print_line
  print_line "This session may #{client.passive_service ? "" : "NOT"} be detached."
  print_line
end
cmd_disable_unicode_encoding() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1396
def cmd_disable_unicode_encoding
  client.encode_unicode = false
  print_status("Unicode encoding is disabled")
end
cmd_enable_unicode_encoding() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1391
def cmd_enable_unicode_encoding
  client.encode_unicode = true
  print_status("Unicode encoding is enabled")
end
cmd_exit(*args) click to toggle source

Terminates the meterpreter session.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 272
def cmd_exit(*args)
  print_status("Shutting down Meterpreter...")
  client.core.shutdown rescue nil
  client.shutdown_passive_dispatcher
  shell.stop
end
Also aliased as: cmd_quit
cmd_get_timeouts(*args) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 410
def cmd_get_timeouts(*args)
  # Calling set without passing values is the same as
  # getting all the current timeouts
  timeouts = client.core.set_transport_timeouts
  print_timeouts(timeouts)
end
cmd_info(*args) click to toggle source

Show info for a given Post module.

See also cmd_info in lib/msf/ui/console/command_dispatcher/core.rb

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1236
def cmd_info(*args)
  return unless msf_loaded?

  if args.length != 1 or args.include?("-h")
    cmd_info_help
    return
  end

  module_name = args.shift
  mod = client.framework.modules.create(module_name);

  if mod.nil?
    print_error 'Invalid module: ' << module_name
  end

  if (mod)
    print_line(::Msf::Serializer::ReadableText.dump_module(mod))
    mod_opt = ::Msf::Serializer::ReadableText.dump_options(mod, '   ')
    print_line("\nModule options (#{mod.fullname}):\n\n#{mod_opt}") if (mod_opt and mod_opt.length > 0)
  end
end
cmd_info_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1224
def cmd_info_help
  print_line 'Usage: info <module>'
  print_line
  print_line 'Prints information about a post-exploitation module'
  print_line
end
cmd_info_tabs(*args) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1258
def cmd_info_tabs(*args)
  return unless msf_loaded?
  tab_complete_postmods
end
cmd_interact(*args) click to toggle source

Interacts with a channel.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 310
def cmd_interact(*args)
  if (args.length == 0)
    cmd_info_help
    return true
  end

  cid     = args[0].to_i
  channel = client.find_channel(cid)

  if (channel)
    print_line("Interacting with channel #{cid}...\n")

    shell.interact_with_channel(channel)
  else
    print_error("Invalid channel identifier specified.")
  end
end
cmd_interact_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 300
def cmd_interact_help
  print_line "Usage: interact <channel_id>"
  print_line
  print_line "Interacts with the supplied channel."
  print_line
end
cmd_interact_tabs(str, words)
Alias for: cmd_close_tabs
cmd_irb(*args) click to toggle source

Runs the IRB scripting shell

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 340
def cmd_irb(*args)
  expressions = []

  # Parse the command options
  @@irb_opts.parse(args) do |opt, idx, val|
    case opt
    when '-e'
      expressions << val
    when '-h'
      return cmd_irb_help
    end
  end

  session = client
  framework = client.framework

  if expressions.empty?
    print_status("Starting IRB shell")
    print_status("The 'client' variable holds the meterpreter client\n")

    Rex::Ui::Text::IrbShell.new(binding).run
  else
    expressions.each { |expression| eval(expression, binding) }
  end
end
cmd_irb_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 330
def cmd_irb_help
  print_line "Usage: irb"
  print_line
  print_line "Execute commands in a Ruby environment"
  print @@irb_opts.usage
end
cmd_load(*args) click to toggle source

Loads one or more meterpreter extensions.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 960
def cmd_load(*args)
  if (args.length == 0)
    args.unshift("-h")
  end

  @@load_opts.parse(args) { |opt, idx, val|
    case opt
    when "-l"
      exts = SortedSet.new
      msf_path = MetasploitPayloads.msf_meterpreter_dir
      gem_path = MetasploitPayloads.local_meterpreter_dir
      [msf_path, gem_path].each do |path|
        ::Dir.entries(path).each { |f|
          if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
            exts.add($1)
          end
        }
      end
      print(exts.to_a.join("\n") + "\n")

      return true
    when "-h"
      cmd_load_help
      return true
    end
  }

  # Load each of the modules
  args.each { |m|
    md = m.downcase

    if (extensions.include?(md))
      print_error("The '#{md}' extension has already been loaded.")
      next
    end

    print("Loading extension #{md}...")

    begin
      # Use the remote side, then load the client-side
      if (client.core.use(md) == true)
        add_extension_client(md)
      end
    rescue
      print_line
      log_error("Failed to load extension: #{$!}")
      next
    end

    print_line("success.")
  }

  return true
end
cmd_load_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 950
def cmd_load_help
  print_line("Usage: load ext1 ext2 ext3 ...")
  print_line
  print_line "Loads a meterpreter extension module or modules."
  print_line @@load_opts.usage
end
Also aliased as: cmd_use_help
cmd_load_tabs(str, words) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1015
def cmd_load_tabs(str, words)
  tabs = SortedSet.new
  msf_path = MetasploitPayloads.msf_meterpreter_dir
  gem_path = MetasploitPayloads.local_meterpreter_dir
  [msf_path, gem_path].each do |path|
  ::Dir.entries(path).each { |f|
    if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
      if (not extensions.include?($1))
        tabs.add($1)
      end
    end
  }
  end
  return tabs.to_a
end
Also aliased as: cmd_use_tabs
cmd_machine_id(*args) click to toggle source

Get the machine ID of the target

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 435
def cmd_machine_id(*args)
  client.machine_id = client.core.machine_id unless client.machine_id
  print_good("Machine ID: #{client.machine_id}")
end
cmd_migrate(*args) click to toggle source

Migrates the server to the supplied process identifier.

@param args [Array<String>] Commandline arguments, -h or a pid. On linux

platforms a path for the unix domain socket used for IPC.

@return [void]

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 843
def cmd_migrate(*args)
  if args.length == 0 || args.any? { |arg| %w(-h --pid --name).include? arg }
    cmd_migrate_help
    return true
  end

  pid = nil
  writable_dir = nil
  opts = {
    timeout: nil
  }

  @@migrate_opts.parse(args) do |opt, idx, val|
    case opt
    when '-t'
      opts[:timeout] = val.to_i
    when '-p'
      writable_dir = val
    when '-P'
      unless val =~ /^\d+$/
        print_error("Not a PID: #{val}")
        return
      end
      pid = val.to_i
    when '-N'
      if val.to_s.empty?
        print_error("No process name provided")
        return
      end
      # this will migrate to the first process with a matching name
      unless (process = client.sys.process.processes.find { |p| p['name'] == val })
        print_error("Could not find process name #{val}")
        return
      end
      pid = process['pid']
    end
  end

  unless pid
    unless (pid = args.first)
      print_error('A process ID or name argument must be provided')
      return
    end
    unless pid =~ /^\d+$/
      print_error("Not a PID: #{pid}")
      return
    end
    pid = pid.to_i
  end

  begin
    server = client.sys.process.open
  rescue TimeoutError => e
    elog(e.to_s)
  rescue RequestError => e
    elog(e.to_s)
  end

  service = client.pfservice

  # If we have any open port forwards, we need to close them down
  # otherwise we'll end up with local listeners which aren't connected
  # to valid channels in the migrated meterpreter instance.
  existing_relays = []

  if service
    service.each_tcp_relay do |lhost, lport, rhost, rport, opts|
      next unless opts['MeterpreterRelay']
      if existing_relays.empty?
        print_status('Removing existing TCP relays...')
      end
      if (service.stop_tcp_relay(lport, lhost))
        print_status("Successfully stopped TCP relay on #{lhost || '0.0.0.0'}:#{lport}")
        existing_relays << {
          :lport => lport,
          :opts => opts
        }
      else
        print_error("Failed to stop TCP relay on #{lhost || '0.0.0.0'}:#{lport}")
        next
      end
    end
    unless existing_relays.empty?
      print_status("#{existing_relays.length} TCP relay(s) removed.")
    end
  end

  server ? print_status("Migrating from #{server.pid} to #{pid}...") : print_status("Migrating to #{pid}")

  # Do this thang.
  client.core.migrate(pid, writable_dir, opts)

  print_status('Migration completed successfully.')

  # Update session info (we may have a new username)
  client.update_session_info

  unless existing_relays.empty?
    print_status('Recreating TCP relay(s)...')
    existing_relays.each do |r|
      client.pfservice.start_tcp_relay(r[:lport], r[:opts])
      print_status("Local TCP relay recreated: #{r[:opts]['LocalHost'] || '0.0.0.0'}:#{r[:lport]} <-> #{r[:opts]['PeerHost']}:#{r[:opts]['PeerPort']}")
    end
  end

end
cmd_migrate_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 825
def cmd_migrate_help
  if client.platform =~ /linux/
    print_line('Usage: migrate <<pid> | -P <pid> | -N <name>> [-p writable_path] [-t timeout]')
  else
    print_line('Usage: migrate <<pid> | -P <pid> | -N <name>> [-t timeout]')
  end
  print_line
  print_line('Migrates the server instance to another process.')
  print_line('NOTE: Any open channels or other dynamic state will be lost.')
  print_line
end
cmd_quit(*args)
Alias for: cmd_exit
cmd_read(*args) click to toggle source

Reads data from a channel.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1048
def cmd_read(*args)
  if (args.length == 0)
    cmd_read_help
    return true
  end

  cid     = args[0].to_i
  length  = (args.length >= 2) ? args[1].to_i : 16384
  channel = client.find_channel(cid)

  if (!channel)
    print_error("Channel #{cid} is not valid.")
    return true
  end

  data = channel.read(length)

  if (data and data.length)
    print("Read #{data.length} bytes from #{cid}:\n\n#{data}\n")
  else
    print_error("No data was returned.")
  end

  return true
end
cmd_read_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1038
def cmd_read_help
  print_line "Usage: read <channel_id> [length]"
  print_line
  print_line "Reads data from the supplied channel."
  print_line
end
cmd_read_tabs(str, words)
Alias for: cmd_close_tabs
cmd_resource(*args) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1353
def cmd_resource(*args)
  if args.empty?
    return false
  end
  args.each do |glob|
    files = ::Dir.glob(::File.expand_path(glob))
    if files.empty?
      print_error("No such file #{glob}")
      next
    end
    files.each do |filename|
      print_status("Reading #{filename}")
      if (not ::File.readable?(filename))
        print_error("Could not read file #{filename}")
        next
      else
        ::File.open(filename, "r").each_line do |line|
          next if line.strip.length < 1
          next if line[0,1] == "#"
          begin
            print_status("Running #{line}")
            client.console.run_single(line)
          rescue ::Exception => e
            print_error("Error Running Command #{line}: #{e.class} #{e}")
          end

        end
      end
    end
  end
end
cmd_resource_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1346
def cmd_resource_help
  print_line "Usage: resource <path1> [path2 ...]"
  print_line
  print_line "Run the commands stored in the supplied files."
  print_line
end
cmd_resource_tabs(str, words) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1385
def cmd_resource_tabs(str, words)
  return [] if words.length > 1

  tab_complete_filenames(str, words)
end
cmd_run(*args) click to toggle source

Executes a script in the context of the meterpreter session.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1088
def cmd_run(*args)
  if args.length == 0
    cmd_run_help
    return true
  end

  # Get the script name
  begin
    script_name = args.shift
    # First try it as a Post module if we have access to the Metasploit
    # Framework instance.  If we don't, or if no such module exists,
    # fall back to using the scripting interface.
    if (msf_loaded? and mod = client.framework.modules.create(script_name))
      original_mod = mod
      reloaded_mod = client.framework.modules.reload_module(original_mod)

      unless reloaded_mod
        error = client.framework.modules.module_load_error_by_path[original_mod.file_path]
        print_error("Failed to reload module: #{error}")

        return
      end

      opts = (args + [ "SESSION=#{client.sid}" ]).join(',')
      reloaded_mod.run_simple(
        #'RunAsJob' => true,
        'LocalInput'  => shell.input,
        'LocalOutput' => shell.output,
        'OptionStr'   => opts
      )
    else
      # the rest of the arguments get passed in through the binding
      client.execute_script(script_name, args)
    end
  rescue
    print_error("Error in script: #{$!.class} #{$!}")
    elog("Error in script: #{$!.class} #{$!}")
    dlog("Callstack: #{$@.join("\n")}")
  end
end
cmd_run_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1076
def cmd_run_help
  print_line "Usage: run <script> [arguments]"
  print_line
  print_line "Executes a ruby script or Metasploit Post module in the context of the"
  print_line "meterpreter session.  Post modules can take arguments in var=val format."
  print_line "Example: run post/foo/bar BAZ=abcd"
  print_line
end
cmd_run_tabs(str, words) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1129
def cmd_run_tabs(str, words)
  tabs = []
  if(not words[1] or not words[1].match(/^\//))
    begin
      if (msf_loaded?)
        tabs += tab_complete_postmods
      end
      [
        ::Msf::Sessions::Meterpreter.script_base,
        ::Msf::Sessions::Meterpreter.user_script_base
      ].each do |dir|
        next if not ::File.exist? dir
        tabs += ::Dir.new(dir).find_all { |e|
          path = dir + ::File::SEPARATOR + e
          ::File.file?(path) and ::File.readable?(path)
        }
      end
    rescue Exception
    end
  end
  return tabs.map { |e| e.sub(/\.rb$/, '') }
end
cmd_set_timeouts(*args) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 381
def cmd_set_timeouts(*args)
  if ( args.length == 0 or args.include?("-h") )
    cmd_set_timeouts_help
    return
  end

  opts = {}

  @@set_timeouts_opts.parse(args) do |opt, idx, val|
    case opt
    when '-c'
      opts[:comm_timeout] = val.to_i if val
    when '-x'
      opts[:session_exp] = val.to_i if val
    when '-t'
      opts[:retry_total] = val.to_i if val
    when '-w'
      opts[:retry_wait] = val.to_i if val
    end
  end

  if opts.keys.length == 0
    print_error("No options set")
  else
    timeouts = client.core.set_transport_timeouts(opts)
    print_timeouts(timeouts)
  end
end
cmd_set_timeouts_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 373
def cmd_set_timeouts_help
  print_line('Usage: set_timeouts [options]')
  print_line
  print_line('Set the current timeout options.')
  print_line('Any or all of these can be set at once.')
  print_line(@@set_timeouts_opts.usage)
end
cmd_sleep(*args) click to toggle source

Handle the sleep command.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 545
def cmd_sleep(*args)
  if args.length == 0
    cmd_sleep_help
    return
  end

  seconds = args.shift.to_i

  if seconds <= 0
    cmd_sleep_help
    return
  end

  print_status("Telling the target instance to sleep for #{seconds} seconds ...")
  if client.core.transport_sleep(seconds)
    print_good("Target instance has gone to sleep, terminating current session.")
    client.shutdown_passive_dispatcher
    shell.stop
  else
    print_error("Target instance failed to go to sleep.")
  end
end
cmd_sleep_help() click to toggle source

Display help for the sleep.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 532
def cmd_sleep_help
  print_line('Usage: sleep <time>')
  print_line
  print_line('  time: Number of seconds to wait (positive integer)')
  print_line
  print_line('  This command tells Meterpreter to go to sleep for the specified')
  print_line('  number of seconds. Sleeping will result in the transport being')
  print_line('  shut down and restarted after the designated timeout.')
end
cmd_ssl_verify(*args) click to toggle source

Handle the SSL verification querying and setting function.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 471
def cmd_ssl_verify(*args)
  if ( args.length == 0 or args.include?("-h") )
    cmd_ssl_verify_help
    return
  end

  query = false
  enable = false
  disable = false

  settings = 0

  @@ssl_verify_opts.parse(args) do |opt, idx, val|
    case opt
    when '-q'
      query = true
      settings += 1
    when '-e'
      enable = true
      settings += 1
    when '-d'
      disable = true
      settings += 1
    end
  end

  # Make sure only one action has been chosen
  if settings != 1
    cmd_ssl_verify_help
    return
  end

  if query
    hash = client.core.get_ssl_hash_verify
    if hash
      print_good("SSL verification is enabled. SHA1 Hash: #{hash.unpack("H*")[0]}")
    else
      print_good("SSL verification is disabled.")
    end

  elsif enable
    hash = client.core.enable_ssl_hash_verify
    if hash
      print_good("SSL verification has been enabled. SHA1 Hash: #{hash.unpack("H*")[0]}")
    else
      print_error("Failed to enable SSL verification")
    end

  else
    if client.core.disable_ssl_hash_verify
      print_good('SSL verification has been disabled')
    else
      print_error("Failed to disable SSL verification")
    end
  end

end
cmd_ssl_verify_help() click to toggle source

Help for ssl verification

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 460
def cmd_ssl_verify_help
  print_line('Usage: ssl_verify [options]')
  print_line
  print_line('Change and query the current setting for SSL verification')
  print_line('Only one of the following options can be used at a time')
  print_line(@@ssl_verify_opts.usage)
end
cmd_transport(*args) click to toggle source

Manage transports

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 616
def cmd_transport(*args)
  if ( args.length == 0 or args.include?("-h") )
    cmd_transport_help
    return
  end

  command = args.shift
  unless ['list', 'add', 'change', 'prev', 'next', 'remove'].include?(command)
    cmd_transport_help
    return
  end

  opts = {
    :uuid          => client.payload_uuid,
    :transport     => nil,
    :lhost         => nil,
    :lport         => nil,
    :uri           => nil,
    :ua            => nil,
    :proxy_host    => nil,
    :proxy_port    => nil,
    :proxy_type    => nil,
    :proxy_user    => nil,
    :proxy_pass    => nil,
    :comm_timeout  => nil,
    :session_exp   => nil,
    :retry_total   => nil,
    :retry_wait    => nil,
    :cert          => nil,
    :verbose       => false
  }

  valid = true
  transport_index = 0
  @@transport_opts.parse(args) do |opt, idx, val|
    case opt
    when '-c'
      opts[:cert] = val
    when '-u'
      opts[:uri] = val
    when '-i'
      transport_index = val.to_i
    when '-ph'
      opts[:proxy_host] = val
    when '-pp'
      opts[:proxy_port] = val.to_i
    when '-pt'
      opts[:proxy_type] = val
    when '-pu'
      opts[:proxy_user] = val
    when '-ps'
      opts[:proxy_pass] = val
    when '-ua'
      opts[:ua] = val
    when '-to'
      opts[:comm_timeout] = val.to_i if val
    when '-ex'
      opts[:session_exp] = val.to_i if val
    when '-rt'
      opts[:retry_total] = val.to_i if val
    when '-rw'
      opts[:retry_wait] = val.to_i if val
    when '-p'
      opts[:lport] = val.to_i if val
    when '-l'
      opts[:lhost] = val
    when '-v'
      opts[:verbose] = true
    when '-t'
      unless client.core.valid_transport?(val)
        cmd_transport_help
        return
      end
      opts[:transport] = val
    else
      valid = false
    end
  end

  unless valid
    cmd_transport_help
    return
  end

  update_transport_map

  case command
  when 'list'
    result = client.core.transport_list

    current_transport_url = result[:transports].first[:url]

    sorted_by_url = result[:transports].sort_by { |k| k[:url] }

    # this will output the session timeout first
    print_timeouts(result)

    columns =[
      'ID',
      'Curr',
      'URL',
      'Comms T/O',
      'Retry Total',
      'Retry Wait'
    ]

    if opts[:verbose]
      columns << 'User Agent'
      columns << 'Proxy Host'
      columns << 'Proxy User'
      columns << 'Proxy Pass'
      columns << 'Cert Hash'
    end

    # next draw up a table of transport entries
    tbl = Rex::Ui::Text::Table.new(
      'SortIndex' => 0, # sort by ID
      'Indent'    => 4,
      'Columns'   => columns)

    sorted_by_url.each_with_index do |t, i|
      entry = [ i+1, (current_transport_url == t[:url]) ? '*' : '', t[:url],
                t[:comm_timeout], t[:retry_total], t[:retry_wait] ]

      if opts[:verbose]
        entry << t[:ua]
        entry << t[:proxy_host]
        entry << t[:proxy_user]
        entry << t[:proxy_pass]
        entry << (t[:cert_hash] || '').unpack("H*")[0]
      end

      tbl << entry
    end

    print("\n" + tbl.to_s + "\n")
  when 'next'
    print_status("Changing to next transport ...")
    if client.core.transport_next
      print_good("Successfully changed to the next transport, killing current session.")
      client.shutdown_passive_dispatcher
      shell.stop
    else
      print_error("Failed to change transport, please check the parameters")
    end
  when 'prev'
    print_status("Changing to previous transport ...")
    if client.core.transport_prev
      print_good("Successfully changed to the previous transport, killing current session.")
      client.shutdown_passive_dispatcher
      shell.stop
    else
      print_error("Failed to change transport, please check the parameters")
    end
  when 'change'
    print_status("Changing to new transport ...")
    if client.core.transport_change(opts)
      print_good("Successfully added #{opts[:transport]} transport, killing current session.")
      client.shutdown_passive_dispatcher
      shell.stop
    else
      print_error("Failed to change transport, please check the parameters")
    end
  when 'add'
    print_status("Adding new transport ...")
    if client.core.transport_add(opts)
      print_good("Successfully added #{opts[:transport]} transport.")
    else
      print_error("Failed to add transport, please check the parameters")
    end
  when 'remove'
    if opts[:transport] && !opts[:transport].end_with?('_tcp') && opts[:uri].nil?
      print_error("HTTP/S transport specified without session URI")
      return
    end

    if !transport_index.zero? && @transport_map.has_key?(transport_index)
      # validate the URL
      url_to_delete = @transport_map[transport_index][:url]
      begin
        uri = URI.parse(url_to_delete)
        opts[:transport] = "reverse_#{uri.scheme}"
        opts[:lhost]     = uri.host
        opts[:lport]     = uri.port
        opts[:uri]       = uri.path[1..-2] if uri.scheme.include?("http")

      rescue URI::InvalidURIError
        print_error("Failed to parse URL: #{url_to_delete}")
        return
      end
    end

    print_status("Removing transport ...")
    if client.core.transport_remove(opts)
      print_good("Successfully removed #{opts[:transport]} transport.")
    else
      print_error("Failed to remove transport, please check the parameters")
    end
  end
end
cmd_transport_help() click to toggle source

Display help for transport management.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 594
def cmd_transport_help
  print_line('Usage: transport <list|change|add|next|prev|remove> [options]')
  print_line
  print_line('   list: list the currently active transports.')
  print_line('    add: add a new transport to the transport list.')
  print_line(' change: same as add, but changes directly to the added entry.')
  print_line('   next: jump to the next transport in the list (no options).')
  print_line('   prev: jump to the previous transport in the list (no options).')
  print_line(' remove: remove an existing, non-active transport.')
  print_line(@@transport_opts.usage)
end
cmd_use(*args) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1031
def cmd_use(*args)
  #print_error("Warning: The 'use' command is deprecated in favor of 'load'")
  cmd_load(*args)
end
cmd_use_help()
Alias for: cmd_load_help
cmd_use_tabs(str, words)
Alias for: cmd_load_tabs
cmd_uuid(*args) click to toggle source

Get the machine ID of the target

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 443
def cmd_uuid(*args)
  client.payload_uuid = client.core.uuid unless client.payload_uuid
  print_good("UUID: #{client.payload_uuid}")
end
cmd_write(*args) click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1277
def cmd_write(*args)
  if (args.length == 0 or args.include?("-h"))
    cmd_write_help
    return
  end

  src_file = nil
  cid      = nil

  @@write_opts.parse(args) { |opt, idx, val|
    case opt
    when "-f"
      src_file = val
    else
      cid = val.to_i
    end
  }

  # Find the channel associated with this cid, assuming the cid is valid.
  if ((!cid) or (!(channel = client.find_channel(cid))))
    print_error("Invalid channel identifier specified.")
    return true
  end

  # If they supplied a source file, read in its contents and write it to
  # the channel
  if (src_file)
    begin
      data = ''

      ::File.open(src_file, 'rb') { |f|
        data = f.read(f.stat.size)
      }

    rescue Errno::ENOENT
      print_error("Invalid source file specified: #{src_file}")
      return true
    end

    if (data and data.length > 0)
      channel.write(data)
      print_status("Wrote #{data.length} bytes to channel #{cid}.")
    else
      print_error("No data to send from file #{src_file}")
      return true
    end
  # Otherwise, read from the input descriptor until we're good to go.
  else
    print("Enter data followed by a '.' on an empty line:\n\n")

    data = ''

    # Keep truckin'
    while (s = shell.input.gets)
      break if (s =~ /^\.\r?\n?$/)
      data += s
    end

    if (!data or data.length == 0)
      print_error("No data to send.")
    else
      channel.write(data)
      print_status("Wrote #{data.length} bytes to channel #{cid}.")
    end
  end

  return true
end
cmd_write_help() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1270
def cmd_write_help
  print_line "Usage: write [options] channel_id"
  print_line
  print_line "Writes data to the supplied channel."
  print_line @@write_opts.usage
end
commands() click to toggle source

List of supported commands.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 46
def commands
  c = {
    "?"          => "Help menu",
    "background" => "Backgrounds the current session",
    "close"      => "Closes a channel",
    "channel"    => "Displays information or control active channels",
    "exit"       => "Terminate the meterpreter session",
    "help"       => "Help menu",
    "irb"        => "Drop into irb scripting mode",
    "use"        => "Deprecated alias for 'load'",
    "load"       => "Load one or more meterpreter extensions",
    "machine_id" => "Get the MSF ID of the machine attached to the session",
    "quit"       => "Terminate the meterpreter session",
    "resource"   => "Run the commands stored in a file",
    "uuid"       => "Get the UUID for the current session",
    "read"       => "Reads data from a channel",
    "run"        => "Executes a meterpreter script or Post module",
    "bgrun"      => "Executes a meterpreter script as a background thread",
    "bgkill"     => "Kills a background meterpreter script",
    "get_timeouts" => "Get the current session timeout values",
    "set_timeouts" => "Set the current session timeout values",
    "bglist"     => "Lists running background scripts",
    "write"      => "Writes data to a channel",
    "enable_unicode_encoding"  => "Enables encoding of unicode strings",
    "disable_unicode_encoding" => "Disables encoding of unicode strings"
  }

  if client.passive_service
    c["detach"] = "Detach the meterpreter session (for http/https)"
  end

  # Currently we have some windows-specific core commands`
  if client.platform =~ /win/
    # only support the SSL switching for HTTPS
    if client.passive_service && client.sock.type? == 'tcp-ssl'
      c["ssl_verify"] = "Modify the SSL certificate verification setting"
    end
  end

  if client.platform =~ /win/ || client.platform =~ /linux/
    # Migration only supported on windows and linux
    c["migrate"] = "Migrate the server to another process"
  end

  if client.platform =~ /win/ || client.platform =~ /linux/ || client.platform =~ /python/ || client.platform =~ /java/
    # Yet to implement transport hopping for other meterpreters.
    c["transport"] = "Change the current transport mechanism"

    # sleep functionality relies on the transport features, so only
    # wire that in with the transport stuff.
    c["sleep"] = "Force Meterpreter to go quiet, then re-establish session."
  end

  if (msf_loaded?)
    c["info"] = "Displays information about a Post module"
  end

  c
end
name() click to toggle source

Core baby.

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 109
def name
  "Core"
end
print_timeouts(timeouts) click to toggle source
update_transport_map() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 606
def update_transport_map
  result = client.core.transport_list
  @transport_map.clear
  sorted_by_url = result[:transports].sort_by { |k| k[:url] }
  sorted_by_url.each_with_index { |t, i| @transport_map[i+1] = t }
end

Protected Instance Methods

add_extension_client(mod) click to toggle source

Loads the client extension specified in mod

# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1420
def add_extension_client(mod)
  loaded = false
  klass = nil
  self.class.client_extension_search_paths.each do |path|
    path = ::File.join(path, "#{mod}.rb")
    klass = CommDispatcher.check_hash(path)
    if (klass == nil)
      old   = CommDispatcher.constants
      next unless ::File.exist? path

      if (require(path))
        new  = CommDispatcher.constants
        diff = new - old

        next if (diff.empty?)

        klass = CommDispatcher.const_get(diff[0])

        CommDispatcher.set_hash(path, klass)
        loaded = true
        break
      else
        print_error("Failed to load client script file: #{path}")
        return false
      end
    else
      # the klass is already loaded, from a previous invocation
      loaded = true
      break
    end
  end
  unless loaded
    print_error("Failed to load client portion of #{mod}.")
    return false
  end

  # Enstack the dispatcher
  self.shell.enstack_dispatcher(klass)

  # Insert the module into the list of extensions
  self.extensions << mod
end
tab_complete_channels() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1477
def tab_complete_channels
  client.channels.keys.map { |k| k.to_s }
end
tab_complete_postmods() click to toggle source
# File lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb, line 1463
def tab_complete_postmods
  tabs = client.framework.modules.post.map { |name,klass|
    mod = client.framework.modules.post.create(name)
    if mod and mod.session_compatible?(client)
      mod.fullname.dup
    else
      nil
    end
  }

  # nils confuse readline
  tabs.compact
end