Class: Ronin::UI::CLI::Commands::Fuzzer

Inherits:
Ronin::UI::CLI::Command show all
Includes:
Shellwords
Defined in:
lib/ronin/ui/cli/commands/fuzzer.rb

Overview

Performs basic fuzzing of files, commands or TCP/UDP services.

Usage

ronin fuzzer [options]

Options

-v, --[no-]verbose Enable verbose output. -q, --[no-]quiet Disable verbose output. --[no-]silent Silence all output. --[no-]color Enables color output. Default: true -r [[PATTERN|/REGEXP/]:[METHOD|STRING*N[-M]]], --rule Fuzzing rules. -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.

Examples

ronin fuzzer -i request.txt -r unix_path:bad_strings -o bad.txt

Since:

Instance Method Summary (collapse)

Methods inherited from Ronin::UI::CLI::Command

argument, arguments, arguments?, #cleanup, command_name, each_argument, each_option, examples, #initialize, option, #option_parser, options, options?, run, #run, #start, start, summary, usage

Methods included from Printing

#indent, #initialize, #print_array, #print_hash, #print_section, #print_title, #puts

Constructor Details

This class inherits a constructor from Ronin::UI::CLI::Command

Instance Method Details

- (Object) execute

Since:

  • 1.5.0



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/ronin/ui/cli/commands/fuzzer.rb', line 129

def execute
  data   = if input? then File.read(@input)
           else           $stdin.read
           end

  method = if    output?        then method(:fuzz_file)
           elsif command?       then method(:fuzz_command)
           elsif (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|
    index = index + 1

    method.call(string,index)
  end
end

- (Object) fuzz_command(string, index) (protected)

Runs the fuzzed string in a command.

Parameters:

  • string (String)

    The fuzzed string.

  • index (Integer)

    The iteration number.

Since:

  • 1.5.0



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/ronin/ui/cli/commands/fuzzer.rb', line 180

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

    print_info "Running command #{index}: #{arguments.join(' ')} ..."

    # run the command as it's own process
    unless system(*arguments)
      status = $?

      if status.coredump?
        # jack pot!
        print_error "Process ##{status.pid} coredumped!"
      else
        # process errored out
        print_warning "Process ##{status.pid} exited with status #{status.exitstatus}"
      end
    end
  end
end

- (Object) fuzz_file(string, index) (protected)

Writes the fuzzed string to a file.

Parameters:

  • string (String)

    The fuzzed string.

  • index (Integer)

    The iteration number.

Since:

  • 1.5.0



161
162
163
164
165
166
167
168
169
# File 'lib/ronin/ui/cli/commands/fuzzer.rb', line 161

def fuzz_file(string,index)
  path = "#{@file_name}-#{index}#{@file_ext}"

  print_info "Creating file ##{index}: #{path} ..."

  File.open(path,'wb') do |file|
    file.write string
  end
end

- (Object) fuzz_network(string, index) (protected)

Sends the fuzzed string to a TCP/UDP Service.

Parameters:

  • string (String)

    The fuzzed string.

  • index (Integer)

    The iteration number.

Since:

  • 1.5.0



221
222
223
224
225
226
227
228
229
230
231
# File 'lib/ronin/ui/cli/commands/fuzzer.rb', line 221

def fuzz_network(string,index)
  print_debug "Connecting to #{@host}:#{@port} ..."
  socket = @socket_class.new(@host,@port)

  print_info "Sending message ##{index}: #{string.inspect} ..."
  socket.write(string)
  socket.flush

  print_debug "Disconnecting from #{@host}:#{@port} ..."
  socket.close
end

- (Regexp, String) parse_pattern(string) (protected)

Parses a fuzz pattern.

Parameters:

  • string (String)

    The string to parse.

Returns:

  • (Regexp, String)

    The parsed pattern.

Since:

  • 1.5.0



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/ronin/ui/cli/commands/fuzzer.rb', line 257

def parse_pattern(string)
  case string
  when /^\/.+\/$/
    Regexp.new(string[1..-2])
  when /^[a-z][a-z_]+$/
    const = string.upcase

    if (Regexp.const_defined?(const) &&
        Regexp.const_get(const).kind_of?(Regexp))
      Regexp.const_get(const)
    else
      string
    end
  else
    string
  end
end

- (Enumerator) parse_substitution(string) (protected)

Parses a fuzz substitution Enumerator.

Parameters:

  • string (String)

    The string to parse.

Returns:

  • (Enumerator)

    The parsed substitution Enumerator.

Since:

  • 1.5.0



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/ronin/ui/cli/commands/fuzzer.rb', line 284

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

Prints the fuzzed string to STDOUT.

Parameters:

  • string (String)

    The fuzzed string.

  • index (Integer)

    The iteration number.

Since:

  • 1.5.0



242
243
244
245
246
# File 'lib/ronin/ui/cli/commands/fuzzer.rb', line 242

def print_fuzz(string,index)
  print_debug "String ##{index} ..."

  puts string
end

- (Object) setup

Sets up the fuzz command.

Since:

  • 1.5.0



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/ronin/ui/cli/commands/fuzzer.rb', line 102

def setup
  super

  unless rules?
    print_error "Must specify at least one fuzzing rule"
    exit -1
  end

  @rules = Hash[@rules.map { |pattern,substitution|
    [parse_pattern(pattern), parse_substitution(substitution)]
  }]

  if output?
    @file_ext  = File.extname(@output)
    @file_name = @file.chomp(@file_ext)
  elsif command?
    @command = shellwords(@command)
  elsif (tcp? || udp?)
    @socket_class = if    tcp? then TCPSocket
                    elsif udp? then UDPSocket
                    end

    @host, @port = (@tcp || @udp).split(':',2)
    @port = @port.to_i
  end
end