@@ -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,15 @@ 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_count ||= 0
170
+ capture . each do |pkt |
171
+ yield ( pkt )
172
+ @capture_count += 1
184
173
end
185
-
186
174
@capture_count
187
175
end
188
176
@@ -242,10 +230,9 @@ def inject_pcap(pcap_file, filter=nil, delay = 0, pcap=self.capture)
242
230
pcap . inject ( pkt )
243
231
Rex . sleep ( ( delay * 1.0 ) /1000 )
244
232
end
245
- GC . start
246
233
end
247
234
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
249
236
# a payload and a destination address. To send to the broadcast address, set bcast
250
237
# to true (this will guarantee that packets will be sent even if ARP doesn't work
251
238
# out).
@@ -262,24 +249,20 @@ def capture_sendto(payload="", dhost=nil, bcast=false, dev=nil)
262
249
263
250
# The return value either be a PacketFu::Packet object, or nil
264
251
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
278
261
end
279
- rescue ::Timeout ::Error
280
262
end
263
+ rescue ::Timeout ::Error
281
264
end
282
- return reply
265
+ nil
283
266
end
284
267
285
268
# This ascertains the correct Ethernet addresses one should use to
@@ -328,20 +311,19 @@ def probe_gateway(addr)
328
311
end
329
312
330
313
begin
331
- to = ( datastore [ 'TIMEOUT' ] || 1500 ) . to_f / 1000.0
314
+ to = ( ( datastore [ 'TIMEOUT' ] || 500 ) . to_f * 8 ) / 1000.0
332
315
::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 ]
341
323
end
342
324
end
343
325
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
345
327
# VMWare network interfaces. We'll need to use a fake source hardware address.
346
328
self . arp_cache [ Rex ::Socket . source_address ( addr ) ] = "00:00:00:00:00:00"
347
329
end
@@ -354,26 +336,31 @@ def arp(target_ip=nil)
354
336
return self . arp_cache [ :gateway ] unless should_arp? target_ip
355
337
source_ip = Rex ::Socket . source_address ( target_ip )
356
338
raise RuntimeError , "Could not access the capture process." unless self . arp_capture
339
+
357
340
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
368
356
self . arp_cache [ target_ip ] = my_packet . eth_saddr
369
357
return self . arp_cache [ target_ip ]
370
- else
371
- next
372
358
end
373
359
end
360
+ rescue ::Timeout ::Error
374
361
end
375
- rescue ::Timeout ::Error
376
362
end
363
+ nil
377
364
end
378
365
379
366
# Creates a full ARP packet, mainly for use with inject_eth()
0 commit comments