ronin-fuzzer 0.1.0.beta1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -0
- data/README.md +5 -2
- data/bin/ronin-fuzzer +1 -1
- data/gemspec.yml +8 -6
- data/lib/ronin/fuzzer/cli/command.rb +1 -1
- data/lib/ronin/fuzzer/cli/commands/fuzz.rb +180 -63
- data/lib/ronin/fuzzer/cli.rb +1 -1
- data/lib/ronin/fuzzer/root.rb +1 -1
- data/lib/ronin/fuzzer/version.rb +2 -2
- data/lib/ronin/fuzzing/core_ext/string.rb +1 -1
- data/lib/ronin/fuzzing/core_ext.rb +1 -1
- data/lib/ronin/fuzzing/fuzzer.rb +1 -1
- data/lib/ronin/fuzzing/mutator.rb +1 -1
- data/lib/ronin/fuzzing/repeater.rb +1 -1
- data/lib/ronin/fuzzing/template.rb +1 -1
- data/lib/ronin/fuzzing.rb +1 -1
- data/man/ronin-fuzzer-fuzz.1 +2 -2
- data/man/ronin-fuzzer-fuzz.1.md +2 -2
- data/ronin-fuzzer.gemspec +2 -1
- metadata +14 -26
- data/spec/core_ext/string_spec.rb +0 -87
- data/spec/fuzzer_spec.rb +0 -109
- data/spec/fuzzing_spec.rb +0 -24
- data/spec/mutator_spec.rb +0 -112
- data/spec/repeater_spec.rb +0 -57
- data/spec/spec_helper.rb +0 -4
- data/spec/template_spec.rb +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b75ddebfc52f82912471833f168b9e8813af985b9443cb1c6b88a27b1c730a3b
|
4
|
+
data.tar.gz: 7a0454d2ece994db0151eb7ed1df4ce0edf6ab2e05d48d12f13621930d66cd8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 508b1ede3b5ec7e9be7d1a9bccfab1add955ce60f028559d444613f6e485195ef52f95f293acab505a9493222b2ba31337901df3038a8bd2fee0a3b8668c8a43
|
7
|
+
data.tar.gz: 65fdbda74f4b756e3378e1fbdc5ac533612a6aad873eff7b8b17bc0a0f1a94726bdb15525668f974f18b2a5d50feb2853077d8a8ba00040c64ed88b5a3352a3f
|
data/.github/workflows/ruby.yml
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://github.com/ronin-rb/ronin-fuzzer/actions/workflows/ruby.yml)
|
4
4
|
[](https://codeclimate.com/github/ronin-rb/ronin-fuzzer)
|
5
|
+
[](https://badge.fury.io/rb/ronin-fuzzer)
|
5
6
|
|
6
7
|
* [Website](https://ronin-rb.dev/)
|
7
8
|
* [Source](https://github.com/ronin-rb/ronin-fuzzer)
|
@@ -13,7 +14,9 @@
|
|
13
14
|
|
14
15
|
## Description
|
15
16
|
|
16
|
-
ronin-fuzzer is a Ruby library for generating, mutating, and fuzzing
|
17
|
+
ronin-fuzzer is a Ruby library and CLI for generating, mutating, and fuzzing
|
18
|
+
data. The goal of ronin-fuzzer is to be both easy to use and highly
|
19
|
+
customizable.
|
17
20
|
|
18
21
|
## Features
|
19
22
|
|
@@ -68,7 +71,7 @@ gem.add_dependency 'ronin-fuzzer', '~> 0.1'
|
|
68
71
|
|
69
72
|
## License
|
70
73
|
|
71
|
-
Copyright (c) 2006-
|
74
|
+
Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3@gmail.com)
|
72
75
|
|
73
76
|
This file is part of ronin-fuzzer.
|
74
77
|
|
data/bin/ronin-fuzzer
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
4
4
|
#
|
5
|
-
# Copyright (c) 2006-
|
5
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
6
|
#
|
7
7
|
# This file is part of ronin-fuzzer.
|
8
8
|
#
|
data/gemspec.yml
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
name: ronin-fuzzer
|
2
|
-
summary:
|
2
|
+
summary: A highly configurable fuzzing library and CLI for Ruby.
|
3
3
|
description: |
|
4
|
-
A Ruby library for generating, mutating, and fuzzing data.
|
4
|
+
A Ruby library and CLI for generating, mutating, and fuzzing data.
|
5
|
+
The goal of ronin-fuzzer is to be both easy to use and highly customizable.
|
5
6
|
|
6
7
|
license: LGPL-3.0
|
7
8
|
authors: Postmodern
|
@@ -10,10 +11,11 @@ homepage: https://ronin-rb.dev/
|
|
10
11
|
has_yard: true
|
11
12
|
|
12
13
|
metadata:
|
13
|
-
documentation_uri: https://
|
14
|
+
documentation_uri: https://ronin-rb.dev/docs/ronin-fuzzer
|
14
15
|
source_code_uri: https://github.com/ronin-rb/ronin-fuzzer
|
15
16
|
bug_tracker_uri: https://github.com/ronin-rb/ronin-fuzzer/issues
|
16
|
-
changelog_uri: https://github.com/ronin-rb/ronin-fuzzer/blob/
|
17
|
+
changelog_uri: https://github.com/ronin-rb/ronin-fuzzer/blob/main/ChangeLog.md
|
18
|
+
rubygems_mfa_required: 'true'
|
17
19
|
|
18
20
|
generated_files:
|
19
21
|
- man/ronin-fuzzer-fuzz.1
|
@@ -23,8 +25,8 @@ required_ruby_version: ">= 3.0.0"
|
|
23
25
|
dependencies:
|
24
26
|
combinatorics: ~> 0.4
|
25
27
|
# Ronin dependencies:
|
26
|
-
ronin-support: ~> 1.0
|
27
|
-
ronin-core: ~> 0.1
|
28
|
+
ronin-support: ~> 1.0
|
29
|
+
ronin-core: ~> 0.1
|
28
30
|
|
29
31
|
development_dependencies:
|
30
32
|
bundler: ~> 2.0
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
@@ -20,8 +20,12 @@
|
|
20
20
|
#
|
21
21
|
|
22
22
|
require 'ronin/fuzzer/cli/command'
|
23
|
-
require 'ronin/
|
24
|
-
|
23
|
+
require 'ronin/core/cli/logging'
|
24
|
+
|
25
|
+
require 'ronin/support/text/patterns'
|
26
|
+
require 'ronin/fuzzing/repeater'
|
27
|
+
require 'ronin/fuzzing/fuzzer'
|
28
|
+
require 'ronin/fuzzing'
|
25
29
|
|
26
30
|
require 'shellwords'
|
27
31
|
require 'tempfile'
|
@@ -44,7 +48,7 @@ module Ronin
|
|
44
48
|
# -q, --[no-]quiet Disable verbose output.
|
45
49
|
# --[no-]silent Silence all output.
|
46
50
|
# -r [[PATTERN|/REGEXP/]:[METHOD|STRING*N[-M]]],
|
47
|
-
# --rule
|
51
|
+
# --rule Adds a fuzzing rule.
|
48
52
|
# -i, --input [FILE] Input file to fuzz.
|
49
53
|
# -o, --output [FILE] Output file path.
|
50
54
|
# -c [PROGRAM [OPTIONS|#string#|#path#] ...],
|
@@ -59,6 +63,8 @@ module Ronin
|
|
59
63
|
#
|
60
64
|
class Fuzz < Command
|
61
65
|
|
66
|
+
include Core::CLI::Logging
|
67
|
+
|
62
68
|
option :input, short: '-i',
|
63
69
|
value: {
|
64
70
|
type: String,
|
@@ -68,45 +74,66 @@ module Ronin
|
|
68
74
|
|
69
75
|
option :rules, short: '-r',
|
70
76
|
value: {
|
71
|
-
type:
|
77
|
+
type: String,
|
72
78
|
usage: '[PATTERN|/REGEXP/|STRING]:[METHOD|STRING*N[-M]]'
|
73
79
|
},
|
74
|
-
desc: '
|
80
|
+
desc: 'Adds a fuzzing rule' do |value|
|
81
|
+
@rules << parse_rule(value)
|
82
|
+
end
|
75
83
|
|
76
84
|
option :output, short: '-o',
|
77
85
|
value: {
|
78
86
|
type: String,
|
79
87
|
usage: 'PATH'
|
80
88
|
},
|
81
|
-
desc: 'Output file path'
|
89
|
+
desc: 'Output file path' do |value|
|
90
|
+
@mode = :output
|
91
|
+
|
92
|
+
@output = value
|
93
|
+
@output_ext = File.extname(@output)
|
94
|
+
@output_name = @output.chomp(@output_ext)
|
95
|
+
end
|
82
96
|
|
83
97
|
option :command, short: '-c',
|
84
98
|
value: {
|
85
99
|
type: String,
|
86
100
|
usage: '"PROGRAM [OPTIONS|#string#|#path#] ..."'
|
87
101
|
},
|
88
|
-
desc: 'Template command to run'
|
102
|
+
desc: 'Template command to run' do |value|
|
103
|
+
@mode = :command
|
104
|
+
@command = Shellwords.shellescape(value)
|
105
|
+
end
|
89
106
|
|
90
107
|
option :tcp, short: '-t',
|
91
108
|
value: {
|
92
109
|
type: String,
|
93
110
|
usage: 'HOST:PORT'
|
94
111
|
},
|
95
|
-
desc: 'TCP service to fuzz'
|
112
|
+
desc: 'TCP service to fuzz' do |value|
|
113
|
+
@mode = :tcp
|
114
|
+
|
115
|
+
@host, @port = parse_host_port(value)
|
116
|
+
end
|
96
117
|
|
97
118
|
option :udp, short: '-u',
|
98
119
|
value: {
|
99
120
|
type: String,
|
100
121
|
usage: 'HOST:PORT'
|
101
122
|
},
|
102
|
-
desc: 'UDP service to fuzz'
|
123
|
+
desc: 'UDP service to fuzz' do |value|
|
124
|
+
@mode = :udp
|
125
|
+
|
126
|
+
@host, @port = parse_host_port(value)
|
127
|
+
end
|
103
128
|
|
104
129
|
option :pause, short: '-p',
|
105
130
|
value: {
|
106
131
|
type: Float,
|
107
132
|
usage: 'SECONDS'
|
108
133
|
},
|
109
|
-
desc: 'Pause in between mutations'
|
134
|
+
desc: 'Pause in between mutations' do |value|
|
135
|
+
@pause = value
|
136
|
+
end
|
110
137
|
|
111
138
|
description 'Performs basic fuzzing of files'
|
112
139
|
|
@@ -116,58 +143,99 @@ module Ronin
|
|
116
143
|
|
117
144
|
man_page 'ronin-fuzzer-fuzz.1'
|
118
145
|
|
146
|
+
# The execution mode to run the fuzzer in.
|
147
|
+
#
|
148
|
+
# @return [:output, :command, :tcp, :udp]
|
149
|
+
attr_reader :mode
|
150
|
+
|
151
|
+
# The output file template.
|
119
152
|
#
|
120
|
-
#
|
153
|
+
# @return [String, nil]
|
154
|
+
attr_reader :output
|
155
|
+
|
156
|
+
# The output file extension.
|
157
|
+
#
|
158
|
+
# @return [String, nil]
|
159
|
+
attr_reader :output_ext
|
160
|
+
|
161
|
+
# The output file name.
|
162
|
+
#
|
163
|
+
# @return [String, nil]
|
164
|
+
attr_reader :output_name
|
165
|
+
|
166
|
+
# The command template to execute.
|
167
|
+
#
|
168
|
+
# @return [String, nil]
|
169
|
+
attr_reader :command
|
170
|
+
|
171
|
+
# The host name to send fuzzing data to.
|
172
|
+
#
|
173
|
+
# @return [String, nil]
|
174
|
+
attr_reader :host
|
175
|
+
|
176
|
+
# The port to send fuzzing data to.
|
177
|
+
#
|
178
|
+
# @return [Integer, nil]
|
179
|
+
attr_reader :port
|
180
|
+
|
181
|
+
# The fuzzing rules.
|
182
|
+
#
|
183
|
+
# @return [Array<(Regexp, Enumerator)>]
|
184
|
+
attr_reader :rules
|
185
|
+
|
186
|
+
#
|
187
|
+
# Initializes the `ronin-fuzzer fuzz` command.
|
188
|
+
#
|
189
|
+
# @param [Hash{Symbol => Object}] kwargs
|
190
|
+
# Additional keyword arguments.
|
191
|
+
#
|
192
|
+
def initialize(**kwargs)
|
193
|
+
super(**kwargs)
|
194
|
+
|
195
|
+
@rules = []
|
196
|
+
end
|
197
|
+
|
198
|
+
#
|
199
|
+
# Runs the `ronin-fuzzer fuzz` command.
|
121
200
|
#
|
122
201
|
def run
|
123
|
-
|
202
|
+
if @rules.empty?
|
124
203
|
print_error "Must specify at least one fuzzing rule"
|
125
|
-
exit
|
204
|
+
exit(-1)
|
126
205
|
end
|
127
206
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
if options[:output]
|
133
|
-
@file_ext = File.extname(options[:output])
|
134
|
-
@file_name = @output.chomp(@file_ext)
|
135
|
-
elsif options[:command]
|
136
|
-
@command = shellwords(options[:command])
|
137
|
-
elsif (options[:tcp] || options[:udp])
|
138
|
-
@socket_class = if options[:tcp] then TCPSocket
|
139
|
-
elsif options[:udp] then UDPSocket
|
140
|
-
end
|
141
|
-
|
142
|
-
@host, @port = (options[:tcp] || options[:udp]).split(':',2)
|
143
|
-
@port = @port.to_i
|
144
|
-
end
|
207
|
+
data = if options[:input] then File.read(options[:input])
|
208
|
+
else $stdin.read
|
209
|
+
end
|
145
210
|
|
146
|
-
|
147
|
-
|
211
|
+
method = case @mode
|
212
|
+
when :output then method(:fuzz_file)
|
213
|
+
when :command then method(:fuzz_command)
|
214
|
+
when :tcp, :udp then method(:fuzz_network)
|
215
|
+
else method(:print_fuzz)
|
148
216
|
end
|
149
217
|
|
150
|
-
|
151
|
-
method(:fuzz_file)
|
152
|
-
elsif options[:command]
|
153
|
-
method(:fuzz_command)
|
154
|
-
elsif (options[:tcp] || options[:udp])
|
155
|
-
method(:fuzz_network)
|
156
|
-
else
|
157
|
-
method(:print_fuzz)
|
158
|
-
end
|
218
|
+
fuzzer = Fuzzing::Fuzzer.new(@rules)
|
159
219
|
|
160
|
-
fuzzer = Fuzzer::Fuzzer.new(rules)
|
161
220
|
fuzzer.each(data).each_with_index do |string,index|
|
162
221
|
method.call(string,index + 1)
|
163
222
|
|
164
|
-
sleep(pause) if pause
|
223
|
+
sleep(@pause) if @pause
|
165
224
|
end
|
166
225
|
end
|
167
226
|
|
168
|
-
|
169
|
-
|
170
|
-
|
227
|
+
#
|
228
|
+
# Creates a new output path for the given index.
|
229
|
+
#
|
230
|
+
# @param [Integer] index
|
231
|
+
# The index number of the fuzzing iteration.
|
232
|
+
#
|
233
|
+
# @return [String]
|
234
|
+
# The new output path.
|
235
|
+
#
|
236
|
+
def output_path(index)
|
237
|
+
"#{@output_name}-#{index}#{@output_ext}"
|
238
|
+
end
|
171
239
|
|
172
240
|
#
|
173
241
|
# Writes the fuzzed string to a file.
|
@@ -176,12 +244,12 @@ module Ronin
|
|
176
244
|
# The fuzzed string.
|
177
245
|
#
|
178
246
|
# @param [Integer] index
|
179
|
-
# The iteration number.
|
247
|
+
# The fuzzing iteration number.
|
180
248
|
#
|
181
249
|
def fuzz_file(string,index)
|
182
|
-
path =
|
250
|
+
path = output_path(index)
|
183
251
|
|
184
|
-
|
252
|
+
log_info "Creating file ##{index}: #{path} ..."
|
185
253
|
|
186
254
|
File.open(path,'wb') do |file|
|
187
255
|
file.write string
|
@@ -212,7 +280,7 @@ module Ronin
|
|
212
280
|
end
|
213
281
|
end
|
214
282
|
|
215
|
-
|
283
|
+
log_info "Running command #{index}: #{arguments.join(' ')} ..."
|
216
284
|
|
217
285
|
# run the command as it's own process
|
218
286
|
unless system(*arguments)
|
@@ -220,10 +288,10 @@ module Ronin
|
|
220
288
|
|
221
289
|
if status.coredump?
|
222
290
|
# jack pot!
|
223
|
-
|
291
|
+
log_error "Process ##{status.pid} coredumped!"
|
224
292
|
else
|
225
293
|
# process errored out
|
226
|
-
|
294
|
+
log_warning "Process ##{status.pid} exited with status #{status.exitstatus}"
|
227
295
|
end
|
228
296
|
end
|
229
297
|
end
|
@@ -239,14 +307,18 @@ module Ronin
|
|
239
307
|
# The iteration number.
|
240
308
|
#
|
241
309
|
def fuzz_network(string,index)
|
242
|
-
|
243
|
-
socket = @socket_class.new(@host,@port)
|
310
|
+
log_debug "Connecting to #{@host}:#{@port} ..."
|
244
311
|
|
245
|
-
|
312
|
+
socket = case @mode
|
313
|
+
when :tcp then TCPSocket.new(@host,@port)
|
314
|
+
when :udp then UDPSocket.new(@host,@port)
|
315
|
+
end
|
316
|
+
|
317
|
+
log_info "Sending message ##{index}: #{string.inspect} ..."
|
246
318
|
socket.write(string)
|
247
319
|
socket.flush
|
248
320
|
|
249
|
-
|
321
|
+
log_debug "Disconnecting from #{@host}:#{@port} ..."
|
250
322
|
socket.close
|
251
323
|
end
|
252
324
|
|
@@ -260,11 +332,57 @@ module Ronin
|
|
260
332
|
# The iteration number.
|
261
333
|
#
|
262
334
|
def print_fuzz(string,index)
|
263
|
-
|
335
|
+
log_debug "String ##{index} ..."
|
264
336
|
|
265
337
|
puts string
|
266
338
|
end
|
267
339
|
|
340
|
+
#
|
341
|
+
# Parses the host and port from the value.
|
342
|
+
#
|
343
|
+
# @param [String] value
|
344
|
+
# The value to parse.
|
345
|
+
#
|
346
|
+
# @return [(String, Integer)]
|
347
|
+
# The parsed host and port.
|
348
|
+
#
|
349
|
+
def parse_host_port(value)
|
350
|
+
host, port = value.split(':',2)
|
351
|
+
|
352
|
+
return host, port.to_i
|
353
|
+
end
|
354
|
+
|
355
|
+
#
|
356
|
+
# Parses a fuzzing rule.
|
357
|
+
#
|
358
|
+
# @param [String] value
|
359
|
+
# The fuzzing rule.
|
360
|
+
#
|
361
|
+
# @return [(Regexp, Enumerator)]
|
362
|
+
# The fuzzing pattern and list of substitutions.
|
363
|
+
#
|
364
|
+
def parse_rule(value)
|
365
|
+
if value.start_with?('/')
|
366
|
+
unless (index = value.rindex('/:'))
|
367
|
+
raise(OptionParser::InvalidArgument,"argument must be of the form /REGEXP/:REPLACE, but was: #{value}")
|
368
|
+
end
|
369
|
+
|
370
|
+
regexp = parse_pattern(value[1...index])
|
371
|
+
substitution = parse_substitution(value[index+2..])
|
372
|
+
|
373
|
+
return [regexp, substitution]
|
374
|
+
else
|
375
|
+
unless (index = value.rindex(':'))
|
376
|
+
raise(OptionParser::InvalidArgument,"argument must be of the form STRING:STYLE but was: #{value}")
|
377
|
+
end
|
378
|
+
|
379
|
+
pattern = parse_pattern(value[0...index])
|
380
|
+
substitution = parse_substitution(value[index+1..])
|
381
|
+
|
382
|
+
return [pattern, substitution]
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
268
386
|
#
|
269
387
|
# Parses a fuzz pattern.
|
270
388
|
#
|
@@ -281,9 +399,8 @@ module Ronin
|
|
281
399
|
when /^[a-z][a-z_]+$/
|
282
400
|
const = string.upcase
|
283
401
|
|
284
|
-
if
|
285
|
-
|
286
|
-
Regexp.const_get(const)
|
402
|
+
if Support::Text::Patterns.const_defined?(const,false)
|
403
|
+
Support::Text::Patterns.const_get(const,false)
|
287
404
|
else
|
288
405
|
string
|
289
406
|
end
|
@@ -313,9 +430,9 @@ module Ronin
|
|
313
430
|
lengths.to_i
|
314
431
|
end
|
315
432
|
|
316
|
-
|
433
|
+
Fuzzing::Repeater.new(lengths).each(string)
|
317
434
|
else
|
318
|
-
|
435
|
+
Fuzzing[string]
|
319
436
|
end
|
320
437
|
end
|
321
438
|
|
data/lib/ronin/fuzzer/cli.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
data/lib/ronin/fuzzer/root.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
data/lib/ronin/fuzzer/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
@@ -22,6 +22,6 @@
|
|
22
22
|
module Ronin
|
23
23
|
module Fuzzer
|
24
24
|
# ronin-fuzzer version
|
25
|
-
VERSION = '0.1.0
|
25
|
+
VERSION = '0.1.0'
|
26
26
|
end
|
27
27
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
data/lib/ronin/fuzzing/fuzzer.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
data/lib/ronin/fuzzing.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# ronin-fuzzer - A Ruby library for generating, mutating, and fuzzing data.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2006-
|
4
|
+
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
5
|
#
|
6
6
|
# This file is part of ronin-fuzzer.
|
7
7
|
#
|
data/man/ronin-fuzzer-fuzz.1
CHANGED
@@ -53,8 +53,8 @@ The output PATH to write the fuzzer to\.
|
|
53
53
|
.LP
|
54
54
|
.TP
|
55
55
|
\fB-c\fR, \fB--command\fR \fICOMMAND\fP
|
56
|
-
The command to run with the fuzzed data\. All
|
57
|
-
will be replaced with the fuzzed data, and
|
56
|
+
The command to run with the fuzzed data\. All occurrences of \fB#string#\fR
|
57
|
+
will be replaced with the fuzzed data, and occurrences of \fB#path#\fR will
|
58
58
|
be replaced with the path to the fuzzed data\.
|
59
59
|
.LP
|
60
60
|
.TP
|
data/man/ronin-fuzzer-fuzz.1.md
CHANGED
@@ -40,8 +40,8 @@ to output files, run in commands or sent to TCP/UDP services.
|
|
40
40
|
The output PATH to write the fuzzer to.
|
41
41
|
|
42
42
|
`-c`, `--command` *COMMAND*
|
43
|
-
The command to run with the fuzzed data. All
|
44
|
-
will be replaced with the fuzzed data, and
|
43
|
+
The command to run with the fuzzed data. All occurrences of `#string#`
|
44
|
+
will be replaced with the fuzzed data, and occurrences of `#path#` will
|
45
45
|
be replaced with the path to the fuzzed data.
|
46
46
|
|
47
47
|
`-t`, `--tcp` *HOST*:*PORT*
|
data/ronin-fuzzer.gemspec
CHANGED
@@ -27,13 +27,14 @@ Gem::Specification.new do |gem|
|
|
27
27
|
gem.files = `git ls-files`.split($/)
|
28
28
|
gem.files = glob[gemspec['files']] if gemspec['files']
|
29
29
|
gem.files += Array(gemspec['generated_files'])
|
30
|
+
# exclude test files from the packages gem
|
31
|
+
gem.files -= glob[gemspec['test_files'] || 'spec/{**/}*']
|
30
32
|
|
31
33
|
gem.executables = gemspec.fetch('executables') do
|
32
34
|
glob['bin/*'].map { |path| File.basename(path) }
|
33
35
|
end
|
34
36
|
|
35
37
|
gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
|
36
|
-
gem.test_files = glob[gemspec['test_files'] || 'spec/{**/}*_spec.rb']
|
37
38
|
gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
|
38
39
|
|
39
40
|
gem.require_paths = Array(gemspec.fetch('require_paths') {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ronin-fuzzer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Postmodern
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: combinatorics
|
@@ -30,28 +30,28 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.0
|
33
|
+
version: '1.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.0
|
40
|
+
version: '1.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: ronin-core
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.1
|
47
|
+
version: '0.1'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.1
|
54
|
+
version: '0.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,9 +66,9 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '2.0'
|
69
|
-
description:
|
70
|
-
|
71
|
-
|
69
|
+
description: |
|
70
|
+
A Ruby library and CLI for generating, mutating, and fuzzing data.
|
71
|
+
The goal of ronin-fuzzer is to be both easy to use and highly customizable.
|
72
72
|
email: postmodern.mod3@gmail.com
|
73
73
|
executables:
|
74
74
|
- ronin-fuzzer
|
@@ -106,21 +106,15 @@ files:
|
|
106
106
|
- man/ronin-fuzzer-fuzz.1
|
107
107
|
- man/ronin-fuzzer-fuzz.1.md
|
108
108
|
- ronin-fuzzer.gemspec
|
109
|
-
- spec/core_ext/string_spec.rb
|
110
|
-
- spec/fuzzer_spec.rb
|
111
|
-
- spec/fuzzing_spec.rb
|
112
|
-
- spec/mutator_spec.rb
|
113
|
-
- spec/repeater_spec.rb
|
114
|
-
- spec/spec_helper.rb
|
115
|
-
- spec/template_spec.rb
|
116
109
|
homepage: https://ronin-rb.dev/
|
117
110
|
licenses:
|
118
111
|
- LGPL-3.0
|
119
112
|
metadata:
|
120
|
-
documentation_uri: https://
|
113
|
+
documentation_uri: https://ronin-rb.dev/docs/ronin-fuzzer
|
121
114
|
source_code_uri: https://github.com/ronin-rb/ronin-fuzzer
|
122
115
|
bug_tracker_uri: https://github.com/ronin-rb/ronin-fuzzer/issues
|
123
|
-
changelog_uri: https://github.com/ronin-rb/ronin-fuzzer/blob/
|
116
|
+
changelog_uri: https://github.com/ronin-rb/ronin-fuzzer/blob/main/ChangeLog.md
|
117
|
+
rubygems_mfa_required: 'true'
|
124
118
|
post_install_message:
|
125
119
|
rdoc_options: []
|
126
120
|
require_paths:
|
@@ -139,11 +133,5 @@ requirements: []
|
|
139
133
|
rubygems_version: 3.3.26
|
140
134
|
signing_key:
|
141
135
|
specification_version: 4
|
142
|
-
summary:
|
143
|
-
test_files:
|
144
|
-
- spec/core_ext/string_spec.rb
|
145
|
-
- spec/fuzzer_spec.rb
|
146
|
-
- spec/fuzzing_spec.rb
|
147
|
-
- spec/mutator_spec.rb
|
148
|
-
- spec/repeater_spec.rb
|
149
|
-
- spec/template_spec.rb
|
136
|
+
summary: A highly configurable fuzzing library and CLI for Ruby.
|
137
|
+
test_files: []
|
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ronin/fuzzing/core_ext/string'
|
3
|
-
|
4
|
-
describe String do
|
5
|
-
it "should provide String.generate" do
|
6
|
-
expect(described_class).to respond_to(:generate)
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should provide String#repeating" do
|
10
|
-
expect(subject).to respond_to(:repeating)
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should provide String#fuzz" do
|
14
|
-
expect(subject).to respond_to(:fuzz)
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should provide String#mutate" do
|
18
|
-
expect(subject).to respond_to(:mutate)
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "generate" do
|
22
|
-
subject { described_class }
|
23
|
-
|
24
|
-
it "should generate Strings from a template" do
|
25
|
-
strings = subject.generate([:numeric, 2]).to_a
|
26
|
-
|
27
|
-
expect(strings.grep(/^[0-9]{2}$/)).to eq(strings)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe "#repeating" do
|
32
|
-
subject { 'A' }
|
33
|
-
|
34
|
-
context "when n is an Integer" do
|
35
|
-
let(:n) { 100 }
|
36
|
-
|
37
|
-
it "should multiply the String by n" do
|
38
|
-
expect(subject.repeating(n)).to eq(subject * n)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
context "when n is Enumerable" do
|
43
|
-
let(:n) { [128, 512, 1024] }
|
44
|
-
|
45
|
-
it "should repeat the String by each length" do
|
46
|
-
strings = subject.repeating(n).to_a
|
47
|
-
|
48
|
-
expect(strings).to eq(n.map { |length| subject * length })
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "#fuzz" do
|
54
|
-
subject { "foo bar" }
|
55
|
-
|
56
|
-
it "should apply each fuzzing rule individually" do
|
57
|
-
strings = subject.fuzz(/o/ => ['O', '0'], /a/ => ['A', '@']).to_a
|
58
|
-
|
59
|
-
expect(strings).to match_array([
|
60
|
-
"fOo bar",
|
61
|
-
"f0o bar",
|
62
|
-
"foO bar",
|
63
|
-
"fo0 bar",
|
64
|
-
"foo bAr",
|
65
|
-
"foo b@r"
|
66
|
-
])
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe "#mutate" do
|
71
|
-
subject { "foo bar" }
|
72
|
-
|
73
|
-
it "should apply every combination of mutation rules" do
|
74
|
-
strings = subject.mutate(/o/ => ['0'], /a/ => ['@']).to_a
|
75
|
-
|
76
|
-
expect(strings).to match_array([
|
77
|
-
"f0o bar",
|
78
|
-
"fo0 bar",
|
79
|
-
"f00 bar",
|
80
|
-
"foo b@r",
|
81
|
-
"f0o b@r",
|
82
|
-
"fo0 b@r",
|
83
|
-
"f00 b@r"
|
84
|
-
])
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
data/spec/fuzzer_spec.rb
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ronin/fuzzing/fuzzer'
|
3
|
-
|
4
|
-
describe Ronin::Fuzzing::Fuzzer do
|
5
|
-
let(:string) { 'GET /one/two/three' }
|
6
|
-
|
7
|
-
describe "#initialize" do
|
8
|
-
subject { described_class }
|
9
|
-
|
10
|
-
context "patterns" do
|
11
|
-
let(:substitutions) { ['bar'] }
|
12
|
-
|
13
|
-
it "should accept Regexps" do
|
14
|
-
fuzzer = subject.new(/foo/ => substitutions)
|
15
|
-
|
16
|
-
expect(fuzzer.rules).to have_key(/foo/)
|
17
|
-
end
|
18
|
-
|
19
|
-
context "when given Strings" do
|
20
|
-
subject { described_class.new('foo' => substitutions) }
|
21
|
-
|
22
|
-
it "should convert to Regexp" do
|
23
|
-
expect(subject.rules).to have_key(/foo/)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
context "when given Symbols" do
|
28
|
-
subject { described_class.new(:word => substitutions) }
|
29
|
-
|
30
|
-
it "should lookup the Ronin::Support::Text::Patterns constant" do
|
31
|
-
expect(subject.rules).to have_key(Ronin::Support::Text::Patterns::WORD)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context "otherwise" do
|
36
|
-
it "should raise a TypeError" do
|
37
|
-
expect {
|
38
|
-
subject.new(Object.new => substitutions)
|
39
|
-
}.to raise_error(TypeError)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context "substitutions" do
|
45
|
-
let(:pattern) { /foo/ }
|
46
|
-
|
47
|
-
it "should accept Enumerable values" do
|
48
|
-
fuzzer = subject.new(pattern => ['bar'])
|
49
|
-
|
50
|
-
expect(fuzzer.rules[pattern]).to eq(['bar'])
|
51
|
-
end
|
52
|
-
|
53
|
-
context "when given Symbols" do
|
54
|
-
subject { described_class.new(pattern => :bad_strings) }
|
55
|
-
|
56
|
-
it "should map to an Enumerator for a Fuzzing method" do
|
57
|
-
expect(subject.rules[pattern]).to be_kind_of(Enumerable)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
context "otherwise" do
|
62
|
-
it "should raise a TypeError" do
|
63
|
-
expect {
|
64
|
-
subject.new(pattern => Object.new)
|
65
|
-
}.to raise_error(TypeError)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
describe "#each" do
|
72
|
-
let(:string) { "foo bar" }
|
73
|
-
|
74
|
-
subject { described_class.new(/o/ => ['O', '0'], /a/ => ['A', '@']) }
|
75
|
-
|
76
|
-
it "should apply each fuzzing rule individually" do
|
77
|
-
expect(subject.each(string).to_a).to match_array([
|
78
|
-
"fOo bar",
|
79
|
-
"f0o bar",
|
80
|
-
"foO bar",
|
81
|
-
"fo0 bar",
|
82
|
-
"foo bAr",
|
83
|
-
"foo b@r"
|
84
|
-
])
|
85
|
-
end
|
86
|
-
|
87
|
-
context "when mutations contain Integers" do
|
88
|
-
subject { described_class.new(/o/ => [48]) }
|
89
|
-
|
90
|
-
it "should convert them to characters" do
|
91
|
-
expect(subject.each(string).to_a).to match_array([
|
92
|
-
"f0o bar",
|
93
|
-
"fo0 bar"
|
94
|
-
])
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
context "when mutations contain Procs" do
|
99
|
-
subject { described_class.new(/o/ => [lambda { |str| str.upcase }]) }
|
100
|
-
|
101
|
-
it "should call them with the matched String" do
|
102
|
-
expect(subject.each(string).to_a).to match_array([
|
103
|
-
"fOo bar",
|
104
|
-
"foO bar"
|
105
|
-
])
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
data/spec/fuzzing_spec.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ronin/fuzzing'
|
3
|
-
|
4
|
-
describe Ronin::Fuzzing do
|
5
|
-
describe "[]" do
|
6
|
-
let(:method) { :bad_strings }
|
7
|
-
|
8
|
-
it "should return Enumerators for fuzzing methods" do
|
9
|
-
expect(subject[method]).to be_kind_of(Enumerable)
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should raise NoMethodError for unknown methods" do
|
13
|
-
expect {
|
14
|
-
subject[:foo]
|
15
|
-
}.to raise_error(NoMethodError)
|
16
|
-
end
|
17
|
-
|
18
|
-
it "should not allow accessing inherited methods" do
|
19
|
-
expect {
|
20
|
-
subject[:instance_eval]
|
21
|
-
}.to raise_error(NoMethodError)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/spec/mutator_spec.rb
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ronin/fuzzing/mutator'
|
3
|
-
|
4
|
-
describe Ronin::Fuzzing::Mutator do
|
5
|
-
let(:string) { 'GET /one/two/three' }
|
6
|
-
|
7
|
-
describe "#initialize" do
|
8
|
-
subject { described_class }
|
9
|
-
|
10
|
-
context "patterns" do
|
11
|
-
let(:substitutions) { ['bar'] }
|
12
|
-
|
13
|
-
it "should accept Regexps" do
|
14
|
-
fuzzer = subject.new(/foo/ => substitutions)
|
15
|
-
|
16
|
-
expect(fuzzer.rules).to have_key(/foo/)
|
17
|
-
end
|
18
|
-
|
19
|
-
context "when given Strings" do
|
20
|
-
subject { described_class.new('foo' => substitutions) }
|
21
|
-
|
22
|
-
it "should convert to Regexp" do
|
23
|
-
expect(subject.rules).to have_key(/foo/)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
context "when given Symbols" do
|
28
|
-
subject { described_class.new(:word => substitutions) }
|
29
|
-
|
30
|
-
it "should lookup the Ronin::Support::Text::Patterns constant" do
|
31
|
-
expect(subject.rules).to have_key(Ronin::Support::Text::Patterns::WORD)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context "otherwise" do
|
36
|
-
it "should raise a TypeError" do
|
37
|
-
expect {
|
38
|
-
subject.new(Object.new => substitutions)
|
39
|
-
}.to raise_error(TypeError)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context "mutations" do
|
45
|
-
let(:pattern) { /foo/ }
|
46
|
-
|
47
|
-
it "should accept Enumerable values" do
|
48
|
-
fuzzer = subject.new(pattern => ['bar'])
|
49
|
-
|
50
|
-
expect(fuzzer.rules[pattern]).to eq(['bar'])
|
51
|
-
end
|
52
|
-
|
53
|
-
context "when given Symbols" do
|
54
|
-
subject { described_class.new(pattern => :bad_strings) }
|
55
|
-
|
56
|
-
it "should map to an Enumerator for a Fuzzing method" do
|
57
|
-
expect(subject.rules[pattern]).to be_kind_of(Enumerable)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
context "otherwise" do
|
62
|
-
it "should raise a TypeError" do
|
63
|
-
expect {
|
64
|
-
subject.new(pattern => Object.new)
|
65
|
-
}.to raise_error(TypeError)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
describe "#each" do
|
72
|
-
let(:string) { "foo bar" }
|
73
|
-
|
74
|
-
subject { described_class.new(/o/ => ['0'], /a/ => ['@']) }
|
75
|
-
|
76
|
-
it "should apply every combination of mutation rules" do
|
77
|
-
expect(subject.each(string).to_a).to match_array([
|
78
|
-
"f0o bar",
|
79
|
-
"fo0 bar",
|
80
|
-
"f00 bar",
|
81
|
-
"foo b@r",
|
82
|
-
"f0o b@r",
|
83
|
-
"fo0 b@r",
|
84
|
-
"f00 b@r"
|
85
|
-
])
|
86
|
-
end
|
87
|
-
|
88
|
-
context "when mutations contain Integers" do
|
89
|
-
subject { described_class.new(/o/ => [48]) }
|
90
|
-
|
91
|
-
it "should convert them to characters" do
|
92
|
-
expect(subject.each(string).to_a).to match_array([
|
93
|
-
"f0o bar",
|
94
|
-
"fo0 bar",
|
95
|
-
"f00 bar"
|
96
|
-
])
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
context "when mutations contain Procs" do
|
101
|
-
subject { described_class.new(/o/ => [lambda { |str| str.upcase }]) }
|
102
|
-
|
103
|
-
it "should call them with the matched String" do
|
104
|
-
expect(subject.each(string).to_a).to match_array([
|
105
|
-
"fOo bar",
|
106
|
-
"foO bar",
|
107
|
-
"fOO bar"
|
108
|
-
])
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
data/spec/repeater_spec.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ronin/fuzzing/repeater'
|
3
|
-
|
4
|
-
describe Ronin::Fuzzing::Repeater do
|
5
|
-
describe "#initialize" do
|
6
|
-
subject { described_class }
|
7
|
-
|
8
|
-
context "when lengths is an Integer" do
|
9
|
-
it "should coerce lengths to an Enumerable" do
|
10
|
-
repeator = subject.new(10)
|
11
|
-
|
12
|
-
expect(repeator.lengths).to be_kind_of(Enumerable)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context "when lengths is not Enumerable or an Integer" do
|
17
|
-
it "should raise a TypeError" do
|
18
|
-
expect {
|
19
|
-
subject.new(Object.new)
|
20
|
-
}.to raise_error(TypeError)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "#each" do
|
26
|
-
let(:repeatable) { 'A' }
|
27
|
-
|
28
|
-
context "when lengths was an Integer" do
|
29
|
-
let(:length) { 10 }
|
30
|
-
|
31
|
-
subject { described_class.new(length) }
|
32
|
-
|
33
|
-
it "should yield one repeated value" do
|
34
|
-
values = subject.each(repeatable).to_a
|
35
|
-
|
36
|
-
expect(values).to eq([repeatable * length])
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context "when lengths was Enumerable" do
|
41
|
-
let(:lengths) { (1..4) }
|
42
|
-
|
43
|
-
subject { described_class.new(lengths) }
|
44
|
-
|
45
|
-
it "should yield repeated values for each length" do
|
46
|
-
values = subject.each(repeatable).to_a
|
47
|
-
|
48
|
-
expect(values).to eq([
|
49
|
-
repeatable * 1,
|
50
|
-
repeatable * 2,
|
51
|
-
repeatable * 3,
|
52
|
-
repeatable * 4
|
53
|
-
])
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/spec/spec_helper.rb
DELETED
data/spec/template_spec.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ronin/fuzzing/template'
|
3
|
-
|
4
|
-
describe Ronin::Fuzzing::Template do
|
5
|
-
subject { described_class }
|
6
|
-
|
7
|
-
it "should generate Strings from CharSets" do
|
8
|
-
strings = subject.new([:lowercase_hexadecimal, :numeric]).to_a
|
9
|
-
|
10
|
-
expect(strings.grep(/^[0-9a-f][0-9]$/)).to eq(strings)
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should generate Strings from lengths of CharSets" do
|
14
|
-
strings = subject.new([[:numeric, 2]]).to_a
|
15
|
-
|
16
|
-
expect(strings.grep(/^[0-9]{2}$/)).to eq(strings)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should generate Strings from varying lengths of CharSets" do
|
20
|
-
strings = subject.new([[:numeric, 1..2]]).to_a
|
21
|
-
|
22
|
-
expect(strings.grep(/^[0-9]{1,2}$/)).to eq(strings)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should generate Strings from custom CharSets" do
|
26
|
-
strings = subject.new([[%w[a b c], 2]]).to_a
|
27
|
-
|
28
|
-
expect(strings.grep(/^[abc]{2}$/)).to eq(strings)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should generate Strings containing known Strings" do
|
32
|
-
strings = subject.new(['foo', [%w[a b c], 2]]).to_a
|
33
|
-
|
34
|
-
expect(strings.grep(/^foo[abc]{2}$/)).to eq(strings)
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should raise a TypeError for non String, Symbol, Enumerable CharSets" do
|
38
|
-
expect {
|
39
|
-
subject.new([[Object.new, 2]]).to_a
|
40
|
-
}.to raise_error(TypeError)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "should raise an ArgumentError for unknown CharSets" do
|
44
|
-
expect {
|
45
|
-
subject.new([[:foo_bar, 2]]).to_a
|
46
|
-
}.to raise_error(ArgumentError)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should raise a TypeError for non Integer,Array,Range lengths" do
|
50
|
-
expect {
|
51
|
-
subject.new([[:numeric, 'foo']]).to_a
|
52
|
-
}.to raise_error(TypeError)
|
53
|
-
end
|
54
|
-
end
|