|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionIn 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 The second parameter passed to Analysing the PacketsThe 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 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. ReferencesUpdates
|
||||||||||||||||||||||