Class: Msf::Sessions::WinrmCommandShell::WinRMStreamAdapter
- Inherits:
-
Object
- Object
- Msf::Sessions::WinrmCommandShell::WinRMStreamAdapter
- Includes:
- Msf::Sessions::WinrmStreamAdapterCommon
- Defined in:
- lib/msf/base/sessions/winrm_command_shell.rb
Overview
Abstract WinRM to look like a stream so CommandShell can be happy
Instance Attribute Summary collapse
-
#interactive_command_id ⇒ Object
rubocop:enable Lint/SuppressedException.
-
#keep_alive_thread ⇒ Object
rubocop:enable Lint/SuppressedException.
-
#on_shell_ended ⇒ Object
rubocop:enable Lint/SuppressedException.
-
#shell ⇒ Object
rubocop:enable Lint/SuppressedException.
Instance Method Summary collapse
-
#close ⇒ Object
Close the shell; cleanly terminating it on the server if possible.
-
#get_once(length = -1,, timeout = 1) ⇒ Object
Read from the command shell, hurrying the keep-alive background thread along each time we loop back without a result.
-
#initialize(shell, interactive_command_id, on_shell_ended) ⇒ WinRMStreamAdapter
constructor
A new instance of WinRMStreamAdapter.
-
#refresh_stdout ⇒ Object
Trigger the background thread to go get more stdout.
-
#start_keep_alive_loop(framework) ⇒ Object
Start a background thread for regularly checking for stdout.
-
#stop_keep_alive_loop ⇒ Object
Stop the background thread.
- #write(buf) ⇒ Object
Methods included from Msf::Sessions::WinrmStreamAdapterCommon
#_get_once, #init_stream_buffer, #localinfo, #peerinfo
Constructor Details
#initialize(shell, interactive_command_id, on_shell_ended) ⇒ WinRMStreamAdapter
Returns a new instance of WinRMStreamAdapter.
19 20 21 22 23 24 25 26 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 19 def initialize(shell, interactive_command_id, on_shell_ended) # To buffer input received while a session is backgrounded, we stick responses in a list init_stream_buffer @check_stdin_event = Rex::Sync::Event.new(false, true) self.interactive_command_id = interactive_command_id self.shell = shell self.on_shell_ended = on_shell_ended end |
Instance Attribute Details
#interactive_command_id ⇒ Object
rubocop:enable Lint/SuppressedException
111 112 113 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 111 def interactive_command_id @interactive_command_id end |
#keep_alive_thread ⇒ Object
rubocop:enable Lint/SuppressedException
111 112 113 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 111 def keep_alive_thread @keep_alive_thread end |
#on_shell_ended ⇒ Object
rubocop:enable Lint/SuppressedException
111 112 113 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 111 def on_shell_ended @on_shell_ended end |
#shell ⇒ Object
rubocop:enable Lint/SuppressedException
111 112 113 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 111 def shell @shell end |
Instance Method Details
#close ⇒ Object
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
104 105 106 107 108 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 104 def close stop_keep_alive_loop shell.cleanup_command(interactive_command_id) rescue WinRM::WinRMWSManFault end |
#get_once(length = -1,, timeout = 1) ⇒ Object
Read from the command shell, hurrying the keep-alive background thread along each time we loop back without a result.
40 41 42 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 40 def get_once(length = -1, timeout = 1) super(length, timeout) { refresh_stdout } end |
#refresh_stdout ⇒ Object
Trigger the background thread to go get more stdout
29 30 31 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 29 def refresh_stdout @check_stdin_event.set end |
#start_keep_alive_loop(framework) ⇒ Object
Start a background thread for regularly checking for stdout
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 45 def start_keep_alive_loop(framework) self.keep_alive_thread = framework.threads.spawn('WinRM-shell-keepalive', false, shell) do |_thr_shell| loop_delay = 0.5 loop do tmp_buffer = [] output_seen = false shell.read_stdout(interactive_command_id) do |stdout, stderr| if stdout || stderr output_seen = true end tmp_buffer << stdout if stdout tmp_buffer << stderr if stderr end @buffer_mutex.synchronize do @buffer.concat(tmp_buffer) end # If our last request received stdout, let's be ready for some more if output_seen @received_stdout_event.set loop_delay = 0.5 else # Gradual backoff loop_delay *= 4 loop_delay = [loop_delay, 30].min end # Wait loop_delay seconds, or until an interactive thread wakes us up begin @check_stdin_event.wait(loop_delay) # rubocop:disable Lint/SuppressedException rescue ::Timeout::Error end # rubocop:enable Lint/SuppressedException Thread.pass rescue WinRM::WinRMWSManFault => e print_error(e.fault_description) on_shell_ended.call rescue EOFError # Shell has been terminated on_shell_ended.call rescue Rex::HostUnreachable => e on_shell_ended.call(e.) rescue StandardError => e on_shell_ended.call(e.) end end end |
#stop_keep_alive_loop ⇒ Object
Stop the background thread
95 96 97 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 95 def stop_keep_alive_loop keep_alive_thread.kill end |
#write(buf) ⇒ Object
33 34 35 36 |
# File 'lib/msf/base/sessions/winrm_command_shell.rb', line 33 def write(buf) shell.send_stdin(buf, interactive_command_id) refresh_stdout end |