@@ -42,7 +42,7 @@ def initialize(info = {})
42
42
[
43
43
true ,
44
44
'Send a TTL=1 random UDP datagram to this host to discover the default gateway\'s MAC' ,
45
- 'www.metasploit.com ' ] ) ,
45
+ '8.8.8.8 ' ] ) ,
46
46
OptPort . new ( 'GATEWAY_PROBE_PORT' ,
47
47
[
48
48
false ,
@@ -143,7 +143,6 @@ def close_pcap
143
143
return unless self . capture
144
144
self . capture = nil
145
145
self . arp_capture = nil
146
- GC . start ( )
147
146
end
148
147
149
148
def capture_extract_ies ( raw )
@@ -163,26 +162,14 @@ def capture_extract_ies(raw)
163
162
end
164
163
165
164
#
166
- # This monstrosity works around a series of bugs in the interrupt
167
- # signal handling of Ruby 1.9
165
+ # Loop through each packet
168
166
#
169
167
def each_packet
170
168
return unless capture
171
- begin
172
- @capture_count = 0
173
- reader = framework . threads . spawn ( "PcapReceiver" , false ) do
174
- capture . each do |pkt |
175
- yield ( pkt )
176
- @capture_count += 1
177
- end
178
- end
179
- reader . join
180
- rescue ::Exception
181
- raise $!
182
- ensure
183
- reader . kill if reader . alive?
169
+ capture . each do |pkt |
170
+ yield ( pkt )
171
+ @capture_count += 1
184
172
end
185
-
186
173
@capture_count
187
174
end
188
175
@@ -242,10 +229,9 @@ def inject_pcap(pcap_file, filter=nil, delay = 0, pcap=self.capture)
242
229
pcap . inject ( pkt )
243
230
Rex . sleep ( ( delay * 1.0 ) /1000 )
244
231
end
245
- GC . start
246
232
end
247
233
248
- # Capture_sendto is intended to replace the old Rex::Socket::Ip.sendto method. It requires
234
+ # capture_sendto is intended to replace the old Rex::Socket::Ip.sendto method. It requires
249
235
# a payload and a destination address. To send to the broadcast address, set bcast
250
236
# to true (this will guarantee that packets will be sent even if ARP doesn't work
251
237
# out).
@@ -262,24 +248,20 @@ def capture_sendto(payload="", dhost=nil, bcast=false, dev=nil)
262
248
263
249
# The return value either be a PacketFu::Packet object, or nil
264
250
def inject_reply ( proto = :udp , pcap = self . capture )
265
- reply = nil
266
- to = ( datastore [ 'TIMEOUT' ] || 500 ) . to_f / 1000.0
267
- if not pcap
268
- raise RuntimeError , "Could not access the capture process (remember to open_pcap first!)"
269
- else
270
- begin
271
- ::Timeout . timeout ( to ) do
272
- pcap . each do |r |
273
- packet = PacketFu ::Packet . parse ( r )
274
- next unless packet . proto . map { |x | x . downcase . to_sym } . include? proto
275
- reply = packet
276
- break
277
- end
251
+ # Defaults to ~2 seconds
252
+ to = ( datastore [ 'TIMEOUT' ] * 4 ) / 1000.0
253
+ raise RuntimeError , "Could not access the capture process (remember to open_pcap first!)" if not pcap
254
+ begin
255
+ ::Timeout . timeout ( to ) do
256
+ pcap . each do |r |
257
+ packet = PacketFu ::Packet . parse ( r )
258
+ next unless packet . proto . map { |x | x . downcase . to_sym } . include? proto
259
+ return packet
278
260
end
279
- rescue ::Timeout ::Error
280
261
end
262
+ rescue ::Timeout ::Error
281
263
end
282
- return reply
264
+ nil
283
265
end
284
266
285
267
# This ascertains the correct Ethernet addresses one should use to
@@ -328,20 +310,19 @@ def probe_gateway(addr)
328
310
end
329
311
330
312
begin
331
- to = ( datastore [ 'TIMEOUT' ] || 1500 ) . to_f / 1000.0
313
+ to = ( ( datastore [ 'TIMEOUT' ] || 500 ) . to_f * 8 ) / 1000.0
332
314
::Timeout . timeout ( to ) do
333
- while ( my_packet = inject_reply ( :udp , self . arp_capture ) )
334
- if my_packet . payload == secret
335
- dst_mac = self . arp_cache [ :gateway ] = my_packet . eth_daddr
336
- src_mac = self . arp_cache [ Rex ::Socket . source_address ( addr ) ] = my_packet . eth_saddr
337
- return [ dst_mac , src_mac ]
338
- else
339
- next
340
- end
315
+ while true
316
+ my_packet = inject_reply ( :udp , self . arp_capture )
317
+ next unless my_packet
318
+ next unless my_packet . payload == secret
319
+ dst_mac = self . arp_cache [ :gateway ] = my_packet . eth_daddr
320
+ src_mac = self . arp_cache [ Rex ::Socket . source_address ( addr ) ] = my_packet . eth_saddr
321
+ return [ dst_mac , src_mac ]
341
322
end
342
323
end
343
324
rescue ::Timeout ::Error
344
- # Well, that didn't work (this common on networks where there's no gatway , like
325
+ # Well, that didn't work (this is common on networks where there's no gateway , like
345
326
# VMWare network interfaces. We'll need to use a fake source hardware address.
346
327
self . arp_cache [ Rex ::Socket . source_address ( addr ) ] = "00:00:00:00:00:00"
347
328
end
@@ -354,26 +335,31 @@ def arp(target_ip=nil)
354
335
return self . arp_cache [ :gateway ] unless should_arp? target_ip
355
336
source_ip = Rex ::Socket . source_address ( target_ip )
356
337
raise RuntimeError , "Could not access the capture process." unless self . arp_capture
338
+
357
339
p = arp_packet ( target_ip , source_ip )
358
- inject_eth ( :eth_type => 0x0806 ,
359
- :payload => p ,
360
- :pcap => self . arp_capture ,
361
- :eth_saddr => self . arp_cache [ Rex ::Socket . source_address ( target_ip ) ]
362
- )
363
- begin
364
- to = ( datastore [ 'TIMEOUT' ] || 500 ) . to_f / 1000.0
365
- ::Timeout . timeout ( to ) do
366
- while ( my_packet = inject_reply ( :arp , self . arp_capture ) )
367
- if my_packet . arp_saddr_ip == target_ip
340
+
341
+ # Try up to 3 times to get an ARP response
342
+ 1 . upto ( 3 ) do
343
+ inject_eth ( :eth_type => 0x0806 ,
344
+ :payload => p ,
345
+ :pcap => self . arp_capture ,
346
+ :eth_saddr => self . arp_cache [ Rex ::Socket . source_address ( target_ip ) ]
347
+ )
348
+ begin
349
+ to = ( ( datastore [ 'TIMEOUT' ] || 500 ) . to_f * 8 ) / 1000.0
350
+ ::Timeout . timeout ( to ) do
351
+ while true
352
+ my_packet = inject_reply ( :arp , self . arp_capture )
353
+ next unless my_packet
354
+ next unless my_packet . arp_saddr_ip == target_ip
368
355
self . arp_cache [ target_ip ] = my_packet . eth_saddr
369
356
return self . arp_cache [ target_ip ]
370
- else
371
- next
372
357
end
373
358
end
359
+ rescue ::Timeout ::Error
374
360
end
375
- rescue ::Timeout ::Error
376
361
end
362
+ nil
377
363
end
378
364
379
365
# Creates a full ARP packet, mainly for use with inject_eth()
0 commit comments