Passive service locator, a python sniffer that identifies servers, clients, names and much more
Quick notes for getting going with passer, the passive service sniffer. You're responsible for getting permission to sniff.
Passer can work off a live packet capture or from a pcap file (command line parameter, see examples below). It reports live services and clients, ethernet cards on the lan, dns entries, operating systems, and routers - all passively!
If you're using windows or your paths to the support files don't match mine for some other reason, let me know where they are and I'll be glad to update the script.
# Install system dependencies sudo apt-get install arp-scan ettercap-text-only nmap wireshark # Install python dependencies sudo pip install -r requirements.txt # Prevent Scapy from performing DNS lookups echo 'noenum = [ Resolve(), TCP_SERVICES, UDP_SERVICES ]' >> ~/.scapy_startup.py
# Install system dependencies sudo yum install arp-scan ettercap nmap wireshark # Install python dependencies sudo pip install -r requirements.txt # Prevent Scapy from performing DNS lookups echo 'noenum = [ Resolve(), TCP_SERVICES, UDP_SERVICES ]' >> ~/.scapy_startup.py
To install scapy, see the installation guide.
Passer also comes packaged as a Docker image. If you don't already have Docker here is a quick and dirty way to install it on Linux:
curl -fsSL https://get.docker.com | sh -
Otherwise, follow the install instructions for your operating system.
For most uses, we recommend the
passer script included in this repo. This script will handle all docker-specific
wget https://raw.githubusercontent.com/activecm/passer/master/passer chmod +x passer
You can then use this script just as you would in any of the examples below. For example:
./passer -i eth0 # The equivalent without using the included script would be: docker run --rm --name=passer -i --init --net=host --cap-add=net_raw activecm/passer -i eth0
In order to stop passer run:
docker stop passer
This sniffs from all network interfaces and sends all output lines to your console.
su - -c '/path/to/passer.py'
/path/to/passer.py -i IfaceName
route should give some live interfaces you might use.
-iis incompatible with
/path/to/passer.py -r /path/to/packets.pcap
-ris incompatible with
cat packetdata.pcap | ./passer.py -r /proc/self/fd/0 zcat packetdata.pcap.gz | ./passer.py -r /proc/self/fd/0 bzcat packetdata.pcap.bz2 | ./passer.py -r /proc/self/fd/0 tcpdump -i eth0 -qtnp -w - | ./passer.py -r /proc/self/fd/0 # etc...
This lets you capture packets with any tool that can save packets to a pcap file, and later process them with passer on a different system.
/path/to/passer.py -l /path/to/networkinfo.txt
/path/to/passer.py -u /path/to/oddpackets.pcap
This is generally intended for the development process; packets saved to this file are ones that need to have signatures written. If you'd like to help improve the program, get in touch with the author, Bill Stearns ([email protected]). Contributions of odd packets, descriptions of services, and patches to the program are gratefully accepted.
This should be as simple as placing the BPF filter in single quotes at the end of the command line. As of version 1.16, the underlying library does not appear to successfully use the supplied filter, but there's a workaround. Use tcpdump to do the filtering, and hand the pared-down set of packets to passer on stdin, like above:
tcpdump -r packets.pcap -w - 'icmp or arp' | ./passer.py -r /proc/self/fd/0
See the "Sample filters" section, below, for some suggestions of filters to use in either capturing packets in advance or live sniffing.
socket.error: (1, 'Operation not permitted')
You're probably trying to sniff live as a non-root user. Either log in as root, use sudo/su, or work with pcap files.
If passer crashes or won't work on your system, send me an email (Bill Stearns, [email protected]). It would be very helpful if you could include the error message, if any, and any details about your operating system.
Passer's output goes to stdout, and if you give the command line
-l /path/to/logfile, to that file as well. Here's the format:
|Type||IPAddr||Proto||State||Optional description (may be empty)|
|'IP'||IPaddr||'IP'||dead or live||p0f OS description|
|'TC'||IPaddr||'TCP_'Port||closed or open||client description|
|'TS'||IPaddr||'TCP_'Port||closed or listening||server description|
|'UC'||IPaddr||'UDP_'Port||open or closed||udp client port description|
|'US'||IPaddr||'UDP_'Port||open or closed||udp server port description|
|'DN'||IPaddr||'A' or 'PTR'||hostname||possible extra info|
|'RO'||IPaddr||'TTLEx'||router||possible extra info|
Lines are comma separated for easy loading into a spreadsheet or SQL import. None of the fields should contain commas. There is a sample output file at http://www.stearns.org/passer/passer-sample-log.txt .
Here are some examples of how to get the data you want out of these lines:
cat /var/tmp/passer-log | sort -u | less
cat /var/tmp/passer-log | sort -t, -k2 -u | less
cat /var/tmp/passer-log | sort -u | egrep '(^DN|^RO)' | less
cat /var/tmp/passer-log | sort -u | grep ',192\.168\.0\.17,' | less
cat /var/tmp/passer-log | sort -u | grep ',192\.168\.' | less
cat /var/tmp/passer-log | sort -u | grep ',TCP_25,listening,' | less
cat /var/tmp/passer-log | sort -u | grep -v ',closed,' | less
cat /var/tmp/passer-log | sort -u | grep ',closed,' | less
cat /var/tmp/passer-log | sort -u | grep -i 'google\.com\.,' | less
/path/to/make-hosts /var/tmp/passer-log | /path/to/mergehosts.pl >/var/tmp/passer-hosts
"make-hosts" and merge-hosts are separate shell and perl scripts at http://www.stearns.org/passer/make-hosts .
This is just a start! Send in your favourite ways to extract items of interest and I'll add them and give you credit.
The individual record types need certain types of packets to give them their raw data. If you want to include or exclude these, use the accompanying filter.
'IP', IPaddr, 'IP', dead or live, p0f OS description
This needs TCP SYN packets:
'tcp & 0x12 = 0x02'
'MA', IPaddr, 'Ethernet', MacAddr, ManufDescription
These come from arp replies(*1):
'TC', IPaddr, 'TCP_'Port, closed or open, client description
These need TCP SYN/ACK's, FIN's and RST's(*2):
'tcp & 0x07 != 0'
'TS', IPaddr, 'TCP_'Port, closed or listening, server description
We need TCP SYN's, SYN/ACK's, and RST's to see if the port is open or closed:
'tcp & 0x06 != 0'
To come up with a server description string, we also need to see the ACK packets that make up the bulk of the traffic on the wire:
'tcp & 0x17 = 0x10'
If you want both, just grab all TCP traffic:
'UC', IPaddr, 'UDP_'Port, open or closed, udp client port description
Easiest to just hand it all udp ports and ICMP port unreachables:
'udp or icmp[0:2] = 0x0303'
'US', IPaddr, 'UDP_'Port, open or closed, udp server port description
Same as above:
'udp or icmp[0:2] = 0x0303'
'DN', IPaddr, A,AAAA,PTR,CNAME hostname, possible extra info
UDP or TCP port 53 (*3):
'udp src port 53 or tcp src port 53'
'RO', IPaddr, 'TTLEx', router, possible extra info
We identify routers because they're sending Time-To-Live-Exceeded or unreachable messages:
'icmp[0:2] = 0x0B00 or icmp = 0x03'
*1 This grabs arp requests too, but these are ignored.
*2 The filter technically includes SYNs as well, but that's a small amount of extra data
*3 As of version 1.16, only UDP port 53 answers are extracted.
'not(tcp & 0x17 = 0x10)'
This chops out 90+% of the number and volume of packets to be handled, letting passer keep up with moderate bandwidth links.
'not udp src port 53'
There's quite a bit of work to extract dns records; this may also be a good one to turn off if you're trying to keep up with a fast link.
'host 220.127.116.11' 'net 1.2'
Questions? Bug reports? Issues? Try [email protected] and please include "passer" somewhere in the subject line.