Class: Msf::Sessions::CommandShellWindows

Inherits:
CommandShell show all
Defined in:
lib/msf/base/sessions/command_shell_windows.rb

Instance Attribute Summary

Attributes inherited from CommandShell

#arch, #banner, #max_threads, #platform

Attributes included from Msf::Session::Interactive

#rstream

Attributes included from Rex::Ui::Interactive

#completed, #interacting, #next_session, #on_command_proc, #on_print_proc, #on_run_command_error_proc, #orig_suspend, #orig_usr1, #orig_winch

Attributes included from Rex::Ui::Subscriber::Input

#user_input

Attributes included from Rex::Ui::Subscriber::Output

#user_output

Attributes included from Msf::Session

#alive, #db_record, #exploit, #exploit_datastore, #exploit_task, #exploit_uuid, #framework, #info, #machine_id, #payload_uuid, #routes, #sid, #sname, #target_host, #target_port, #username, #uuid, #via, #workspace

Attributes included from Framework::Offspring

#framework

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from CommandShell

#_file_transfer, _glue_cmdline_escape, #_interact, #_interact_stream, #abort_foreground_supported, #binary_exists, binary_exists, #bootstrap, can_cleanup_files, #cleanup, #cmd_background, #cmd_background_help, #cmd_download, #cmd_download_help, #cmd_help, #cmd_help_help, #cmd_irb, #cmd_irb_help, #cmd_pry, #cmd_pry_help, #cmd_resource, #cmd_resource_help, #cmd_sessions, #cmd_sessions_help, #cmd_shell, #cmd_shell_help, #cmd_source, #cmd_source_help, #cmd_upload, #cmd_upload_help, #commands, #desc, #docs_dir, #execute_file, #process_autoruns, #run_builtin_cmd, #run_single, #shell_close, #shell_command, #shell_init, #shell_read, #shell_write, type, #type

Methods included from Rex::Ui::Text::Resource

#load_resource

Methods included from Scriptable

#execute_file, #execute_script, included, #legacy_script_to_post_module

Methods included from Msf::Session::Provider::SingleCommandShell

#command_termination, #set_is_echo_shell, #shell_close, #shell_command_token_base, #shell_command_token_unix, #shell_command_token_win32, #shell_init, #shell_read, #shell_read_until_token, #shell_write

Methods included from Msf::Session::Basic

#_interact, #desc, #type

Methods included from Msf::Session::Interactive

#_interact, #_interact_complete, #_interrupt, #_suspend, #_usr1, #abort_foreground, #abort_foreground_supported, #cleanup, #comm_channel, #interactive?, #kill, #run_cmd, #tunnel_local, #tunnel_peer, #user_want_abort?

Methods included from Rex::Ui::Interactive

#_interact, #_interact_complete, #_interrupt, #_local_fd, #_remote_fd, #_stream_read_local_write_remote, #_stream_read_remote_write_local, #_suspend, #_winch, #detach, #handle_suspend, #handle_usr1, #handle_winch, #interact, #interact_stream, #prompt, #prompt_yesno, #restore_suspend, #restore_usr1, #restore_winch

Methods included from Rex::Ui::Subscriber

#copy_ui, #init_ui, #reset_ui

Methods included from Rex::Ui::Subscriber::Input

#gets

Methods included from Rex::Ui::Subscriber::Output

#flush, #print, #print_blank_line, #print_error, #print_good, #print_line, #print_status, #print_warning

Methods included from Msf::Session

#alive?, #cleanup, #comm_channel, #dead?, #desc, #inspect, #interactive?, #kill, #log_file_name, #log_source, #name, #name=, #register?, #session_host, #session_host=, #session_port, #session_port=, #session_type, #set_from_exploit, #set_via, #tunnel_local, #tunnel_peer, #tunnel_to_s, #type, type, #via_exploit, #via_payload

Constructor Details

#initialize(*args) ⇒ CommandShellWindows

Returns a new instance of CommandShellWindows.

[View source] [View on GitHub]

4
5
6
7
# File 'lib/msf/base/sessions/command_shell_windows.rb', line 4

def initialize(*args)
  self.platform = "windows"
  super
end

Class Method Details

.argv_to_commandline(args) ⇒ Object

Convert the executable and argument array to a commandline that can be passed to CreateProcessAsUserW.

Parameters:

  • args (Array<String>)

    The arguments to the process

[View source] [View on GitHub]

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

def self.argv_to_commandline(args)
  escaped_args = args.map do |arg|
    escape_arg(arg)
  end

  escaped_args.join(' ')
end

