module Rex::Exploitation::Powershell::Output

Public Instance Methods

compress_code(eof = nil, gzip = true) click to toggle source

Compresses script contents with gzip (default) or deflate

@param eof [String] End of file identifier to append to code @param gzip [Boolean] Whether to use gzip compression or deflate

@return [String] Compressed code wrapped in decompression stub

# File lib/rex/exploitation/powershell/output.rb, line 121
def compress_code(eof = nil, gzip = true)
  @code = gzip ? gzip_code(eof) : deflate_code(eof)
end
decompress_code() click to toggle source

Reverse the compression process Try gzip, inflate if that fails

@return [String] Decompressed powershell code

# File lib/rex/exploitation/powershell/output.rb, line 130
def decompress_code
  # Extract substring with payload
  encoded_stream = @code.scan(/FromBase64String\('(.*)'/).flatten.first
  # Decode and decompress the string
  unencoded = Rex::Text.decode_base64(encoded_stream)
  begin
    @code = Rex::Text.ungzip(unencoded) || Rex::Text.zlib_inflate(unencoded)
  rescue Zlib::GzipFile::Error
    begin
      @code = Rex::Text.zlib_inflate(unencoded)
    rescue Zlib::DataError => e
      raise RuntimeError, 'Invalid compression'
    end
  end

  @code
end
deflate_code(eof = nil) click to toggle source

Return a zlib compressed powershell code wrapped in decode stub

@param eof [String] End of file identifier to append to code

@return [String] Zlib compressed powershell code wrapped in decompression stub

# File lib/rex/exploitation/powershell/output.rb, line 45
def deflate_code(eof = nil)
  # Compress using the Deflate algorithm
  compressed_stream = ::Zlib::Deflate.deflate(code,
                                              ::Zlib::BEST_COMPRESSION)

  # Base64 encode the compressed file contents
  encoded_stream = Rex::Text.encode_base64(compressed_stream)

  # Build the powershell expression
  # Decode base64 encoded command and create a stream object
  psh_expression =  '$s=New-Object IO.MemoryStream(,'
  psh_expression << "[Convert]::FromBase64String('#{encoded_stream}'));"
  # Read & delete the first two bytes due to incompatibility with MS
  psh_expression << '$s.ReadByte();'
  psh_expression << '$s.ReadByte();'
  # Uncompress and invoke the expression (execute)
  psh_expression << 'IEX (New-Object IO.StreamReader('
  psh_expression << 'New-Object IO.Compression.DeflateStream('
  psh_expression << '$s,'
  psh_expression << '[IO.Compression.CompressionMode]::Decompress)'
  psh_expression << ')).ReadToEnd();'

  # If eof is set, add a marker to signify end of code output
  # if (eof && eof.length == 8) then psh_expression += "'#{eof}'" end
  psh_expression << "echo '#{eof}';" if eof

  @code = psh_expression
end
encode_code() click to toggle source

Return Base64 encoded powershell code

@return [String] Base64 encoded powershell code

# File lib/rex/exploitation/powershell/output.rb, line 78
def encode_code
  @code = Rex::Text.encode_base64(Rex::Text.to_unicode(code))
end
gzip_code(eof = nil) click to toggle source

Return a gzip compressed powershell code wrapped in decoder stub

@param eof [String] End of file identifier to append to code

@return [String] Gzip compressed powershell code wrapped in decompression stub

# File lib/rex/exploitation/powershell/output.rb, line 89
def gzip_code(eof = nil)
  # Compress using the Deflate algorithm
  compressed_stream = Rex::Text.gzip(code)

  # Base64 encode the compressed file contents
  encoded_stream = Rex::Text.encode_base64(compressed_stream)

  # Build the powershell expression
  # Decode base64 encoded command and create a stream object
  psh_expression =  '$s=New-Object IO.MemoryStream(,'
  psh_expression << "[Convert]::FromBase64String('#{encoded_stream}'));"
  # Uncompress and invoke the expression (execute)
  psh_expression << 'IEX (New-Object IO.StreamReader('
  psh_expression << 'New-Object IO.Compression.GzipStream('
  psh_expression << '$s,'
  psh_expression << '[IO.Compression.CompressionMode]::Decompress)'
  psh_expression << ')).ReadToEnd();'

  # If eof is set, add a marker to signify end of code output
  # if (eof && eof.length == 8) then psh_expression += "'#{eof}'" end
  psh_expression << "echo '#{eof}';" if eof

  @code = psh_expression
end
size() click to toggle source

Returns code size

@return [Integer] Code size

# File lib/rex/exploitation/powershell/output.rb, line 21
def size
  code.size
end
to_s() click to toggle source

To String

@return [String] Code

# File lib/rex/exploitation/powershell/output.rb, line 13
def to_s
  code
end
to_s_lineno() click to toggle source

Return code with numbered lines

@return [String] Powershell code with line numbers

# File lib/rex/exploitation/powershell/output.rb, line 29
def to_s_lineno
  numbered = ''
  code.split(/\r\n|\n/).each_with_index do |line, idx|
    numbered << "#{idx}: #{line}"
  end

  numbered
end