ronin 0.2.3 → 0.2.4

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.
Files changed (76) hide show
  1. data.tar.gz.sig +2 -0
  2. data/History.txt +43 -0
  3. data/Manifest.txt +27 -10
  4. data/README.txt +2 -1
  5. data/Rakefile +12 -11
  6. data/TODO.txt +8 -0
  7. data/bin/{ronin-ls → ronin-list} +2 -2
  8. data/bin/{ronin-rm → ronin-remove} +2 -2
  9. data/lib/ronin/cacheable.rb +25 -4
  10. data/lib/ronin/code/reference.rb +0 -9
  11. data/lib/ronin/code/symbol_table.rb +5 -5
  12. data/lib/ronin/code/token.rb +1 -1
  13. data/lib/ronin/database/database.rb +3 -1
  14. data/lib/ronin/extensions/kernel.rb +25 -3
  15. data/lib/ronin/formatting/extensions/binary/file.rb +60 -0
  16. data/lib/ronin/formatting/extensions/text.rb +1 -0
  17. data/lib/ronin/formatting/extensions/text/array.rb +67 -0
  18. data/lib/ronin/model.rb +1 -40
  19. data/lib/ronin/{has_license.rb → model/has_description.rb} +16 -18
  20. data/lib/ronin/model/has_license.rb +53 -0
  21. data/lib/ronin/model/has_name.rb +49 -0
  22. data/lib/ronin/model/has_version.rb +46 -0
  23. data/lib/ronin/model/model.rb +64 -0
  24. data/lib/ronin/network/extensions/http/net.rb +580 -99
  25. data/lib/ronin/network/http.rb +54 -6
  26. data/lib/ronin/os.rb +7 -7
  27. data/lib/ronin/platform/extension.rb +4 -6
  28. data/lib/ronin/platform/maintainer.rb +1 -1
  29. data/lib/ronin/platform/object_cache.rb +10 -2
  30. data/lib/ronin/platform/overlay_cache.rb +1 -1
  31. data/lib/ronin/platform/platform.rb +5 -3
  32. data/lib/ronin/platform/ronin.rb +3 -3
  33. data/lib/ronin/scanners.rb +25 -0
  34. data/lib/ronin/scanners/exceptions.rb +24 -0
  35. data/lib/ronin/scanners/exceptions/unknown_category.rb +29 -0
  36. data/lib/ronin/scanners/scanner.rb +239 -0
  37. data/lib/ronin/sessions/http.rb +548 -7
  38. data/lib/ronin/{translators.rb → templates.rb} +1 -1
  39. data/lib/ronin/templates/erb.rb +56 -0
  40. data/lib/ronin/ui/command_line/command_line.rb +10 -1
  41. data/lib/ronin/ui/command_line/commands/{ls.rb → list.rb} +1 -1
  42. data/lib/ronin/ui/command_line/commands/{rm.rb → remove.rb} +1 -1
  43. data/lib/ronin/ui/command_line/commands/uninstall.rb +2 -2
  44. data/lib/ronin/ui/console.rb +66 -17
  45. data/lib/ronin/ui/shell.rb +16 -36
  46. data/lib/ronin/version.rb +1 -1
  47. data/spec/cacheable_spec.rb +1 -1
  48. data/spec/code/classes/thing.rb +4 -0
  49. data/spec/code/reference_spec.rb +4 -0
  50. data/spec/code/symbol_table_spec.rb +5 -1
  51. data/spec/extensions/kernel_spec.rb +45 -5
  52. data/spec/extensions/string_spec.rb +4 -0
  53. data/spec/formatting/binary/integer_spec.rb +3 -3
  54. data/spec/formatting/binary/string_spec.rb +5 -5
  55. data/spec/formatting/digest/string_spec.rb +5 -9
  56. data/spec/formatting/http/string_spec.rb +5 -9
  57. data/spec/formatting/text/array_spec.rb +64 -0
  58. data/spec/formatting/text/string_spec.rb +3 -3
  59. data/spec/model/classes/licensed_model.rb +12 -0
  60. data/spec/{has_license_spec.rb → model/has_license_spec.rb} +5 -5
  61. data/spec/network/http_spec.rb +197 -0
  62. data/spec/os_spec.rb +2 -5
  63. data/spec/platform/maintainer_spec.rb +30 -0
  64. data/spec/platform/ronin_spec.rb +2 -2
  65. data/spec/scanners/classes/another_scanner.rb +16 -0
  66. data/spec/scanners/classes/example_scanner.rb +22 -0
  67. data/spec/scanners/scanner_spec.rb +148 -0
  68. data/spec/spec_helper.rb +1 -1
  69. data/spec/templates/classes/uses_erb.rb +11 -0
  70. data/spec/templates/erb_spec.rb +20 -0
  71. data/static/ronin/platform/overlay.xsl +128 -49
  72. metadata +83 -30
  73. metadata.gz.sig +0 -0
  74. data/lib/ronin/translators/translator.rb +0 -75
  75. data/spec/classes/licensed_model.rb +0 -12
  76. data/spec/translators/translator_spec.rb +0 -61
