ronin-fuzzer 0.1.0.beta1 → 0.1.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9564e6b05be69b5d8ca409a2a8c95f831727c3319f71303c477b2f60080b4592
4
- data.tar.gz: de9f24233b6435549ea06c5ec7db4211c432fe77313af905482edd444ce09764
3
+ metadata.gz: fde32c033540f388c627ee8b3eb89ecaddfb9b7295b54c74c238e2428ae79920
4
+ data.tar.gz: cf340e17d54ad2eb0176769ead999b1e0860fd7008878499411504c3556b844a
5
5
  SHA512:
6
- metadata.gz: 7350b4af7a680571e4dd1674cdd7e064248a6028e3aac0836077cc8730ceb52feb7f065d39c2b0654dcf951b5773a8f237823ec7a94fe58c36ef3707ea4369d3
7
- data.tar.gz: 23488e361a02a84dd0bcb332289cbf7b0c94949b6dfa6698a23771bb507c361c790e5f6c0aa079291c74b7ecb91eb738c5f4077cd12f4359f46923117c6c02e9
6
+ metadata.gz: 45d00600b8480887e556b8fc17eafbc6398faa0d7fdf8c9a165e8e98a78d0ea21ec9f6f99e83616eff9425b3de1ced9e9de038f3e09ab9a6b90c51f78993c227
7
+ data.tar.gz: fbdc37d64734e0ee7448e23071367786b044a4e937b8b6cc4f296ce85c73e64f02a19bb3c5d014fdc7c94de79640f81ca58aea6c7c06e81b0f4a15c09a407c74
@@ -21,6 +21,7 @@ jobs:
21
21
  uses: ruby/setup-ruby@v1
22
22
  with:
23
23
  ruby-version: ${{ matrix.ruby }}
24
+ bundler-cache: true
24
25
  - name: Install libsqlite3
25
26
  run: |
26
27
  sudo apt update -y && \
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![CI](https://github.com/ronin-rb/ronin-fuzzer/actions/workflows/ruby.yml/badge.svg)](https://github.com/ronin-rb/ronin-fuzzer/actions/workflows/ruby.yml)
4
4
  [![Code Climate](https://codeclimate.com/github/ronin-rb/ronin-fuzzer.svg)](https://codeclimate.com/github/ronin-rb/ronin-fuzzer)
5
+ [![Gem Version](https://badge.fury.io/rb/ronin-fuzzer.svg)](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 data.
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-2022 Hal Brodigan (postmodern.mod3@gmail.com)
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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: generate, mutate, and fuzz data
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://rubydoc.info/gems/ronin-fuzzer
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/master/ChangeLog.md
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
@@ -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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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/fuzzer/repeater'
24
- require 'ronin/fuzzer/fuzzer'
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 Fuzzing rules.
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: Hash[String => String],
77
+ type: String,
72
78
  usage: '[PATTERN|/REGEXP/|STRING]:[METHOD|STRING*N[-M]]'
73
79
  },
74
- desc: 'Fuzzing rules'
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
- # Sets up the fuzz command.
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
- unless options[:rules]
202
+ if @rules.empty?
124
203
  print_error "Must specify at least one fuzzing rule"
125
- exit -1
204
+ exit(-1)
126
205
  end
127
206
 
128
- rules = Hash[options[:rules].map { |pattern,substitution|
129
- [parse_pattern(pattern), parse_substitution(substitution)]
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
- data = if options[:input] then File.read(options[:input])
147
- else $stdin.read
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
- method = if options[:output]
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
- private
169
-
170
- include Shellwords
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 = "#{@file_name}-#{index}#{@file_ext}"
250
+ path = output_path(index)
183
251
 
184
- print_info "Creating file ##{index}: #{path} ..."
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
- print_info "Running command #{index}: #{arguments.join(' ')} ..."
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
- print_error "Process ##{status.pid} coredumped!"
291
+ log_error "Process ##{status.pid} coredumped!"
224
292
  else
225
293
  # process errored out
226
- print_warning "Process ##{status.pid} exited with status #{status.exitstatus}"
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
- print_debug "Connecting to #{@host}:#{@port} ..."
243
- socket = @socket_class.new(@host,@port)
310
+ log_debug "Connecting to #{@host}:#{@port} ..."
244
311
 
245
- print_info "Sending message ##{index}: #{string.inspect} ..."
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
- print_debug "Disconnecting from #{@host}:#{@port} ..."
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
- print_debug "String ##{index} ..."
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 (Regexp.const_defined?(const) &&
285
- Regexp.const_get(const).kind_of?(Regexp))
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
- Fuzzer::Repeater.new(lengths).each(string)
433
+ Fuzzing::Repeater.new(lengths).each(string)
317
434
  else
318
- Fuzzer[string]
435
+ Fuzzing[string]
319
436
  end
320
437
  end
321
438
 
@@ -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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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.beta1'
25
+ VERSION = '0.1.0.beta2'
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
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
  #
@@ -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 ocurrences of \fB#string#\fR
57
- will be replaced with the fuzzed data, and ocurrences of \fB#path#\fR will
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
@@ -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 ocurrences of `#string#`
44
- will be replaced with the fuzzed data, and ocurrences of `#path#` will
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.beta1
4
+ version: 0.1.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-01 00:00:00.000000000 Z
11
+ date: 2023-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: combinatorics
@@ -66,9 +66,9 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.0'
69
- description: 'A Ruby library for generating, mutating, and fuzzing data.
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://rubydoc.info/gems/ronin-fuzzer
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/master/ChangeLog.md
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: generate, mutate, and fuzz data
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
@@ -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
@@ -1,4 +0,0 @@
1
- require 'rspec'
2
- require 'simplecov'
3
-
4
- SimpleCov.start
@@ -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