Class: Msf::RPC::RPC_Session

Inherits:
RPC_Base show all
Defined in:
lib/msf/core/rpc/v10/rpc_session.rb

Instance Attribute Summary

Attributes inherited from RPC_Base

#framework, #job_status_tracker, #service, #tokens, #users

Instance Method Summary collapse

Methods inherited from RPC_Base

#error, #initialize

Constructor Details

This class inherits a constructor from Msf::RPC::RPC_Base

Instance Method Details

#rpc_compatible_modules(sid) ⇒ Hash

Returns all the compatible modules for this session.

Examples:

Here's how you would use this from the client:

rpc.call('session.compatible_modules', 3)

Parameters:

  • sid (Integer)

    Session ID.

Returns:

  • (Hash)

    Modules. It contains the following key:

    • 'modules' [Array<string>] An array of module names. Example: ['post/windows/wlan/wlan_profile', 'auxiliary/scanner/postgres_version', 'exploit/windows/local/alpc_taskscheduler']



508
509
510
511
512
513
514
515
516
517
518
519
520
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 508

def rpc_compatible_modules(sid)
  session_type = self.framework.sessions[sid].type
  search_params = { 'session_type' => [[session_type], []] }
  cached_modules = Msf::Modules::Metadata::Cache.instance.find(search_params)

  compatible_modules = []
  cached_modules.each do |cached_module|
    m = _find_module(cached_module.type, cached_module.fullname)
    compatible_modules << m.fullname if m.session_compatible?(sid)
  end

  { "modules" => compatible_modules }
end

#rpc_interactive_read(sid) ⇒ Hash

Note:

Multiple concurrent callers writing and reading the same Meterperter session can lead to a conflict, where one caller gets the others output and vice versa. Concurrent access to a Meterpreter session is best handled by post modules.

Reads the output from an interactive session (meterpreter, DB sessions, SMB)

Examples:

Here's how you would use this from the client:

rpc.call('session.interactive_read', 2)

Parameters:

  • sid (Integer)

    Session ID.

Returns:

  • (Hash)

    It contains the following key:

    • 'data' [String] Data read.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Unknown Session ID.

    • 500 Session doesn't support interactive operations.



197
198
199
200
201
202
203
204
205
206
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 197

def rpc_interactive_read(sid)
  session = _valid_interactive_session(sid)

  unless session.user_output.respond_to?(:dump_buffer)
    session.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
  end

  data = session.user_output.dump_buffer
  { 'data' => data }
end

#rpc_interactive_write(sid, data) ⇒ Hash

Note:

Multiple concurrent callers writing and reading the same Meterperter session can lead to a conflict, where one caller gets the others output and vice versa. Concurrent access to a Meterpreter session is best handled by post modules.

Sends an input to an interactive prompt (meterpreter, DB sessions, SMB) You may want to use #rpc_interactive_read to retrieve the output. rpc.call('session.interactive_write', 2, “sysinfo”)

Examples:

Here's how you would use this from the client:

Parameters:

  • sid (Integer)

    Session ID.

  • data (String)

    Input to the session prompt.

Returns:

  • (Hash)

    A hash indicating the action was successful or not. It contains the following key:

    • 'result' [String] Either 'success' or 'failure'.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Unknown Session ID.

    • 500 Session doesn't support interactive operations.



319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 319

def rpc_interactive_write(sid, data)
  session = _valid_interactive_session(sid)

  unless session.user_output.respond_to? :dump_buffer
    session.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
  end

  interacting = false
  if session.respond_to? :channels
    session.channels.each_value do |ch|
      interacting ||= ch.respond_to?('interacting') && ch.interacting
    end
  else
    interacting = session.interacting
  end

  if interacting
    session.user_input.put(data + "\n")
  else
    framework.threads.spawn("InteractiveRunSingle-#{session.sid}-#{session.type}", false, session) do |s|
      s.console.run_single(data)
    end
  end

  { 'result' => 'success' }
end

#rpc_listHash

Returns a list of sessions that belong to the framework instance used by the RPC service.

Examples:

Here's how you would use this from the client:

rpc.call('session.list')

