Hello again, in this blog post, I will be detailing how I used Scapy to gain more analysis from my .pcap captures. Please see my prior post where I captured wireless packet information using Mac’s built-in WiFi sniffer. 

Scapy is a powerful Python library for packet manipulation. It allows you to create, send, capture, and analyze network packets. While it’s commonly used for crafting custom packets and network exploration, it doesn’t directly edit existing PCAP files. Instead, Scapy enables you to build packets from scratch or modify their fields programmatically.

Using Scapy

To use Scapy you need to first have python3 installed. Scapy can then be installed by the following command:

pip install scapy

I will be utilizing the packet processing feature to read in the packets I captured in my previous post. This script will print the source IP, destination IP, and some other HTTP header info. Attached is the code I used to do that.  

from scapy.all import *
import re


def process_packet(packet, output_file, ssid_filter):
    """
    Process each packet in the pcap file.
    """
    with open(output_file, "a") as file:
        # Example: Print the summary of the packet
        file.write(packet.summary() + "\n")

        # You can access more attributes of the packet and perform analysis here
        # Example: Print the source and destination IP addresses
        if IP in packet:
            file.write("Source IP: " + packet[IP].src + "\n")
            file.write("Destination IP: " + packet[IP].dst + "\n")

        # Example: Print the source and destination ports for TCP/UDP packets
        if TCP in packet:
            file.write("Source Port (TCP): " + str(packet[TCP].sport) + "\n")
            file.write("Destination Port (TCP): " + str(packet[TCP].dport) + "\n")
            # Example: Print TCP flags
            file.write("TCP Flags: " + str(packet[TCP].flags) + "\n")
            # Example: Look for HTTP requests
            if packet.haslayer(Raw):
                load = packet[Raw].load.decode(errors='ignore')
                if load.startswith("GET") or load.startswith("POST"):
                    file.write("HTTP Request:\n")
                    file.write(load + "\n")
                    # Extracting host from HTTP request
                    host = re.search(r'Host: (.+?)\r\n', load)
                    if host:
                        file.write("Requested Host: " + host.group(1) + "\n")

        elif UDP in packet:
            file.write("Source Port (UDP): " + str(packet[UDP].sport) + "\n")
            file.write("Destination Port (UDP): " + str(packet[UDP].dport) + "\n")

        # Look for DNS queries
        if DNS in packet:
            dns_layer = packet.getlayer(DNS)
            if dns_layer and dns_layer.opcode == 0 and dns_layer.qd:
                file.write("DNS Query: " + dns_layer.qd.qname.decode() + "\n")

        # Look for ARP packets
        if ARP in packet:
            if packet.op == 1:  # ARP request
                file.write("ARP Request: Who has " + packet.pdst + "? Tell " + packet.psrc + "\n")
            elif packet.op == 2:  # ARP reply
                file.write("ARP Reply: " + packet.psrc + " is at " + packet.hwsrc + "\n")
                # Example: Infer device type based on MAC address
                mac_address = packet.hwsrc
                if mac_address.startswith("00:50:56"):  # VMware virtual machine
                    file.write("Device Type: VMware Virtual Machine\n")
                elif mac_address.startswith("00:1E:8C"):  # Cisco device
                    file.write("Device Type: Cisco Device\n")
                elif mac_address.startswith("00:0C:29"):  # VMware virtual machine
                    file.write("Device Type: VMware Virtual Machine\n")
                # Add more conditions as needed for other device types

        # Filter packets for specific SSID
        if packet.haslayer(Dot11) and packet.type == 0 and packet.subtype == 8:  # Management frames (type=0, subtype=8)
            ssid = packet[Dot11Elt].info.decode()
            if ssid == ssid_filter:
                file.write("SSID: " + ssid + "\n")

        # Look for HTTP requests
        if packet.haslayer(Raw):
            load = packet[Raw].load.decode(errors='ignore')
            if load.startswith("GET") or load.startswith("POST"):
                file.write("HTTP Request:\n")
                file.write(load + "\n")
                # Extracting host from HTTP request
                host = re.search(r'Host: (.+?)\r\n', load)
                if host:
                    file.write("Requested Host: " + host.group(1) + "\n")

def main():
    #SIOBHAN CHANGE 
    pcap_file = "~/desktop/long_canisius.pcap"
    output_file = "l_canisius.txt"
    ssid_filter = "canisius_guest"  # Specify the SSID you want to filter for

    packets = rdpcap(pcap_file)

    # Process each packet
    for packet in packets:
        process_packet(packet, output_file, ssid_filter )

if __name__ == "__main__":
    main()

Scapy allows you to filter packets based on specific criteria. Filtering helps you selectively process only the packets that match certain conditions. This allows for me to filter specifically onto the network that I am looking to target and exclude any nuisance traffic that may also be on the scan.  In the instance below I provide an example of how I filtered on my University’s guest wireless network. You can imagine being in any public location with free wifi and doing the same.

What It Tells Us

The output is recorded in a text file that is easier to read.  What does this tell us. One item is – where are people connecting to – the Destination IP. Using the NordVPN IP lookup, we see it goes to Google. See the image below – this person was connecting to the Google search site.

All of the HTTP traffic that I was able to collect is on port 443. This means it’s all encrypted. The next hurdle will be tackling to see if I can find ways to leverage the encrypted web traffic.