librex 0.0.35 → 0.0.36

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.
@@ -0,0 +1,290 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)),"nokogiri_doc_mixin")
2
+
3
+ module Rex
4
+ module Parser
5
+
6
+ # If Nokogiri is available, define Burp Session document class.
7
+ #
8
+ # Burp Session XML files actually provide a lot, but since it also
9
+ # provides the originating url, we can pull most of the detail from
10
+ # the URI object.
11
+ load_nokogiri && class BurpSessionDocument < Nokogiri::XML::SAX::Document
12
+
13
+ include NokogiriDocMixin
14
+
15
+ # The resolver prefers your local /etc/hosts (or windows equiv), but will
16
+ # fall back to regular DNS. It retains a cache for the import to avoid
17
+ # spamming your network with DNS requests.
18
+ attr_reader :resolv_cache
19
+
20
+ # Since we try to resolve every time we hit a new web page, need to
21
+ # hang on to our misses. Presume that it's a permanent enough failure
22
+ # that it won't get fixed during this particular import
23
+ attr_reader :missed_cache
24
+
25
+ # If name resolution of the host fails out completely, you will not be
26
+ # able to import that Scan task. Other scan tasks in the same report
27
+ # should be unaffected.
28
+ attr_reader :parse_warning
29
+
30
+ def start_document
31
+ @parse_warnings = []
32
+ @parse_warned = []
33
+ @resolv_cache = {}
34
+ @missed_cache = []
35
+ end
36
+
37
+ def start_element(name=nil,attrs=[])
38
+ attrs = normalize_attrs(attrs)
39
+ block = @block
40
+ @state[:current_tag][name] = true
41
+ case name
42
+ when "host", "port", "protocol", "path"
43
+ @state[:has_text] = true
44
+ when "status"
45
+ @state[:has_text] = true
46
+ when "response"
47
+ @state[:has_text] = true
48
+ end
49
+ end
50
+
51
+ def end_element(name=nil)
52
+ block = @block
53
+ case name
54
+ when "item" # Wrap up this item, but keep resolved web sites
55
+ collect_uri
56
+ report_web_site(&block)
57
+ handle_parse_warnings(&block)
58
+ report_web_page(&block)
59
+ report_web_service_info
60
+ report_web_host_info
61
+ # Reset the state once we close a host
62
+ @state = @state.select {|k| [:current_tag, :web_sites].include? k}
63
+ when "host"
64
+ @state[:has_text] = false
65
+ collect_host
66
+ @text = nil
67
+ when "port"
68
+ @state[:has_text] = false
69
+ collect_port
70
+ @text = nil
71
+ when "protocol"
72
+ @state[:has_text] = false
73
+ collect_protocol
74
+ @text = nil
75
+ when "path"
76
+ @state[:has_text] = false
77
+ collect_path_and_query
78
+ @text = nil
79
+ when "status"
80
+ @state[:has_text] = false
81
+ collect_status
82
+ @text = nil
83
+ when "response"
84
+ @state[:has_text] = false
85
+ collect_response
86
+ @text = nil
87
+ end
88
+ @state[:current_tag].delete name
89
+ end
90
+
91
+ def collect_host
92
+ return unless in_item
93
+ return unless has_text
94
+ @state[:host] = @text
95
+ end
96
+
97
+ def collect_port
98
+ return unless in_item
99
+ return unless has_text
100
+ return unless @text.to_i.to_s == @text.to_s
101
+ @state[:port] = @text.to_i
102
+ end
103
+
104
+ def collect_protocol
105
+ return unless in_item
106
+ return unless has_text
107
+ @state[:protocol] = @text
108
+ end
109
+
110
+ def collect_path_and_query
111
+ return unless in_item
112
+ return unless has_text
113
+ path,query = @text.split(/\?+/,2)
114
+ return unless path
115
+ if query
116
+ @state[:query] = "?#{query}" # Can be nil
117
+ end
118
+ if path =~ /https?:[\x5c\x2f][\x5c\x2f]+[^\x5c\x2f][^\x5c\x2f]+([^?]+)/
119
+ real_path = "/#{$1}"
120
+ else
121
+ real_path = path
122
+ end
123
+ @state[:path] = real_path
124
+ end
125
+
126
+ def collect_status
127
+ return unless in_item
128
+ return unless has_text
129
+ return unless @text.to_i.to_s == @text
130
+ @state[:status] = @text.to_i
131
+ end
132
+
133
+ def collect_uri
134
+ return unless in_item
135
+ return unless @state[:host]
136
+ return unless @state[:port]
137
+ return unless @state[:protocol]
138
+ return unless @state[:path]
139
+ url = @state[:protocol].to_s
140
+ url << "://"
141
+ url << @state[:host].to_s
142
+ url << ":"
143
+ url << @state[:port].to_s
144
+ url << @state[:path]
145
+ if @state[:query]
146
+ url << "?"
147
+ url << @state[:query]
148
+ end
149
+ @state[:uri] = URI.parse(url) rescue nil
150
+ end
151
+
152
+ def report_web_host_info
153
+ return unless @state[:web_site]
154
+ return unless @state[:uri].kind_of? URI::HTTP
155
+ return unless @state[:web_site].service.host.name.to_s.empty?
156
+ host_info = {:workspace => @args[:wspace]}
157
+ host_info[:address] = @state[:web_site].service.host.address
158
+ host_info[:name] = @state[:uri].host
159
+ report_db(:host, host_info)
160
+ end
161
+
162
+ def report_web_service_info
163
+ return unless @state[:web_site]
164
+ return unless @state[:service_info]
165
+ return unless @state[:web_site].service.info.to_s.empty?
166
+ service_info = {}
167
+ service_info[:host] = @state[:web_site].service.host
168
+ service_info[:port] = @state[:web_site].service.port
169
+ service_info[:proto] = @state[:web_site].service.proto
170
+ service_info[:info] = @state[:service_info]
171
+ db_report(:service, service_info)
172
+ end
173
+
174
+ def report_web_page(&block)
175
+ return unless @state[:uri].kind_of? URI::HTTP
176
+ return unless @state[:status]
177
+ return unless @state[:web_site]
178
+ return unless @state[:response_headers].kind_of? Hash
179
+ headers = {}
180
+ @state[:response_headers].each do |k,v|
181
+ headers[k.to_s.downcase] ||= []
182
+ headers[k.to_s.downcase] << v
183
+ end
184
+ if headers["server"].kind_of? Array
185
+ @state[:service_info] = headers["server"].first
186
+ end
187
+ return unless @state[:response_body]
188
+ web_page_info = {:workspace => @args[:wspace]}
189
+ web_page_info[:web_site] = @state[:web_site]
190
+ web_page_info[:code] = @state[:status]
191
+ web_page_info[:path] = @state[:uri].path
192
+ web_page_info[:headers] = headers
193
+ web_page_info[:body] = @state[:response_body]
194
+ web_page_info[:query] = @state[:uri].query
195
+ url = @state[:uri].to_s.gsub(/\?.*/,"")
196
+ db.emit(:web_page, url, &block) if block
197
+ db_report(:web_page, web_page_info)
198
+ end
199
+
200
+ def report_web_site(&block)
201
+ return unless @state[:uri].kind_of? URI::HTTP
202
+ vhost = @state[:uri].host
203
+ web_site_info = {:workspace => @args[:wspace]}
204
+ web_site_info[:vhost] = vhost
205
+ address = resolve_vhost_address(@state[:uri])
206
+ return unless address
207
+ web_site_info[:host] = address
208
+ web_site_info[:port] = @state[:uri].port
209
+ web_site_info[:ssl] = @state[:uri].kind_of? URI::HTTPS
210
+ web_site_obj = db_report(:web_site, web_site_info)
211
+ return unless web_site_obj
212
+ @state[:web_sites] ||= []
213
+ url = "#{@state[:uri].scheme}://#{@state[:uri].host}:#{@state[:uri].port}"
214
+ unless @state[:web_sites].include? web_site_obj
215
+ db.emit(:web_site, url, &block)
216
+ @state[:web_sites] << web_site_obj
217
+ end
218
+ @state[:web_site] = web_site_obj
219
+ end
220
+
221
+ def collect_response
222
+ return unless in_item
223
+ return unless has_text
224
+ response_text = @text.dup
225
+ response_header_text,response_body_text = response_text.split(/\r*\n\r*\n/n,2)
226
+ return unless response_header_text
227
+ response_header = Rex::Proto::Http::Packet::Header.new
228
+ response_header.from_s response_header_text
229
+ @state[:response_headers] = response_header
230
+ @state[:response_body] = response_body_text
231
+ end
232
+
233
+ def in_item
234
+ return false unless in_tag("item")
235
+ return false unless in_tag("items")
236
+ return true
237
+ end
238
+
239
+ def has_text
240
+ return false unless @text
241
+ return false if @text.strip.empty?
242
+ @text = @text.strip
243
+ end
244
+
245
+ def handle_parse_warnings(&block)
246
+ return if @parse_warnings.empty?
247
+ return unless block
248
+ @parse_warnings.each_with_index do |pwarn,i|
249
+ unless @parse_warned.include? i
250
+ db.emit(:warning, pwarn, &block)
251
+ @parse_warned << i
252
+ end
253
+ end
254
+ end
255
+
256
+ def resolve_address(host)
257
+ return @resolv_cache[host] if @resolv_cache[host]
258
+ return false if @missed_cache.include? host
259
+ address = Rex::Socket.resolv_to_dotted(host) rescue nil
260
+ @resolv_cache[host] = address
261
+ if address
262
+ block = @block
263
+ db.emit(:address, address, &block) if block
264
+ else
265
+ @missed_cache << host
266
+ end
267
+ return address
268
+ end
269
+
270
+ # Alias this
271
+ def resolve_vhost_address(uri)
272
+ if uri.host
273
+ address = resolve_address(uri.host)
274
+ case address
275
+ when false
276
+ return false
277
+ when nil
278
+ @parse_warnings << "Could not resolve address for '#{uri.host}', skipping."
279
+ end
280
+ else
281
+ @parse_warnings << "Could not determine a host for this import."
282
+ end
283
+ address
284
+ end
285
+
286
+ end
287
+
288
+ end
289
+ end
290
+
@@ -126,7 +126,8 @@ module Parser
126
126
  nonempty_data = data.reject {|k,v| v.nil?}