@@ -79,6 +79,42 @@ module Ronin
79
79
  @@http_user_agent = agent
80
80
  end
81
81
 
82
+ #
83
+ # Expands the given HTTP _options_.
84
+ #
85
+ def HTTP.expand_options(options={})
86
+ new_options = options.dup
87
+
88
+ if new_options[:url]
89
+ url = URI(new_options.delete(:url).to_s)
90
+
91
+ new_options[:host] = url.host
92
+ new_options[:port] = url.port
93
+
94
+ new_options[:user] = url.user if url.user
95
+ new_options[:password] = url.password if url.password
96
+
97
+ unless url.path.empty?
98
+ new_options[:path] = url.path
99
+ else
100
+ new_options[:path] = '/'
101
+ end
102
+
103
+ new_options[:path] << "?#{url.query}" if url.query
104
+ else
105
+ new_options[:port] ||= ::Net::HTTP.default_port
106
+ new_options[:path] ||= '/'
107
+ end
108
+
109
+ if (proxy = new_options[:proxy])
110
+ proxy[:port] ||= Ronin::Network::HTTP.default_proxy_port
111
+ else
112
+ new_options[:proxy] = Ronin::Network::HTTP.proxy
113
+ end
114
+
115
+ return new_options
116
+ end
117
+
82
118
  #
83
119
  # Returns Ronin HTTP headers created from the given _options_.
84
120
  #
@@ -91,7 +127,7 @@ module Ronin
91
127
 
92
128
  if options
93
129
  options.each do |name,value|
