Class: Ronin::Fuzzer::CLI::Commands::Fuzz
- Inherits:
-
Ronin::Fuzzer::CLI::Command
- Object
- Core::CLI::Command
- Ronin::Fuzzer::CLI::Command
- Ronin::Fuzzer::CLI::Commands::Fuzz
- Includes:
- Core::CLI::Logging
- Defined in:
- lib/ronin/fuzzer/cli/commands/fuzz.rb
Overview
Performs basic fuzzing of files, commands or TCP/UDP services.
Usage
ronin-fuzzer fuzz [options]
Options
-v, --[no-]verbose Enable verbose output.
-q, --[no-]quiet Disable verbose output.
--[no-]silent Silence all output.
-r [[PATTERN|/REGEXP/]:[METHOD|STRING*N[-M]]],
--rule Adds a fuzzing rule.
-i, --input [FILE] Input file to fuzz.
-o, --output [FILE] Output file path.
-c [PROGRAM [OPTIONS|#string#|#path#] ...],
--command Template command to run.
-t, --tcp [HOST:PORT] TCP service to fuzz.
-u, --udp [HOST:PORT] UDP service to fuzz.
-p, --pause [SECONDS] Pause in between mutations.
Examples
ronin-fuzzer fuzz -i request.txt -r unix_path:bad_strings -o bad.txt
Instance Attribute Summary collapse
-
#command ⇒ String?
readonly
The command template to execute.
-
#host ⇒ String?
readonly
The host name to send fuzzing data to.
-
#mode ⇒ :output, ...
readonly
The execution mode to run the fuzzer in.
-
#output ⇒ String?
readonly
The output file template.
-
#output_ext ⇒ String?
readonly
The output file extension.
-
#output_name ⇒ String?
readonly
The output file name.
-
#port ⇒ Integer?
readonly
The port to send fuzzing data to.
-
#rules ⇒ Array<(Regexp, Enumerator)>
readonly
The fuzzing rules.
Instance Method Summary collapse
-
#fuzz_command(string, index) ⇒ Object
Runs the fuzzed string in a command.
-
#fuzz_file(string, index) ⇒ Object
Writes the fuzzed string to a file.
-
#fuzz_network(string, index) ⇒ Object
Sends the fuzzed string to a TCP/UDP Service.
-
#initialize(**kwargs) ⇒ Fuzz
constructor
Initializes the
ronin-fuzzer fuzz
command. -
#output_path(index) ⇒ String
Creates a new output path for the given index.
-
#parse_host_port(value) ⇒ (String, Integer)
Parses the host and port from the value.
-
#parse_pattern(string) ⇒ Regexp, String
Parses a fuzz pattern.
-
#parse_rule(value) ⇒ (Regexp, Enumerator)
Parses a fuzzing rule.
-
#parse_substitution(string) ⇒ Enumerator
Parses a fuzz substitution Enumerator.
-
#print_fuzz(string, index) ⇒ Object
Prints the fuzzed string to STDOUT.
-
#run ⇒ Object
Runs the
ronin-fuzzer fuzz
command.
Constructor Details
#initialize(**kwargs) ⇒ Fuzz
Initializes the ronin-fuzzer fuzz
command.
192 193 194 195 196 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 192 def initialize(**kwargs) super(**kwargs) @rules = [] end |
Instance Attribute Details
#command ⇒ String? (readonly)
The command template to execute.
169 170 171 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 169 def command @command end |
#host ⇒ String? (readonly)
The host name to send fuzzing data to.
174 175 176 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 174 def host @host end |
#mode ⇒ :output, ... (readonly)
The execution mode to run the fuzzer in.
149 150 151 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 149 def mode @mode end |
#output ⇒ String? (readonly)
The output file template.
154 155 156 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 154 def output @output end |
#output_ext ⇒ String? (readonly)
The output file extension.
159 160 161 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 159 def output_ext @output_ext end |
#output_name ⇒ String? (readonly)
The output file name.
164 165 166 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 164 def output_name @output_name end |
#port ⇒ Integer? (readonly)
The port to send fuzzing data to.
179 180 181 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 179 def port @port end |
#rules ⇒ Array<(Regexp, Enumerator)> (readonly)
The fuzzing rules.
184 185 186 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 184 def rules @rules end |
Instance Method Details
#fuzz_command(string, index) ⇒ Object
Runs the fuzzed string in a command.
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 268 def fuzz_command(string,index) Tempfile.open("ronin-fuzzer-#{index}") do |tempfile| tempfile.write(string) tempfile.flush arguments = @command.map do |argument| if argument.include?('#path#') argument.sub('#path#',tempfile.path) elsif argument.include?('#string#') argument.sub('#string#',string) else argument end end log_info "Running command #{index}: #{arguments.join(' ')} ..." # run the command as it's own process unless system(*arguments) status = $? if status.coredump? # jack pot! log_error "Process ##{status.pid} coredumped!" else # process errored out log_warning "Process ##{status.pid} exited with status #{status.exitstatus}" end end end end |
#fuzz_file(string, index) ⇒ Object
Writes the fuzzed string to a file.
249 250 251 252 253 254 255 256 257 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 249 def fuzz_file(string,index) path = output_path(index) log_info "Creating file ##{index}: #{path} ..." File.open(path,'wb') do |file| file.write string end end |
#fuzz_network(string, index) ⇒ Object
Sends the fuzzed string to a TCP/UDP Service.
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 309 def fuzz_network(string,index) log_debug "Connecting to #{@host}:#{@port} ..." socket = case @mode when :tcp then TCPSocket.new(@host,@port) when :udp then UDPSocket.new(@host,@port) end log_info "Sending message ##{index}: #{string.inspect} ..." socket.write(string) socket.flush log_debug "Disconnecting from #{@host}:#{@port} ..." socket.close end |
#output_path(index) ⇒ String
Creates a new output path for the given index.
236 237 238 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 236 def output_path(index) "#{@output_name}-#{index}#{@output_ext}" end |
#parse_host_port(value) ⇒ (String, Integer)
Parses the host and port from the value.
349 350 351 352 353 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 349 def parse_host_port(value) host, port = value.split(':',2) return host, port.to_i end |
#parse_pattern(string) ⇒ Regexp, String
Parses a fuzz pattern.
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 395 def parse_pattern(string) case string when /^\/.+\/$/ Regexp.new(string[1..-2]) when /^[a-z][a-z_]+$/ const = string.upcase if Support::Text::Patterns.const_defined?(const,false) Support::Text::Patterns.const_get(const,false) else string end else string end end |
#parse_rule(value) ⇒ (Regexp, Enumerator)
Parses a fuzzing rule.
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 364 def parse_rule(value) if value.start_with?('/') unless (index = value.rindex('/:')) raise(OptionParser::InvalidArgument,"argument must be of the form /REGEXP/:REPLACE, but was: #{value}") end regexp = parse_pattern(value[1...index]) substitution = parse_substitution(value[index+2..]) return [regexp, substitution] else unless (index = value.rindex(':')) raise(OptionParser::InvalidArgument,"argument must be of the form STRING:STYLE but was: #{value}") end pattern = parse_pattern(value[0...index]) substitution = parse_substitution(value[index+1..]) return [pattern, substitution] end end |
#parse_substitution(string) ⇒ Enumerator
Parses a fuzz substitution Enumerator.
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 421 def parse_substitution(string) if string.include?('*') string, lengths = string.split('*',2) lengths = if lengths.include?('-') min, max = lengths.split('-',2) (min.to_i .. max.to_i) else lengths.to_i end Fuzzing::Repeater.new(lengths).each(string) else Fuzzing[string] end end |
#print_fuzz(string, index) ⇒ Object
Prints the fuzzed string to STDOUT.
334 335 336 337 338 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 334 def print_fuzz(string,index) log_debug "String ##{index} ..." puts string end |
#run ⇒ Object
Runs the ronin-fuzzer fuzz
command.
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/ronin/fuzzer/cli/commands/fuzz.rb', line 201 def run if @rules.empty? print_error "Must specify at least one fuzzing rule" exit(-1) end data = if [:input] then File.read([:input]) else $stdin.read end method = case @mode when :output then method(:fuzz_file) when :command then method(:fuzz_command) when :tcp, :udp then method(:fuzz_network) else method(:print_fuzz) end fuzzer = Fuzzing::Fuzzer.new(@rules) fuzzer.each(data).each_with_index do |string,index| method.call(string,index + 1) sleep(@pause) if @pause end end |