module Rex::Powershell::Parser

Constants

RESERVED_VARIABLE_NAMES

Reserved special variables Acquired with: Get-Variable | Format-Table name, value -auto

Public Instance Methods

block_extract(idx) click to toggle source

Extract block of code inside brackets/parenthesis

Attempts to match the bracket at idx, handling nesting manually Once the balanced matching bracket is found, all script content between idx and the index of the matching bracket is returned

@param idx [Integer] index of opening bracket

@return [String] content between matching brackets

# File lib/rex/powershell/parser.rb, line 133
def block_extract(idx)
  fail ArgumentError unless idx

  if idx < 0 || idx >= code.length
    fail ArgumentError, 'Invalid index'
  end

  start = code[idx]
  stop = match_start(start)
  delims = scan_with_index(/#{Regexp.escape(start)}|#{Regexp.escape(stop)}/, code[idx + 1..-1])
  delims.map { |x| x[1] = x[1] + idx + 1 }
  c = 1
  sidx = nil
  # Go through delims till we balance, get idx
  while (c != 0) && (x = delims.shift)
    sidx = x[1]
    x[0] == stop ? c -= 1 : c += 1
  end

  code[idx..sidx]
end
get_func(func_name, delete = false) click to toggle source

Extract a block of function code

@param func_name [String] function name @param delete [Boolean] delete the function from the code

@return [String] function block

# File lib/rex/powershell/parser.rb, line 162
def get_func(func_name, delete = false)
  start = code.index(func_name)

  return nil unless start

  idx = code[start..-1].index('{') + start
  func_txt = block_extract(idx)

  if delete
    delete_code = code[0..idx]
    delete_code << code[(idx + func_txt.length)..-1]
    @code = delete_code
  end

  Function.new(func_name, func_txt)
end
get_func_names() click to toggle source

Get function names from code

@return [Array] function names

# File lib/rex/powershell/parser.rb, line 75
def get_func_names
  code.scan(/function\s([a-zA-Z\-\_0-9]+)/).uniq.flatten
end
get_string_literals() click to toggle source

Attempt to find string literals in PSH expression

@return [Array] string literals

# File lib/rex/powershell/parser.rb, line 83
def get_string_literals
  code.scan(/@"(.+?)"@|@'(.+?)'@/m)
end
get_var_names() click to toggle source

Get variable names from code, removes reserved names from return

@return [Array] variable names

# File lib/rex/powershell/parser.rb, line 66
def get_var_names
  our_vars = code.scan(/\$[a-zA-Z\-\_0-9]+/).uniq.flatten.map(&:strip)
  our_vars.select { |v| !RESERVED_VARIABLE_NAMES.include?(v.downcase) }
end
match_start(char) click to toggle source

Return matching bracket type

@param char [String] opening bracket character

@return [String] matching closing bracket

# File lib/rex/powershell/parser.rb, line 108
def match_start(char)
  case char
  when '{'
    '}'
  when '('
    ')'
  when '['
    ']'
  when '<'
    '>'
  else
    fail ArgumentError, 'Unknown starting bracket'
  end
end
scan_with_index(str, source = code) click to toggle source

Scan code and return matches with index

@param str [String] string to match in code @param source [String] source code to match, defaults to @code

@return [Array] matched items with index

# File lib/rex/powershell/parser.rb, line 94
def scan_with_index(str, source = code)
  ::Enumerator.new do |y|
    source.scan(str) do
      y << ::Regexp.last_match
    end
  end.map { |m| [m.to_s, m.offset(0)[0]] }
end