Thursday, June 27, 2013

Code raw sockets in C on Linux

http://www.binarytides.com/raw-sockets-c-code-linux

Raw tcp sockets in C

Raw sockets can be used to construct a packet manually inside an
application. In normal sockets when any data is send over the network,
the kernel of the operating system adds some headers to it like IP
header and TCP header. So an application only needs to take care of what
data it is sending and what reply it is expecting.

But there are other cases when an application needs to set its own
headers. Raw sockets are used in security related applications like nmap
, packets sniffer etc. In this article we are going to program raw
sockets on linux using native sockets. Windows for example does not
support raw socket programming directly. To program raw sockets on windows a packet crafting library like winpcap has to be used.
In this article we are going to do some raw socket programming by
constructing a raw TCP packet and sending it over the network. Before
programming raw sockets, it is recommended that you learn about the
basics of socket programming in c.

Raw TCP packets

A TCP packet is constructed like this
Packet = IP Header + TCP Header + Data
The plus means to attach the binary data side by side. So when making
a raw tcp packet we need to know how to construct the headers properly.
The structures of all headers are established standards which are
described in RFCs.

Ip header

The structure of IP Header as given by RFC 791

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The "Source Address" field stores the ip address of the system
sending the packet and the "Destination Address" contains the ip address
of the destination system. Ip addresses are stored in long number
format. The "Protocol" field stores a number that indicates the
protocol, which is TCP in this case.

Structure of tcp header

The structure of a TCP header as given by RFC 793

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

So we need to construct the headers according to the formats specified above.

Raw tcp sockets

Create a raw socket like this

1

ints = socket (AF_INET, SOCK_RAW, IPPROTO_TCP);

The above function call creates a raw socket of protocol TCP. This
means that we have to provide the TCP header along with the data. The
kernel or the network stack of Linux shall provide the IP header.
If we want to provide the IP header as well then there are 2 ways of doing this
1. Use protocol IPPROTO_RAW - This will allow to specify the IP header and everything that is contained in the packet.

1

ints = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);

2. Set the IP_HDRINCL socket option to 1 - This is same as the above. Just another way of doing.

When using the IP_HDRINCL the protocol used in the socket function is effectively of no use.

In this example we are creating raw sockets
where we specify the Ip header and TCP header. The packet that moves out
of the machine actually has 1 more header attached to it called the
Ethernet header. So the actual packet structure is somewhat like this.
Packet = Ethernet header + Ip header + TCP header + Data
Take a look at the packets sniffed by wireshark to understand this
better. It is important to note here that the Ethernet header is
provided by the OS kernel and we do not have to construct it. However it
is possible to make such raw packets where we can even specify the
ethernet header, but we shall look into those in a separate article.

Below is an example code which constructs a raw TCP packet with some data

Compile and Run

Compile by program by doing a gcc raw_socket.c at the terminal.
Remember to run the program with root privileges. Raw sockets require
root privileges. Note the while loop in the above program. It has been
put for testing purpose and should be removed if you dont intend to
flood the target.
Use a packet sniffer like wireshark to check the output and verify
that the packets have actually been generated and send over the network.
Also note that if some kind of firewall like firestarter is running
then it might block raw packets.