How to Sniff a Network: Packet Sniffing on Windows and Linux
Network sniffers allow you to see packets entering and exiting a target machine. As a result, they have many practical uses before and after exploitation. In some cases, you’ll be able to use Wireshark (https://wireshark.org/) to monitor traffic or use a Pythonic solution like Scapy (which we’ll explore in the later posts). Nevertheless, you can read more: How to Sniff a Network : Raw Sockets and Sniffing.
Accessing raw sockets in Windows is slightly different than on its Linux brethren, but we want to have the flexibility to deploy the same sniffer to multiple platforms. We will create our socket object and then determine which platform we are running on. Windows requires us to set some additional flags through a socket input/output control (IOCTL),1 which enables promiscuous mode on the network interface. In our first example, we simply set up our raw socket sniffer, read in a single packet, and then quit.
import socket import os # host to listen on host = "192.168.0.196" # create a raw socket and bind it to the public interface if os.name == "nt": u socket_protocol = socket.IPPROTO_IP else: socket_protocol = socket.IPPROTO_ICMP sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) sniffer.bind((host, 0)) # we want the IP headers included in the capture v sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) # if we're using Windows, we need to send an IOCTL # to set up promiscuous mode w if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) # read in a single packet x print sniffer.recvfrom(65565) # if we're using Windows, turn off promiscuous mode y if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
We start by constructing our socket object with the parameters necessary for sniffing packets on our network interface u. The difference between Windows and Linux is that Windows will allow us to sniff all incoming packets regardless of protocol, whereas Linux forces us to specify that we are sniffing ICMP. Note that we are using promiscuous mode, which requires administrative privileges on Windows or root on Linux. Promiscuous mode allows us to sniff all packets that the network card sees, even those not destined for your specific host. Next we set a socket option v that includes the IP headers in our captured packets. The next step w is to determine if we are using Windows, and if so, we perform the additional step of sending an IOCTL to the network card driver to enable promiscuous mode. If you’re running Windows in a virtual machine, you will likely get a notification that the guest operating system is enabling promiscuous mode; you, of course, will allow it. Now we are ready to actually perform some sniffing, and in this case we are simply printing out the entire raw packet x with no packet decoding. This is just to test to make sure we have the core of our sniffing code working. After a single packet is sniffed, we again test for Windows, and disable promiscuous mode y before exiting the script.
Kicking the Tires
Open up a fresh terminal or cmd.exe shell under Windows and run the
In another terminal or shell window, you can simply pick a host to ping.
Here, we’ll ping nostarch.com:
In your first window where you executed your sniffer, you should see
some garbled output that closely resembles the following:
('E\x00\x00:\x0f\x98\x00\x00\x80\x11\xa9\x0e\xc0\xa8\x00\xbb\xc0\xa8\x0 0\x01\x04\x01\x005\x00&\xd6d\n\xde\x01\x00\x00\x01\x00\x00\x00\x00\x00\ x00\x08nostarch\x03com\x00\x00\x01\x00\x01', ('192.168.0.187', 0))
You can see that we have captured the initial ICMP ping request destined for nostarch.com (based on the appearance of the string nostarch.com).
If you are running this example on Linux, then you would receive the response from nostarch.com. Sniffing one packet is not overly useful, so let’s add some functionality to process more packets and decode their contents in the following post.