Module: Rex::Powershell::Output

Included in:
Function, Script
Defined in:
lib/rex/powershell/output.rb

Instance Method Summary collapse

Instance Method Details

#compress_code(eof = nil, gzip = true) ⇒ String

Compresses script contents with gzip (default) or deflate

Parameters:

  • eof (String) (defaults to: nil)

    End of file identifier to append to code

  • gzip (Boolean) (defaults to: true)

    Whether to use gzip compression or deflate

Returns:

  • (String)

    Compressed code wrapped in decompression stub



129
130
131
# File 'lib/rex/powershell/output.rb', line 129

def compress_code(eof = nil, gzip = true)
  @code = gzip ? gzip_code(eof) : deflate_code(eof)
end

#decode_codeString

Return ASCII powershell code from base64/unicode

Returns:

  • (String)

    ASCII powershell code



86
87
88
# File 'lib/rex/powershell/output.rb', line 86

def decode_code
  @code = Rex::Text.to_ascii(Rex::Text.decode_base64(code))
end

#decompress_codeString

Reverse the compression process Try gzip, inflate if that fails

Returns:

  • (String)

    Decompressed powershell code



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/rex/powershell/output.rb', line 138

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) ⇒ String

Return a zlib compressed powershell code wrapped in decode stub

decompression stub

Parameters:

  • eof (String) (defaults to: nil)

    End of file identifier to append to code

Returns:

  • (String)

    Zlib compressed powershell code wrapped in



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/rex/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(eof = nil) ⇒ String

Return Base64 encoded powershell code

Returns:

  • (String)

    Base64 encoded powershell code



78
79
80
# File 'lib/rex/powershell/output.rb', line 78

def encode_code(eof = nil)
  @code = Rex::Text.encode_base64(Rex::Text.to_unicode(code))
end

#gzip_code(eof = nil) ⇒ String

Return a gzip compressed powershell code wrapped in decoder stub

decompression stub

Parameters:

  • eof (String) (defaults to: nil)

    End of file identifier to append to code

Returns:

  • (String)

    Gzip compressed powershell code wrapped in



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/rex/powershell/output.rb', line 97

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

#sizeInteger

Returns code size

Returns:

  • (Integer)

    Code size



21
22
23
# File 'lib/rex/powershell/output.rb', line 21

def size
  code.size
end

#to_sString

To String

Returns:

  • (String)

    Code



13
14
15
# File 'lib/rex/powershell/output.rb', line 13

def to_s
  code
end

#to_s_linenoString

Return code with numbered lines

Returns:

  • (String)

    Powershell code with line numbers



29
30
31
32
33
34
35
36
# File 'lib/rex/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