Module: Ronin::Support::Encoding::PowerShell

Defined in:
lib/ronin/support/encoding/powershell.rb

Overview

Since:

  • 1.0.0

Constant Summary collapse

ESCAPE_BYTES =

Special PowerShell bytes and their escaped Strings.

{
  0x00 => "`0",
  0x07 => "`a",
  0x08 => "`b",
  0x09 => "`t",
  0x0a => "`n",
  0x0b => "`v",
  0x0c => "`f",
  0x0d => "`r",
  0x22 => '`"',
  0x23 => "`#",
  0x27 => "`'",
  0x5c => "\\\\", # \\
  0x60 => "``"
}
BACKSLASHED_CHARS =

PowerShell characters that must be grave-accent escaped.

{
  '0'  => "\0",
  'a'  => "\a",
  'b'  => "\b",
  't'  => "\t",
  'n'  => "\n",
  'v'  => "\v",
  'f'  => "\f",
  'r'  => "\r",
  '"'  => '"',
  '#'  => '#',
  "'"  => "'",
  "`"  => "`"
}

Class Method Summary collapse

Class Method Details

.decode(data) ⇒ String

Alias for unescape.

Parameters:

  • data (String)

    The PowerShell encoded data to unescape.

Returns:

  • (String)

    The unescaped string.

See Also:

Since:

  • 1.0.0



262
263
264
# File 'lib/ronin/support/encoding/powershell.rb', line 262

def self.decode(data)
  unescape(data)
end

.encode(data) ⇒ String

PowerShell encodes every character in the data.

Examples:

Encoding::PowerShell.encode("hello world")
# => "$([char]0x68)$([char]0x65)$([char]0x6c)$([char]0x6c)$([char]0x6f)$([char]0x20)$([char]0x77)$([char]0x6f)$([char]0x72)$([char]0x6c)$([char]0x64)"

Parameters:

  • data (String)

    The data to encode.

Returns:

  • (String)

    The PowerShell encoded String.

See Also:

Since:

  • 1.0.0



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/ronin/support/encoding/powershell.rb', line 235

def self.encode(data)
  encoded = String.new

  if data.valid_encoding?
    data.each_codepoint do |codepoint|
      encoded << encode_byte(codepoint)
    end
  else
    data.each_byte do |byte|
      encoded << encode_byte(byte)
    end
  end

  return encoded
end

.encode_byte(byte) ⇒ String

Encodes the byte as a PowerShell character.

Examples:

Encoding::PowerShell.encode_byte(0x41)
# => "[char]0x41"
Encoding::PowerShell.encode_byte(0x0a)
# => "`n"

Encoding unicode characters:

Encoding::PowerShell.encode_byte(1001)
# => "`u{1001}"

Parameters:

  • byte (Integer)

    The byte to escape.

Returns:

  • (String)

    The encoded PowerShell character.

Raises:

  • (RangeError)

    The integer value is negative.

See Also:

Since:

  • 1.0.0



85
86
87
88
89
90
91
92
93
# File 'lib/ronin/support/encoding/powershell.rb', line 85

def self.encode_byte(byte)
  if byte >= 0x00 && byte <= 0xff
    "$([char]0x%.2x)" % byte
  elsif byte > 0xff
    "$([char]0x%x)" % byte
  else
    raise(RangeError,"#{byte.inspect} out of char range")
  end
end

.escape(data) ⇒ String

PowerShell escapes the special characters in the data.

Examples:

Encoding::PowerShell.escape("hello\nworld")
# => "hello`nworld"

Parameters:

  • data (String)

    The data to PowerShell escape.

Returns:

  • (String)

    The PowerShell escaped string.

See Also:

Since:

  • 1.0.0



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/ronin/support/encoding/powershell.rb', line 168

def self.escape(data)
  escaped = String.new

  if data.valid_encoding?
    data.each_codepoint do |codepoint|
      escaped << escape_byte(codepoint)
    end
  else
    data.each_byte do |byte|
      escaped << escape_byte(byte)
    end
  end

  return escaped