Returns:

  • (Hash)

    Information about sessions. Each key is the session ID, and each value is a hash that contains the following:

    • 'type' [String] Payload type. Example: meterpreter.

    • 'tunnel_local' [String] Tunnel (where the malicious traffic comes from).

    • 'tunnel_peer' [String] Tunnel (local).

    • 'via_exploit' [String] Name of the exploit used by the session.

    • 'desc' [String] Session description.

    • 'info' [String] Session info (most likely the target's computer name).

    • 'workspace' [String] Name of the workspace.

    • 'session_host' [String] Session host.

    • 'session_port' [Integer] Session port.

    • 'target_host' [String] Target host.

    • 'username' [String] Username.

    • 'uuid' [String] UUID.

    • 'exploit_uuid' [String] Exploit's UUID.

    • 'routes' [String] Routes.

    • 'platform' [String] Platform.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 29

def rpc_list
  res = {}
  self.framework.sessions.each do |sess|
    i,s = sess
    res[s.sid] = {
      'type'         => s.type.to_s,
      'tunnel_local' => s.tunnel_local.to_s,
      'tunnel_peer'  => s.tunnel_peer.to_s,
      'via_exploit'  => s.via_exploit.to_s,
      'via_payload'  => s.via_payload.to_s,
      'desc'         => s.desc.to_s,
      'info'         => s.info.to_s,
      'workspace'    => s.workspace.to_s,
      'session_host' => s.session_host.to_s,
      'session_port' => s.session_port.to_i,
      'target_host'  => s.target_host.to_s,
      'username'     => s.username.to_s,
      'uuid'         => s.uuid.to_s,
      'exploit_uuid' => s.exploit_uuid.to_s,
      'routes'       => s.routes.join(","),
      'arch'         => s.arch.to_s
    }
    if(s.type.to_s == "meterpreter")
      res[s.sid]['platform'] = s.platform.to_s
    end
  end
  res
end

#rpc_meterpreter_directory_separator(sid) ⇒ Hash

Returns the separator used by the meterpreter.

Examples:

Here's how you would use this from the client:

# This returns:
# {"separator"=>"\\"}
rpc.call('session.meterpreter_directory_separator', 3)

Parameters:

  • sid (Integer)

    Session ID.

Returns:

  • (Hash)

    A hash that contains the separator. It contains the following key:

    • 'separator' [String] The separator used by the meterpreter.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.



494
495
496
497
498
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 494

def rpc_meterpreter_directory_separator(sid)
  s = _valid_session(sid,"meterpreter")

  { "separator" => s.fs.file.separator }
end

#rpc_meterpreter_read(sid) ⇒ Hash

Deprecated.

in favour of #rpc_interactive_read

Note:

Multiple concurrent callers writing and reading the same Meterperter session can lead to a conflict, where one caller gets the others output and vice versa. Concurrent access to a Meterpreter session is best handled by post modules.

Reads the output from a meterpreter session (such as a command output).

Examples:

Here's how you would use this from the client:

rpc.call('session.meterpreter_read', 2)

Parameters:

  • sid (Integer)

    Session ID.

Returns:

  • (Hash)

    It contains the following key:

    • 'data' [String] Data read.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.



180
181
182
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 180

def rpc_meterpreter_read(sid)
  rpc_interactive_read(sid)
end

#rpc_meterpreter_run_single(sid, data) ⇒ Hash

Runs a meterpreter command even if interacting with a shell or other channel. You will want to use the #rpc_meterpreter_read to retrieve the output.

Examples:

Here's how you would use this from the client:

rpc.call('session.meterpreter_run_single', 3, 'getpid')

Parameters:

  • sid (Integer)

    Session ID.

  • data (String)

    Command.

Returns:

  • (Hash)

    A hash indicating the action was successful. It contains the following key:

    • 'result' [String] 'success'

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.



422
423
424
425
426
427
428
429
430
431
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 422

def rpc_meterpreter_run_single( sid, data)
  s = _valid_session(sid,"meterpreter")

  if not s.user_output.respond_to? :dump_buffer
    s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
  end

  self.framework.threads.spawn("MeterpreterRunSingle", false, s) { |sess| sess.console.run_single(data) }
  { "result" => "success" }
end

#rpc_meterpreter_script(sid, data) ⇒ Hash

Deprecated.

Metasploit no longer maintains or accepts meterpreter scripts. Please try to use post modules instead.

Runs a meterpreter script.

Examples:

Here's how you would use this from the client:

rpc.call('session.meterpreter_script', 3, 'checkvm')

Parameters:

  • sid (Integer)

    Session ID.

  • data (String)

    Meterpreter script name.

Returns:

  • (Hash)

    A hash indicating the action was successful. It contains the following key:

    • 'result' [String] 'success'

See Also:



445
446
447
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 445

def rpc_meterpreter_script( sid, data)
  rpc_meterpreter_run_single( sid, "run #{data}")
end

#rpc_meterpreter_session_detach(sid) ⇒ Hash

Detaches from a meterpreter session. Serves the same purpose as [CTRL]+.

Examples:

Here's how you would use this from the client:

rpc.call('session.meterpreter_session_detach', 3)

Parameters:

  • sid (Integer)

    Session ID.

Returns:

  • (Hash)

    A hash indicating the action was successful or not. It contains:

    • 'result' [String] Either 'success' or 'failure'.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.



356
357
358
359
360
361
362
363
364
365
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 356

def rpc_meterpreter_session_detach(sid)
  s = _valid_session(sid,"meterpreter")
  s.channels.each_value do |ch|
    if(ch.respond_to?('interacting') && ch.interacting)
      ch.detach()
      return { "result" => "success" }
    end
  end
  { "result" => "failure" }
end

#rpc_meterpreter_session_kill(sid) ⇒ Hash

Kills a meterpreter session. Serves the same purpose as [CTRL]+.

* 'result' [String] Either 'success' or 'failure'.

Examples:

Here's how you would use this from the client:

rpc.call('session.meterpreter_session_kill', 3)

Parameters:

  • sid (Integer)

    Session ID.

Returns:

  • (Hash)

    A hash indicating the action was successful or not. It contains the following key:

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.



379
380
381
382
383
384
385
386
387
388
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 379

def rpc_meterpreter_session_kill(sid)
  s = _valid_session(sid,"meterpreter")
  s.channels.each_value do |ch|
    if(ch.respond_to?('interacting') && ch.interacting)
      ch._close
      return { "result" => "success" }
    end
  end
  { "result" => "failure" }
end

#rpc_meterpreter_tabs(sid, line) ⇒ Hash

Returns a tab-completed version of your meterpreter prompt input.

Examples:

Here's how you would use this from the client:

# This returns:
# {"tabs"=>["sysinfo"]}
rpc.call('session.meterpreter_tabs', 3, 'sysin')

Parameters:

  • sid (Integer)

    Session ID.

  • line (String)

    Input.

Returns:

  • (Hash)

    The tab-completed result. It contains the following key:

    • 'tabs' [String] The tab-completed version of your input.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.



404
405
406
407
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 404

def rpc_meterpreter_tabs(sid, line)
  s = _valid_session(sid,"meterpreter")
  { "tabs" => s.console.tab_complete(line) }
end

#rpc_meterpreter_transport_change(sid, opts = {}) ⇒ Boolean

Changes the Transport of a given Meterpreter Session

Parameters:

  • sid (Integer)

    The Session ID of the `Msf::Session`

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • :transport (String)

    The transport protocol to use (e.g. reverse_tcp, reverse_http, bind_tcp etc)

  • :lhost (String)

    The LHOST of the listener to use

  • :lport (String)

    The LPORT of the listener to use

  • :ua (String)

    The User Agent String to use for reverse_http(s)

  • :proxy_host (String)

    The address of the proxy to route transport through

  • :proxy_port (String)

    The port the proxy is listening on

  • :proxy_type (String)

    The type of proxy to use

  • :proxy_user (String)

    The username to authenticate to the proxy with

  • :proxy_pass (String)

    The password to authenticate to the proxy with

  • :comm_timeout (String)

    Connection timeout in seconds

  • :session_exp (String)

    Session Expiration Timeout

  • :retry_total (String)

    Total number of times to retry etsablishing the transport

  • :retry_wait (String)

    The number of seconds to wait between retries

  • :cert (String)

    Path to the SSL Cert to use for HTTPS

Returns:

  • (Boolean)

    whether the transport was changed successfully



467
468
469
470
471
472
473
474
475
476
477
478
479
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 467

def rpc_meterpreter_transport_change(sid,opts={})
  session = _valid_session(sid,"meterpreter")
  real_opts = {}
  opts.each_pair do |key, value|
    real_opts[key.to_sym] = value
  end
  real_opts[:uuid] = session.payload_uuid
  result = session.core.transport_change(real_opts)
  if result == true
    rpc_stop(sid)
  end
  result
end

#rpc_meterpreter_write(sid, data) ⇒ Hash

Deprecated.

in favour of #rpc_interactive_write

Note:

Multiple concurrent callers writing and reading the same Meterperter session can lead to a conflict, where one caller gets the others output and vice versa. Concurrent access to a Meterpreter session is best handled by post modules.

Sends an input to a meterpreter prompt. You may want to use #rpc_meterpreter_read to retrieve the output.

Examples:

Here's how you would use this from the client:

rpc.call('session.meterpreter_write', 2, "sysinfo")

Parameters:

  • sid (Integer)

    Session ID.

  • data (String)

    Input to the meterpreter prompt.

Returns:

  • (Hash)

    A hash indicating the action was successful or not. It contains the following key:

    • 'result' [String] Either 'success' or 'failure'.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.

See Also:



301
302
303
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 301

def rpc_meterpreter_write(sid, data)
  rpc_interactive_write(sid, data)
end

#rpc_ring_clear(sid) ⇒ Hash

Clears a shell session. This may be useful to reclaim memory for idle background sessions.

Examples:

Here's how you would use this from the client:

rpc.call('session.ring_clear', 2)

Parameters:

  • sid (Integer)

    Session ID.

Returns:

  • (Hash)

    A hash indicating whether the action was successful or not. It contains:

    • 'result' [String] Either 'success' or 'failure'.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.



280
281
282
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 280

def rpc_ring_clear(sid)
  { "result" => "success" }
end

#rpc_ring_last(sid) ⇒ Hash

Returns the last sequence (last issued ReadPointer) for a shell session.

Examples:

Here's how you would use this from the client:

rpc.call('session.ring_last', 2)

Parameters:

  • sid (Integer)

    Session ID.

Returns:

  • (Hash)

    It contains the following key:

    • 'seq' [String] Sequence.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.



264
265
266
267
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 264

def rpc_ring_last(sid)
  s = _valid_session(sid,"ring")
  { "seq" => 0 }
end

#rpc_ring_put(sid, data) ⇒ Hash

Sends an input to a session (such as a command).

Examples:

Here's how you would use this from the client:

rpc.call('session.ring_put', 2, "DATA")

Parameters:

  • sid (Integer)

    Session ID.

  • data (String)

    Data to write.

Returns:

  • (Hash)

    It contains the following key:

    • 'write_count' [String] Number of bytes written.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.

    • 500 Session is disconnected.



244
245
246
247
248
249
250
251
252
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 244

def rpc_ring_put(sid, data)
  s = _valid_session(sid,"ring")
  begin
    res = s.shell_write(data)
    { "write_count" => res.to_s}
  rescue ::Exception => e
    error(500, "Session Disconnected: #{e.class} #{e}")
  end
end

#rpc_ring_read(sid, ptr = nil) ⇒ Hash

Reads from a session (such as a command output).

Examples:

Here's how you would use this from the client:

rpc.call('session.ring_read', 2)

Parameters:

  • sid (Integer)

    Session ID.

  • ptr (Integer) (defaults to: nil)

    Pointer (ignored)

Returns:

  • (Hash)

    It contains the following key:

    • 'seq' [String] Sequence.

    • 'data' [String] Read data.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.

    • 500 Session is disconnected.



221
222
223
224
225
226
227
228
229
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 221

def rpc_ring_read(sid, ptr = nil)
  s = _valid_session(sid,"ring")
  begin
    res = s.shell_read()
    { "seq" => 0, "data" => res.to_s }
  rescue ::Exception => e
    error(500, "Session Disconnected: #{e.class} #{e}")
  end
end

#rpc_shell_read(sid, ptr = nil) ⇒ Hash

Reads the output of a shell session (such as a command output).

Examples:

Here's how you would use this from the client:

rpc.call('session.shell_read', 2)

Parameters:

  • sid (Integer)

    Session ID.

  • ptr (Integer) (defaults to: nil)

    Pointer.

Returns:

  • (Hash)

    It contains the following keys:

    • 'seq' [String] Sequence.

    • 'data' [String] Read data.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.

    • 500 Session is disconnected.



112
113
114
115
116
117
118
119
120
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 112

def rpc_shell_read( sid, ptr=nil)
  s = _valid_session(sid,"shell")
  begin
    res = s.shell_read()
    { "seq" => 0, "data" => res.to_s}
  rescue ::Exception => e
    error(500, "Session Disconnected: #{e.class} #{e}")
  end
end

#rpc_shell_upgrade(sid, lhost, lport) ⇒ Hash

Note:

This uses post/multi/manage/shell_to_meterpreter.

Upgrades a shell to a meterpreter.

Examples:

Here's how you would use this from the client:

rpc.call('session.shell_upgrade', 2, payload_lhost, payload_lport)

Parameters:

  • sid (Integer)

    Session ID.

  • lhost (String)

    Local host.

  • lport (Integer)

    Local port.

Returns:

  • (Hash)

    A hash indicating the action was successful. It contains the following key:

    • 'result' [String] A message that says 'success'



158
159
160
161
162
163
164
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 158

def rpc_shell_upgrade( sid, lhost, lport)
  s = _valid_session(sid,"shell")
  s.exploit_datastore['LHOST'] = lhost
  s.exploit_datastore['LPORT'] = lport
  s.execute_script('post/multi/manage/shell_to_meterpreter')
  { "result" => "success" }
end

#rpc_shell_write(sid, data) ⇒ Hash

Writes to a shell session (such as a command). Note that you will to manually add a newline at the enf of your input so the system will process it. You may want to use #rpc_shell_read to retrieve the output.

Examples:

Here's how you would use this from the client:

rpc.call('session.shell_write', 2, "DATA")

Parameters:

  • sid (Integer)

    Session ID.

  • data (String)

    The data to write.

Returns:

  • (Hash)
    • 'write_count' [Integer] Number of bytes written.

Raises:

  • (Msf::RPC::Exception)

    An error that could be one of these:

    • 500 Session ID is unknown.

    • 500 Invalid session type.

    • 500 Session is disconnected.



137
138
139
140
141
142
143
144
145
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 137

def rpc_shell_write( sid, data)
  s = _valid_session(sid,"shell")
  begin
    res = s.shell_write(data)
    { "write_count" => res.to_s}
  rescue ::Exception => e
    error(500, "Session Disconnected: #{e.class} #{e}")
  end
end

#rpc_stop(sid) ⇒ Hash

Stops a session - alias for killing a session in `msfconsole`

>> rpc.call('session.list')

{7=>
 {"type"=>"meterpreter",
  "tunnel_local"=>"192.168.xxx.xxx:4444",
  "tunnel_peer"=>"192.168.xxx.xxx:64688",
  "via_exploit"=>"exploit/windows/smb/ms17_010_eternalblue",
  "via_payload"=>"payload/windows/x64/meterpreter/reverse_tcp",
  "desc"=>"Meterpreter",
  "info"=>"NT AUTHORITY\\SYSTEM @ DC1",
  "workspace"=>"default",
  "session_host"=>"192.168.xxx.xxx",
  "session_port"=>445,
  "target_host"=>"192.168.xxx.xxx",
  "username"=>"foo",
  "uuid"=>"h9pbmuoh",
  "exploit_uuid"=>"tcjj1fqo",
  "routes"=>"",
  "arch"=>"x86",
  "platform"=>"windows"}}

>> rpc.call('session.stop', 7)

> “result”=>“success”

Examples:

Here's how you would use this from the client:

# You have an active session, you run session list to view the session number, then pass that session number to the `stop` command:

Parameters:

  • sid (Integer)

    Session ID.

Returns:

  • (Hash)

    A hash indicating the action was successful. It contains the following key:

    • 'result' [String] A message that says 'success'.

Raises:



88
89
90
91
92
93
94
95
96
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 88

def rpc_stop( sid)

  s = self.framework.sessions[sid.to_i]
  if(not s)
    error(500, "Unknown Session ID")
  end
  s.kill rescue nil
  { "result" => "success" }
end