Module: Msf::Session::Provider::SingleCommandShell
- Included in:
- MultiCommandShell, Msf::Sessions::CommandShell, Msf::Sessions::EncryptedShell, Msf::Sessions::MainframeShell, Msf::Sessions::Meterpreter, Msf::Sessions::SshCommandShellReverse, Msf::Sessions::TTY
- Defined in:
- lib/msf/core/session/provider/single_command_shell.rb
Overview
This interface is to be implemented by a session that is only capable of providing an interface to a single command shell.
Instance Method Summary collapse
- #command_termination ⇒ Object
-
#set_shell_token_index(timeout) ⇒ Object
NOTE: if the session echoes input we don't need to echo the token twice.
-
#shell_close ⇒ Object
Closes the command shell.
- #shell_command_token(cmd, timeout = 10) ⇒ Object
-
#shell_command_token_unix(cmd, timeout = 10) ⇒ Object
Explicitly run a single command and return the output.
-
#shell_command_token_win32(cmd, timeout = 10) ⇒ Object
Explicitly run a single command and return the output.
-
#shell_init ⇒ Object
Initializes the command shell.
-
#shell_read(length = nil) ⇒ Object
Reads data from the command shell.
-
#shell_read_until_token(token, wanted_idx = 0, timeout = 10) ⇒ Object
Read data until we find the token.
-
#shell_write(buf) ⇒ Object
Writes data to the command shell.
Instance Method Details
#command_termination ⇒ Object
42 43 44 |
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 42 def command_termination "\n" end |
#set_shell_token_index(timeout) ⇒ Object
NOTE: if the session echoes input we don't need to echo the token twice. This setting will persist for the duration of the session.
113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 113 def set_shell_token_index(timeout) return @shell_token_index if @shell_token_index token = ::Rex::Text.rand_text_alpha(32) numeric_token = rand(0xffffffff) + 1 cmd = "echo #{numeric_token}" shell_write(cmd + ";echo #{token}#{command_termination}") res = shell_read_until_token(token, 0, timeout) if res.to_i == numeric_token @shell_token_index = 0 else @shell_token_index = 1 end end |
#shell_close ⇒ Object
Closes the command shell.
38 39 40 |
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 38 def shell_close() raise NotImplementedError end |
#shell_command_token(cmd, timeout = 10) ⇒ Object
87 88 89 90 91 92 93 94 |
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 87 def shell_command_token(cmd, timeout=10) if platform == 'windows' output = shell_command_token_win32(cmd, timeout) else output = shell_command_token_unix(cmd, timeout) end output end |
#shell_command_token_unix(cmd, timeout = 10) ⇒ Object
Explicitly run a single command and return the output. This version uses a marker to denote the end of data (instead of a timeout).
100 101 102 103 104 105 106 107 108 109 |
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 100 def shell_command_token_unix(cmd, timeout=10) # read any pending data buf = shell_read(-1, 0.01) set_shell_token_index(timeout) token = ::Rex::Text.rand_text_alpha(32) # Send the command to the session's stdin. shell_write(cmd + ";echo #{token}\n") shell_read_until_token(token, @shell_token_index, timeout) end |
#shell_command_token_win32(cmd, timeout = 10) ⇒ Object
Explicitly run a single command and return the output. This version uses a marker to denote the end of data (instead of a timeout).
131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 131 def shell_command_token_win32(cmd, timeout=10) # read any pending data buf = shell_read(-1, 0.01) set_shell_token_index(timeout) token = ::Rex::Text.rand_text_alpha(32) # Send the command to the session's stdin. # NOTE: if the session echoes input we don't need to echo the token twice. shell_write(cmd + "&echo #{token}#{command_termination}") res = shell_read_until_token(token, @shell_token_index, timeout) res end |
#shell_init ⇒ Object
Initializes the command shell.
17 18 19 |
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 17 def shell_init() raise NotImplementedError end |
#shell_read(length = nil) ⇒ Object
Reads data from the command shell.
24 25 26 |
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 24 def shell_read(length = nil) raise NotImplementedError end |
#shell_read_until_token(token, wanted_idx = 0, timeout = 10) ⇒ Object
Read data until we find the token
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 |
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 49 def shell_read_until_token(token, wanted_idx=0, timeout=10) return if timeout.to_i == 0 if wanted_idx == 0 parts_needed = 2 else parts_needed = 1 + (wanted_idx * 2) end # Read until we get the data between two tokens or absolute timeout. begin ::Timeout.timeout(timeout) do buf = '' idx = nil loop do if (tmp = shell_read(-1)) buf << tmp # see if we have the wanted idx unless buf.nil? # normalize the line endings following the token and parse them buf.gsub!("#{token}\n", "#{token}\r\n") parts = buf.split("#{token}\r\n", -1) if parts.length == parts_needed # cause another prompt to appear (just in case) shell_write(command_termination) return parts[wanted_idx] end end end end end rescue Timeout::Error # This is expected in many cases end # failed to get any data or find the token! nil end |
#shell_write(buf) ⇒ Object
Writes data to the command shell.
31 32 33 |
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 31 def shell_write(buf) raise NotImplementedError end |