127
127
  valid_attrs = db_valid_attributes(table)
128
128
  raise "Unknown table `#{table}'" if valid_attrs.empty?
129
- if table == :note # Notes don't whine about extra stuff
129
+ case table
130
+ when :note, :web_site, :web_page, :web_form, :web_vuln
130
131
  just_the_facts = nonempty_data
131
132
  else
132
133
  just_the_facts = nonempty_data.select {|k,v| valid_attrs.include? k.to_s.to_sym}
@@ -149,8 +150,9 @@ module Parser
149
150
  when :vuln
150
151
  Msf::DBManager::Vuln.new.attribute_names.map {|x| x.to_sym} |
151
152
  [:host, :refs, :workspace, :port, :proto]
152
- when :note
153
- [:anything]
153
+ when :note, :web_site, :web_page, :web_form, :web_vuln
154
+ # These guys don't complain
155
+ [:anything]
154
156
  else
155
157
  []
156
158
  end
@@ -31,6 +31,7 @@ module Scanner
31
31
  if(param['disasm'])
32
32
  #puts [msg].pack('H*').inspect
33
33
  insns = []
34
+
34
35
  msg.gsub!("; ", "\n")
35
36
  if msg.include?("retn")
36
37
  msg.gsub!("retn", "ret")
@@ -39,7 +40,7 @@ module Scanner
39
40
  begin
