ronin 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
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