Introduction

Over the years various network packet capture tools have been released for the Windows platform. Two common tools that come to mind are the open-source Wireshark, and the Windows Message Analyzer from Microsoft.

On Linux platforms packet capture tools are typically installed and available to use. Even when not available installation is fairly simple, non-invasive and will normally have no impact on a server.

On Windows however, tools are not always installed and available, and normally require installation at the time it is required. Installation is not as simple, since most tools will require and install some form of kernel network driver. Any new driver introduces risk to the server’s stability, and the stability of the services it hosts.

Luckily, there are ways to capture packets on Windows without requiring software to be installed, and more importantly no kernel drivers!

In this post we discuss a novel method not typically known, which can be used to capture packets into the common and widley used PCAP file format.

Raw Sockets

A raw socket is a network socket created by an application which provides access and control to transport layer protocols, i.e. TCP and UDP. Raw sockets are typically associated with the IPv4 and IPv6 protocols.

When reading data from a non-raw socket only the payload data is received, and neither the ethernet, IP, UDP or TCP headers will be included. For example, given a DNS query over UDP, IP and ethernet, only the DNS payload would be given to the application reading from a UDP socket. For raw sockets the data is preceeded with the UDP or TCP header, and optionally the IP header. In our DNS case the data read from the socket would consist of the IP header, then the UDP header, which is then followed by the DNS payload.

After creating a raw socket, the sockets behaviour can be modified using various IO control codes, to instruct the networking stack to include even more packet data than would normally be included. The socket can be modified to report all IP packets that are sent and received by a network interface, regardless of their source and destination IP address, i.e. it can be used to sniff for packets.

The NoSpaceships raw-socket-sniffer project contains several programs that can be used on production servers to capture packets using this method, each producing PCAP files. The resulting PCAP files can be opened in tools such as WireShark installed on a different host.

Packet Capture with PowerShell

PowerShell provides considerable access to various system objects, ones which would normally require a compiled program. PowerShell scripts can use the New-Object interface to create raw sockets as follows (all of the code here is taken from the raw-socket-sniffer.ps1 file found in the raw-socket-sniffer projects repository):

$socket = New-object System.Net.Sockets.Socket( [Net.Sockets.AddressFamily]::InterNetwork, [Net.Sockets.SocketType]::Raw, [Net.Sockets.ProtocolType]::Unspecified )

The socket can then be modified to capture all inbound and outbound packets for a network interface with a specified IP address assigned:

$socket.Bind(( New-Object System.Net.IPEndPoint( [Net.IPAddress]"127.0.0.1", 0 ) )) $null = $socket.IOControl( [Net.Sockets.IOControlCode]::ReceiveAll, [BitConverter]::GetBytes(1), $null )

A simple loop can then be used to receive all packets:

$buffer = New-Object Byte[] $socket.ReceiveBufferSize while($true) { $rc = $socket.Receive($buffer, 0, $buffer.Length, 0) // Do something with the packet }

The same can be achieved in most programming languages, for example, here are the same steps in the C programming language (minus error handling for clarity):

SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_port = htons(0); bind(s, (struct sockaddr*) &addr, sizeof(addr)); int value = RCVALL_IPLEVEL; DWORD out = 0; WSAIoctl(s, SIO_RCVALL, &value, sizeof(value), NULL, 0, &out, NULL, NULL); unsigned char buffer[65535]; while (1) { int rc = recv(sd, (char*) buffer, 65535, 0); // Do something with the packet }

And here’s another example in Python:

import socket s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP) s.bind(("127.0.0.1", 0)) s.ioctl(socket.SIO_RCVALL, 1) while True: buffer = s.recvfrom(65565) # Do something with the packet

The programs available in the raw-socket-sniffer project are each documented in their source. Refer to each program’s source file to understand how packet capture is achieved.

Using the PowerShell Program

As an example, the following commands were used on a clean installation of Windows 2012 server - i.e. with no packet capture tools installed:

$url = "https://raw.githubusercontent.com/nospaceships/raw-socket-sniffer/master/raw-socket-sniffer.ps1" Invoke-WebRequest -Uri $url ` -OutFile "raw-socket-sniffer.ps1" PowerShell.exe -ExecutionPolicy bypass .\raw-socket-sniffer.ps1 ` -InterfaceIp "192.168.1.199" ` -CaptureFile "capture.cap"

After a while CTRL+C was used to stop the capture and the resulting capture.cap file copied to a host with WireShark installed. The capture.cap file was then double clicked. All the captured packets were then displayed (here a display filter has been used to show DNS packets only):

Summary

This post highlights how raw sockets can be used as a replacement for tools such as WireShark, to perform packet capture on Windows platforms without requiring and installing a kernel driver.

Here we introduced the NoSpaceships raw-socket-sniffer project which provides a reference for this method, and gives several complete programs which can be used as is to capture packets and create PCAP files.

If you have any questions, queries or feedback regarding this post please contact us >