@@ -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,15 @@ 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_count ||= 0
170+ capture . each do |pkt |
171+ yield ( pkt )
172+ @capture_count += 1
184173 end
185-
186174 @capture_count
187175 end
188176
@@ -242,10 +230,9 @@ def inject_pcap(pcap_file, filter=nil, delay = 0, pcap=self.capture)
242230 pcap . inject ( pkt )
243231 Rex . sleep ( ( delay * 1.0 ) /1000 )
244232 end
245- GC . start
246233 end
247234
248- # Capture_sendto is intended to replace the old Rex::Socket::Ip.sendto method. It requires
235+ # capture_sendto is intended to replace the old Rex::Socket::Ip.sendto method. It requires
249236 # a payload and a destination address. To send to the broadcast address, set bcast
250237 # to true (this will guarantee that packets will be sent even if ARP doesn't work
251238 # out).
@@ -262,24 +249,20 @@ def capture_sendto(payload="", dhost=nil, bcast=false, dev=nil)
262249
263250 # The return value either be a PacketFu::Packet object, or nil
264251 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
252+ # Defaults to ~2 seconds
253+ to = ( datastore [ 'TIMEOUT' ] * 4 ) / 1000.0
254+ raise RuntimeError , "Could not access the capture process (remember to open_pcap first!)" if not pcap
255+ begin
256+ ::Timeout . timeout ( to ) do
257+ pcap . each do |r |
258+ packet = PacketFu ::Packet . parse ( r )
259+ next unless packet . proto . map { |x | x . downcase . to_sym } . include? proto
260+ return packet
278261 end
279- rescue ::Timeout ::Error
280262 end
263+ rescue ::Timeout ::Error
281264 end
282- return reply
265+ nil
283266 end
284267
285268 # This ascertains the correct Ethernet addresses one should use to
@@ -328,20 +311,19 @@ def probe_gateway(addr)
328311 end
329312
330313 begin
331- to = ( datastore [ 'TIMEOUT' ] || 1500 ) . to_f / 1000.0
314+ to = ( ( datastore [ 'TIMEOUT' ] || 500 ) . to_f * 8 ) / 1000.0
332315 ::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
316+ loop do
317+ my_packet = inject_reply ( :udp , self . arp_capture )
318+ next unless my_packet
319+ next unless my_packet . payload == secret
320+ dst_mac = self . arp_cache [ :gateway ] = my_packet . eth_daddr
321+ src_mac = self . arp_cache [ Rex ::Socket . source_address ( addr ) ] = my_packet . eth_saddr
322+ return [ dst_mac , src_mac ]
341323 end
342324 end
343325 rescue ::Timeout ::Error
344- # Well, that didn't work (this common on networks where there's no gatway , like
326+ # Well, that didn't work (this is common on networks where there's no gateway , like
345327 # VMWare network interfaces. We'll need to use a fake source hardware address.
346328 self . arp_cache [ Rex ::Socket . source_address ( addr ) ] = "00:00:00:00:00:00"
347329 end
@@ -354,26 +336,31 @@ def arp(target_ip=nil)
354336 return self . arp_cache [ :gateway ] unless should_arp? target_ip
355337 source_ip = Rex ::Socket . source_address ( target_ip )
356338 raise RuntimeError , "Could not access the capture process." unless self . arp_capture
339+
357340 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
341+
342+ # Try up to 3 times to get an ARP response
343+ 1 . upto ( 3 ) do
344+ inject_eth ( :eth_type => 0x0806 ,
345+ :payload => p ,
346+ :pcap => self . arp_capture ,
347+ :eth_saddr => self . arp_cache [ Rex ::Socket . source_address ( target_ip ) ]
348+ )
349+ begin
350+ to = ( ( datastore [ 'TIMEOUT' ] || 500 ) . to_f * 8 ) / 1000.0
351+ ::Timeout . timeout ( to ) do
352+ loop do
353+ my_packet = inject_reply ( :arp , self . arp_capture )
354+ next unless my_packet
355+ next unless my_packet . arp_saddr_ip == target_ip
368356 self . arp_cache [ target_ip ] = my_packet . eth_saddr
369357 return self . arp_cache [ target_ip ]
370- else
371- next
372358 end
373359 end
360+ rescue ::Timeout ::Error
374361 end
375- rescue ::Timeout ::Error
376362 end
363+ nil
377364 end
378365
379366 # Creates a full ARP packet, mainly for use with inject_eth()
0 commit comments