40
41
  d2 = Metasm::Shellcode.assemble(Metasm::Ia32.new, msg).disassemble
41
42
  rescue Metasm::ParseError
42
- d2 = Metasm::Shellcode.disassemble(Metasm::Ia32.new, [msg].pack('H*')[0])
43
+ d2 = Metasm::Shellcode.disassemble(Metasm::Ia32.new, [msg].pack('H*'))
43
44
  end
44
45
  addr = 0
45
46
  while ((di = d2.disassemble_instruction(addr)))
@@ -79,6 +79,8 @@ KEY_CREATE_SUB_KEY = 0x00000004
79
79
  KEY_ENUMERATE_SUB_KEYS = 0x00000008
80
80
  KEY_NOTIFY = 0x00000010
81
81
  KEY_CREATE_LINK = 0x00000020
82
+ KEY_WOW64_64KEY = 0x00000100
83
+ KEY_WOW64_32KEY = 0x00000200
82
84
  KEY_READ = (STANDARD_RIGHTS_READ | KEY_QUERY_VALUE |
83
85
  KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & ~SYNCHRONIZE
84
86
  KEY_WRITE = (STANDARD_RIGHTS_WRITE | KEY_SET_VALUE |
@@ -17,6 +17,11 @@ class Def_netapi32
17
17
  ["PWCHAR","username","in"],
18
18
  ])
