Class: Msf::Sessions::WinrmPowerShell::WinRMPowerShellStreamAdapter

Inherits:
Object
  • Object
show all
Includes:
Msf::Sessions::WinrmStreamAdapterCommon
Defined in:
lib/msf/base/sessions/winrm_power_shell.rb

Overview

Abstract WinRM PowerShell to look like a stream so CommandShell can be happy.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Msf::Sessions::WinrmStreamAdapterCommon

#_get_once, #get_once, #init_stream_buffer, #localinfo, #peerinfo

Constructor Details

#initialize(shell, on_shell_ended) ⇒ WinRMPowerShellStreamAdapter

Returns a new instance of WinRMPowerShellStreamAdapter.

Parameters:

  • shell (WinRM::Shells::PowerShell)

    Shell for talking to the WinRM service

  • on_shell_ended (Method)

    Callback for when the background thread notices the shell has ended.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/msf/base/sessions/winrm_power_shell.rb', line 20

def initialize(shell, on_shell_ended)
  # To buffer input received while a session is backgrounded, we stick responses in a list.
  init_stream_buffer
  @pipeline_mutex = Mutex.new
  # A new pipeline thread is spawned on every #write, so threads can start
  # running in a different order than the commands were submitted in.
  # These four track a strictly increasing "ticket" per pipeline and let
  # each thread wait its turn, so pipelines still run in submission order
  # against the shared PSRP runspace.
  @pipeline_order_mutex = Mutex.new
  @pipeline_order_cond = ConditionVariable.new
  @next_pipeline_ticket = 0
  @current_pipeline_ticket = 0
  # Threads currently executing a pipeline against `shell`. Tracked as a
  # set rather than a single reference because a new pipeline thread is
  # spawned on every #write; without tracking them all, #close could
  # only ever kill the most recently spawned thread while an earlier
  # one was still mid-flight against the same shell.
  @pipeline_threads_mutex = Mutex.new
  @pipeline_threads = []
  self.shell = shell
  self.on_shell_ended = on_shell_ended
end

Instance Attribute Details

#frameworkObject

rubocop:enable Lint/SuppressedException



62
63
64
# File 'lib/msf/base/sessions/winrm_power_shell.rb', line 62

def framework
  @framework
end

#on_shell_endedObject

rubocop:enable Lint/SuppressedException



62
63
64
# File 'lib/msf/base/sessions/winrm_power_shell.rb', line 62

def on_shell_ended
  @on_shell_ended
end

#shellObject

rubocop:enable Lint/SuppressedException



62
63
64
# File 'lib/msf/base/sessions/winrm_power_shell.rb', line 62

def shell
  @shell
end

Instance Method Details

#closeObject

Close the shell; cleanly terminating it on the server if possible.

The shell may already be dead, or unreachable at this point, so do a best effort, and capture exceptions. rubocop:disable Lint/SuppressedException



55
56
57
58
59
# File 'lib/msf/base/sessions/winrm_power_shell.rb', line 55

def close
  kill_pipeline_threads
  shell.close
rescue WinRM::WinRMWSManFault
end

#write(buf) ⇒ Object



44
45
46
47
48
# File 'lib/msf/base/sessions/winrm_power_shell.rb', line 44

def write(buf)
  return if buf.nil? || buf.empty?

  run_pipeline(buf)
end