Module: Rex::Exploitation::Powershell::Output

Included in:
Function, Script
Defined in:
lib/rex/exploitation/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



122
123
124
# File 'lib/rex/exploitation/powershell/output.rb', line 122

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

#decompress_codeString

Reverse the compression process Try gzip, inflate if that fails

Returns:

  • (String)

    Decompressed powershell code



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/rex/exploitation/powershell/output.rb', line 131

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



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
73
# File 'lib/rex/exploitation/powershell/output.rb', line 46

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_codeString

Return Base64 encoded powershell code

Returns:

  • (String)

    Base64 encoded powershell code



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

def encode_code
  @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



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/rex/exploitation/powershell/output.rb', line 90

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



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

def size
  code.size
end

#to_sString

To String

Returns:

  • (String)

    Code



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

def to_s
  code
end

#to_s_linenoString

Return code with numbered lines

Returns:

  • (String)

    Powershell code with line numbers



30
31
32
33
34
35
36
37
# File 'lib/rex/exploitation/powershell/output.rb', line 30

def to_s_lineno
  numbered = ''
  code.split(/\r\n|\n/).each_with_index do |line, idx|
    numbered << "#{idx}: #{line}"
  end

  numbered
end