19
19
 
20
+ railgun.add_function( 'netapi32', 'NetGetJoinInformation', 'DWORD',[
21
+ ["PBLOB","lpServer","in"],
22
+ ["PDWORD","lpNameBugger","out"],
23
+ ["PDWORD","BufferType","out"]
24
+ ])
20
25
  end
21
26
 
22
27
  end
@@ -7,6 +7,7 @@ require 'rex/post/meterpreter/extensions/stdapi/constants'
7
7
  require 'rex/post/meterpreter/extensions/stdapi/stdapi'
8
8
  require 'rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key'
9
9
  require 'rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value'
10
+ require 'rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key'
10
11
 
11
12
  module Rex
12
13
  module Post
@@ -44,9 +45,37 @@ class Registry
44
45
  return RegistrySubsystem::RegistryKey.new(client, root_key, base_key, perm, root_key)
45
46
  end
46
47
 
47
- return self.create_key(root_key, base_key, perm)
48
+ request = Packet.create_request('stdapi_registry_open_key')
49
+
50
+ request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)
51
+ request.add_tlv(TLV_TYPE_BASE_KEY, base_key)
52
+ request.add_tlv(TLV_TYPE_PERMISSION, perm)
53
+
54
+ response = client.send_request(request)
55
+
56
+ return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryKey.new(
57
+ client, root_key, base_key, perm, response.get_tlv(TLV_TYPE_HKEY).value)
48
58
  end
49
59
 
60
+ #
61
+ # Opens the supplied registry key on the specified remote host. Requires that the
62
+ # current process has credentials to access the target and that the target has the
63
+ # remote registry service running.
64
+ #
65
+ def Registry.open_remote_key(target_host, root_key)
66
+
67
+ request = Packet.create_request('stdapi_registry_open_remote_key')
68
+
69
+ request.add_tlv(TLV_TYPE_TARGET_HOST, target_host)
70
+ request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)
71
+
72
+
73
+ response = client.send_request(request)
74
+
75
+ return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RemoteRegistryKey.new(
76
+ client, target_host, root_key, response.get_tlv(TLV_TYPE_HKEY).value)
77
+ end
78
+
50
79
  #
51
80
  # Creates the supplied registry key or opens it if it already exists.
