Determining Windows application ports
Situation: we wanted to determine all network ports used by various
Windows applications. Our solution consisted of capturing all network
traffic with WinDump while executing the applications, and analyzing
the traffic with a UNIX shell script. Cygwin was installed on the
Windows machines to provide us with the UNIX shell and utilities used
to analyze the network traffic.
The goal of the solution was to provide a client with a set of firewall
rules needed for the Windows applications to function in a firewalled
environment. The solution is not perfect: the network captures include
all traffic, some of which is not generated by the application.
However,
after running the application packet captures through the analyzer
script, it should become obvious which traffic was generated by the
applications.
1. On a Windows machine, install WinPCap,
WinDump, and
Cygwin.
2. Open up a Command Prompt, and run WinDump
-n -w application_name
The -n disables DNS
reverse-lookups, and -w writes
the output in binary format.
3. Thoroughly test the application.
4. Stop the WinDump capture.
5. Repeat steps 2 through 4 for all applicable Windows applications.
6. Run Cygwin, and analyze one or more application_name binary WinDump
capture(s) with the following Bourne shell script.
Before executing the
script, change the values of IP_ADDRESS,
DB_ADDRESS, WINDUMP, USE_NSLOOKUP, and DNS_DATA. In this example, nslookup is used to determine
hostname information instead of searching the $DNS_DATA file.
#!/bin/sh
# The script requires the IP address of the machine that ran
# the packet capture and the WINDUMP capture file in binary
# format as arguments
if [ "$#" -lt 1 ] ; then
echo "Usage: $0 WINDUMP_capture_file(s)"
exit 1
fi
# Declare variables
# IP address of machine that ran packet capture
IP_ADDRESS=192.168.1.100
# Subnet directed broadcast address of machine that ran packet capture
# Ex. 192.168.1.51/25 (255.255.255.128 subnet mask) = 192.168.1.127
# Ex. 192.168.1.152/25 (255.255.255.128 subnet mask) = 192.168.1.255
DB_ADDRESS=192.168.1.127
# Path to WinDump executable
WINDUMP=/cygdrive/c/windump/WinDump.exe
# If $USE_NSLOOKUP is "true", use "nslookup" for DNS resolution
# Otherwise, set $USE_NSLOOKUP to "false" to search for hostnames in $DNS_DATA
USE_NSLOOKUP=true
DNS_DATA=/cygdrive/c/windump/DNS_data
# Berkeley Packet Format (BPF) filters
# Outbound traffic
# Interested in traffic from the host's IP address (src host $1)
# Interested in IP traffic (ip)
# Not interested in broadcast traffic (dst host 255.255.255.255)
# Not interested in directed broadcast traffic (dst host $DB_ADDRESS)
# Not interested in multicast traffic (dst net 224.0.0.0/24)
# Inbound traffic
# Interested in TCP SYN packets destined to $IP_ADDRESS
for FILE in $@
do
# Outbound traffic
$WINDUMP -n -r $FILE "\
src host $IP_ADDRESS and \
ip and \
not (dst host 255.255.255.255) and \
not (dst host $DB_ADDRESS) and \
not (dst net 224.0.0/24)" 2>/dev/null \
| awk '{if ($6 ~ /UDP,/) PROTO = "udp"; else PROTO = "tcp"} {print $5"\t"PROTO"\t"FILE}' FILE=$FILE | sort | uniq -c | sort -n >> $$_outbound.tmp
# Inbound traffic
$WINDUMP -n -r $FILE 2>/dev/null \
| awk '$6 == "S" && $8 == "win" && $5 ~ IP_ADDRESS {print $3"\ttcp\t"FILE"\t"$5}' FILE=$FILE IP_ADDRESS=$IP_ADDRESS | sort | uniq -c | sort -n >> $$_inbound.tmp
done
# Generate report sorted by occurrence(s) of network traffic
printf "Outbound traffic\n\n"
printf "%-4s %-10s %-15s %-22s %s\n" "Mtch" "App" "Destination" "Prot/Port/Srv" "Hostname"
printf "%-4s %-10s %-15s %-22s %s\n" "----" "----------" "---------------" "----------------------" "--------"
while read LINE
do
set $LINE
COUNT=$1
DST_IP=`echo $2 | cut -d. -f1-4`
DST_PORT=`echo $2 | cut -d. -f5 | tr -d ':'`
PROTO=$3
FILE=$4
SERVICE=`grep -w "${DST_PORT}/${PROTO}" /etc/services | awk '{print $1}'`
# If $USE_NSLOOKUP is true, use "nslookup" for DNS resolution
# Otherwise, search for hostnames in $DNS_DATA
if [ "$USE_NSLOOKUP" = true ] ; then
HOSTNAME=`nslookup $DST_IP 2>/dev/null | awk 'NR == 4 && $1 ~ /^Address:/ {print $2}'`
else
HOSTNAME=`grep $DST_IP $DNS_DATA | awk '{print $1}' | head -n1`
fi
if [ -n "$SERVICE" ] ; then
printf "%-4s %-10s %-15s %-22s %s\n" $COUNT $FILE $DST_IP "${PROTO}/${DST_PORT} (${SERVICE})" $HOSTNAME
else
printf "%-4s %-10s %-15s %-22s %s\n" $COUNT $FILE $DST_IP "${PROTO}/${DST_PORT}" $HOSTNAME
fi
done < $$_outbound.tmp
printf "\nInbound traffic\n\n"
printf "%-4s %-10s %-15s %-22s %s\n" "Sess" "App" "Source" "Prot/Port/Srv" "Hostname"
printf "%-4s %-10s %-15s %-22s %s\n" "----" "----------" "---------------" "----------------------" "--------"
while read LINE
do
set $LINE
COUNT=$1
SRC_IP=`echo $2 | cut -d. -f1-4`
DST_PORT=`echo $5 | cut -d. -f5 | tr -d ':'`
PROTO=$3
FILE=$4
SERVICE=`grep -w "${DST_PORT}/${PROTO}" /etc/services | awk '{print $1}'`
# If $USE_NSLOOKUP is true, use "nslookup" for DNS resolution
# Otherwise, search for hostnames in $DNS_DATA
if [ "$USE_NSLOOKUP" = true ] ; then
HOSTNAME=`nslookup $DST_IP 2>/dev/null | awk 'NR == 4 && $1 ~ /^Address:/ {print $2}'`
else
HOSTNAME=`grep $DST_IP $DNS_DATA | awk '{print $1}' | head -n1`
fi
if [ -n "$SERVICE" ] ; then
printf "%-4s %-10s %-15s %-22s %s\n" $COUNT $FILE $SRC_IP "${PROTO}/${DST_PORT} (${SERVICE})" $HOSTNAME
else
printf "%-4s %-10s %-15s %-22s %s\n" $COUNT $FILE $SRC_IP "${PROTO}/${DST_PORT}" $HOSTNAME
fi
done < $$_inbound.tmp
# Remote temporary file
rm $$_outbound.tmp
rm $$_inbound.tmp
Example:
./analyze_traffic app1 app2
Outbound traffic
Mtch App
Destination
Prot/Port/Srv
Hostname
---- ---------- --------------- ---------------------- --------
1 app1 192.168.65.144
udp/137 (netbios-ns)
1 app1
192.168.73.66 tcp/53
(domain) host1.example.com
1 app1
192.168.20.247 tcp/443 (https)
2 app1
192.168.65.222
tcp/5432
host2.example.com
3 app1
192.168.248.15
tcp/8082
host3.example.com
4 app1
192.168.65.222
tcp/1084
host2.example.com
9 app1
192.168.9.17
tcp/1601
host4.example.com
9 app1
192.168.9.45 tcp/3593
96 app1
192.168.74.67
tcp/8080
host5.example.com
988 app1 192.168.65.222
tcp/4194
host2.example.com
1 app2
192.168.9.89 tcp/4621
2 app2
192.168.74.67
tcp/8080
host5.example.com
8 app2
192.168.9.39 tcp/1790
Inbound traffic
Sess App
Source
Prot/Port/Srv
Hostname
---- ---------- --------------- ---------------------- --------
1 app1
192.168.9.17 tcp/445 (microsoft-ds) host4.example.com
1 app1
192.168.9.45 tcp/445 (microsoft-ds)
1 app2
192.168.9.39 tcp/445 (microsoft-ds)
Explanation:
"Outbound traffic" is traffic initiated from IP_ADDRESS to "Destination," and
associated response traffic from "Destination" to IP_ADDRESS. Outbound traffic is
sorted by application and by the number of matches for the type of
traffic. Both TCP and UDP traffic is listed in the "Outbound traffic"
section.
"Inbound traffic" is traffic initiated from "Source" to IP_ADDRESS. Inbound traffic
is sorted by application and by the number of sockets created by the
source to the destination; this does not include the actual number of
packets in the "inbound traffic" exchange. Only TCP traffic is listed
in the "Inbound traffic" section.
Back to brandonhutchinson.com.
Last modified: 10/11/2004