Click here to Skip to main content
11,639,765 members (60,086 online)
Click here to Skip to main content

A Network Sniffer in C#

, 11 Feb 2008 CPOL 498.5K 28.2K 317
Rate this:
Please Sign up or sign in to vote.
A simple network sniffer which can parse IP, TCP, UDP, and DNS packets.
Sample Image - CSNetworkSniffer.jpg

Introduction

In this article, I will discuss the working of a simple network sniffer which can parse IP, TCP, UDP, and DNS packets.

Capturing the Packets

// For sniffing the socket to capture the packets 
// has to be a raw socket, with the address family
// being of type internetwork, and protocol being IP
mainSocket = newSocket(AddressFamily.InterNetwork, SocketType.Raw,
                       ProtocolType.IP);

// Bind the socket to the selected IP address
mainSocket.Bind(newIPEndPoint(IPAddress.Parse(cmbInterfaces.Text),0));

// Set the socket options
mainSocket.SetSocketOption(SocketOptionLevel.IP,  //Applies only to IP packets
                           SocketOptionName.HeaderIncluded, //Set the include header
                           true);                           //option to true

byte[] byTrue = newbyte[4]{1, 0, 0, 0};
byte[] byOut = newbyte[4];

//Socket.IOControl is analogous to the WSAIoctl method of Winsock 2
mainSocket.IOControl(IOControlCode.ReceiveAll,  //SIO_RCVALL of Winsock
                     byTrue, byOut);

//Start receiving the packets asynchronously
mainSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None,
                        newAsyncCallback(OnReceive), null);

For capturing the packets, we use a raw socket and bind it to the IP address. After setting the proper options for the socket, we then call the IOControl method on it. Notice that IOControl is analogous to the Winsock2WSAIoctl method. The IOControlCode.ReceiveAll implies that all incoming and outgoing packets on the particular interface be captured.

The second parameter passed to IOControl with IOControlCode.ReceiveAll should be TRUE so an array byTrue is created and passed to it (thanks to Leonid Molochniy for this). Next we start receiving all packets asynchronously.

Analysing the Packets

The IP datagram encapsulates the TCP and UDP packets. This further contains the data sent by the application layer protocols such as DNS, HTTP, FTP, SMTP, SIP, etc. Thus a TCP packet is received inside the IP datagram, like this:

                       
+-----------+------------+--------------------+
| IP header | TCP header |        Data        |  
+-----------+------------+--------------------+

So the first thing that we need to do is to parse the IP header. The stripped version of the IP header class is shown below, the comments describe the things as they happen.

public classIPHeader 
{ 
  //IP Header fields 
  private byte byVersionAndHeaderLength; // Eight bits for version and header 
                                         // length 
  private byte byDifferentiatedServices; // Eight bits for differentiated 
                                         // services
  private ushort usTotalLength;          // Sixteen bits for total length 
  private ushort usIdentification;       // Sixteen bits for identification
  private ushort usFlagsAndOffset;       // Eight bits for flags and frag. 
                                         // offset 
  private byte byTTL;                    // Eight bits for TTL (Time To Live) 
  private byte byProtocol;               // Eight bits for the underlying 
                                         // protocol 
  private short sChecksum;               // Sixteen bits for checksum of the 
                                         //  header 
  private uint uiSourceIPAddress;        // Thirty two bit source IP Address 
  private uint uiDestinationIPAddress;   // Thirty two bit destination IP Address 

  //End IP Header fields   
  private byte byHeaderLength;             //Header length 
  private byte[] byIPData = new byte[4096]; //Data carried by the datagram
  public IPHeader(byte[] byBuffer, int nReceived)
  {
    try
    {
    //Create MemoryStream out of the received bytes
    MemoryStream memoryStream = newMemoryStream(byBuffer, 0, nReceived);
    
    //Next we create a BinaryReader out of the MemoryStream
    BinaryReader binaryReader = newBinaryReader(memoryStream);

    //The first eight bits of the IP header contain the version and
    //header length so we read them
    byVersionAndHeaderLength = binaryReader.ReadByte();

    //The next eight bits contain the Differentiated services
    byDifferentiatedServices = binaryReader.ReadByte();
    
    //Next eight bits hold the total length of the datagram
    usTotalLength = 
             (ushort) IPAddress.NetworkToHostOrder(binaryReader.ReadInt16());

    //Next sixteen have the identification bytes
    usIdentification = 
              (ushort)IPAddress.NetworkToHostOrder(binaryReader.ReadInt16());

    //Next sixteen bits contain the flags and fragmentation offset
    usFlagsAndOffset = 
              (ushort)IPAddress.NetworkToHostOrder(binaryReader.ReadInt16());

    //Next eight bits have the TTL value
    byTTL = binaryReader.ReadByte();

    //Next eight represent the protocol encapsulated in the datagram
    byProtocol = binaryReader.ReadByte();

    //Next sixteen bits contain the checksum of the header
    sChecksum = IPAddress.NetworkToHostOrder(binaryReader.ReadInt16());

    //Next thirty two bits have the source IP address
    uiSourceIPAddress = (uint)(binaryReader.ReadInt32());

    //Next thirty two hold the destination IP address
    uiDestinationIPAddress = (uint)(binaryReader.ReadInt32());

    //Now we calculate the header length
    byHeaderLength = byVersionAndHeaderLength;

    //The last four bits of the version and header length field contain the
    //header length, we perform some simple binary arithmetic operations to
    //extract them
    byHeaderLength <<= 4;
    byHeaderLength >>= 4;

    //Multiply by four to get the exact header length
    byHeaderLength *= 4;

    //Copy the data carried by the datagram into another array so that
    //according to the protocol being carried in the IP datagram
    Array.Copy(byBuffer, 
               byHeaderLength, //start copying from the end of the header
               byIPData, 0, usTotalLength - byHeaderLength);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "MJsniff", MessageBoxButtons.OK, 
                        MessageBoxIcon.Error);
    }
 }
