Module: Msf::Session::Provider::SingleCommandShell

Included in:
MultiCommandShell, Msf::Sessions::CommandShell, Msf::Sessions::Meterpreter, Msf::Sessions::NetwareConsole, 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

Instance Method Details

#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.


105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 105

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}\n")
  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_closeObject

Closes the command shell.

Raises:

  • (NotImplementedError)

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


79
80
81
82
83
84
85
86
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 79

def shell_command_token(cmd, timeout=10)
  if platform =~ /win/
    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).


92
93
94
95
96
97
98
99
100
101
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 92

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


123
124
125
126
127
128
129
130
131
132
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 123

def shell_command_token_win32(cmd, timeout=10)
  # read any pending data
  buf = shell_read(-1, 0.01)
  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}\n")
  shell_read_until_token(token, 1, timeout)
end

#shell_initObject

Initializes the command shell.

Raises:

  • (NotImplementedError)

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.

Raises:

  • (NotImplementedError)

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


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
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 45

def shell_read_until_token(token, wanted_idx=0, timeout=10)
  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, 2))
          buf << tmp

          # see if we have the wanted idx
          parts = buf.split(token, -1)
          if (parts.length == parts_needed)
            # cause another prompt to appear (just in case)
            shell_write("\n")
            return parts[wanted_idx]
          end
        end
      end
    end
  rescue
    # nothing, just continue
  end

  # failed to get any data or find the token!
  nil
end

#shell_write(buf) ⇒ Object

Writes data to the command shell.

Raises:

  • (NotImplementedError)

31
32
33
# File 'lib/msf/core/session/provider/single_command_shell.rb', line 31

def shell_write(buf)
  raise NotImplementedError
end