94
- header_name = name.to_s.split('_').map { |word|
130
+ header_name = name.to_s.split(/[\s+_-]/).map { |word|
95
131
  word.capitalize
96
132
  }.join('-')
97
133
 
@@ -107,18 +143,30 @@ module Ronin
107
143
  # given _options_. If type does not represent the name of an Net:HTTP
108
144
  # Request Class an UnknownRequest exception will be raised.
109
145
  #
110
- def HTTP.request(type,options={})
111
- name = type.to_s.capitalize
146
+ def HTTP.request(options={})
147
+ unless options[:method]
148
+ raise(ArgumentError,"the :method option must be specified",caller)
149
+ end
150
+
151
+ name = options[:method].to_s.capitalize
112
152
 
113
153
  unless Net::HTTP.const_defined?(name)
114
154
  raise(UnknownRequest,"unknown HTTP request type #{name.dump}",caller)
115
155
  end
116
156
 
117
157
  headers = HTTP.headers(options[:headers])
118
- request = Net::HTTP.const_get(name).new(options[:path].to_s,headers)
158
+ path = (options[:path] || '/').to_s
159
+
160
+ request = Net::HTTP.const_get(name).new(path,headers)
161
+
162
+ if (user = options.delete(:user))
163
+ user = user.to_s
164
+
165
+ if (password = options.delete(:password))
166
+ password = password.to_s
167
+ end
119
168
 
120
- if options[:user]
121
- request.basic_auth(options[:user].to_s,options[:password].to_s)
169
+ request.basic_auth(user,password)
122
170
  end
123
171
 
124
172
  return request
data/lib/ronin/os.rb CHANGED
@@ -41,7 +41,7 @@ module Ronin
41
41
  property :version, String, :index => true
42
42
 
43
43
  # Validates
44
- validates_present :name, :version
44
+ validates_present :name
45
45
 
46
46
  #
47
47
  # Returns the String form of the os.
@@ -66,12 +66,12 @@ module Ronin
66
66
  name = name.to_s
67
67
  method_name = name.snake_case
68
68
 
69
- meta_def(method_name) do
70
- OS.new(:name => name)
71
- end
72
-
73
- meta_def("#{method_name}_version") do |version|
74
- OS.first_or_create(:name => name, :version => version.to_s)
69
+ meta_def(method_name) do |*arguments|
70
+ if (version = arguments.first)
71
+ OS.first_or_create(:name => name, :version => version.to_s)
72
+ else
73
+ OS.new(:name => name)
74
+ end
75
75
  end
76
76
 
77
77
  return nil
@@ -24,7 +24,9 @@
24
24
  require 'ronin/platform/exceptions/extension_not_found'
25
25
  require 'ronin/platform/extension_cache'
26
26
  require 'ronin/platform/platform'
27
+ require 'ronin/extensions/kernel'
27
28
  require 'ronin/static/finders'
29
+ require 'ronin/ui/diagnostics'
28
30
 
29
31
  require 'contextify'
30
32
 
@@ -34,6 +36,7 @@ module Ronin
34
36
 
35
37
  include Contextify
36
38
  include Static::Finders
39
+ include UI::Diagnostics
37
40
 
38
41
  contextify :ronin_extension
39
42
 
@@ -141,12 +144,7 @@ module Ronin
141
144
  context_block = Extension.load_context_block(extension_file)
142
145
 
143
146
  if context_block
144
- begin
145
- instance_eval(&context_block)
146
- rescue SyntaxError, RuntimeError, StandardError => e
147
- STDERR.puts "#{e.class}: #{e}"
148
- e.backtrace.each { |trace| STDERR.puts "\t#{trace}" }
149
- end
147
+ catch_all { instance_eval(&context_block) }
150
148
  end
151
149
  end
152
150
 
@@ -54,7 +54,7 @@ module Ronin
54
54
  # Inspects the maintainer object.
55
55
  #
56
56
  def inspect
57
- "#<#{self.class.name}: #{self}"
57
+ "#<#{self.class.name}: #{self}>"
58
58
  end
59
59
 
60
60
  end
@@ -21,7 +21,9 @@
21
21
  #++
22
22
  #
23
23
 
24
+ require 'ronin/database'
24
25
  require 'ronin/cacheable'
26
+ require 'ronin/extensions/kernel'
25
27
 
26
28
  module Ronin
27
29
  module Platform
@@ -56,8 +58,10 @@ module Ronin
56
58
  # _directory_.
57
59
  #
58
60
  def ObjectCache.cache(directory)
61
+ Database.setup unless Database.setup?
62
+
59
63
  ObjectCache.paths(directory).each do |path|
60
- Cacheable.cache(path)
64
+ catch_all { Cacheable.cache_all(path) }
61
65
  end
62
66
 
63
67
  return true
@@ -71,10 +75,12 @@ module Ronin
71
75
  def ObjectCache.sync(directory)
72
76
  new_paths = ObjectCache.paths(directory)
73
77
 
78
+ Database.setup unless Database.setup?
79
+
74
80
  ObjectCache.each(directory) do |obj|
75
81
  new_paths.delete(obj.cached_path)
76
82
 
77
- obj.sync!
83
+ catch_all { obj.sync! }
78
84
  end
79
85
 
80
86
  # cache the remaining new paths
@@ -87,6 +93,8 @@ module Ronin
87
93
  # _directory_.
88
94
  #
89
95
  def ObjectCache.clean(directory)
96
+ Database.setup unless Database.setup?
97
+
90
98
  ObjectCache.each(directory) { |obj| obj.destroy }
91
99
  return true
92
100
  end
@@ -271,7 +271,7 @@ module Ronin
271
271
  # end
272
272
  #
273
273
  def uninstall(name,&block)
274
- remove do |overlay|
274
+ remove(name) do |overlay|
275
275
  overlay.uninstall(&block)
276
276
  end
277
277
  end
@@ -26,6 +26,8 @@ require 'ronin/platform/overlay_cache'
26
26
  require 'ronin/platform/object_cache'
27
27
  require 'ronin/platform/extension_cache'
28
28
 
29
+ require 'uri'
30
+
29
31
  module Ronin
30
32
  module Platform
31
33
  #
@@ -145,11 +147,11 @@ module Ronin
145
147
  # has been uninstalled.
146
148
  #
147
149
  def Platform.uninstall(name,&block)
148
- Platform.remove(name) do |overlay|
149
- ObjectCache.expunge(overlay.objects_dir)
150
+ Platform.overlays.uninstall(name) do |overlay|
151
+ ObjectCache.clean(overlay.objects_dir)
150
152
  end
151
153
 
152
- block.call if block
154
+ block.call() if block
153
155
  return nil
154
156
  end
155
157
 
@@ -48,14 +48,14 @@ module Ronin
48
48
  #
49
49
  # Provides transparent access to Platform.extension via methods.
50
50
  #
51
- # Ronin.shellcode
51
+ # shellcode
52
52
  # # => #<Ronin::Platform::Extension: ...>
53
53
  #
54
- # Ronin.shellcode do |ext|
54
+ # shellcode do |ext|
55
55
  # ...
56
56
  # end
57
57
  #
58
- def Ronin.method_missing(sym,*args,&block)
58
+ def method_missing(sym,*args,&block)
59
59
  if args.length == 0
60
60
  name = sym.id2name
61
61
 
@@ -0,0 +1,25 @@
1
+ #
2
+ #--
3
+ # Ronin - A Ruby platform designed for information security and data
4
+ # exploration tasks.
5
+ #
6
+ # Copyright (c) 2006-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #++
22
+ #
23
+
24
+ require 'ronin/scanners/exceptions'
25
+ require 'ronin/scanners/scanner'
@@ -0,0 +1,24 @@
1
+ #
2
+ #--
3
+ # Ronin - A Ruby platform designed for information security and data
4
+ # exploration tasks.
5
+ #
6
+ # Copyright (c) 2006-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #++
22
+ #
23
+
24
+ require 'ronin/scanners/exceptions/unknown_category'
@@ -0,0 +1,29 @@
1
+ #
2
+ #--
3
+ # Ronin - A Ruby platform designed for information security and data
4
+ # exploration tasks.
5
+ #
6
+ # Copyright (c) 2006-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #++
22
+ #
23
+
24
+ module Ronin
25
+ module Scanners
26
+ class UnknownCategory < StandardError
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,239 @@
1
+ #
2
+ #--
3
+ # Ronin - A Ruby platform designed for information security and data
4
+ # exploration tasks.
5
+ #
6
+ # Copyright (c) 2006-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #++
22
+ #
23
+
24
+ require 'ronin/scanners/exceptions/unknown_category'
25
+ require 'ronin/extensions/meta'
26
+
27
+ require 'set'
28
+
29
+ module Ronin
30
+ module Scanners
31
+ module Scanner
32
+ def self.included(base)
33
+ base.metaclass_eval do
34
+ #
35
+ # Returns the +Hash+ of the categories and the scanners defined
36
+ # for the class.
37
+ #
38
+ def scanners
39
+ @scanners ||= {}
40
+ end
41
+
42
+ #
43
+ # Returns the category names of all defined scanners.
44
+ #
45
+ def scans_for
46
+ names = Set[]
47
+
48
+ ancestors.each do |ancestor|
49
+ if ancestor.include?(Ronin::Scanners::Scanner)
50
+ names += ancestor.scanners.keys
51
+ end
52
+ end
53
+
54
+ return names
55
+ end
56
+
57
+ #
58
+ # Returns +true+ if there is a scanner with the specified category
59
+ # _name_ was defined, returns +false+ otherwise.
60
+ #
61
+ def scans_for?(name)
62
+ name = name.to_sym
63
+
64
+ ancestors.each do |ancestor|
65
+ if ancestor.include?(Ronin::Scanners::Scanner)
66
+ return true if ancestor.scanners.has_key?(name)
67
+ end
68
+ end
69
+
70
+ return false
71
+ end
72
+
73
+ #
74
+ # Returns all scanner tests in the specified _category_.
75
+ #
76
+ def scanners_in(name)
77
+ name = name.to_sym
78
+
79
+ unless scans_for?(name)
80
+ raise(Ronin::Scanners::UnknownCategory,"unknown scanner category #{name}",caller)
81
+ end
82
+
83
+ tests = []
84
+
85
+ ancestors.each do |ancestor|
86
+ if ancestor.include?(Ronin::Scanners::Scanner)
87
+ if ancestor.scanners.has_key?(name)
88
+ tests += ancestor.scanners[name]
89
+ end
90
+ end
91
+ end
92
+
93
+ return tests
94
+ end
95
+
96
+ #
97
+ # Defines a scanner with the specified category _name_ and
98
+ # _block_.
99
+ #
100
+ # When scanning against a target, a callback for saving results
101
+ # and the target object to be scanned will be passed to the
102
+ # _block_.
103
+ #
104
+ # scanner(:lfi) do |url,results|
105
+ # ...
106
+ # end
107
+ #
108
+ # If the scanner accepts a 3rd argument, it will be passed a
109
+ # +Hash+ of configuration options when the scanner is called.
110
+ #
111
+ # scanner(:sqli) do |url,results,options|
112
+ # ...
113
+ # end
114
+ #
115
+ def scanner(name,&block)
116
+ method_name = name.to_s.downcase.gsub(/[\s\._-]+/,'_')
117
+ name = name.to_sym
118
+
119
+ (scanners[name] ||= []) << block
120
+
121
+ class_def("first_#{method_name}") do |*arguments|
122
+ options = case arguments.length
123
+ when 1
124
+ arguments.first
125
+ when 0
126
+ true
127
+ else
128
+ raise(ArgumentError,"wrong number of arguments (#{arguments.length} for 1)",caller)
129
+ end
130
+
131
+ first_result = nil
132
+
133
+ scan(name => options) do |category,result|
134
+ first_result = result
135
+ break
136
+ end
137
+
138
+ return first_result
139
+ end
140
+
141
+ class_def("has_#{method_name}?") do |*arguments|
142
+ !(self.send("first_#{method_name}",*arguments).nil?)
143
+ end
144
+
145
+ name = name.to_s
146
+
147
+ module_eval %{
148
+ def #{method_name}_scan(options=true,&block)
149
+ results = scan(:#{name.dump} => options) do |category,result|
150
+ block.call(result) if block
151
+ end
152
+
153
+ return results[:#{name.dump}]
154
+ end
155
+ }
156
+
157
+ return true
158
+ end
159
+ end
160
+ end
161
+
162
+ #
163
+ # Runs the scanners in the given _categories_ against each_target.
164
+ # If _categories_ is not specified, all categories will be ran
165
+ # against each_target. Returns a +Hash+ of results grouped by
166
+ # scanner category.
167
+ #
168
+ # If a _block_ is given, it will be passed each result and the
169
+ # category the result belongs to.
170
+ #
171
+ # url.scan(:rfi => true)
172
+ #
173
+ # url.scan(:lfi => true, :sqli => {:params => ['id', 'catid']})
174
+ #
175
+ # url.scan(:lfi => true, :rfi => true) do |category,result|
176
+ # puts "[#{category}] #{result.inspect}"
177
+ # end
178
+ #
179
+ def scan(categories={},&block)
180
+ tests = {}
181
+ options = {}
182
+ results = {}
183
+
184
+ if categories.empty?
185
+ self.class.scans_for.each { |name| categories[name] = true }
186
+ end
187
+
188
+ categories.each do |name,opts|
189
+ name = name.to_sym
190
+
191
+ if opts
192
+ tests[name] = self.class.scanners_in(name)
193
+
194
+ options[name] = if opts.kind_of?(Hash)
195
+ opts
196
+ else
197
+ {}
198
+ end
199
+
200
+ results[name] = []
201
+ end
202
+ end
203
+
204
+ current_category = nil
205
+ result_callback = lambda { |result|
206
+ results[current_category] << result
207
+ block.call(current_category,result) if block
208
+ }
209
+
210
+ each_target do |target|
211
+ tests.each do |name,scanners|
212
+ current_category = name
213
+
214
+ scanners.each do |scanner|
215
+ if scanner.arity == 3
216
+ scanner.call(target,result_callback,options[name])
217
+ else
218
+ scanner.call(target,result_callback)
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ return results
225
+ end
226
+
227
+ protected
228
+
229
+ #
230
+ # A place holder method which will call the specified _block_ with
231
+ # each target object to be scanned. By default, the method will call
232
+ # the specified _block_ once, simply passing it the +self+ object.
233
+ #
234
+ def each_target(&block)
235
+ block.call(self)
236
+ end
237
+ end
238
+ end
239
+ end