//Please see the attached codes for the properties…
}

Firstly, the class contains the data members corresponding to the fields of the IP header. Kindly see RFC 791 for a detailed explanation of the IP header and its fields. The constructor of the class takes the bytes received and creates a MemoryStream on the received bytes and then creates a BinaryReader to read the data from the MemoryStream byte-by-byte. Also note that the data received from the network is in big-endian form so we use the IPAddress.NetworkToHostOrder to correct the byte ordering. This has to be done for all non-byte data members.

The TCP, UDP headers are also parsed in an identical fashion, the only difference is that they are read from the point where the IP header ends. As an example of parsing the application layer protocols, the attached project can detect DNS packets as well.

References

Updates

  • 9th February, 2008: Fixed the code to capture both incoming and outgoing packets. Thanks to Darren_vms for pointing this in the comments.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Hitesh Sharma
United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionTrying to sniff on a local network Pin
Hammett199322-Apr-13 10:11
memberHammett199322-Apr-13 10:11 
QuestionStart Sniff while Cable Disconnected? Pin
Ali Fakoor6-Feb-13 19:31
memberAli Fakoor6-Feb-13 19:31 
QuestionProblem with VISTA Pin
dot net tech20-Dec-12 21:15
memberdot net tech20-Dec-12 21:15 
QuestionNetwork problems Pin
AJMAL SHAHZAD10-Dec-12 18:45
memberAJMAL SHAHZAD10-Dec-12 18:45 
QuestionHow can decode package Pin
Bilgisoft30-Oct-12 10:00
memberBilgisoft30-Oct-12 10:00 
QuestionSniffing out ALL wifi devices? Pin
pwsmietan17-Jul-12 23:23
memberpwsmietan17-Jul-12 23:23 
QuestionHow do we find the MAC address of the IP we sniffed? Pin
pwsmietan17-Jul-12 12:53
memberpwsmietan17-Jul-12 12:53 
QuestionTrying to filter only all UDP pakets on a single port from any sources Pin
SharePointerrr2-Mar-12 5:01
memberSharePointerrr2-Mar-12 5:01 
QuestionProblem with mainSocket.IOControl Pin
byval26-Feb-12 5:35
memberbyval26-Feb-12 5:35 
QuestionProblem... Pin
byval26-Feb-12 5:35
memberbyval26-Feb-12 5:35 
QuestionCaptures Only inward traffic Pin
saneehaAamir13-Feb-12 18:47
membersaneehaAamir13-Feb-12 18:47 
AnswerRe: Captures Only inward traffic Pin
Member 372970625-Feb-13 0:04
memberMember 372970625-Feb-13 0:04 
GeneralWorks perfect. Vote 5. Pin
lboy2-Feb-12 18:51
memberlboy2-Feb-12 18:51 
QuestionHow I can get the process PID of the current packet?? Pin
terrinfo10-Jan-12 3:34
memberterrinfo10-Jan-12 3:34 
AnswerRe: How I can get the process PID of the current packet?? Pin
Member 372970625-Feb-13 0:06
memberMember 372970625-Feb-13 0:06 
QuestionThis doesnt work correctly...source and destination IPs mixed up Pin
nukenuts7-Dec-11 11:20
membernukenuts7-Dec-11 11:20 
Bugno capturing incoming packets with Windows 7 Pin
Direx0077-Nov-11 22:43
memberDirex0077-Nov-11 22:43 
GeneralRe: no capturing incoming packets with Windows 7 Pin
0Pointer18-Jul-12 20:28
member0Pointer18-Jul-12 20:28 
GeneralRe: no capturing incoming packets with Windows 7 Pin
Member 372970625-Feb-13 0:09
memberMember 372970625-Feb-13 0:09 
QuestionTrying to convert this to web forms Pin
Kasey Krehbiel13-Oct-11 3:46
memberKasey Krehbiel13-Oct-11 3:46 
Question5 and you earned it Pin
Damian 228-Sep-11 23:25
memberDamian 228-Sep-11 23:25 
QuestionPackets of other nodes Pin
Mehrdad Seyrafi18-Jun-11 22:46
memberMehrdad Seyrafi18-Jun-11 22:46 
GeneralGeneral question Pin
hanskarl200024-May-11 10:35
memberhanskarl200024-May-11 10:35 
GeneralCapture To a Variable Pin
Member 776618027-Apr-11 13:30
memberMember 776618027-Apr-11 13:30 
Questionmac address Pin
Member 77196069-Mar-11 20:18
memberMember 77196069-Mar-11 20:18 
QuestionHow to capture URL Pin
eg_Anubhava23-Feb-11 22:45
membereg_Anubhava23-Feb-11 22:45 
Questionintialization of some fields to 555 in tcp header? Pin
ashborg20-Feb-11 7:52
memberashborg20-Feb-11 7:52 
Questionconfigure to listen to SMTP Pin
sbeesu11-Feb-11 11:56
membersbeesu11-Feb-11 11:56 
GeneralCouple of points [modified] Pin
peaco34410-Nov-10 1:19
memberpeaco34410-Nov-10 1:19 
GeneralAn invalid argument was supplied Pin
edsfunsite28-Oct-10 1:16
memberedsfunsite28-Oct-10 1:16 
GeneralRe: An invalid argument was supplied Pin
peaco34422-Nov-10 3:44
memberpeaco34422-Nov-10 3:44 
Questionwinpcap Pin
ngok9-Oct-10 12:18
memberngok9-Oct-10 12:18 
GeneralAn attempt was made to access the socket in a way forbidden by its access permissions Pin
ars.029-Oct-10 7:57
memberars.029-Oct-10 7:57 
AnswerRe: An attempt was made to access the socket in a way forbidden by its access permissions Pin
Jonathan Laloz15-Oct-10 10:29
memberJonathan Laloz15-Oct-10 10:29 
GeneralRe: An attempt was made to access the socket in a way forbidden by its access permissions Pin
ars.0220-Oct-10 18:16
memberars.0220-Oct-10 18:16 
GeneralRe: An attempt was made to access the socket in a way forbidden by its access permissions Pin
ars.0220-Oct-10 18:17
memberars.0220-Oct-10 18:17 
GeneralRe: An attempt was made to access the socket in a way forbidden by its access permissions Pin
priyashivasamy6-Dec-10 21:21
memberpriyashivasamy6-Dec-10 21:21 
QuestionHow to capture incoming packets Pin
Gr3Ger24-Aug-10 5:07
memberGr3Ger24-Aug-10 5:07 
Generalproblem with working more time Pin
sinan balcin23-Aug-10 22:37
membersinan balcin23-Aug-10 22:37 
GeneralRe: problem with working more time Pin
sinan balcin23-Aug-10 22:48
membersinan balcin23-Aug-10 22:48 
Generalhi i have aproblem in the code Pin
aws227-Aug-10 11:45
memberaws227-Aug-10 11:45 
GeneralFirewall Pin
bx35-Aug-10 14:27
memberbx35-Aug-10 14:27 
QuestionWorks great! Is there a VB .NET version of this application? Pin
spicture8-Jul-10 9:23
memberspicture8-Jul-10 9:23 
GeneralExcellent Pin
Michael Langman28-May-10 11:01
memberMichael Langman28-May-10 11:01 
GeneralNice project, need assistance Pin
mask_129-Apr-10 10:34
membermask_129-Apr-10 10:34 
GeneralExcelent project, but exception in W7 Pin
elboya27-Apr-10 4:18
memberelboya27-Apr-10 4:18 
GeneralRe: Excelent project, but exception in W7 Pin
mask_129-Apr-10 10:26
membermask_129-Apr-10 10:26 
GeneralRe: Excelent project, but exception in W7 Pin
elboya30-Apr-10 2:49
memberelboya30-Apr-10 2:49 
GeneralRe: Excelent project, but exception in W7 Pin
mask_130-Apr-10 9:26
membermask_130-Apr-10 9:26 
GeneralQuestions Pin
aimeh12-Mar-10 0:48
memberaimeh12-Mar-10 0:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150731.1 | Last Updated 11 Feb 2008
Article Copyright 2007 by Hitesh Sharma
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid