![]() |
General Programming »
Internet / Network »
General
Intermediate
License: The Code Project Open License (CPOL)
Raw Sockets Using WinsockBy Prasshhant PugaliaRaw socket programming using the Winsock API. |
VC6, Windows, MFC, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Raw sockets, or "Raw Packets", give you the facility to access the entire contents of a packet or datagram, both for reading and writing purpose. In other words, you can fabricate a whole packet according to your likes and dislikes. For example, a TCP packet would contain an IP header, a TCP header, and then the actual data that needs to be transmitted. When working with normal sockets, whatever we send to a socket is actually the data part. In such a scenario, the OS network stack takes the responsibility of adding the header with all fields set to relevant values. When we send the data to a destination, the stack adds the headers and sends the packet, and when we receive some data, then the stack removes the headers and hands out the data to our application. So we are saved from the work of designing the headers. For normal internet applications, there is no need to be concerned about the header operations as they are there for the safe transmission and reception of data, and once the transfer is complete, their need is over and they are dumped. But the story doesn't end there, there are some people who need raw sockets. Raw sockets are widely used in the field of network security for creating both security and insecurity!
In this article, we will take a look at the contents of a general TCP packet, and try to make a raw packet and transmit it. We shall do this on Windows XP using the VC++ 6.0 compiler. OK, so let's have a look at the IP and TCP headers.
RFC 791 gives the structure of an IP header as:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Next comes the TCP header for transmission using the TCP protocol. RFC 793 gives the structure.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
and at the end is your data, bla bla bla bla bla bla.......................
----------------------------------------------------------- <<end of packet
To understand the significance of each field, read up the necessary RFC or some other good TCP/IP tutorial on the net as there are plenty. If you have previous knowledge of socket programming, then the headers are self-explanatory. Now, why is the raw socket feature of importance to network security? Well, one important aspect of network security which needs this feature is scanning. Scanning is of many types. For example, scanning for open ports, scanning the type of OS, scanning for vulnerabilities etc.
First of all, it must be understood very clearly that raw sockets is not a feature of the network API (although it must be present there as an option) but of the OS protocol stack. To implement raw sockets, all we have to do is to inform the OS that the packet buffer we are providing will have the header and so the OS should transmit it as is without "adding any header"; that's all, nothing more to do. The Unix operating system has raw socket support since ancient times. But the problem is with Windows. None of Windows 95, 98, 98SE supported raw sockets. Raw sockets became available on Windows from Windows 2000; Windows XP continued this. But suddenly, raw socket support was removed from Windows XP through a patch in SP2. Vista probably doesn't have it. Windows 95, 98, 98SE do not support raw sockets, but this doesn't end the story. If you want the facility, then the solution is to use a third party packet driver like Winpcap. Such packet drivers will do your task irrespective of what the OS likes and dislikes. Windows XP and XP SP1 have full raw socket support and so life is easy. So if you want to do raw socketing on Windows, then either use Winpcap or don't feel desperate to install SP2, or otherwise use Windows 2003 which, as per my knowledge, has raw socket support. So let's brief up.
Note : Winsock Ver. >=2.0
So if your system doesn't support raw sockets, then switch to Linux or use Winpcap.
SOCKET s; s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); //Create a RAW socket int optval=1; setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof optval); //Set it to include the header
The last line, setsockopt, tells the OS that the socket s will have the header included (IP_HDRINCL) at the IP (IPPROTO_IP) level in the data buffer it sends. IPPROTO_RAW creates an absolutely raw socket, and you have to write all headers yourself. IPPROTO_UDP, IPROTO_TCP are also available for the respective types of packets.
Now, we shall need two structures like this:
typedef struct ip_hdr { unsigned char ip_header_len:4; // 4-bit header length (in 32-bit words) // normally=5 (Means 20 Bytes may be 24 also) unsigned char ip_version :4; // 4-bit IPv4 version unsigned char ip_tos; // IP type of service unsigned short ip_total_length; // Total length unsigned short ip_id; // Unique identifier unsigned char ip_frag_offset :5; // Fragment offset field unsigned char ip_more_fragment :1; unsigned char ip_dont_fragment :1; unsigned char ip_reserved_zero :1; unsigned char ip_frag_offset1; //fragment offset unsigned char ip_ttl; // Time to live unsigned char ip_protocol; // Protocol(TCP,UDP etc) unsigned short ip_checksum; // IP checksum unsigned int ip_srcaddr; // Source address unsigned int ip_destaddr; // Source address } IPV4_HDR, *PIPV4_HDR, FAR * LPIPV4_HDR; // TCP header typedef struct tcp_header { unsigned short source_port; // source port unsigned short dest_port; // destination port unsigned int sequence; // sequence number - 32 bits unsigned int acknowledge; // acknowledgement number - 32 bits unsigned char ns :1; //Nonce Sum Flag Added in RFC 3540. unsigned char reserved_part1:3; //according to rfc unsigned char data_offset:4; /*The number of 32-bit words in the TCP header. This indicates where the data begins. The length of the TCP header is always a multiple of 32 bits.*/ unsigned char fin :1; //Finish Flag unsigned char syn :1; //Synchronise Flag unsigned char rst :1; //Reset Flag unsigned char psh :1; //Push Flag unsigned char ack :1; //Acknowledgement Flag unsigned char urg :1; //Urgent Flag unsigned char ecn :1; //ECN-Echo Flag unsigned char cwr :1; //Congestion Window Reduced Flag //////////////////////////////// unsigned short window; // window unsigned short checksum; // checksum unsigned short urgent_pointer; // urgent pointer } TCP_HDR , *PTCP_HDR , FAR * LPTCP_HDR , TCPHeader , TCP_HEADER;
Did you notice a difference between the RFC specification and the structures declared above? IP header and version have swapped their positions.The urg, ack, and psh flags of the TCP header are all in reverse order? Mistake? Well, this depends on the byte order that is implemented in the machine architecture. There are two types: Little Endian and Big Endian. In Big Endian, the bytes and bits are arranged in their normal order as we read them, which means the MSB (most significant byte) comes first and the LSB (least significant byte) last. But in Little Endian, the thing is totally reversed. And it must be remembered that all bits are byte wise reversed, which means they are reversed in groups of 8. That's the rule for making segments of sizes 3 or 5 etc. If it's a long or int, then a htons() will do the job. Well, enough said, now let's make our packet.
char packet[65536]; //thats big! IPV4_HDR *v4hdr=NULL; TCP_HDR *tcphdr=NULL;
v4hdr = (IPV4_HDR *)packet; //lets point to the ip header portion v4hdr->ip_version=4; v4hdr->ip_header_len=5; v4hdr->ip_tos = 0; v4hdr->ip_total_length = htons ( sizeof(IPV4_HDR) + sizeof(TCP_HDR) + payload ); v4hdr->ip_id = htons(2); ...............and so on tcphdr = (TCP_HDR *)&buf[sizeof(IPV4_HDR)]; //get the pointer to the tcp header in the packet tcphdr->source_port = htons(1234); tcphdr->dest_port = htons(50000); tcphdr->cwr=0; tcphdr->ecn=1; tcphdr->urg=0; tcphdr->ack=0; ..................and so on // Initialize the TCP payload to some rubbish data = &buf[sizeof(IPV4_HDR) + sizeof(TCP_HDR)]; memset(data, '^', payload);
Get the remote host details in a sockaddr_in dest and call:
sendto(s , buf , sizeof(IPV4_HDR)+sizeof(TCP_HDR) + payload, 0,(SOCKADDR *)&dest, sizeof(dest))
where payload is the size of the data after the TCP header. That's it! We are done.
To check whether the packets went out as you expected them to, use a sniffer like Ethereal and sniff them. Note: If you have any firewall running, then raw packets may be blocked.
Feel free to send your comments: prashant.pugalia@yahoo.co.in.
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 3 Jan 2007 Editor: Smitha Vijayan |
Copyright 2007 by Prasshhant Pugalia Everything else Copyright © CodeProject, 1999-2010 Web19 | Advertise on the Code Project |