end

.escape_byte(byte) ⇒ String

Escapes the byte as a PowerShell character.

Examples:

Encoding::PowerShell.escape_byte(0x41)
# => "A"
Encoding::PowerShell.escape_byte(0x08)
# => "`b"
Encoding::PowerShell.escape_byte(0xff)
# => "[char]0xff"

Escaping unicode characters:

Encoding::PowerShell.escape_byte(1001)
# => "`u{1001}"

Parameters:

  • byte (Integer)

    The byte to escape.

Returns:

  • (String)

    The escaped PowerShell character.

Raises:

  • (RangeError)

    The integer value is negative.

See Also:

Since:

  • 1.0.0



121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/ronin/support/encoding/powershell.rb', line 121

def self.escape_byte(byte)
  if byte >= 0x00 && byte <= 0xff
    ESCAPE_BYTES.fetch(byte) do
      if byte >= 0x20 && byte <= 0x7e
        byte.chr
      else
        encode_byte(byte)
      end
    end
  else
    encode_byte(byte)
  end
end

.quote(data) ⇒ String

Converts the data into a double-quoted PowerShell escaped String.

Examples:

Encoding::PowerShell.quote("hello\nworld")
# => "\"hello`nworld\""

Parameters:

  • data (String)

    the data to escape and quote.

Returns:

  • (String)

    The quoted and escaped PowerShell string.

Since:

  • 1.0.0



279
280
281
# File 'lib/ronin/support/encoding/powershell.rb', line 279

def self.quote(data)
  "\"#{escape(data)}\""
end

.unescape(data) ⇒ String

PowerShell unescapes the characters in the data.

Examples:

Encoding::PowerShell.unescape("hello`nworld")
# => "hello\nworld"

Parameters:

  • data (String)

    The PowerShell encoded data to unescape.

Returns:

  • (String)

    The unescaped string.

See Also:

Since:

  • 1.0.0



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/ronin/support/encoding/powershell.rb', line 199

def self.unescape(data)
  unescaped = String.new(encoding: Encoding::UTF_8)
  scanner   = StringScanner.new(data)

  until scanner.eos?
    unescaped << if (grave_escape      = scanner.scan(/`[0abetnvfr]/)) # `c
                   BACKSLASHED_CHARS.fetch(grave_escape[1,1])
                 elsif (hex_escape     = scanner.scan(/\$\(\[char\]0x[0-9a-fA-F]{1,2}\)/)) # [char]0xXX
                   hex_escape[10..-2].to_i(16).chr
                 elsif (hex_escape     = scanner.scan(/\$\(\[char\]0x[0-9a-fA-F]{3,}\)/)) # [char]0xXX
                   hex_escape[10..-2].to_i(16).chr(Encoding::UTF_8)
                 elsif (unicode_escape = scanner.scan(/`u\{[0-9a-fA-F]+\}/)) # `u{XXXX}'
                   unicode_escape[3..-2].to_i(16).chr(Encoding::UTF_8)
                 else
                   scanner.getch
                 end
  end

  return unescaped
end

.unquote(data) ⇒ String

Removes the quotes an unescapes a PowerShell string.

Examples:

Encoding::PowerShell.unquote("\"hello`nworld\"")
# => "hello\nworld"
Encoding::PowerShell.unquote("'hello''world'")
# => "hello'world"

Parameters:

  • data (String)

    The PowerShell string to unquote.

Returns:

  • (String)

    The un-quoted String if the String begins and ends with quotes, or the same String if it is not quoted.

Since:

  • 1.0.0



299
300
301
302
303
304
305
306
307
# File 'lib/ronin/support/encoding/powershell.rb', line 299

def self.unquote(data)
  if (data.start_with?('"') && data.end_with?('"'))
    unescape(data[1..-2])
  elsif (data.start_with?("'") && data.end_with?("'"))
    data[1..-2].gsub("''","'")
  else
    data
  end
end