ronin-support 0.4.1 → 0.5.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog.md +75 -32
- data/Gemfile +17 -18
- data/README.md +9 -10
- data/Rakefile +10 -2
- data/gemspec.yml +1 -1
- data/lib/ronin/binary.rb +21 -0
- data/lib/ronin/binary/hexdump.rb +20 -0
- data/lib/ronin/binary/hexdump/parser.rb +411 -0
- data/lib/ronin/binary/struct.rb +579 -0
- data/lib/ronin/binary/template.rb +437 -0
- data/lib/ronin/extensions/ip_addr.rb +17 -13
- data/lib/ronin/extensions/regexp.rb +45 -0
- data/lib/ronin/extensions/string.rb +3 -3
- data/lib/ronin/formatting/extensions/binary.rb +1 -0
- data/lib/ronin/formatting/extensions/binary/array.rb +63 -0
- data/lib/ronin/formatting/extensions/binary/base64.rb +106 -0
- data/lib/ronin/formatting/extensions/binary/file.rb +39 -6
- data/lib/ronin/formatting/extensions/binary/float.rb +65 -0
- data/lib/ronin/formatting/extensions/binary/integer.rb +56 -43
- data/lib/ronin/formatting/extensions/binary/string.rb +75 -187
- data/lib/ronin/formatting/extensions/text/string.rb +61 -0
- data/lib/ronin/fuzzing/extensions/string.rb +21 -8
- data/lib/ronin/fuzzing/fuzzing.rb +19 -17
- data/lib/ronin/network.rb +2 -1
- data/lib/ronin/network/dns.rb +57 -15
- data/lib/ronin/network/extensions.rb +0 -1
- data/lib/ronin/network/ftp.rb +145 -0
- data/lib/ronin/network/http/http.rb +13 -14
- data/lib/ronin/network/imap.rb +11 -10
- data/lib/ronin/network/mixins.rb +1 -0
- data/lib/ronin/network/mixins/ftp.rb +155 -0
- data/lib/ronin/network/mixins/ssl.rb +1 -1
- data/lib/ronin/network/mixins/tcp.rb +39 -6
- data/lib/ronin/network/mixins/udp.rb +121 -1
- data/lib/ronin/network/mixins/unix.rb +279 -0
- data/lib/ronin/network/pop3.rb +5 -5
- data/lib/ronin/network/proxy.rb +578 -0
- data/lib/ronin/network/smtp/email.rb +1 -1
- data/lib/ronin/network/smtp/smtp.rb +7 -8
- data/lib/ronin/network/ssl.rb +1 -6
- data/lib/ronin/network/tcp.rb +2 -305
- data/lib/ronin/network/tcp/proxy.rb +377 -0
- data/lib/ronin/network/tcp/tcp.rb +435 -0
- data/lib/ronin/network/telnet.rb +27 -23
- data/lib/ronin/network/udp.rb +2 -266
- data/lib/ronin/network/udp/proxy.rb +169 -0
- data/lib/ronin/network/udp/udp.rb +442 -0
- data/lib/ronin/network/unix.rb +287 -0
- data/lib/ronin/path.rb +2 -2
- data/lib/ronin/spec/ui/output.rb +1 -7
- data/lib/ronin/support.rb +1 -0
- data/lib/ronin/support/inflector.rb +3 -7
- data/lib/ronin/support/support.rb +2 -1
- data/lib/ronin/support/version.rb +1 -1
- data/lib/ronin/ui/output/helpers.rb +13 -15
- data/lib/ronin/ui/output/output.rb +2 -2
- data/lib/ronin/ui/output/terminal/color.rb +10 -4
- data/lib/ronin/wordlist.rb +92 -17
- data/ronin-support.gemspec +38 -109
- data/spec/binary/hexdump/helpers/hexdumps.rb +13 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/ascii.bin +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_decimal_shorts.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_hex_bytes.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_hex_shorts.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_octal_bytes.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_octal_shorts.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/hexdump_repeated.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_bytes.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_ints.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_quads.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_decimal_shorts.txt +0 -0
- data/spec/binary/hexdump/helpers/hexdumps/od_doubles.txt +17 -0
- data/spec/binary/hexdump/helpers/hexdumps/od_floats.txt +17 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_bytes.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_ints.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_quads.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_hex_shorts.txt +0 -0
- data/spec/binary/hexdump/helpers/hexdumps/od_named_chars.txt +17 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_bytes.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_ints.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_quads.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_octal_shorts.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/od_repeated.txt +0 -0
- data/spec/{formatting/binary → binary/hexdump}/helpers/hexdumps/repeated.bin +0 -0
- data/spec/binary/hexdump/parser_spec.rb +302 -0
- data/spec/binary/struct_spec.rb +496 -0
- data/spec/binary/template_spec.rb +400 -0
- data/spec/extensions/ip_addr_spec.rb +58 -32
- data/spec/extensions/regexp_spec.rb +60 -0
- data/spec/extensions/string_spec.rb +1 -1
- data/spec/formatting/binary/array_spec.rb +22 -0
- data/spec/formatting/binary/base64_spec.rb +50 -0
- data/spec/formatting/binary/float_spec.rb +30 -0
- data/spec/formatting/binary/integer_spec.rb +54 -40
- data/spec/formatting/binary/string_spec.rb +69 -182
- data/spec/formatting/text/string_spec.rb +30 -0
- data/spec/network/dns_spec.rb +64 -0
- data/spec/network/ftp_spec.rb +65 -0
- data/spec/network/proxy_spec.rb +121 -0
- data/spec/network/shared/unix_server.rb +31 -0
- data/spec/network/tcp/proxy_spec.rb +116 -0
- data/spec/network/{tcp_spec.rb → tcp/tcp_spec.rb} +24 -1
- data/spec/network/telnet_spec.rb +67 -0
- data/spec/network/{udp_spec.rb → udp/udp_spec.rb} +24 -1
- data/spec/network/unix_spec.rb +183 -0
- data/spec/wordlist_spec.rb +74 -13
- metadata +129 -85
- data/spec/formatting/binary/helpers/hexdumps.rb +0 -16
@@ -17,23 +17,62 @@
|
|
17
17
|
# along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
|
18
18
|
#
|
19
19
|
|
20
|
+
require 'ronin/formatting/extensions/binary/base64'
|
20
21
|
require 'ronin/formatting/extensions/binary/integer'
|
21
|
-
require 'ronin/formatting/extensions/text'
|
22
|
-
|
23
|
-
require '
|
24
|
-
require 'enumerator'
|
22
|
+
require 'ronin/formatting/extensions/text/string'
|
23
|
+
require 'ronin/binary/hexdump/parser'
|
24
|
+
require 'ronin/binary/template'
|
25
25
|
|
26
26
|
begin
|
27
27
|
require 'zlib'
|
28
|
+
rescue Gem::LoadError => e
|
29
|
+
raise(e)
|
28
30
|
rescue ::LoadError
|
29
|
-
$stderr.puts "WARNING: Ruby was not compiled with zlib support"
|
30
31
|
end
|
31
32
|
|
32
33
|
class String
|
33
34
|
|
35
|
+
alias unpack_original unpack
|
36
|
+
|
37
|
+
#
|
38
|
+
# Unpacks the String.
|
39
|
+
#
|
40
|
+
# @param [String, Array<Symbol>] arguments
|
41
|
+
# The `String#unpack` template or a list of {Ronin::Binary::Template} types.
|
42
|
+
#
|
43
|
+
# @return [Array]
|
44
|
+
# The values unpacked from the String.
|
45
|
+
#
|
46
|
+
# @raise [ArgumentError]
|
47
|
+
# The arguments were not a String or a list of Symbols.
|
48
|
+
#
|
49
|
+
# @example using {Ronin::Binary::Template} types:
|
50
|
+
# "A\0\0\0hello\0".unpack(:uint32_le, :string)
|
51
|
+
# # => [10, "hello"]
|
52
|
+
#
|
53
|
+
# @example using a `String#unpack` template:
|
54
|
+
# "A\0\0\0".unpack('V')
|
55
|
+
# # => 65
|
56
|
+
#
|
57
|
+
# @see http://rubydoc.info/stdlib/core/String:unpack
|
58
|
+
#
|
59
|
+
# @since 0.5.0
|
60
|
+
#
|
61
|
+
# @api public
|
62
|
+
#
|
63
|
+
def unpack(*arguments)
|
64
|
+
case arguments.first
|
65
|
+
when String
|
66
|
+
unpack_original(arguments.first)
|
67
|
+
when Symbol
|
68
|
+
unpack_original(Ronin::Binary::Template.compile(arguments))
|
69
|
+
else
|
70
|
+
raise(ArgumentError,"first argument to String#unpack must be a String or Symbol")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
34
74
|
#
|
35
|
-
#
|
36
|
-
# a specific architecture and address-length.
|
75
|
+
# Unpacks the String into an Integer.
|
37
76
|
#
|
38
77
|
# @param [Ronin::Arch, #endian, #address_length, String] arch
|
39
78
|
# The architecture that the Integer was originally packed with.
|
@@ -45,34 +84,35 @@ class String
|
|
45
84
|
# The depacked Integer.
|
46
85
|
#
|
47
86
|
# @raise [ArgumentError]
|
48
|
-
# The given `arch` does not respond to the `endian` or
|
49
|
-
#
|
87
|
+
# The given `arch` does not respond to the `endian` or `address_length`
|
88
|
+
# methods.
|
50
89
|
#
|
51
|
-
# @example using archs other than `Ronin::Arch
|
90
|
+
# @example using archs other than `Ronin::Arch`:
|
52
91
|
# arch = OpenStruct.new(:endian => :little, :address_length => 4)
|
53
92
|
#
|
54
93
|
# "A\0\0\0".depack(arch)
|
55
94
|
# # => 65
|
56
95
|
#
|
57
|
-
# @example using a `Ronin::Arch` arch
|
96
|
+
# @example using a `Ronin::Arch` arch:
|
58
97
|
# "A\0\0\0".depack(Arch.i386)
|
59
98
|
# # => 65
|
60
99
|
#
|
61
|
-
# @example specifying a custom address-length
|
100
|
+
# @example specifying a custom address-length:
|
62
101
|
# "A\0".depack(Arch.ppc,2)
|
63
102
|
# # => 65
|
64
103
|
#
|
65
|
-
# @example using a `String#unpack` template
|
66
|
-
# "A\0\0\0".depack('
|
104
|
+
# @example using a `String#unpack` template:
|
105
|
+
# "A\0\0\0".depack('V')
|
67
106
|
# # => 65
|
68
107
|
#
|
69
|
-
# @
|
108
|
+
# @deprecated
|
109
|
+
# Deprecated as of 0.5.0, use {#unpack} instead.
|
70
110
|
#
|
71
111
|
# @api public
|
72
|
-
#
|
112
|
+
#
|
73
113
|
def depack(arch,address_length=nil)
|
74
114
|
if arch.kind_of?(String)
|
75
|
-
return
|
115
|
+
return unpack(arch)
|
76
116
|
end
|
77
117
|
|
78
118
|
unless arch.respond_to?(:address_length)
|
@@ -86,7 +126,7 @@ class String
|
|
86
126
|
endian = arch.endian.to_sym
|
87
127
|
address_length ||= arch.address_length
|
88
128
|
|
89
|
-
integer
|
129
|
+
integer = 0x0
|
90
130
|
byte_index = 0
|
91
131
|
|
92
132
|
case endian
|
@@ -128,66 +168,7 @@ class String
|
|
128
168
|
format_bytes(options) { |b| b.hex_escape }
|
129
169
|
end
|
130
170
|
|
131
|
-
|
132
|
-
# Unescapes the hex-escaped String.
|
133
|
-
#
|
134
|
-
# @return [String]
|
135
|
-
# The unescaped version of the hex escaped String.
|
136
|
-
#
|
137
|
-
# @example
|
138
|
-
# "\\x68\\x65\\x6c\\x6c\\x6f".hex_unescape
|
139
|
-
# # => "hello"
|
140
|
-
#
|
141
|
-
# @api public
|
142
|
-
#
|
143
|
-
def hex_unescape
|
144
|
-
buffer = ''
|
145
|
-
hex_index = 0
|
146
|
-
hex_length = length
|
147
|
-
|
148
|
-
while (hex_index < hex_length)
|
149
|
-
hex_substring = self[hex_index..-1]
|
150
|
-
|
151
|
-
if hex_substring =~ /^\\[0-7]{3}/
|
152
|
-
buffer << hex_substring[0..3].to_i(8)
|
153
|
-
hex_index += 3
|
154
|
-
elsif hex_substring =~ /^\\x[0-9a-fA-F]{1,2}/
|
155
|
-
hex_substring[2..-1].scan(/^[0-9a-fA-F]{1,2}/) do |hex_byte|
|
156
|
-
buffer << hex_byte.to_i(16)
|
157
|
-
hex_index += (2 + hex_byte.length)
|
158
|
-
end
|
159
|
-
elsif hex_substring =~ /^\\./
|
160
|
-
escaped_char = hex_substring[1..1]
|
161
|
-
|
162
|
-
buffer << case escaped_char
|
163
|
-
when '0'
|
164
|
-
"\0"
|
165
|
-
when 'a'
|
166
|
-
"\a"
|
167
|
-
when 'b'
|
168
|
-
"\b"
|
169
|
-
when 't'
|
170
|
-
"\t"
|
171
|
-
when 'n'
|
172
|
-
"\n"
|
173
|
-
when 'v'
|
174
|
-
"\v"
|
175
|
-
when 'f'
|
176
|
-
"\f"
|
177
|
-
when 'r'
|
178
|
-
"\r"
|
179
|
-
else
|
180
|
-
escaped_char
|
181
|
-
end
|
182
|
-
hex_index += 2
|
183
|
-
else
|
184
|
-
buffer << hex_substring[0]
|
185
|
-
hex_index += 1
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
return buffer
|
190
|
-
end
|
171
|
+
alias hex_unescape unescape
|
191
172
|
|
192
173
|
#
|
193
174
|
# XOR encodes the String.
|
@@ -250,19 +231,9 @@ class String
|
|
250
231
|
def base64_encode(mode=nil)
|
251
232
|
case mode
|
252
233
|
when :strict
|
253
|
-
|
254
|
-
# backported from Ruby 1.9.2
|
255
|
-
[self].pack("m")
|
256
|
-
else
|
257
|
-
Base64.strict_encode64(self)
|
258
|
-
end
|
234
|
+
Base64.strict_encode64(self)
|
259
235
|
when :url, :urlsafe
|
260
|
-
|
261
|
-
# backported from Ruby 1.9.2
|
262
|
-
[self].pack("m").tr("+/", "-_")
|
263
|
-
else
|
264
|
-
Base64.urlsafe_encode64(self)
|
265
|
-
end
|
236
|
+
Base64.urlsafe_encode64(self)
|
266
237
|
else
|
267
238
|
Base64.encode64(self)
|
268
239
|
end
|
@@ -293,19 +264,9 @@ class String
|
|
293
264
|
def base64_decode(mode=nil)
|
294
265
|
case mode
|
295
266
|
when :strict
|
296
|
-
|
297
|
-
# backported from Ruby 1.9.2
|
298
|
-
unpack("m0").first
|
299
|
-
else
|
300
|
-
Base64.strict_decode64(self)
|
301
|
-
end
|
267
|
+
Base64.strict_decode64(self)
|
302
268
|
when :url, :urlsafe
|
303
|
-
|
304
|
-
# backported from Ruby 1.9.2
|
305
|
-
tr("-_", "+/").unpack("m0").first
|
306
|
-
else
|
307
|
-
Base64.urlsafe_decode64(self)
|
308
|
-
end
|
269
|
+
Base64.urlsafe_decode64(self)
|
309
270
|
else
|
310
271
|
Base64.decode64(self)
|
311
272
|
end
|
@@ -362,108 +323,35 @@ class String
|
|
362
323
|
# * `:octal_bytes`
|
363
324
|
# * `:octal_shorts`
|
364
325
|
# * `:octal_ints`
|
365
|
-
# * `:octal_quads`
|
326
|
+
# * `:octal_quads` (Ruby 1.9 only)
|
366
327
|
# * `:decimal`
|
367
328
|
# * `:decimal_bytes`
|
368
329
|
# * `:decimal_shorts`
|
369
330
|
# * `:decimal_ints`
|
370
|
-
# * `:decimal_quads`
|
331
|
+
# * `:decimal_quads` (Ruby 1.9 only)
|
371
332
|
# * `:hex`
|
333
|
+
# * `:hex_chars`
|
372
334
|
# * `:hex_bytes`
|
373
335
|
# * `:hex_shorts`
|
374
336
|
# * `:hex_ints`
|
375
337
|
# * `:hex_quads`
|
338
|
+
# * `:named_chars` (Ruby 1.9 only)
|
339
|
+
# * `:floats`
|
340
|
+
# * `:doubles`
|
341
|
+
#
|
342
|
+
# @option options [:little, :big, :network] :endian (:little)
|
343
|
+
# The endianness of the words.
|
376
344
|
#
|
377
345
|
# @option options [Integer] :segment (16)
|
378
346
|
# The length in bytes of each segment in the hexdump.
|
379
347
|
#
|
380
|
-
# @return [String]
|
348
|
+
# @return [String]
|
349
|
+
# The raw-data from the hexdump.
|
381
350
|
#
|
382
351
|
# @api public
|
383
352
|
#
|
384
353
|
def unhexdump(options={})
|
385
|
-
|
386
|
-
when :od
|
387
|
-
address_base = 8
|
388
|
-
base = 8
|
389
|
-
word_size = 2
|
390
|
-
when :hexdump
|
391
|
-
address_base = 16
|
392
|
-
base = 16
|
393
|
-
word_size = 2
|
394
|
-
else
|
395
|
-
address_base = 16
|
396
|
-
base = 16
|
397
|
-
word_size = 1
|
398
|
-
end
|
399
|
-
|
400
|
-
case options[:encoding]
|
401
|
-
when :binary
|
402
|
-
base = 2
|
403
|
-
when :octal, :octal_bytes, :octal_shorts, :octal_ints, :octal_quads
|
404
|
-
base = 8
|
405
|
-
when :decimal, :decimal_bytes, :decimal_shorts, :decimal_ints, :decimal_quads
|
406
|
-
base = 10
|
407
|
-
when :hex, :hex_bytes, :hex_shorts, :hex_ints, :hex_quads
|
408
|
-
base = 16
|
409
|
-
end
|
410
|
-
|
411
|
-
case options[:encoding]
|
412
|
-
when :binary, :octal_bytes, :decimal_bytes, :hex_bytes
|
413
|
-
word_size = 1
|
414
|
-
when :octal_shorts, :decimal_shorts, :hex_shorts
|
415
|
-
word_size = 2
|
416
|
-
when :octal_ints, :decimal_ints, :hex_ints
|
417
|
-
word_size = 4
|
418
|
-
when :octal_quads, :decimal_quads, :hex_quads
|
419
|
-
word_size = 8
|
420
|
-
end
|
421
|
-
|
422
|
-
current_addr = last_addr = first_addr = nil
|
423
|
-
repeated = false
|
424
|
-
|
425
|
-
segment_length = (options[:segment] || 16)
|
426
|
-
segment = []
|
427
|
-
buffer = []
|
428
|
-
|
429
|
-
each_line do |line|
|
430
|
-
if format == :hexdump
|
431
|
-
line = line.gsub(/\s+\|.+\|\s*$/,'')
|
432
|
-
end
|
433
|
-
|
434
|
-
words = line.split
|
435
|
-
|
436
|
-
if words.first == '*'
|
437
|
-
repeated = true
|
438
|
-
elsif words.length > 0
|
439
|
-
current_addr = words.shift.to_i(address_base)
|
440
|
-
first_addr ||= current_addr
|
441
|
-
|
442
|
-
if repeated
|
443
|
-
(((current_addr - last_addr) / segment.length) - 1).times do
|
444
|
-
buffer += segment
|
445
|
-
end
|
446
|
-
|
447
|
-
repeated = false
|
448
|
-
end
|
449
|
-
|
450
|
-
segment.clear
|
451
|
-
|
452
|
-
words.each do |word|
|
453
|
-
if (base != 10 && word =~ /^(\\[0abtnvfr\\]|.)$/)
|
454
|
-
word.hex_unescape.each_byte { |b| segment << b }
|
455
|
-
else
|
456
|
-
segment += word.to_i(base).bytes(word_size)
|
457
|
-
end
|
458
|
-
end
|
459
|
-
|
460
|
-
segment = segment[0,segment_length]
|
461
|
-
buffer += segment
|
462
|
-
last_addr = current_addr
|
463
|
-
end
|
464
|
-
end
|
465
|
-
|
466
|
-
return buffer[0,(last_addr - first_addr)]
|
354
|
+
Ronin::Binary::Hexdump::Parser.new(options).parse(self)
|
467
355
|
end
|
468
356
|
|
469
357
|
end
|
@@ -237,4 +237,65 @@ class String
|
|
237
237
|
return padded
|
238
238
|
end
|
239
239
|
|
240
|
+
alias escape dump
|
241
|
+
|
242
|
+
# Common escaped characters.
|
243
|
+
UNESCAPE_CHARS = Hash.new do |hash,char|
|
244
|
+
if char[0,1] == '\\'
|
245
|
+
char[1,1]
|
246
|
+
else
|
247
|
+
char
|
248
|
+
end
|
249
|
+
end
|
250
|
+
UNESCAPE_CHARS['\0'] = "\0"
|
251
|
+
UNESCAPE_CHARS['\a'] = "\a"
|
252
|
+
UNESCAPE_CHARS['\b'] = "\b"
|
253
|
+
UNESCAPE_CHARS['\t'] = "\t"
|
254
|
+
UNESCAPE_CHARS['\n'] = "\n"
|
255
|
+
UNESCAPE_CHARS['\v'] = "\v"
|
256
|
+
UNESCAPE_CHARS['\f'] = "\f"
|
257
|
+
UNESCAPE_CHARS['\r'] = "\r"
|
258
|
+
|
259
|
+
#
|
260
|
+
# Unescapes the escaped String.
|
261
|
+
#
|
262
|
+
# @return [String]
|
263
|
+
# The unescaped version of the hex escaped String.
|
264
|
+
#
|
265
|
+
# @example
|
266
|
+
# "\\x68\\x65\\x6c\\x6c\\x6f".unescape
|
267
|
+
# # => "hello"
|
268
|
+
#
|
269
|
+
# @api public
|
270
|
+
#
|
271
|
+
# @since 0.5.0
|
272
|
+
#
|
273
|
+
def unescape
|
274
|
+
buffer = ''
|
275
|
+
hex_index = 0
|
276
|
+
hex_length = length
|
277
|
+
|
278
|
+
while (hex_index < hex_length)
|
279
|
+
hex_substring = self[hex_index..-1]
|
280
|
+
|
281
|
+
if hex_substring =~ /^\\[0-7]{3}/
|
282
|
+
buffer << hex_substring[0,4].to_i(8)
|
283
|
+
hex_index += 3
|
284
|
+
elsif hex_substring =~ /^\\x[0-9a-fA-F]{1,2}/
|
285
|
+
hex_substring[2..-1].scan(/^[0-9a-fA-F]{1,2}/) do |hex_byte|
|
286
|
+
buffer << hex_byte.to_i(16)
|
287
|
+
hex_index += (2 + hex_byte.length)
|
288
|
+
end
|
289
|
+
elsif hex_substring =~ /^\\./
|
290
|
+
buffer << UNESCAPE_CHARS[hex_substring[0,2]]
|
291
|
+
hex_index += 2
|
292
|
+
else
|
293
|
+
buffer << hex_substring[0,1]
|
294
|
+
hex_index += 1
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
return buffer
|
299
|
+
end
|
300
|
+
|
240
301
|
end
|
@@ -50,34 +50,34 @@ class String
|
|
50
50
|
# A given string set was not a String, Symbol or Enumerable.
|
51
51
|
# A given string set length was not an Integer or Enumerable.
|
52
52
|
#
|
53
|
-
# @example Generate Strings with ranges of repeating sub-strings
|
53
|
+
# @example Generate Strings with ranges of repeating sub-strings:
|
54
54
|
#
|
55
|
-
# @example Generate Strings with three alpha chars and one numeric chars
|
55
|
+
# @example Generate Strings with three alpha chars and one numeric chars:
|
56
56
|
# String.generate([:alpha, 3], :numeric) do |password|
|
57
57
|
# puts password
|
58
58
|
# end
|
59
59
|
#
|
60
|
-
# @example Generate Strings with two to four alpha chars
|
60
|
+
# @example Generate Strings with two to four alpha chars:
|
61
61
|
# String.generate([:alpha, 2..4]) do |password|
|
62
62
|
# puts password
|
63
63
|
# end
|
64
64
|
#
|
65
|
-
# @example Generate Strings using alpha and punctuation chars
|
65
|
+
# @example Generate Strings using alpha and punctuation chars:
|
66
66
|
# String.generate([Chars.alpha + Chars.punctuation, 4]) do |password|
|
67
67
|
# puts password
|
68
68
|
# end
|
69
69
|
#
|
70
|
-
# @example Generate Strings from a custom char set
|
70
|
+
# @example Generate Strings from a custom char set:
|
71
71
|
# String.generate([['a', 'b', 'c'], 3], [['1', '2', '3'], 3]) do |password|
|
72
72
|
# puts password
|
73
73
|
# end
|
74
74
|
#
|
75
|
-
# @example Generate Strings containing known Strings
|
75
|
+
# @example Generate Strings containing known Strings:
|
76
76
|
# String.generate("rock", [:numeric, 4]) do |password|
|
77
77
|
# puts password
|
78
78
|
# end
|
79
79
|
#
|
80
|
-
# @example Generate Strings with ranges of repeating sub-strings
|
80
|
+
# @example Generate Strings with ranges of repeating sub-strings:
|
81
81
|
# String.generate(['/AA', (1..100).step(5)]) do |path|
|
82
82
|
# puts path
|
83
83
|
# end
|
@@ -285,7 +285,7 @@ class String
|
|
285
285
|
#
|
286
286
|
# Permutes over every possible mutation of the String.
|
287
287
|
#
|
288
|
-
# @param [Hash{Regexp,String,Symbol => Symbol
|
288
|
+
# @param [Hash{Regexp,String,Symbol => Symbol,Enumerable}] mutations
|
289
289
|
# The patterns and substitutions to mutate the String with.
|
290
290
|
#
|
291
291
|
# @yield [mutant]
|
@@ -297,6 +297,10 @@ class String
|
|
297
297
|
# @return [Enumerator]
|
298
298
|
# If no block is given, an Enumerator will be returned.
|
299
299
|
#
|
300
|
+
# @raise [TypeError]
|
301
|
+
# A mutation pattern was not a Regexp, String or Symbol.
|
302
|
+
# A mutation substitution was not a Symbol or Enumerable.
|
303
|
+
#
|
300
304
|
# @example
|
301
305
|
# "hello old dog".mutate('e' => ['3'], 'l' => ['1'], 'o' => ['0']) do |str|
|
302
306
|
# puts str
|
@@ -323,6 +327,15 @@ class String
|
|
323
327
|
raise(TypeError,"cannot convert #{pattern.inspect} to a Regexp")
|
324
328
|
end
|
325
329
|
|
330
|
+
mutation = case mutation
|
331
|
+
when Symbol
|
332
|
+
Ronin::Fuzzing[mutation]
|
333
|
+
when Enumerable
|
334
|
+
mutation
|
335
|
+
else
|
336
|
+
raise(TypeError,"mutation #{mutation.inspect} must be a Symbol or Enumerable")
|
337
|
+
end
|
338
|
+
|
326
339
|
scanner = StringScanner.new(self)
|
327
340
|
|
328
341
|
while scanner.scan_until(pattern)
|