.escape_arg(arg) ⇒ Object

Escape an individual argument per Windows shell rules

Parameters:

  • arg (String)

    Shell argument

[View source] [View on GitHub]

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/msf/base/sessions/command_shell_windows.rb', line 52

def self.escape_arg(arg)
    needs_quoting = space_chars.any? do |char|
      arg.include?(char)
    end

    # Fix the weird behaviour when backslashes are treated differently when immediately prior to a double-quote
    # We need to send double the number of backslashes to make it work as expected
    # See: https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw#remarks
    arg = arg.gsub(/(\\*)"/, '\\1\\1"')

    # Quotes need to be escaped
    arg = arg.gsub('"', '\\"')

    if needs_quoting
      # At the end of the argument, we're about to add another quote - so any backslashes need to be doubled here too
      arg = arg.gsub(/(\\*)$/, '\\1\\1')
      arg = "\"#{arg}\""
    end

    # Empty string needs to be coerced to have a value
    arg = '""' if arg == ''

    arg
end

.escape_cmd(executable) ⇒ Object

Escape a process for the command line

Parameters:

  • executable (String)

    The process to launch

[View source] [View on GitHub]

25
26
27
28
29
30
31
32
33
34
35
# File 'lib/msf/base/sessions/command_shell_windows.rb', line 25

def self.escape_cmd(executable)
  needs_quoting = space_chars.any? do |char|
    executable.include?(char)
  end

  if needs_quoting
    executable = "\"#{executable}\""
  end

  executable
end

.space_charsObject

[View source] [View on GitHub]

9
10
11
# File 'lib/msf/base/sessions/command_shell_windows.rb', line 9

def self.space_chars
  [' ', '\t', '\v']
end

.to_cmd(cmd_and_args) ⇒ Object

Convert the executable and argument array to a command that can be run in this command shell

Parameters:

  • cmd_and_args (Array<String>)

    The process path and the arguments to the process

[View source] [View on GitHub]

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/msf/base/sessions/command_shell_windows.rb', line 79

def self.to_cmd(cmd_and_args)
  # The space, caret and quote chars need to be inside double-quoted strings.
  # The percent character needs to be escaped using a caret char, while being outside a double-quoted string.
  #
  # Situations where these two situations combine are going to be the trickiest cases: something that has quote-requiring
  # characters (e.g. spaces), but which also needs to avoid expanding an environment variable. In this case,
  # the string needs to end up being partially quoted; with parts of the string in quotes, but others (i.e. bits with percents) not.
  # For example:
  # 'env var is %temp%, yes, %TEMP%' needs to end up as '"env var is "^%temp^%", yes, "^%TEMP^%'
  #
  # There is flexibility in how you might implement this, but I think this one looks the most "human" to me,
  # which would make it less signaturable.
  #
  # To do this, we'll consider each argument character-by-character. Each time we encounter a percent sign, we break out of any quotes
  # (if we've been inside them in the current "token"), and then start a new "token".

  quote_requiring = ['"', '^', ' ', "\t", "\v", '&', '<', '>', '|']

  escaped_cmd_and_args = cmd_and_args.map do |arg|
    # Escape quote chars by doubling them up, except those preceeded by a backslash (which are already effectively escaped, and handled below)
    arg = arg.gsub(/([^\\])"/, '\\1""')
    arg = arg.gsub(/^"/, '""')

    result = CommandShell._glue_cmdline_escape(arg, quote_requiring, '%', '^%', '"')

    # Fix the weird behaviour when backslashes are treated differently when immediately prior to a double-quote
    # We need to send double the number of backslashes to make it work as expected
    # See: https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw#remarks
    result.gsub!(/(\\*)"/, '\\1\\1"')

    # Empty string needs to be coerced to have a value
    result = '""' if result == ''

    result
  end

  escaped_cmd_and_args.join(' ')
end

Instance Method Details

#shell_command_token(cmd, timeout = 10) ⇒ Object

[View source] [View on GitHub]

13
14
15
# File 'lib/msf/base/sessions/command_shell_windows.rb', line 13

def shell_command_token(cmd,timeout = 10)
  shell_command_token_win32(cmd,timeout)
end

#to_cmd(cmd_and_args) ⇒ Object

Convert the executable and argument array to a command that can be run in this command shell

Parameters:

  • cmd_and_args (Array<String>)

    The process path and the arguments to the process

[View source] [View on GitHub]

19
20
21
# File 'lib/msf/base/sessions/command_shell_windows.rb', line 19

def to_cmd(cmd_and_args)
  self.class.to_cmd(cmd_and_args)
end