@@ -42,7 +42,7 @@ def initialize(info = {})
4242 [
4343 true ,
4444 '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 ' ] ) ,
4646 OptPort . new ( 'GATEWAY_PROBE_PORT' ,
4747 [
4848 false ,
@@ -143,7 +143,6 @@ def close_pcap
143143 return unless self . capture
144144 self . capture = nil
145145 self . arp_capture = nil
146- GC . start ( )
147146 end
148147
149148 def capture_extract_ies ( raw )
@@ -163,26 +162,14 @@ def capture_extract_ies(raw)
163162 end
164163
165164 #
166- # This monstrosity works around a series of bugs in the interrupt
167- # signal handling of Ruby 1.9
165+ # Loop through each packet
168166 #
169167 def each_packet
170168 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
184172 end
185-
186173 @capture_count
187174 end
188175
@@ -242,10 +229,9 @@ def inject_pcap(pcap_file, filter=nil, delay = 0, pcap=self.capture)
242229 pcap . inject ( pkt )
243230 Rex . sleep ( ( delay * 1.0 ) /1000 )
244231 end
245- GC . start
246232 end
247233
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
249235 # a payload and a destination address. To send to the broadcast address, set bcast
250236 # to true (this will guarantee that packets will be sent even if ARP doesn't work
251237 # out).
@@ -262,24 +248,20 @@ def capture_sendto(payload="", dhost=nil, bcast=false, dev=nil)
262248
263249 # The return value either be a PacketFu::Packet object, or nil
264250 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
278260 end
279- rescue ::Timeout ::Error
280261 end
262+ rescue ::Timeout ::Error
281263 end
282- return reply
264+ nil
283265 end
284266
285267 # This ascertains the correct Ethernet addresses one should use to
@@ -328,20 +310,19 @@ def probe_gateway(addr)
328310 end
329311
330312 begin
331- to = ( datastore [ 'TIMEOUT' ] || 1500 ) . to_f / 1000.0
313+ to = ( ( datastore [ 'TIMEOUT' ] || 500 ) . to_f * 8 ) / 1000.0
332314 ::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 ]
341322 end
342323 end
343324 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
345326 # VMWare network interfaces. We'll need to use a fake source hardware address.
346327 self . arp_cache [ Rex ::Socket . source_address ( addr ) ] = "00:00:00:00:00:00"
347328 end
@@ -354,26 +335,31 @@ def arp(target_ip=nil)
354335 return self . arp_cache [ :gateway ] unless should_arp? target_ip
355336 source_ip = Rex ::Socket . source_address ( target_ip )
356337 raise RuntimeError , "Could not access the capture process." unless self . arp_capture
338+
357339 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
368355 self . arp_cache [ target_ip ] = my_packet . eth_saddr
369356 return self . arp_cache [ target_ip ]
370- else
371- next
372357 end
373358 end
359+ rescue ::Timeout ::Error
374360 end
375- rescue ::Timeout ::Error
376361 end
362+ nil
377363 end
378364
379365 # Creates a full ARP packet, mainly for use with inject_eth()
0 commit comments