Class: String

Inherits:
Object show all
Defined in:
lib/ronin/extensions/string.rb,
lib/ronin/fuzzing/extensions/string.rb,
lib/ronin/formatting/extensions/sql/string.rb,
lib/ronin/formatting/extensions/html/string.rb,
lib/ronin/formatting/extensions/text/string.rb,
lib/ronin/formatting/extensions/http/string.rb,
lib/ronin/formatting/extensions/binary/string.rb,
lib/ronin/formatting/extensions/digest/string.rb

Overview

Copyright (c) 2006-2012 Hal Brodigan (postmodern.mod3 at gmail.com)

This file is part of Ronin Support.

Ronin Support is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Ronin Support is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with Ronin Support. If not, see <www.gnu.org/licenses/>.

Constant Summary

ESCAPE_BYTES =

Special ASCII bytes and their escaped character forms

Hash.new do |escape,byte|
  escape[byte] = if (byte >= 0x20 && byte <= 0x7e)
                   byte.chr
                 else
                   "\\x%.2X" % byte
                 end
end
JS_BACKSLASHED_CHARS =

JavaScript characters that must be back-slashed.

{
  "\\b" => "\b",
  "\\t" => "\t",
  "\\n" => "\n",
  "\\f" => "\f",
  "\\r" => "\r",
  "\\\"" => "\"",
  "\\\\" => "\\"
}

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Enumerator) generate(*template) {|string| ... }

Generate permutations of Strings from a format template.

Examples:

Generate Strings with ranges of repeating sub-strings.

Generate Strings with three alpha chars and one numeric chars.

String.generate([:alpha, 3], :numeric) do |password|
  puts password
end

Generate Strings with two to four alpha chars.

String.generate([:alpha, 2..4]) do |password|
  puts password
end

Generate Strings using alpha and punctuation chars.

String.generate([Chars.alpha + Chars.punctuation, 4]) do |password|
  puts password
end

Generate Strings from a custom char set.

String.generate([['a', 'b', 'c'], 3], [['1', '2', '3'], 3]) do |password|
  puts password
end

Generate Strings containing known Strings.

String.generate("rock", [:numeric, 4]) do |password|
  puts password
end

Generate Strings with ranges of repeating sub-strings.

String.generate(['/AA', (1..100).step(5)]) do |path|
  puts path
end

Parameters:

  • template (Array(<String,Symbol,Enumerable>, <Integer,Array,Range>))

    The template which defines the string or character sets which will make up parts of the String.

Yields:

  • (string)

    The given block will be passed each unique String.

Yield Parameters:

  • string (String)

    A newly generated String.

Returns:

  • (Enumerator)

    If no block is given, an Enumerator will be returned.

Raises:

  • (ArgumentError)

    A given character set name was unknown.

  • (TypeError)

    A given string set was not a String, Symbol or Enumerable. A given string set length was not an Integer or Enumerable.

Since:

  • 0.3.0



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/ronin/fuzzing/extensions/string.rb', line 89

def self.generate(*template)
  return enum_for(:generate,*template) unless block_given?

  sets = []

  template.each do |pattern|
    set, length = pattern
    set = case set
          when String
            [set].each
          when Symbol
            name = set.to_s.upcase

            unless Chars.const_defined?(name)
              raise(ArgumentError,"unknown charset #{set.inspect}")
            end

            Chars.const_get(name).each_char
          when Enumerable
            set
          else
            raise(TypeError,"set must be a String, Symbol or Enumerable")
          end

    case length
    when Integer
      length.times { sets << set.dup }
    when Array, Range
      sets << Combinatorics::Generator.new do |g|
        length.each do |sublength|
          superset = Array.new(sublength) { set.dup }

          superset.comprehension { |strings| g.yield strings.join }
        end
      end
    when nil
      sets << set
    else
      raise(TypeError,"length must be an Integer, Range or Array")
    end
  end

  sets.comprehension do |strings|
    new_string = ''

    strings.each do |string|
      new_string << case string
                    when Integer
                      string.chr
                    else
                      string.to_s
                    end
    end

    yield new_string
  end
  return nil
end

Instance Method Details

- (String) base64_decode(mode = nil)

Note:

`mode` argument is only available on Ruby >= 1.9.

Base64 decodes a string.

Examples:

"aGVsbG8=\n".base64_decode
# => "hello"

Parameters:

  • mode (Symbol, nil) (defaults to: nil)

    The base64 mode to use. May be either:

    • `nil`

    • `:strict`

    • `:url` / `:urlsafe`

Returns:

  • (String)

    The base64 decoded form of the string.



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/ronin/formatting/extensions/binary/string.rb', line 293

def base64_decode(mode=nil)
  case mode
  when :strict
    if RUBY_VERSION < '1.9'
      # backported from Ruby 1.9.2
      unpack("m0").first
    else
      Base64.strict_decode64(self)
    end
  when :url, :urlsafe
    if RUBY_VERSION < '1.9'
      # backported from Ruby 1.9.2
      tr("-_", "+/").unpack("m0").first
    else
      Base64.urlsafe_decode64(self)
    end
  else
    Base64.decode64(self)
  end
