ronin 1.5.0.rc2 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- ### 1.5.0 / 2012-05-28
1
+ ### 1.5.0 / 2012-06-16
2
2
 
3
3
  * Require ronin-support ~> 0.5.
4
4
  * Added {Ronin::UI::CLI::Command#setup}.
data/Gemfile CHANGED
@@ -23,8 +23,7 @@ gem 'jruby-openssl', '~> 0.7', :platforms => :jruby
23
23
  # gem 'dm-timestamps', DM_VERSION, :git => "#{DM_URI}/dm-timestamps.git"
24
24
 
25
25
  # Library dependencies
26
- # gem 'ronin-support', '~> 0.5.0.rc1', :git => "#{RONIN_URI}/ronin-support.git",
27
- # :branch => '0.5.0'
26
+ # gem 'ronin-support', '~> 0.5', :git => "#{RONIN_URI}/ronin-support.git"
28
27
 
29
28
  group :development do
30
29
  gem 'rake', '~> 0.8'
data/README.md CHANGED
@@ -109,6 +109,10 @@ View available commands:
109
109
 
110
110
  $ ronin help
111
111
 
112
+ View a man-page for a command:
113
+
114
+ $ ronin help wordlist
115
+
112
116
  Install a Repository:
113
117
 
114
118
  $ ronin install svn://example.com/path/to/repo
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+
5
+ root_dir = File.expand_path(File.join(File.dirname(__FILE__),'..'))
6
+ if File.directory?(File.join(root_dir,'.git'))
7
+ Dir.chdir(root_dir) do |path|
8
+ require 'bundler'
9
+
10
+ begin
11
+ Bundler.setup(:default)
12
+ rescue Bundler::BundlerError => e
13
+ warn e.message
14
+ warn "Run `bundle install` to install missing gems"
15
+ exit e.status_code
16
+ end
17
+ end
18
+ end
19
+
20
+ lib_dir = File.join(root_dir,'lib')
21
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
22
+
23
+ require 'ronin/ui/cli/commands/fuzzer'
24
+
25
+ Ronin::UI::CLI::Commands::Fuzzer.start
@@ -8,7 +8,7 @@ description:
8
8
  license: GPL-3
9
9
  authors: Postmodern
10
10
  email: postmodern.mod3@gmail.com
11
- homepage: http://github.com/ronin-ruby/ronin
11
+ homepage: http://ronin-ruby.github.com/
12
12
  has_yard: true
13
13
  post_install_message: |
14
14
  *************************************************************************
@@ -41,6 +41,7 @@ generated_files:
41
41
  - man/ronin-database.1
42
42
  - man/ronin-emails.1
43
43
  - man/ronin-exec.1
44
+ - man/ronin-fuzzer.1
44
45
  - man/ronin-help.1
45
46
  - man/ronin-hosts.1
46
47
  - man/ronin-install.1
@@ -80,7 +81,7 @@ dependencies:
80
81
  ripl-short_errors: ~> 0.1
81
82
  ripl-color_result: ~> 0.3
82
83
  # Ronin dependencies:
83
- ronin-support: ~> 0.5.0.rc2
84
+ ronin-support: ~> 0.5
84
85
 
85
86
  development_dependencies:
86
87
  bundler: ~> 1.0
@@ -25,6 +25,8 @@ module Ronin
25
25
  # When included into other namespaces, it allows for auto-loading Classes
26
26
  # or Modules via {ClassMethods#const_missing}.
27
27
  #
28
+ # @api semipublic
29
+ #
28
30
  # @since 1.1.0
29
31
  #
30
32
  module AutoLoad
@@ -212,7 +212,7 @@ module Ronin
212
212
  # @api semipublic
213
213
  #
214
214
  def upto(position_or_name=nil)
215
- return enum_for(:upto,position_or_name) unless block_given?
215
+ return enum_for(__method__,position_or_name) unless block_given?
216
216
 
217
217
  name = name_of(position_or_name)
218
218
 
@@ -250,7 +250,7 @@ module Ronin
250
250
  # @api semipublic
251
251
  #
252
252
  def downto(position_or_name=nil)
253
- return enum_for(:downto,position_or_name) unless block_given?
253
+ return enum_for(__method__,position_or_name) unless block_given?
254
254
 
255
255
  name = name_of(position_or_name)
256
256
 
@@ -76,7 +76,7 @@ module Ronin
76
76
  # @api public
77
77
  #
78
78
  def self.extract(text)
79
- return enum_for(:extract,text).to_a unless block_given?
79
+ return enum_for(__method__,text).to_a unless block_given?
80
80
 
81
81
  scanner = StringScanner.new(text)
82
82
 
@@ -83,7 +83,7 @@ module Ronin
83
83
  # @api public
84
84
  #
85
85
  def self.extract(text)
86
- return enum_for(:extract,text).to_a unless block_given?
86
+ return enum_for(__method__,text).to_a unless block_given?
87
87
 
88
88
  scanner = StringScanner.new(text)
89
89
 
@@ -39,7 +39,7 @@ module Ronin
39
39
  #
40
40
  # @api semipublic
41
41
  #
42
- def Installation.gems
42
+ def self.gems
43
43
  load! if @gems.empty?
44
44
  return @gems
45
45
  end
@@ -54,7 +54,7 @@ module Ronin
54
54
  #
55
55
  # @api semipublic
56
56
  #
57
- def Installation.paths
57
+ def self.paths
58
58
  load! if @paths.empty?
59
59
  return @paths
60
60
  end
@@ -69,7 +69,7 @@ module Ronin
69
69
  #
70
70
  # @api semipublic
71
71
  #
72
- def Installation.libraries
72
+ def self.libraries
73
73
  gems.keys
74
74
  end
75
75
 
@@ -93,8 +93,8 @@ module Ronin
93
93
  #
94
94
  # @api semipublic
95
95
  #
96
- def Installation.each_file(pattern)
97
- return enum_for(:each_file,pattern) unless block_given?
96
+ def self.each_file(pattern)
97
+ return enum_for(__method__,pattern) unless block_given?
98
98
 
99
99
  # query the installed gems
100
100
  paths.each do |gem_path|
@@ -130,16 +130,16 @@ module Ronin
130
130
  #
131
131
  # @api semipublic
132
132
  #
133
- def Installation.each_file_in(directory,ext=nil)
134
- return enum_for(:each_file_in,directory,ext) unless block_given?
133
+ def self.each_file_in(directory,ext=nil)
134
+ return enum_for(__method__,directory,ext) unless block_given?
135
+
136
+ directory = File.join(directory,File::SEPARATOR)
135
137
 
136
138
  pattern = File.join(directory,'**','*')
137
139
  pattern << ".#{ext}" if ext
138
140
 
139
- slice_index = directory.length + 1
140
-
141
141
  each_file(pattern) do |path|
142
- yield path[slice_index..-1]
142
+ yield path.sub(directory,'')
143
143
  end
144
144
  end
145
145
 
@@ -155,7 +155,7 @@ module Ronin
155
155
  #
156
156
  # @api private
157
157
  #
158
- def Installation.load_gems!
158
+ def self.load_gems!
159
159
  register_gem = lambda { |gem|
160
160
  @gems[gem.name] = gem
161
161
  @paths << gem.full_gem_path
@@ -184,7 +184,7 @@ module Ronin
184
184
  #
185
185
  # @api private
186
186
  #
187
- def Installation.load_gemspecs!
187
+ def self.load_gemspecs!
188
188
  $LOAD_PATH.each do |lib_dir|
189
189
  root_dir = File.expand_path(File.join(lib_dir,'..'))
190
190
  gemspec_path = Dir[File.join(root_dir,'ronin*.gemspec')][0]
@@ -216,7 +216,7 @@ module Ronin
216
216
  #
217
217
  # @api private
218
218
  #
219
- def Installation.load!
219
+ def self.load!
220
220
  if Gem.loaded_specs.has_key?('ronin')
221
221
  load_gems!
222
222
  else
@@ -98,7 +98,7 @@ module Ronin
98
98
  # @api public
99
99
  #
100
100
  def self.extract(text,version=nil)
101
- return enum_for(:extract,text,version).to_a unless block_given?
101
+ return enum_for(__method__,text,version).to_a unless block_given?
102
102
 
103
103
  IPAddr.extract(text,version) do |ip|
104
104
  yield parse(ip)
@@ -64,7 +64,7 @@ module Ronin
64
64
  # @api public
65
65
  #
66
66
  def self.extract(text)
67
- return enum_for(:extract,text).to_a unless block_given?
67
+ return enum_for(__method__,text).to_a unless block_given?
68
68
 
69
69
  scanner = StringScanner.new(text)
70
70
 
@@ -49,7 +49,7 @@ module Ronin
49
49
  # @api public
50
50
  #
51
51
  def import(path)
52
- return enum_for(:import,path).to_a unless block_given?
52
+ return enum_for(__method__,path).to_a unless block_given?
53
53
 
54
54
  File.open(path) do |file|
55
55
  file.each_line do |line|
@@ -475,7 +475,7 @@ module Ronin
475
475
  # @api private
476
476
  #
477
477
  def each_script(&block)
478
- return enum_for(:each_script) unless block
478
+ return enum_for(__method__) unless block
479
479
 
480
480
  @script_dirs.each do |dir|
481
481
  Pathname.glob(dir.join('**','*.rb'),&block)
@@ -94,8 +94,9 @@ module Ronin
94
94
  #
95
95
  def CLI.command(name)
96
96
  name = name.to_s
97
+ path = name.tr(':','/')
97
98
 
98
- unless (command = Commands.require_const(name))
99
+ unless (command = Commands.require_const(path))
99
100
  raise(UnknownCommand,"unable to load the command #{name.dump}",caller)
100
101
  end
101
102
 
@@ -471,7 +471,7 @@ module Ronin
471
471
  # @api private
472
472
  #
473
473
  def self.each_option(&block)
474
- return enum_for(:each_option) unless block
474
+ return enum_for(__method__) unless block
475
475
 
476
476
  ancestors.reverse_each do |ancestor|
477
477
  if ancestor <= Command
@@ -557,7 +557,7 @@ module Ronin
557
557
  # @api semipublic
558
558
  #
559
559
  def self.each_argument(&block)
560
- return enum_for(:each_argument) unless block
560
+ return enum_for(__method__) unless block
561
561
 
562
562
  ancestors.reverse_each do |ancestor|
563
563
  if ancestor <= Command
@@ -121,12 +121,9 @@ module Ronin
121
121
  return
122
122
  end
123
123
 
124
- if add?
125
- add_repository
126
- elsif set?
127
- set_repository
128
- elsif delete?
129
- delete_repository
124
+ if add? then add_repository
125
+ elsif set? then set_repository
126
+ elsif remove? then remove_repository
130
127
  else
131
128
  Ronin::Database.repositories.each do |name,uri|
132
129
  print_hash uri, :title => name
@@ -174,7 +171,7 @@ module Ronin
174
171
  def set_repository
175
172
  unless Ronin::Database.repository?(@set)
176
173
  print_error "Unknown Database repository #{@set}"
177
- return
174
+ exit -1
178
175
  end
179
176
 
180
177
  Ronin::Database.save do
@@ -190,7 +187,7 @@ module Ronin
190
187
  def remove_repository
191
188
  unless Ronin::Database.repository?(@remove)
192
189
  print_error "Unknown Database repository #{@remove}"
193
- return
190
+ exit -1
194
191
  end
195
192
 
196
193
  Ronin::Database.save do
@@ -0,0 +1,306 @@
1
+ #
2
+ # Copyright (c) 2006-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
3
+ #
4
+ # This file is part of Ronin.
5
+ #
6
+ # Ronin is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Ronin is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Ronin. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+
20
+ require 'ronin/ui/cli/command'
21
+ require 'ronin/fuzzing/repeater'
22
+ require 'ronin/fuzzing/fuzzer'
23
+
24
+ require 'shellwords'
25
+ require 'tempfile'
26
+ require 'socket'
27
+
28
+ module Ronin
29
+ module UI
30
+ module CLI
31
+ module Commands
32
+ #
33
+ # Performs basic fuzzing of files, commands or TCP/UDP services.
34
+ #
35
+ # ## Usage
36
+ #
37
+ # ronin fuzzer [options]
38
+ #
39
+ # ## Options
40
+ #
41
+ # -v, --[no-]verbose Enable verbose output.
42
+ # -q, --[no-]quiet Disable verbose output.
43
+ # --[no-]silent Silence all output.
44
+ # --[no-]color Enables color output.
45
+ # Default: true
46
+ # -r [[PATTERN|/REGEXP/]:[METHOD|STRING*N[-M]]],
47
+ # --rule Fuzzing rules.
48
+ # -i, --input [FILE] Input file to fuzz.
49
+ # -o, --output [FILE] Output file path.
50
+ # -c [PROGRAM [OPTIONS|#string#|#path#] ...],
51
+ # --command Template command to run.
52
+ # -t, --tcp [HOST:PORT] TCP service to fuzz.
53
+ # -u, --udp [HOST:PORT] UDP service to fuzz.
54
+ #
55
+ # ## Examples
56
+ #
57
+ # ronin fuzzer -i request.txt -r unix_path:bad_strings -o bad.txt
58
+ #
59
+ # @since 1.5.0
60
+ #
61
+ class Fuzzer < Command
62
+
63
+ summary 'Performs basic fuzzing of files'
64
+
65
+ option :input, :type => String,
66
+ :flag => '-i',
67
+ :usage => 'FILE',
68
+ :description => 'Input file to fuzz'
69
+
70
+ option :rules, :type => Hash[String => String],
71
+ :flag => '-r',
72
+ :usage => '[PATTERN|/REGEXP/|STRING]:[METHOD|STRING*N[-M]]',
73
+ :description => 'Fuzzing rules'
74
+
75
+ option :output, :type => String,
76
+ :flag => '-o',
77
+ :usgae => 'PATH',
78
+ :description => 'Output file path'
79
+
80
+ option :command, :type => String,
81
+ :flag => '-c',
82
+ :usage => 'PROGRAM [OPTIONS|#string#|#path#] ...',
83
+ :description => 'Template command to run'
84
+
85
+ option :tcp, :type => String,
86
+ :flag => '-t',
87
+ :usage => 'HOST:PORT',
88
+ :description => 'TCP service to fuzz'
89
+
90
+ option :udp, :type => String,
91
+ :flag => '-u',
92
+ :usage => 'HOST:PORT',
93
+ :description => 'UDP service to fuzz'
94
+
95
+ examples [
96
+ "ronin fuzzer -i request.txt -o bad.txt -r unix_path:bad_strings"
97
+ ]
98
+
99
+ #
100
+ # Sets up the fuzz command.
101
+ #
102
+ def setup
103
+ super
104
+
105
+ unless rules?
106
+ print_error "Must specify at least one fuzzing rule"
107
+ exit -1
108
+ end
109
+
110
+ @rules = Hash[@rules.map { |pattern,substitution|
111
+ [parse_pattern(pattern), parse_substitution(substitution)]
112
+ }]
113
+
114
+ if output?
115
+ @file_ext = File.extname(@output)
116
+ @file_name = @file.chomp(@file_ext)
117
+ elsif command?
118
+ @command = shellwords(@command)
119
+ elsif (tcp? || udp?)
120
+ @socket_class = if tcp? then TCPSocket
121
+ elsif udp? then UDPSocket
122
+ end
123
+
124
+ @host, @port = (@tcp || @udp).split(':',2)
125
+ @port = @port.to_i
126
+ end
127
+ end
128
+
129
+ def execute
130
+ data = if input? then File.read(@input)
131
+ else $stdin.read
132
+ end
133
+
134
+ method = if output? then method(:fuzz_file)
135
+ elsif command? then method(:fuzz_command)
136
+ elsif (tcp? || udp?) then method(:fuzz_network)
137
+ else method(:print_fuzz)
138
+ end
139
+
140
+ fuzzer = Fuzzing::Fuzzer.new(@rules)
141
+ fuzzer.each(data).each_with_index do |string,index|
142
+ index = index + 1
143
+
144
+ method.call(string,index)
145
+ end
146
+ end
147
+
148
+ protected
149
+
150
+ include Shellwords
151
+
152
+ #
153
+ # Writes the fuzzed string to a file.
154
+ #
155
+ # @param [String] string
156
+ # The fuzzed string.
157
+ #
158
+ # @param [Integer] index
159
+ # The iteration number.
160
+ #
161
+ def fuzz_file(string,index)
162
+ path = "#{@file_name}-#{index}#{@file_ext}"
163
+
164
+ print_info "Creating file ##{index}: #{path} ..."
165
+
166
+ File.open(path,'wb') do |file|
167
+ file.write string
168
+ end
169
+ end
170
+
171
+ #
172
+ # Runs the fuzzed string in a command.
173
+ #
174
+ # @param [String] string
175
+ # The fuzzed string.
176
+ #
177
+ # @param [Integer] index
178
+ # The iteration number.
179
+ #
180
+ def fuzz_command(string,index)
181
+ Tempfile.open("ronin-fuzzer-#{index}") do |tempfile|
182
+ tempfile.write(string)
183
+ tempfile.flush
184
+
185
+ arguments = @command.map do |argument|
186
+ if argument.include?('#path#')
187
+ argument.sub('#path#',tempfile.path)
188
+ elsif argument.include?('#string#')
189
+ argument.sub('#string#',string)
190
+ else
191
+ argument
192
+ end
193
+ end
194
+
195
+ print_info "Running command #{index}: #{arguments.join(' ')} ..."
196
+
197
+ # run the command as it's own process
198
+ unless system(*arguments)
199
+ status = $?
200
+
201
+ if status.coredump?
202
+ # jack pot!
203
+ print_error "Process ##{status.pid} coredumped!"
204
+ else
205
+ # process errored out
206
+ print_warning "Process ##{status.pid} exited with status #{status.exitstatus}"
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ #
213
+ # Sends the fuzzed string to a TCP/UDP Service.
214
+ #
215
+ # @param [String] string
216
+ # The fuzzed string.
217
+ #
218
+ # @param [Integer] index
219
+ # The iteration number.
220
+ #
221
+ def fuzz_network(string,index)
222
+ print_debug "Connecting to #{@host}:#{@port} ..."
223
+ socket = @socket_class.new(@host,@port)
224
+
225
+ print_info "Sending message ##{index}: #{string.inspect} ..."
226
+ socket.write(string)
227
+ socket.flush
228
+
229
+ print_debug "Disconnecting from #{@host}:#{@port} ..."
230
+ socket.close
231
+ end
232
+
233
+ #
234
+ # Prints the fuzzed string to STDOUT.
235
+ #
236
+ # @param [String] string
237
+ # The fuzzed string.
238
+ #
239
+ # @param [Integer] index
240
+ # The iteration number.
241
+ #
242
+ def print_fuzz(string,index)
243
+ print_debug "String ##{index} ..."
244
+
245
+ puts string
246
+ end
247
+
248
+ #
249
+ # Parses a fuzz pattern.
250
+ #
251
+ # @param [String] string
252
+ # The string to parse.
253
+ #
254
+ # @return [Regexp, String]
255
+ # The parsed pattern.
256
+ #
257
+ def parse_pattern(string)
258
+ case string
259
+ when /^\/.+\/$/
260
+ Regexp.new(string[1..-2])
261
+ when /^[a-z][a-z_]+$/
262
+ const = string.upcase
263
+
264
+ if (Regexp.const_defined?(const) &&
265
+ Regexp.const_get(const).kind_of?(Regexp))
266
+ Regexp.const_get(const)
267
+ else
268
+ string
269
+ end
270
+ else
271
+ string
272
+ end
273
+ end
274
+
275
+ #
276
+ # Parses a fuzz substitution Enumerator.
277
+ #
278
+ # @param [String] string
279
+ # The string to parse.
280
+ #
281
+ # @return [Enumerator]
282
+ # The parsed substitution Enumerator.
283
+ #
284
+ def parse_substitution(string)
285
+ if string.include?('*')
286
+ string, lengths = string.split('*',2)
287
+
288
+ lengths = if lengths.include?('-')
289
+ min, max = lengths.split('-',2)
290
+
291
+ (min.to_i .. max.to_i)
292
+ else
293
+ lengths.to_i
294
+ end
295
+
296
+ Fuzzing::Repeater.new(lengths).each(string)
297
+ else
298
+ Fuzzing[string]
299
+ end
300
+ end
301
+
302
+ end
303
+ end
304
+ end
305
+ end
306
+ end
@@ -313,6 +313,7 @@ module Ronin
313
313
  print_data data
314
314
  end
315
315
 
316
+ print_info "Listening on #{@host}:#{@port} ..."
316
317
  @proxy.start
317
318
  end
318
319
 
@@ -61,7 +61,7 @@ module Ronin
61
61
  # @since 1.1.0
62
62
  #
63
63
  def self.each_query_option(&block)
64
- return enum_for(:each_query_option) unless block
64
+ return enum_for(__method__) unless block
65
65
 
66
66
  self.class.ancestors.each do |ancestor|
67
67
  if ancestor < ModelCommand
@@ -43,8 +43,8 @@ module Ronin
43
43
  # Mapping of URL Schemes and URI classes
44
44
  SCHEMES = {
45
45
  'https' => ::URI::HTTPS,
46
- 'http' => ::URI::HTTP,
47
- 'ftp' => ::URI::FTP
46
+ 'http' => ::URI::HTTP,
47
+ 'ftp' => ::URI::FTP
48
48
  }
49
49
 
50
50
  # Primary key of the URL
@@ -100,7 +100,7 @@ module Ronin
100
100
  # @api public
101
101
  #
102
102
  def self.extract(text)
103
- return enum_for(:extract,text).to_a unless block_given?
103
+ return enum_for(__method__,text).to_a unless block_given?
104
104
 
105
105
  ::URI.extract(text) do |uri|
106
106
  uri = begin
@@ -287,10 +287,10 @@ module Ronin
287
287
 
288
288
  # create the initial query
289
289
  query = all(
290
- 'scheme.name' => url.scheme,
290
+ 'scheme.name' => url.scheme,
291
291
  'host_name.address' => url.host,
292
- :path => normalized_path(url),
293
- :fragment => url.fragment
292
+ :path => normalized_path(url),
293
+ :fragment => url.fragment
294
294
  )
295
295
 
296
296
  if url.port
@@ -300,10 +300,10 @@ module Ronin
300
300
 
301
301
  if url.query
302
302
  # add the query params to the query
303
- URI::QueryParams.parse(url.query).each do |name,value|
303
+ ::URI::QueryParams.parse(url.query).each do |name,value|
304
304
  query = query.all(
305
305
  'query_params.name.name' => name,
306
- 'query_params.value' => value
306
+ 'query_params.value' => value
307
307
  )
308
308
  end
309
309
  end
@@ -326,13 +326,13 @@ module Ronin
326
326
  #
327
327
  def self.from(uri)
328
328
  # find or create the URL scheme, host_name and port
329
- scheme = URLScheme.first_or_new(:name => uri.scheme)
329
+ scheme = URLScheme.first_or_new(:name => uri.scheme)
330
330
  host_name = HostName.first_or_new(:address => uri.host)
331
- port = if uri.port
332
- TCPPort.first_or_new(:number => uri.port)
333
- end
331
+ port = if uri.port
332
+ TCPPort.first_or_new(:number => uri.port)
333
+ end
334
334
 
335
- path = normalized_path(uri)
335
+ path = normalized_path(uri)
336
336
  fragment = uri.fragment
337
337
 
338
338
  query_params = []
@@ -341,7 +341,7 @@ module Ronin
341
341
  # find or create the URL query params
342
342
  uri.query_params.each do |name,value|
343
343
  query_params << {
344
- :name => URLQueryParamName.first_or_new(:name => name),
344
+ :name => URLQueryParamName.first_or_new(:name => name),
345
345
  :value => value
346
346
  }
347
347
  end
@@ -349,11 +349,11 @@ module Ronin
349
349
 
350
350
  # find or create the URL
351
351
  return first_or_new(
352
- :scheme => scheme,
353
- :host_name => host_name,
354
- :port => port,
355
- :path => path,
356
- :fragment => fragment,
352
+ :scheme => scheme,
353
+ :host_name => host_name,
354
+ :port => port,
355
+ :path => path,
356
+ :fragment => fragment,
357
357
  :query_params => query_params
358
358
  )
359
359
  end
@@ -422,7 +422,7 @@ module Ronin
422
422
  params[param.name] = param.value
423
423
  end
424
424
 
425
- return URI::QueryParams.dump(params)
425
+ return ::URI::QueryParams.dump(params)
426
426
  end
427
427
 
428
428
  #
@@ -441,9 +441,9 @@ module Ronin
441
441
  def query_string=(query)
442
442
  self.query_params.clear
443
443
 
444
- URI::QueryParams.parse(query).each do |name,value|
444
+ ::URI::QueryParams.parse(query).each do |name,value|
445
445
  self.query_params.new(
446
- :name => URLQueryParamName.first_or_new(:name => name),
446
+ :name => URLQueryParamName.first_or_new(:name => name),
447
447
  :value => value
448
448
  )
449
449
  end
@@ -478,11 +478,11 @@ module Ronin
478
478
 
479
479
  # build the URI
480
480
  return url_class.build(
481
- :scheme => self.scheme.name,
482
- :host => host,
483
- :port => port,
484
- :path => self.path,
485
- :query => query,
481
+ :scheme => self.scheme.name,
482
+ :host => host,
483
+ :port => port,
484
+ :path => self.path,
485
+ :query => query,
486
486
  :fragment => self.fragment
487
487
  )
488
488
  end
@@ -532,7 +532,7 @@ module Ronin
532
532
  #
533
533
  def self.normalized_path(uri)
534
534
  case uri
535
- when URI::HTTP
535
+ when ::URI::HTTP
536
536
  # map empty HTTP paths to '/'
537
537
  unless uri.path.empty?
538
538
  uri.path
@@ -19,5 +19,5 @@
19
19
 
20
20
  module Ronin
21
21
  # Ronin version
22
- VERSION = '1.5.0.rc2'
22
+ VERSION = '1.5.0'
23
23
  end
@@ -0,0 +1,73 @@
1
+ # ronin-fuzzer 1 "April 2012" Ronin "User Manuals"
2
+
3
+ ## SYNOPSIS
4
+
5
+ `ronin fuzzer` [*options*] [*TEMPLATE*]
6
+
7
+ ## DESCRIPTION
8
+
9
+ Fuzzes data read from a *FILE* or from `STDIN`. The fuzzed data can be written
10
+ to output files, run in commands or sent to TCP/UDP services.
11
+
12
+ ## OPTIONS
13
+
14
+ `-v`, `--[no-]verbose`
15
+ Enable verbose output.
16
+
17
+ `-q`, `--[no-]quiet`
18
+ Disable verbose output.
19
+
20
+ `--[no-]silent`
21
+ Silence all output.
22
+
23
+ `--[no-]color`
24
+ Enables color output.
25
+
26
+ `-i`, `--input` *FILE*
27
+ The input text FILE to parse. Data will be read from `STDIN` by default.
28
+
29
+ `-r`, `--rule` [*PATTERN*|*/REGEXP/*|STRING]:[*METHOD*|*STRING***N*[-*M*]]
30
+ The rule to apply to the *INPUT*. Fuzzer rules consist of a pattern and
31
+ substitution. Patterns may be one of the following:
32
+
33
+ * A name of a Ronin Regular Expression (ex: `unix_path`)
34
+ * A custom Regular Expression (ex: `/\d+/`)
35
+ * A plain String (ex: `example.com`).
36
+
37
+ Substitutions may be one of the following:
38
+
39
+ * A method from `Ronin::Fuzzing` (ex: `bad_strings`)
40
+ * A *STRING*, repeated *N* or *M* times (ex: `A*100-200`).
41
+
42
+ `-o`, `--output` *PATH*
43
+ The output PATH to write the fuzzer to.
44
+
45
+ `-c`, `--command` *COMMAND*
46
+ The command to run with the fuzzed data. All ocurrences of `#string#` will be
47
+ replaced with the fuzzed data, and ocurrences of `#path#` will be replaced
48
+ with the path to the fuzzed data.
49
+
50
+ `-t`, `--tcp` *HOST*:*PORT*
51
+ The TCP service to send the fuzzed data to.
52
+
53
+ `-u`, `--udp` *HOST*:*PORT*
54
+ The UDP service to send the fuzzed data to.
55
+
56
+ ## EXAMPLES
57
+
58
+ `ronin fuzzer -i http_request.txt -o bad.txt -r unix_path:bad_strings`
59
+ Fuzzes a HTTP request, replacing every occurrence of a UNIX path, with
60
+ strings from the `bad_strings` method.
61
+
62
+ ## LINKS
63
+
64
+ Ronin Regular Expressions
65
+ http://ronin-ruby.github.com/docs/ronin-support/Regexp.html
66
+
67
+ `Ronin::Fuzzing`
68
+ http://ronin-ruby.github.com/docs/ronin-support/Ronin/Fuzzing.html
69
+
70
+ ## AUTHOR
71
+
72
+ Postmodern <postmodern.mod3@gmail.com>
73
+
@@ -10,40 +10,18 @@ describe Installation do
10
10
  subject.libraries.should include('ronin')
11
11
  end
12
12
 
13
- let(:directory) { 'lib/ronin/ui/cli/commands' }
14
- let(:files) {
15
- %w[
16
- campaigns.rb
17
- console.rb
18
- creds.rb
19
- database.rb
20
- emails.rb
21
- exec.rb
22
- help.rb
23
- hosts.rb
24
- install.rb
25
- ips.rb
26
- net/proxy.rb
27
- repos.rb
28
- update.rb
29
- urls.rb
30
- uninstall.rb
31
- wordlist.rb
32
- ]
33
- }
13
+ let(:directory) { 'lib/ronin/ui/cli/commands/' }
14
+ let(:pattern) { File.join(directory,'**','*.rb') }
15
+ let(:paths) { Dir[pattern] }
16
+ let(:files) { paths.map { |path| path.sub(directory,'') } }
34
17
 
35
18
  describe "each_file" do
36
- let(:pattern) { File.join(directory,'**','*.rb') }
37
- let(:expected) { files.map { |name| File.join(directory,name) } }
38
-
39
19
  it "should enumerate over the files which match a glob pattern" do
40
- subject.each_file(pattern).to_a.should =~ expected
20
+ subject.each_file(pattern).to_a.should =~ paths
41
21
  end
42
22
 
43
23
  it "should return an Enumerator when no block is given" do
44
- subject.each_file(pattern).all? { |file|
45
- expected.include?(file)
46
- }.should == true
24
+ subject.each_file(pattern).should respond_to(:each)
47
25
  end
48
26
  end
49
27
 
@@ -56,9 +34,7 @@ describe Installation do
56
34
  end
57
35
 
58
36
  it "should return an Enumerator when no block is given" do
59
- subject.each_file_in(directory,ext).all? { |file|
60
- expected.include?(file)
61
- }.should == true
37
+ subject.each_file_in(directory,ext).should respond_to(:each)
62
38
  end
63
39
  end
64
40
  end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ require 'ronin/ui/cli/cli'
3
+
4
+ describe UI::CLI do
5
+ describe "commands" do
6
+ subject { described_class.commands }
7
+
8
+ it { should_not be_empty }
9
+
10
+ it "should replace '/' characters with a ':'" do
11
+ subject.all? { |command| command.include?('/') }.should be_false
12
+ end
13
+ end
14
+
15
+ describe "command" do
16
+ it "should load classes from 'ronin/ui/cli/commands/'" do
17
+ command = subject.command('help')
18
+
19
+ command.name.should == 'Ronin::UI::CLI::Commands::Help'
20
+ end
21
+
22
+ it "should load classes from namespaces within 'ronin/ui/cli/commands/'" do
23
+ command = subject.command('net:proxy')
24
+
25
+ command.name.should == 'Ronin::UI::CLI::Commands::Net::Proxy'
26
+ end
27
+
28
+ it "should raise UnknownCommand for unknown commands" do
29
+ lambda {
30
+ subject.command('foo')
31
+ }.should raise_error(described_class::UnknownCommand)
32
+ end
33
+ end
34
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ronin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0.rc2
5
- prerelease: 6
4
+ version: 1.5.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Postmodern
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-10 00:00:00.000000000 Z
12
+ date: 2012-06-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dm-sqlite-adapter
@@ -344,7 +344,7 @@ dependencies:
344
344
  requirements:
345
345
  - - ~>
346
346
  - !ruby/object:Gem::Version
347
- version: 0.5.0.rc2
347
+ version: '0.5'
348
348
  type: :runtime
349
349
  prerelease: false
350
350
  version_requirements: !ruby/object:Gem::Requirement
@@ -352,7 +352,7 @@ dependencies:
352
352
  requirements:
353
353
  - - ~>
354
354
  - !ruby/object:Gem::Version
355
- version: 0.5.0.rc2
355
+ version: '0.5'
356
356
  - !ruby/object:Gem::Dependency
357
357
  name: bundler
358
358
  requirement: !ruby/object:Gem::Requirement
@@ -429,6 +429,7 @@ executables:
429
429
  - ronin-database
430
430
  - ronin-emails
431
431
  - ronin-exec
432
+ - ronin-fuzzer
432
433
  - ronin-help
433
434
  - ronin-hosts
434
435
  - ronin-install
@@ -462,6 +463,7 @@ files:
462
463
  - bin/ronin-database
463
464
  - bin/ronin-emails
464
465
  - bin/ronin-exec
466
+ - bin/ronin-fuzzer
465
467
  - bin/ronin-help
466
468
  - bin/ronin-hosts
467
469
  - bin/ronin-install
@@ -561,6 +563,7 @@ files:
561
563
  - lib/ronin/ui/cli/commands/database.rb
562
564
  - lib/ronin/ui/cli/commands/emails.rb
563
565
  - lib/ronin/ui/cli/commands/exec.rb
566
+ - lib/ronin/ui/cli/commands/fuzzer.rb
564
567
  - lib/ronin/ui/cli/commands/help.rb
565
568
  - lib/ronin/ui/cli/commands/hosts.rb
566
569
  - lib/ronin/ui/cli/commands/install.rb
@@ -596,6 +599,7 @@ files:
596
599
  - man/ronin-database.1.md
597
600
  - man/ronin-emails.1.md
598
601
  - man/ronin-exec.1.md
602
+ - man/ronin-fuzzer.1.md
599
603
  - man/ronin-help.1.md
600
604
  - man/ronin-hosts.1.md
601
605
  - man/ronin-install.1.md
@@ -675,6 +679,7 @@ files:
675
679
  - spec/software_spec.rb
676
680
  - spec/spec_helper.rb
677
681
  - spec/ui/cli/classes/test_command.rb
682
+ - spec/ui/cli/cli_spec.rb
678
683
  - spec/ui/cli/command_spec.rb
679
684
  - spec/url_query_param_spec.rb
680
685
  - spec/url_scheme_spec.rb
@@ -687,6 +692,7 @@ files:
687
692
  - man/ronin-database.1
688
693
  - man/ronin-emails.1
689
694
  - man/ronin-exec.1
695
+ - man/ronin-fuzzer.1
690
696
  - man/ronin-help.1
691
697
  - man/ronin-hosts.1
692
698
  - man/ronin-install.1
@@ -697,7 +703,7 @@ files:
697
703
  - man/ronin-update.1
698
704
  - man/ronin-urls.1
699
705
  - man/ronin-wordlist.1
700
- homepage: http://github.com/ronin-ruby/ronin
706
+ homepage: http://ronin-ruby.github.com/
701
707
  licenses:
702
708
  - GPL-3
703
709
  post_install_message: ! "*************************************************************************\n\n