52
81
  #
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rex/post/meterpreter/extensions/stdapi/constants'
4
+ require 'rex/post/meterpreter/extensions/stdapi/sys/registry'
5
+
6
+ module Rex
7
+ module Post
8
+ module Meterpreter
9
+ module Extensions
10
+ module Stdapi
11
+ module Sys
12
+ module RegistrySubsystem
13
+
14
+ ###
15
+ #
16
+ # Class wrapper around a remote registry key on the remote side
17
+ #
18
+ ###
19
+ class RemoteRegistryKey
20
+
21
+
22
+ #
23
+ # Initializes an instance of a registry key using the supplied properties
24
+ # and HKEY handle from the server.
25
+ #
26
+ def initialize(client, target_host, root_key, hkey)
27
+ self.client = client
28
+ self.root_key = root_key
29
+ self.target_host = target_host
30
+ self.hkey = hkey
31
+
32
+ ObjectSpace.define_finalizer( self, self.class.finalize(self.client, self.hkey) )
33
+ end
34
+
35
+ def self.finalize(client,hkey)
36
+ proc { self.close(client,hkey) }
37
+ end
38
+
39
+ ##
40
+ #
41
+ # Enumerators
42
+ #
43
+ ##
44
+
45
+ #
46
+ # Enumerates all of the child keys within this registry key.
47
+ #
48
+ def each_key(&block)
49
+ return enum_key.each(&block)
50
+ end
51
+
52
+ #
53
+ # Enumerates all of the child values within this registry key.
54
+ #
55
+ def each_value(&block)
56
+ return enum_value.each(&block)
57
+ end
58
+
59
+ #
60
+ # Retrieves all of the registry keys that are direct descendents of
61
+ # the class' registry key.
62
+ #
63
+ def enum_key()
64
+ return self.client.sys.registry.enum_key(self.hkey)
65
+ end
66
+
67
+ #
68
+ # Retrieves all of the registry values that exist within the opened
69
+ # registry key.
70
+ #
71
+ def enum_value()
72
+ return self.client.sys.registry.enum_value(self.hkey)
73
+ end
74
+
75
+
76
+ ##
77
+ #
78
+ # Registry key interaction
79
+ #
80
+ ##
81
+
82
+ #
83
+ # Opens a registry key that is relative to this registry key.
84
+ #
85
+ def open_key(base_key, perm = KEY_READ)
86
+ return self.client.sys.registry.open_key(self.hkey, base_key, perm)
87
+ end
88
+
89
+ #
90
+ # Creates a registry key that is relative to this registry key.
91
+ #
92
+ def create_key(base_key, perm = KEY_READ)
93
+ return self.client.sys.registry.create_key(self.hkey, base_key, perm)
94
+ end
95
+
96
+ #
97
+ # Deletes a registry key that is relative to this registry key.
98
+ #
99
+ def delete_key(base_key, recursive = true)
100
+ return self.client.sys.registry.delete_key(self.hkey, base_key, recursive)
101
+ end
102
+
103
+ #
104
+ # Closes the open key. This must be called if the registry
105
+ # key was opened.
106
+ #
107
+ def self.close(client, hkey)
108
+ if hkey != nil
109
+ return client.sys.registry.close_key(hkey)
110
+ end
111
+
112
+ return false
113
+ end
114
+
115
+ # Instance method for the same
116
+ def close()
117
+ self.class.close(self.client, self.hkey)
118
+ end
119
+
120
+ ##
121
+ #
122
+ # Registry value interaction
123
+ #
124
+ ##
125
+
126
+ #
127
+ # Sets a value relative to the opened registry key.
128
+ #
129
+ def set_value(name, type, data)
130
+ return self.client.sys.registry.set_value(self.hkey, name, type, data)
131
+ end
132
+
133
+ #
134
+ # Queries the attributes of the supplied registry value relative to
135
+ # the opened registry key.
136
+ #
137
+ def query_value(name)
138
+ return self.client.sys.registry.query_value(self.hkey, name)
139
+ end
140
+
141
+ #
142
+ # Queries the class of the specified key
143
+ #
144
+ def query_class
145
+ return self.client.sys.registry.query_class(self.hkey)
146
+ end
147
+
148
+ #
149
+ # Delete the supplied registry value.
150
+ #
151
+ def delete_value(name)
152
+ return self.client.sys.registry.delete_value(self.hkey, name)
153
+ end
154
+
155
+ ##
156
+ #
157
+ # Serializers
158
+ #
159
+ ##
160
+
161
+ #
162
+ # Returns the path to the key.
163
+ #
164
+ def to_s
165
+ return "\\\\" + self.target_host + "\\" + self.root_key.to_s + "\\"
166
+ end
167
+
168
+ #
169
+ # The open handle to the key on the server.
170
+ #
171
+ attr_reader :hkey
172
+ #
173
+ # The root key name, such as HKEY_LOCAL_MACHINE.
174
+ #
175
+ attr_reader :root_key
176
+ #
177
+ # The remote machine name, such as PDC01
178
+ #
179
+ attr_reader :target_host
180
+
181
+ protected
182
+
183
+ attr_accessor :client # :nodoc:
184
+ attr_writer :hkey, :root_key, :target_host # :nodoc:
185
+ end
186
+
187
+ end; end; end; end; end; end; end
188
+