end

- (String) base64_encode(mode = nil)

Base64 encodes a string.

Examples:

"hello".base64_encode
# => "aGVsbG8=\n"

Parameters:

  • mode (Symbol, nil) (defaults to: nil)

    The base64 mode to use. May be either:

    • `:normal`

    • `:strict`

    • `:url` / `:urlsafe`

Returns:

  • (String)

    The base64 encoded form of the string.



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/ronin/formatting/extensions/binary/string.rb', line 250

def base64_encode(mode=nil)
  case mode
  when :strict
    if RUBY_VERSION < '1.9'
      # backported from Ruby 1.9.2
      [self].pack("m")
    else
      Base64.strict_encode64(self)
    end
  when :url, :urlsafe
    if RUBY_VERSION < '1.9'
      # backported from Ruby 1.9.2
      [self].pack("m").tr("+/", "-_")
    else
      Base64.urlsafe_encode64(self)
    end
  else
    Base64.encode64(self)
  end
end

- (Object) common_postfix(other)

Deprecated.

Deprecates as of 0.2.0, and will be removed in 1.0.0. Please use #common_suffix instead.



170
171
172
173
174
175
# File 'lib/ronin/extensions/string.rb', line 170

def common_postfix(other)
  warn 'DEPRECATED: String#common_postfix was deprecated in 0.2.0.'
  warn 'DEPRECATED: Please use String#common_suffix instead.'

  common_suffix(other)
end

- (String) common_prefix(other)

The common prefix of the string and the specified other string.

Parameters:

  • other (String)

    The other String to compare against.

Returns:

  • (String)

    The common prefix between the two Strings.



125
126
127
128
129
130
131
132
133
134
135
# File 'lib/ronin/extensions/string.rb', line 125

def common_prefix(other)
  min_length = [length, other.length].min

  min_length.times do |i|
    if self[i] != other[i]
      return self[0,i]
    end
  end

  return self[0,min_length]
end

- (String) common_suffix(other)

Finds the common suffix of the string and the specified other string.

Parameters:

  • pther (String)

    The other String to compare against.

Returns:

  • (String)

    The common suffix of the two Strings.

Since:

  • 0.2.0



150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/ronin/extensions/string.rb', line 150

def common_suffix(other)
  min_length = [length, other.length].min

  (min_length - 1).times do |i|
    index       = (length - i - 1)
    other_index = (other.length - i - 1)

    if self[index] != other[other_index]
      return self[(index + 1)..-1]
    end
  end

  return ''
end

- (Integer) depack(arch, address_length = nil)

Packs an Integer from a String, which was originally packed for a specific architecture and address-length.

Examples:

using archs other than `Ronin::Arch`.

arch = OpenStruct.new(:endian => :little, :address_length => 4)

"A\0\0\0".depack(arch)
# => 65

using a `Ronin::Arch` arch.

"A\0\0\0".depack(Arch.i386)
# => 65

specifying a custom address-length.

"A\0".depack(Arch.ppc,2)
# => 65

using a `String#unpack` template String as the arch.

"A\0\0\0".depack('L')
# => 65

