module Msf ### # # This module provides methods for receiving raw packets. # Please see the pcaprub documentation for more information. # ### module Exploit::Capture # # Initializes an instance of an exploit module that captures traffic # def initialize(info = {}) super register_options( [ OptPath.new('PCAPFILE', [false, 'The name of the PCAP capture file to process']), OptString.new('INTERFACE', [false, 'The name of the interface']), OptString.new('FILTER', [false, 'The filter string for capturing traffic']), OptInt.new('SNAPLEN', [true, 'The number of bytes to capture', 65535]), OptInt.new('TIMEOUT', [true, 'The number of seconds to wait for new data', 1]) ], Msf::Exploit::Capture ) require 'racket' begin require 'pcaprub' @pcaprub_loaded = true rescue ::Exception => e @pcaprub_loaded = false @pcaprub_error = e end end def stats_recv return(0) if not self.capture self.capture.stats['recv'] end def stats_drop return(0) if not self.capture self.capture.stats['drop'] end def stats_ifdrop return(0) if not self.capture self.capture.stats['ifdrop'] end # # Opens a handle to the specified device # def open_pcap(opts={}) if (not @pcaprub_loaded) print_status("The Pcaprub module is not available: #{@pcaprub_error}") raise RuntimeError, "Pcaprub not available" end # Capture device dev = nil len = (opts['SNAPLEN'] || datastore['SNAPLEN'] || 65535).to_i tim = (opts['TIMEOUT'] || datastore['TIMEOUT'] || 0).to_i fil = opts['FILTER'] || datastore['FILTER'] # Look for a PCAP file cap = datastore['PCAPFILE'] || '' if(not cap.empty?) if(not File.exists?(cap)) raise RuntimeError, "The PCAP file #{cap} could not be found" end self.capture = ::Pcap.open_offline(cap) else dev = datastore['INTERFACE'] || ::Pcap.lookupdev system("ifconfig", dev, "up") self.capture = ::Pcap.open_live(dev, len, true, tim) end if (not self.capture) raise RuntimeError, "Could not start the capture process" end self.capture.setfilter(fil) if fil end def close_pcap return if not self.capture self.capture = nil GC.start() end def capture_extract_ies(raw) set = {} ret = 0 idx = 0 len = 0 while (idx < raw.length) len = raw[idx+1] return set if not len set[ raw[idx] ] ||= [] set[ raw[idx] ].push(raw[idx + 2, len]) idx += len + 2 end return set end # # This monstrosity works around a series of bugs in the interrupt # signal handling of Ruby 1.9 # def each_packet return if not capture begin @capture_count = 0 reader = Thread.new do capture.each do |pkt| yield(pkt) @capture_count += 1 end end reader.join rescue ::Exception raise $! ensure reader.kill if reader.alive? end @capture_count end attr_accessor :capture end end