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 post 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)

    Post modules. It contains the following key:

    • 'modules' [Array<string>] An array of post module names. Example: ['post/windows/wlan/wlan_profile']



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

def rpc_compatible_modules( sid)
  ret = []

  mtype = "post"
  names = self.framework.post.keys.map{ |x| "post/#{x}" }
  names.each do |mname|
    m = _find_module(mtype, mname)
    next if not m.session_compatible?(sid)
    ret << m.fullname
  end
  { "modules" => ret }
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.



453
454
455
456
457
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 453

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

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

#rpc_meterpreter_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 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
183
184
185
186
187
188
189
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 180

def rpc_meterpreter_read( sid)
  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

  data = s.user_output.dump_buffer
  { "data" => data }
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.



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

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:



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

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.



315
316
317
318
319
320
321
322
323
324
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 315

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.



338
339
340
341
342
343
344
345
346
347
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 338

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.



363
364
365
366
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 363

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



426
427
428
429
430
431
432
433
434
435
436
437
438
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 426

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

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:



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 285

def rpc_meterpreter_write( 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

  interacting = false
  s.channels.each_value do |ch|
    interacting ||= ch.respond_to?('interacting') && ch.interacting
  end
  if interacting
    s.user_input.put(data + "\n")
  else
    self.framework.threads.spawn("MeterpreterRunSingle", false, s) { |sess| sess.console.run_single(data) }
  end
  { "result" => "success" }
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.



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

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.



248
249
250
251
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 248

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.



228
229
230
231
232
233
234
235
236
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 228

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.



205
206
207
208
209
210
211
212
213
# File 'lib/msf/core/rpc/v10/rpc_session.rb', line 205

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