Parameters:

  • arch (Ronin::Arch, #endian, #address_length, String)

    The architecture that the Integer was originally packed with.

  • address_length (Integer) (defaults to: nil)

    The number of bytes to depack.

Returns:

  • (Integer)

    The depacked Integer.

Raises:

  • (ArgumentError)

    The given `arch` does not respond to the `endian` or `address_length` methods.

See Also:



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/ronin/formatting/extensions/binary/string.rb', line 73

def depack(arch,address_length=nil)
  if arch.kind_of?(String)
    return self.unpack(arch)
  end

  unless arch.respond_to?(:address_length)
    raise(ArgumentError,"first argument to Ineger#pack must respond to address_length")
  end

  unless arch.respond_to?(:endian)
    raise(ArgumentError,"first argument to Ineger#pack must respond to endian")
  end

  endian           = arch.endian.to_sym
  address_length ||= arch.address_length

  integer = 0x0
  byte_index = 0

  case endian
  when :little
    mask = lambda { |b| b << (byte_index * 8) }
  when :big
    mask = lambda { |b|
      b << ((address_length - byte_index - 1) * 8)
    }
  else
    raise(ArgumentError,"invalid endian #{arch.endian.inspect}")
  end

  each_byte do |b|
    break if byte_index >= address_length

    integer |= mask.call(b)
    byte_index += 1
  end

  return integer
end

- (String) dump Also known as: inspect

Note:

This method is only defined on Ruby 1.8.x.

Dumps the string as a C-style string.

Examples:

"hello\x00\073\x90\r\n".dump
# => "hello\0;\x90\r\n"

Returns:

  • (String)

    The C-style encoded version of the String.



230
231
232
233
234
235
# File 'lib/ronin/extensions/string.rb', line 230

def dump
  dumped_string = ''

  each_byte { |b| dumped_string << ESCAPE_BYTES[b] }
  return "\"#{dumped_string}\""
end

- (String) each_substring(min = 1) {|substring, (index)| ... }

Enumerates over every sub-string within the string.

Examples:

"hello".each_substring(3).to_a
# => ["hel", "hell", "hello", "ell", "ello", "llo"]

Parameters:

  • min (Integer) (defaults to: 1)

    Minimum length of each sub-string.

Yields:

  • (substring, (index))

    The given block will receive every sub-string contained within the string. If the block accepts two arguments, then the index of the sub-string will also be passed in.

Yield Parameters:

  • substring (String)

    A sub-string from the string.

  • index (Integer)

    The optional index of the sub-string.

Returns:

  • (String)

    The original string



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ronin/extensions/string.rb', line 48

def each_substring(min=1,&block)
  return enum_for(:each_substring,min) unless block

  (0..(length - min)).each do |i|
    ((i + min)..length).each do |j|
      sub_string = self[i...j]

      if block.arity == 2
        block.call(sub_string,i)
      else
        block.call(sub_string)
      end
    end
  end

  return self
end

- (String) each_unique_substring(min = 1) {|substring, (index)| ... }

Enumerates over the unique sub-strings contained in the string.

Examples:

"xoxo".each_unique_substring(2).to_a
# => ["xo", "xox", "xoxo", "ox", "oxo"]

Parameters:

  • min (Integer) (defaults to: 1)

    Minimum length of each unique sub-string.

Yields:

  • (substring, (index))

    The given block will receive every unique sub-string contained within the string. If the block accepts two arguments, then the index of the unique sub-string will also be passed in.

Yield Parameters:

  • substring (String)

    A unique sub-string from the string.

  • index (Integer)

    The optional index of the unique sub-string.

Returns:

  • (String)

    The original string

See Also:

  • each_substring


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/ronin/extensions/string.rb', line 94

def each_unique_substring(min=1,&block)
  return enum_for(:each_unique_substring,min) unless block

  unique_strings = {}

  each_substring(min) do |sub_string,index|
    unless unique_strings.has_key?(sub_string)
      unique_strings[sub_string] = index

      if block.arity == 2
        block.call(sub_string,index)
      else
        block.call(sub_string)
      end
    end
  end

  return self
end

- (String) format_bytes(options = {}) {|byte| ... }

Creates a new String by formatting each byte.

Examples:

"hello".format_bytes { |b| "%x" % b }
# => "68656c6c6f"

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :include (#include?) — default: 0x00..0xff

    The bytes to format.

  • :exclude (#include?)

    The bytes not to format.

Yields:

  • (byte)

    The block which will return the formatted version of each byte within the String.

Yield Parameters:

  • byte (Integer)

    The byte to format.

Returns:

  • (String)

    The formatted version of the String.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/ronin/formatting/extensions/text/string.rb', line 52

def format_bytes(options={})
  included  = (options[:include] || (0x00..0xff))
  excluded  = (options[:exclude] || Set[])
  formatted = ''

  each_byte do |b|
    formatted << if (included.include?(b) && !excluded.include?(b))
                   yield(b)
                 else
                   b
                 end
  end

  return formatted
end

- (String) format_chars(options = {}) {|char| ... }

Creates a new String by formatting each character.

Examples:

"hello".format_chars { |c| c * 3 }
# => "hhheeellllllooo"

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :include (#include?, Regexp) — default: /./m

    The bytes to format.

  • :exclude (#include?, Regexp)

    The bytes not to format.

Yields:

  • (char)

    The block which will return the formatted version of each character within the String.

Yield Parameters:

  • char (String)

    The character to format.

Returns:

  • (String)

    The formatted version of the String.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/ronin/formatting/extensions/text/string.rb', line 96

def format_chars(options={})
  included  = (options[:include] || /./m)
  excluded  = (options[:exclude] || Set[])
  formatted = ''

  matches = lambda { |filter,c|
    if filter.respond_to?(:include?)
      filter.include?(c)
    elsif filter.kind_of?(Regexp)
      c =~ filter
    end
  }

  each_char do |c|
    formatted << if (matches[included,c] && !matches[excluded,c])
                   yield(c)
                 else
                   c
                 end
  end

  return formatted
end

- (String) format_html(options = {})

Formats the chars in the String for HTML.

Examples:

"abc".format_html
# => "&#97;&#98;&#99;"

Parameters:

  • options (Hash) (defaults to: {})

    Additional options for #format_chars.

Returns:

  • (String)

    The formatted HTML String.

See Also:

Since:

  • 0.2.0



97
98
99
100
101
102
103
104
105
106
# File 'lib/ronin/formatting/extensions/html/string.rb', line 97

def format_html(options={})
  formatter = if RUBY_VERSION < '1.9.'
                # String#ord was not backported to Ruby 1.8.7
                lambda { |c| c[0].format_html }
              else
                lambda { |c| c.ord.format_html }
              end

  format_chars(options,&formatter)
end

- (String) format_http(options = {})

Formats the bytes of the String.

Examples:

"hello".format_http
# => "%68%65%6c%6c%6f"

Returns:

  • (String)

    The HTTP hexadecimal encoded form of the String.

See Also:



106
107
108
# File 'lib/ronin/formatting/extensions/http/string.rb', line 106

def format_http(options={})
  format_bytes(options) { |b| b.format_http }
end

- (String) format_js(options = {})

Escapes a String for JavaScript.

Examples:

"hello".js_escape
# => "\\u0068\\u0065\\u006C\\u006C\\u006F"

Parameters:

  • options (Hash) (defaults to: {})

    Additional options for #format_chars.

Returns:

  • (String)

    The JavaScript escaped String.

See Also:

Since:

  • 0.2.0



191
192
193
194
195
196
197
198
199
200
# File 'lib/ronin/formatting/extensions/html/string.rb', line 191

def format_js(options={})
  formatter = if RUBY_VERSION < '1.9.'
                # String#ord was not backported to Rub 1.8.7
                lambda { |c| c[0].format_js }
              else
                lambda { |c| c.ord.format_js }
              end

  format_chars(options,&formatter)
end

- (Enumerator) fuzz(substitutions = {}) {|fuzz| ... }

Incrementally fuzzes the String.

Examples:

Replace every `e`, `i`, `o`, `u` with `(`, 100 `A`s and a `0`:

"the quick brown fox".fuzz(/[eiou]/ => ['(', ('A' * 100), "\0"]) do |str|
  p str
end

generate with #fuzz:

"GET /".fuzz('/' => String.generate(['A', 1..100])) do |str|
  p str
end

Parameters:

  • substitutions (Hash{Regexp,String => #each}) (defaults to: {})

    Patterns and their substitutions.

Yields:

  • (fuzz)

    The given block will be passed every fuzzed String.

Yield Parameters:

  • fuzz (String)

    A fuzzed String.

Returns:

  • (Enumerator)

    If no block is given, an Enumerator will be returned.

Since:

  • 0.3.0



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/ronin/fuzzing/extensions/string.rb', line 235

def fuzz(substitutions={})
  return enum_for(:fuzz,substitutions) unless block_given?

  substitutions.each do |pattern,substitution|
    pattern = case pattern
              when Regexp
                pattern
              when String
                Regexp.new(Regexp.escape(pattern))
              when Symbol
                Regexp.const_get(pattern.to_s.upcase)
              else
                raise(TypeError,"cannot convert #{pattern.inspect} to a Regexp")
              end

    substitution = case substitution
                    when Enumerable
                      substitution
                    when Symbol
                      Ronin::Fuzzing[substitution]
                    else
                      raise(TypeError,"substitutions must be Enumerable or a Symbol")
                    end

    scanner = StringScanner.new(self)
    indices = []

    while scanner.scan_until(pattern)
      indices << [scanner.pos - scanner.matched_size, scanner.matched_size]
    end

    indices.each do |index,length|
      substitution.each do |substitute|
        substitute = case substitute
                     when Proc
                       substitute.call(self[index,length])
                     when Integer
                       substitute.chr
                     else
                       substitute.to_s
                     end

        fuzzed = dup
        fuzzed[index,length] = substitute
        yield fuzzed
      end
    end
  end
end

- (String) hex_escape(options = {})

Hex-escapes characters in the String.

Examples:

"hello".hex_escape
# => "\\x68\\x65\\x6c\\x6c\\x6f"

Returns:

  • (String)

    The hex escaped version of the String.

See Also:



127
128
129
# File 'lib/ronin/formatting/extensions/binary/string.rb', line 127

def hex_escape(options={})
  format_bytes(options) { |b| b.hex_escape }
end

- (String) hex_unescape

Unescapes the hex-escaped String.

Examples:

"\\x68\\x65\\x6c\\x6c\\x6f".hex_unescape
# => "hello"

Returns:

  • (String)

    The unescaped version of the hex escaped String.



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/ronin/formatting/extensions/binary/string.rb', line 143

def hex_unescape
  buffer = ''
  hex_index = 0
  hex_length = length

  while (hex_index < hex_length)
    hex_substring = self[hex_index..-1]

    if hex_substring =~ /^\\[0-7]{3}/
      buffer << hex_substring[0..3].to_i(8)
      hex_index += 3
    elsif hex_substring =~ /^\\x[0-9a-fA-F]{1,2}/
      hex_substring[2..-1].scan(/^[0-9a-fA-F]{1,2}/) do |hex_byte|
        buffer << hex_byte.to_i(16)
        hex_index += (2 + hex_byte.length)
      end
    elsif hex_substring =~ /^\\./
      escaped_char = hex_substring[1..1]

      buffer << case escaped_char
                when '0'
                  "\0"
                when 'a'
                  "\a"
                when 'b'
                  "\b"
                when 't'
                  "\t"
                when 'n'
                  "\n"
                when 'v'
                  "\v"
                when 'f'
                  "\f"
                when 'r'
                  "\r"
                else
                  escaped_char
                end
      hex_index += 2
    else
      buffer << hex_substring[0]
      hex_index += 1
    end
  end

  return buffer
end

- (String) html_escape

HTML escapes the String.

Examples:

"one & two".html_escape
# => "one &amp; two"

Returns:

  • (String)

    The HTML escaped String.

See Also:

Since:

  • 0.2.0



54
55
56
# File 'lib/ronin/formatting/extensions/html/string.rb', line 54

def html_escape
  CGI.escapeHTML(self)
end

- (String) html_unescape

Unescapes the HTML encoded String.

Examples:

"&lt;p&gt;one &lt;span&gt;two&lt;/span&gt;&lt;/p&gt;".html_unescape
# => "<p>one <span>two</span></p>"

Returns:

  • (String)

    The unescaped String.

See Also:

Since:

  • 0.2.0



74
75
76
# File 'lib/ronin/formatting/extensions/html/string.rb', line 74

def html_unescape
  CGI.unescapeHTML(self)
end

- (String) insert_after(pattern, data)

Inserts data after the occurrence of a pattern.

Parameters:

  • pattern (String, Regexp)

    The pattern to search for.

  • data (String)

    The data to insert after the pattern.

Returns:

  • (String)

    The new modified String.



190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/ronin/formatting/extensions/text/string.rb', line 190

def insert_after(pattern,data)
  string = dup
  match  = string.match(pattern)

  if match
    index = match.end(match.length - 1)

    string.insert(index,data)
  end

  return string
end

- (String) insert_before(pattern, data)

Inserts data before the occurrence of a pattern.

Parameters:

  • pattern (String, Regexp)

    The pattern to search for.

  • data (String)

    The data to insert before the pattern.

Returns:

  • (String)

    The new modified String.



168
169
170
171
172
173
174
# File 'lib/ronin/formatting/extensions/text/string.rb', line 168

def insert_before(pattern,data)
  string = dup
  index  = string.index(pattern)

  string.insert(index,data) if index
  return string
end

- (String) js_escape(options = {})

Escapes a String for JavaScript.

Examples:

"hello\nworld\n".js_escape
# => "hello\\nworld\\n"

Parameters:

  • options (Hash) (defaults to: {})

    Additional options for #format_chars.

Returns:

  • (String)

    The JavaScript escaped String.

See Also:

Since:

  • 0.2.0



127
128
129
130
131
132
133
134
135
136
# File 'lib/ronin/formatting/extensions/html/string.rb', line 127

def js_escape(options={})
  formatter = if RUBY_VERSION < '1.9.'
                # String#ord was not backported to Rub 1.8.7
                lambda { |c| c[0].js_escape }
              else
                lambda { |c| c.ord.js_escape }
              end

  format_chars(options,&formatter)
end

- (String) js_unescape

Unescapes a JavaScript escaped String.

Examples:

"\\u0068\\u0065\\u006C\\u006C\\u006F world".js_unescape
# => "hello world"

Returns:

  • (String)

    The unescaped JavaScript String.

Since:

  • 0.2.0



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/ronin/formatting/extensions/html/string.rb', line 152

def js_unescape
  unescaped = ''

  scan(/([\\%]u[0-9a-fA-F]{1,4}|[\\%][0-9a-fA-F]{1,2}|\\[btnfr"\\]|.)/).each do |match|
    c = match[0]

    unescaped << if JS_BACKSLASHED_CHARS.has_key?(c)
                   JS_BACKSLASHED_CHARS[c]
                 elsif (c.start_with?("\\u") || c.start_with?("%u"))
                   c[2..-1].to_i(16)
                 elsif (c.start_with?("\\") || c.start_with?("%"))
                   c[1..-1].to_i(16)
                 else
                   c
                 end
  end

  return unescaped
end

- (String) md5

The MD5 checksum of the String.

Examples:

"hello".md5
# => "5d41402abc4b2a76b9719d911017c592"

Returns:

  • (String)

    The MD5 checksum of the String.



36
37
38
# File 'lib/ronin/formatting/extensions/digest/string.rb', line 36

def md5
  Digest::MD5.hexdigest(self)
end

- (Enumerator) mutate(mutations = {}) {|mutant| ... }

Permutes over every possible mutation of the String.

Examples:

"hello old dog".mutate('e' => ['3'], 'l' => ['1'], 'o' => ['0']) do |str|
  puts str
end

Parameters:

  • mutations (Hash{Regexp,String,Symbol => Symbol,#each}) (defaults to: {})

    The patterns and substitutions to mutate the String with.

Yields:

  • (mutant)

    The given block will be yielded every possible mutant String.

Yield Parameters:

  • mutant (String)

    A mutated String.

Returns:

  • (Enumerator)

    If no block is given, an Enumerator will be returned.

Since:

  • 0.4.0



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/ronin/fuzzing/extensions/string.rb', line 309

def mutate(mutations={})
  return enum_for(:mutate,mutations) unless block_given?

  matches = Set[]

  mutations.each do |pattern,mutation|
    pattern = case pattern
              when Regexp
                pattern
              when String
                Regexp.new(Regexp.escape(pattern))
              when Symbol
                Regexp.const_get(pattern.to_s.upcase)
              else
                raise(TypeError,"cannot convert #{pattern.inspect} to a Regexp")
              end

    scanner = StringScanner.new(self)

    while scanner.scan_until(pattern)
      length   = scanner.matched_size
      index    = scanner.pos - length
      original = scanner.matched

      mutator = Combinatorics::Generator.new do |g|
                  mutation.each do |mutate|
                    g.yield case mutate
                            when Proc
                              mutate.call(original)
                            when Integer
                              mutate.chr
                            else
                              mutate.to_s
                            end
                  end
                end

      matches << [index, length, mutator]
    end
  end

  matches.powerset do |submatches|
    # ignore the empty Set
    next if submatches.empty?

    # sort the submatches by index
    submatches = submatches.sort_by { |index,length,mutator| index }
    sets       = []
    prev_index = 0

    submatches.each do |index,length,mutator|
      # add the previous substring to the set of Strings
      if index > prev_index
        sets << [self[prev_index,index - prev_index]]
      end

      # add the mutator to the set of Strings
      sets << mutator

      prev_index = index + length
    end

    # add the remaining substring to the set of Strings
    if prev_index < self.length
      sets << [self[prev_index..-1]]
    end

    sets.comprehension { |strings| yield strings.join }
  end
end

- (String) pad(padding, max_length = length)

Creates a new String by padding the String with repeating text, out to a specified length.

Examples:

"hello".pad('A',50)
# => "helloAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"

Parameters:

  • padding (String)

    The text to pad the new String with.

  • max_length (String) (defaults to: length)

    The maximum length to pad the new String out to.

Returns:

  • (String)

    The padded version of the String.



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/ronin/formatting/extensions/text/string.rb', line 222

def pad(padding,max_length=length)
  padding = padding.to_s

  if max_length > length
    max_length -= length
  else
    max_length = 0
  end

  padded = self + (padding * (max_length / padding.length))

  unless (remaining = (max_length % padding.length)) == 0
    padded << padding[0,remaining]
  end

  return padded
end

- (Object) random_case(options = {})

Creates a new String by randomizing the case of each character in the String.

Examples:

"get out your checkbook".random_case
# => "gEt Out YOur CHEckbook"

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :include (Array, Range) — default: 0x00..0xff

    The bytes to format.

  • :exclude (Array, Range)

    The bytes not to format.

  • :probability (Float) — default: 0.5

    The probability that a character will have it's case changed.



142
143
144
145
146
147
148
149
150
151
152
# File 'lib/ronin/formatting/extensions/text/string.rb', line 142

def random_case(options={})
  prob = (options[:probability] || 0.5)

  format_chars(options) do |c|
    if rand <= prob
      c.swapcase 
    else
      c
    end
  end
end

- (Enumerator) repeating(n) {|repeated| ... }

Repeats the String.

Examples:

'A'.repeating(100)
# => "AAAAAAAAAAAAA..."

Generates 100 upto 700 `A`s, increasing by 100 at a time:

'A'.repeating((100..700).step(100)) do |str|
  # ...
end

Generates 128, 1024, 65536 `A`s:

'A'.repeating([128, 1024, 65536]) do |str|
  # ...
end

Parameters:

Yields:

  • (repeated)

    The given block will be passed every repeated String.

Yield Parameters:

  • repeated (String)

    A repeated version of the String.

Returns:

  • (Enumerator)

    If no block is given, an Enumerator will be returned.

Raises:

  • (TypeError)

    `n` must either be Enumerable or an Integer.

Since:

  • 0.4.0



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/ronin/fuzzing/extensions/string.rb', line 184

def repeating(n)
  if n.kind_of?(Integer)
    # if n is an Integer, simply multiply the String and return
    repeated = (self * n)

    yield repeated if block_given?
    return repeated
  end

  return enum_for(:repeating,n) unless block_given?

  unless n.kind_of?(Enumerable)
    raise(TypeError,"argument must be Enumerable or an Integer")
  end

  n.each do |length|
    yield(self * length)
  end

  return self
end

- (String) sha1 Also known as: sha128

The SHA1 checksum of the String.

Examples:

"hello".sha1
# => "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d"

Returns:

  • (String)

    The SHA1 checksum of the String.



50
51
52
# File 'lib/ronin/formatting/extensions/digest/string.rb', line 50

def sha1
  Digest::SHA1.hexdigest(self)
end

- (String) sha256 Also known as: sha2

The SHA2 checksum of the String.

Examples:

"hello".sha2
# => "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

Returns:

  • (String)

    The SHA2 checksum of the String.



66
67
68
# File 'lib/ronin/formatting/extensions/digest/string.rb', line 66

def sha256
  Digest::SHA256.hexdigest(self)
end

- (String) sha512

The SHA512 checksum of the String.

Examples:

"hello".sha512
# => "9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043"

Returns:

  • (String)

    The SHA512 checksum of the String.



82
83
84
# File 'lib/ronin/formatting/extensions/digest/string.rb', line 82

def sha512
  Digest::SHA512.hexdigest(self)
end

- (Object) sql_decode

Returns the SQL decoded form of the String.

Examples:

"'Conan O''Brian'".sql_decode
# => "Conan O'Brian"
"0x2f6574632f706173737764".sql_decode
# => "/etc/passwd"


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/ronin/formatting/extensions/sql/string.rb', line 82

def sql_decode
  if ((self[0...2] == '0x') && (length % 2 == 0))
    raw = ''

    self[2..-1].scan(/[0-9a-fA-F]{2}/).each do |hex_char|
      raw << hex_char.hex.chr
    end

    return raw
  elsif (self[0..0] == "'" && self[-1..-1] == "'")
    self[1..-2].gsub("\\'","'").gsub("''","'")
  else
    return self
  end
end

- (Object) sql_encode

Returns the SQL hex-string encoded form of the String.

Examples:

"/etc/passwd".sql_encode
# => "0x2f6574632f706173737764"


59
60
61
62
63
64
65
66
67
68
69
# File 'lib/ronin/formatting/extensions/sql/string.rb', line 59

def sql_encode
  return '' if empty?

  hex_string = '0x'

  each_byte do |b|
    hex_string << ('%.2x' % b)
  end

  return hex_string
end

- (String) sql_escape(quotes = :single)

Escapes an String for SQL.

Examples:

"O'Brian".sql_escape
# => "'O''Brian'"

Parameters:

  • quotes (Symbol) (defaults to: :single)

    (:single) Specifies whether to create a single or double quoted string. May be either `:single` or `:double`.

Returns:

  • (String)

    The escaped String.

Raises:

  • (ArgumentError)

    The quotes argument was neither `:single` nor `:double`.

Since:

  • 0.3.0



41
42
43
44
45
46
47
48
49
50
# File 'lib/ronin/formatting/extensions/sql/string.rb', line 41

def sql_escape(quotes=:single)
  case quotes
  when :single
    "'#{gsub(/'/,"''")}'"
  when :double
    "\"#{gsub(/"/,'""')}\""
  else
    raise(ArgumentError,"invalid quoting style #{quotes.inspect}")
  end
end

- (String) sql_inject

Prepares the String for injection into a SQL expression.

Examples:

"'1' OR '1'='1'".sql_inject
# => "1' OR '1'='1"
"'1' OR 1=1".sql_inject
# => "1' OR 1=1 OR '"
"'1' OR 1=1".sql_inject(:terminate => true)
# => "1' OR 1=1 --"

Returns:

  • (String)

    The SQL injection ready String.

Since:

  • 0.4.0



120
121
122
123
124
125
126
127
128
129
130
# File 'lib/ronin/formatting/extensions/sql/string.rb', line 120

def sql_inject
  if (start_with?("'") || start_with?('"') || start_with?('`'))
    if self[0,1] == self[-1,1]
      self[1..-2]
    else
      "#{self[1..-1]}--"
    end
  else
    self
  end
end

- (String) uncommon_substring(other)

Finds the uncommon substring within the specified other string, which does not occur within the string.

Parameters:

  • other (String)

    The other String to compare against.

Returns:

  • (String)

    The uncommon substring between the two Strings.



189
190
191
192
193
194
# File 'lib/ronin/extensions/string.rb', line 189

def uncommon_substring(other)
  prefix  = common_prefix(other)
  postfix = self[prefix.length..-1].common_suffix(other[prefix.length..-1])

  return self[prefix.length...(length - postfix.length)]
end

- (String) unhexdump(options = {})

Converts a multitude of hexdump formats back into raw-data.

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :format (Symbol)

    The expected format of the hexdump. Must be either `:od` or `:hexdump`.

  • :encoding (Symbol)

    Denotes the encoding used for the bytes within the hexdump. Must be one of the following:

    • `:binary`

    • `:octal`

    • `:octal_bytes`

    • `:octal_shorts`

    • `:octal_ints`

    • `:octal_quads`

    • `:decimal`

    • `:decimal_bytes`

    • `:decimal_shorts`

    • `:decimal_ints`

    • `:decimal_quads`

    • `:hex`

    • `:hex_bytes`

    • `:hex_shorts`

    • `:hex_ints`

    • `:hex_quads`

  • :segment (Integer) — default: 16

    The length in bytes of each segment in the hexdump.

Returns:

  • (String)

    The raw-data from the hexdump.



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
# File 'lib/ronin/formatting/extensions/binary/string.rb', line 384

def unhexdump(options={})
  case (format = options[:format])
  when :od
    address_base = 8
    base         = 8
    word_size    = 2
  when :hexdump
    address_base = 16
    base         = 16
    word_size    = 2
  else
    address_base = 16
    base         = 16
    word_size    = 1
  end

  case options[:encoding]
  when :binary
    base = 2
  when :octal, :octal_bytes, :octal_shorts, :octal_ints, :octal_quads
    base = 8
  when :decimal, :decimal_bytes, :decimal_shorts, :decimal_ints, :decimal_quads
    base = 10
  when :hex, :hex_bytes, :hex_shorts, :hex_ints, :hex_quads
    base = 16
  end

  case options[:encoding]
  when :binary, :octal_bytes, :decimal_bytes, :hex_bytes
    word_size = 1
  when :octal_shorts, :decimal_shorts, :hex_shorts
    word_size = 2
  when :octal_ints, :decimal_ints, :hex_ints
    word_size = 4
  when :octal_quads, :decimal_quads, :hex_quads
    word_size = 8
  end

  current_addr = last_addr = first_addr = nil
  repeated = false

  segment_length = (options[:segment] || 16)
  segment = []
  buffer = []

  each_line do |line|
    if format == :hexdump
      line = line.gsub(/\s+\|.+\|\s*$/,'')
    end

    words = line.split

    if words.first == '*'
      repeated = true
    elsif words.length > 0
      current_addr = words.shift.to_i(address_base)
      first_addr ||= current_addr

      if repeated
        (((current_addr - last_addr) / segment.length) - 1).times do
          buffer += segment
        end

        repeated = false
      end

      segment.clear

      words.each do |word|
        if (base != 10 && word =~ /^(\\[0abtnvfr\\]|.)$/)
          word.hex_unescape.each_byte { |b| segment << b }
        else
          segment += word.to_i(base).bytes(word_size)
        end
      end

      segment = segment[0,segment_length]
      buffer += segment
      last_addr = current_addr
    end
  end

  return buffer[0,(last_addr - first_addr)]
end

- (String) uri_decode

URI decodes the String.

Examples:

"genre%3f".uri_decode
# => "genre?"

Returns:

  • (String)

    The decoded URI form of the String.



56
57
58
# File 'lib/ronin/formatting/extensions/http/string.rb', line 56

def uri_decode
  URI.decode(self)
end

- (String) uri_encode

URI encodes the String.

Examples:

"art is graffiti".uri_encode
# => "art%20is%20graffiti"

Returns:

  • (String)

    The URI encoded form of the String.



40
41
42
# File 'lib/ronin/formatting/extensions/http/string.rb', line 40

def uri_encode
  URI.encode(self)
end

- (String) uri_escape

URI escapes the String.

Examples:

"x > y".uri_escape
# => "x+%3E+y"

Returns:

  • (String)

    The URI escaped form of the String.



72
73
74
# File 'lib/ronin/formatting/extensions/http/string.rb', line 72

def uri_escape
  CGI.escape(self)
end

- (String) uri_unescape

URI unescapes the String.

Examples:

"sweet+%26+sour".uri_unescape
# => "sweet & sour"

Returns:

  • (String)

    The unescaped URI form of the String.



88
89
90
# File 'lib/ronin/formatting/extensions/http/string.rb', line 88

def uri_unescape
  CGI.unescape(self)
end

- (String) xor(key)

XOR encodes the String.

Examples:

"hello".xor(0x41)
# => ")$--."
"hello again".xor([0x55, 0x41, 0xe1])
# => "=$\x8d9.\xc14&\x80</"

Parameters:

Returns:

  • (String)

    The XOR encoded String.



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/ronin/formatting/extensions/binary/string.rb', line 211

def xor(key)
  key = case key
        when Integer
          [key]
        when String
          key.bytes
        else
          key
        end

  key    = key.cycle
  result = ''

  bytes.each do |b|
    result << (b ^ key.next).chr
  end

  return result
end

- (String) zlib_deflate

Zlib deflate a string.

Examples:

"hello".zlib_deflate
# => "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15"

Returns:

  • (String)

    The Zlib deflated form of the string.



342
343
344
# File 'lib/ronin/formatting/extensions/binary/string.rb', line 342

def zlib_deflate
  Zlib::Deflate.deflate(self)
end

- (String) zlib_inflate

Zlib inflate a string.

Examples:

"x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15".zlib_inflate
# => "hello"

Returns:

  • (String)

    The Zlib inflated form of the string.



326
327
328
# File 'lib/ronin/formatting/extensions/binary/string.rb', line 326

def zlib_inflate
  Zlib::Inflate.inflate(self)
end