Class: Msf::Sessions::PowerShell

Inherits:
CommandShell show all
Includes:
Mixin
Defined in:
lib/msf/base/sessions/powershell.rb

Defined Under Namespace

Modules: Mixin

Instance Attribute Summary

Attributes inherited from CommandShell

#arch, #banner, #max_threads

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 included from Mixin

#shell_command

Methods inherited from CommandShell

#_file_transfer, _glue_cmdline_escape, #_interact, #_interact_stream, #abort_foreground_supported, #binary_exists, binary_exists, #bootstrap, #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, #docs_dir, #execute_file, #initialize, #run_builtin_cmd, #run_single, #shell_close, #shell_command, #shell_init, #shell_read, #shell_write, #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, #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, #type

Methods included from Msf::Session::Interactive

#_interact, #_interact_complete, #_interrupt, #_suspend, #_usr1, #abort_foreground, #abort_foreground_supported, #cleanup, #comm_channel, #initialize, #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?, #initialize, #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, #via_exploit, #via_payload

Constructor Details

This class inherits a constructor from Msf::Sessions::CommandShell

Class Method Details

.can_cleanup_filesObject



151
152
153
# File 'lib/msf/base/sessions/powershell.rb', line 151

def self.can_cleanup_files
  true
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



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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/msf/base/sessions/powershell.rb', line 49

def self.to_cmd(cmd_and_args)
  # The principle here is that we want to launch a process such that it receives *exactly* what is in `args`. 
  # This means we need to:
  # - Escape all special characters
  # - Not escape environment variables
  # - Side-step any PowerShell magic
  # If someone specifically wants to use the PowerShell magic, they can use other APIs

  needs_wrapping_chars = ['$', '`', '(', ')', '@', '>', '<', '{','}', '&', ',', ' ', ';']

  result = ""
  cmd_and_args.each_with_index do |arg, index|
    needs_single_quoting = false
    if arg.include?("'")
      arg = arg.gsub("'", "''")
      needs_single_quoting = true
    end
    
    if arg.include?('"')
      # PowerShell acts weird around quotes and backslashes
      # First we need to escape backslashes immediately prior to a double-quote, because
      # they're treated differently than backslashes anywhere else
      arg = arg.gsub(/(\\+)"/, '\\1\\1"')

      # Then we can safely prepend a backslash to escape our double-quote
      arg = arg.gsub('"', '\\"')
      needs_single_quoting = true
    end
    
    needs_wrapping_chars.each do |char|
      if arg.include?(char)
        needs_single_quoting = true
      end
    end

    # PowerShell magic - https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_special_characters?view=powershell-7.4#stop-parsing-token---
    if arg == '--%'
      needs_single_quoting = true
    end

    will_be_double_quoted_by_powershell = [' ', '\t', '\v'].any? do |bad_char|
      arg.include?(bad_char)
    end

    if will_be_double_quoted_by_powershell
      # This is horrible, and I'm so so sorry.
      # If an argument ends with a series of backslashes, and it will be quoted by PowerShell when *it* launches the process (e.g. because the arg contains a space),
      # PowerShell will not correctly handle backslashes immediately preceeding the quote that it *itself* adds. So we need to be responsible for this.
      arg = arg.gsub(/(\\*)$/, '\\1\\1')
    end

    if needs_single_quoting
      arg = "'#{arg}'"
    end

    if arg == ''
      # Pass in empty strings
      arg = '\'""\''
    end

    if index == 0
      if needs_single_quoting
        # If the executable name (i.e. index 0) has beeen wrapped, then we'll have converted it to a string.
        # We then need to use the call operator ('&') to call it.
        # https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7.3#call-operator-
        result = "& #{arg}"
      else
        result = arg
      end
    else
      result = "#{result} #{arg}"
    end
  end

  result
end

.typeObject

Returns the type of session.



147
148
149
# File 'lib/msf/base/sessions/powershell.rb', line 147

def self.type
  'powershell'
end

Instance Method Details

#descObject

Returns the session description.



165
166
167
# File 'lib/msf/base/sessions/powershell.rb', line 165

def desc
  'Powershell session'
end

#platformObject

Returns the session platform.



158
159
160
# File 'lib/msf/base/sessions/powershell.rb', line 158

def platform
  'windows'
end

#process_autoruns(datastore) ⇒ Object

Execute any specified auto-run scripts for this session



129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/msf/base/sessions/powershell.rb', line 129

def process_autoruns(datastore)
  # Read the username and hostname from the initial banner
  initial_output = shell_read(-1, 2)
  if initial_output =~ /running as user ([^\s]+) on ([^\s]+)/
    username = Regexp.last_match(1)
    hostname = Regexp.last_match(2)
    self.info = "#{username} @ #{hostname}"
  elsif initial_output
    self.info = initial_output.gsub(/[\r\n]/, ' ')
  end

  # Call our parent class's autoruns processing method
  super
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



43
44
45
# File 'lib/msf/base/sessions/powershell.rb', line 43

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